mirror of
https://github.com/github/codeql.git
synced 2025-12-16 16:53:25 +01:00
Dataflow: Replace MakeSets with QlBuiltins::InternSets.
This commit is contained in:
@@ -239,17 +239,7 @@ class CastNode extends Node {
|
||||
CastNode() { none() } // stub implementation
|
||||
}
|
||||
|
||||
class DataFlowCallable extends Function {
|
||||
/** Gets a best-effort total ordering. */
|
||||
int totalorder() {
|
||||
this =
|
||||
rank[result](DataFlowCallable c, string file, int startline, int startcolumn |
|
||||
c.getLocation().hasLocationInfo(file, startline, startcolumn, _, _)
|
||||
|
|
||||
c order by file, startline, startcolumn
|
||||
)
|
||||
}
|
||||
}
|
||||
class DataFlowCallable extends Function { }
|
||||
|
||||
class DataFlowExpr = Expr;
|
||||
|
||||
@@ -269,24 +259,12 @@ class DataFlowCall extends Expr instanceof Call {
|
||||
|
||||
/** Gets the enclosing callable of this call. */
|
||||
DataFlowCallable getEnclosingCallable() { result = this.getEnclosingFunction() }
|
||||
|
||||
/** Gets a best-effort total ordering. */
|
||||
int totalorder() {
|
||||
this =
|
||||
rank[result](DataFlowCall c, int startline, int startcolumn |
|
||||
c.getLocation().hasLocationInfo(_, startline, startcolumn, _, _)
|
||||
|
|
||||
c order by startline, startcolumn
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
class NodeRegion instanceof Unit {
|
||||
string toString() { result = "NodeRegion" }
|
||||
|
||||
predicate contains(Node n) { none() }
|
||||
|
||||
int totalOrder() { result = 1 }
|
||||
}
|
||||
|
||||
predicate isUnreachableInCall(NodeRegion nr, DataFlowCall call) { none() } // stub implementation
|
||||
|
||||
@@ -1060,16 +1060,6 @@ class DataFlowCallable extends TDataFlowCallable {
|
||||
result = this.asSummarizedCallable() or // SummarizedCallable = Function (in CPP)
|
||||
result = this.asSourceCallable()
|
||||
}
|
||||
|
||||
/** Gets a best-effort total ordering. */
|
||||
int totalorder() {
|
||||
this =
|
||||
rank[result](DataFlowCallable c, string file, int startline, int startcolumn |
|
||||
c.getLocation().hasLocationInfo(file, startline, startcolumn, _, _)
|
||||
|
|
||||
c order by file, startline, startcolumn
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1167,16 +1157,6 @@ class DataFlowCall extends TDataFlowCall {
|
||||
* Gets the location of this call.
|
||||
*/
|
||||
Location getLocation() { none() }
|
||||
|
||||
/** Gets a best-effort total ordering. */
|
||||
int totalorder() {
|
||||
this =
|
||||
rank[result](DataFlowCall c, int startline, int startcolumn |
|
||||
c.getLocation().hasLocationInfo(_, startline, startcolumn, _, _)
|
||||
|
|
||||
c order by startline, startcolumn
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1269,15 +1249,6 @@ module IsUnreachableInCall {
|
||||
string toString() { result = "NodeRegion" }
|
||||
|
||||
predicate contains(Node n) { this = n.getBasicBlock() }
|
||||
|
||||
int totalOrder() {
|
||||
this =
|
||||
rank[result](IRBlock b, int startline, int startcolumn |
|
||||
b.getLocation().hasLocationInfo(_, startline, startcolumn, _, _)
|
||||
|
|
||||
b order by startline, startcolumn
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
predicate isUnreachableInCall(NodeRegion block, DataFlowCall call) {
|
||||
|
||||
@@ -191,16 +191,6 @@ class DataFlowCallable extends TDataFlowCallable {
|
||||
or
|
||||
result = this.asCapturedVariable().getLocation()
|
||||
}
|
||||
|
||||
/** Gets a best-effort total ordering. */
|
||||
int totalorder() {
|
||||
this =
|
||||
rank[result](DataFlowCallable c, string file, int startline, int startcolumn |
|
||||
c.getLocation().hasLocationInfo(file, startline, startcolumn, _, _)
|
||||
|
|
||||
c order by file, startline, startcolumn
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/** A call relevant for data flow. */
|
||||
@@ -244,16 +234,6 @@ abstract class DataFlowCall extends TDataFlowCall {
|
||||
) {
|
||||
this.getLocation().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
|
||||
}
|
||||
|
||||
/** Gets a best-effort total ordering. */
|
||||
int totalorder() {
|
||||
this =
|
||||
rank[result](DataFlowCall c, int startline, int startcolumn |
|
||||
c.hasLocationInfo(_, startline, startcolumn, _, _)
|
||||
|
|
||||
c order by startline, startcolumn
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/** A non-delegate C# call relevant for data flow. */
|
||||
|
||||
@@ -2379,15 +2379,6 @@ class NodeRegion instanceof ControlFlow::BasicBlock {
|
||||
string toString() { result = "NodeRegion" }
|
||||
|
||||
predicate contains(Node n) { this = n.getControlFlowNode().getBasicBlock() }
|
||||
|
||||
int totalOrder() {
|
||||
this =
|
||||
rank[result](ControlFlow::BasicBlock b, int startline, int startcolumn |
|
||||
b.getLocation().hasLocationInfo(_, startline, startcolumn, _, _)
|
||||
|
|
||||
b order by startline, startcolumn
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -318,16 +318,6 @@ class DataFlowCallable extends TDataFlowCallable {
|
||||
result = this.asFileScope().getLocation() or
|
||||
result = getCallableLocation(this.asSummarizedCallable())
|
||||
}
|
||||
|
||||
/** Gets a best-effort total ordering. */
|
||||
int totalorder() {
|
||||
this =
|
||||
rank[result](DataFlowCallable c, string file, int startline, int startcolumn |
|
||||
c.hasLocationInfo(file, startline, startcolumn, _, _)
|
||||
|
|
||||
c order by file, startline, startcolumn
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private Location getCallableLocation(Callable c) {
|
||||
@@ -361,16 +351,6 @@ class DataFlowCall extends Expr {
|
||||
|
||||
/** Gets the location of this call. */
|
||||
Location getLocation() { result = super.getLocation() }
|
||||
|
||||
/** Gets a best-effort total ordering. */
|
||||
int totalorder() {
|
||||
this =
|
||||
rank[result](DataFlowCall c, int startline, int startcolumn |
|
||||
c.getLocation().hasLocationInfo(_, startline, startcolumn, _, _)
|
||||
|
|
||||
c order by startline, startcolumn
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/** Holds if `e` is an expression that always has the same Boolean value `val`. */
|
||||
@@ -413,15 +393,6 @@ class NodeRegion instanceof BasicBlock {
|
||||
string toString() { result = "NodeRegion" }
|
||||
|
||||
predicate contains(Node n) { n.getBasicBlock() = this }
|
||||
|
||||
int totalOrder() {
|
||||
this =
|
||||
rank[result](BasicBlock b, int startline, int startcolumn |
|
||||
b.hasLocationInfo(_, startline, startcolumn, _, _)
|
||||
|
|
||||
b order by startline, startcolumn
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -400,21 +400,6 @@ class CastNode extends ExprNode {
|
||||
}
|
||||
}
|
||||
|
||||
private predicate id_member(Member x, Member y) { x = y }
|
||||
|
||||
private predicate idOf_member(Member x, int y) = equivalenceRelation(id_member/2)(x, y)
|
||||
|
||||
private int summarizedCallableId(SummarizedCallable c) {
|
||||
c =
|
||||
rank[result](SummarizedCallable c0, int b, int i, string s |
|
||||
b = 0 and idOf_member(c0.asCallable(), i) and s = ""
|
||||
or
|
||||
b = 1 and i = 0 and s = c0.asSyntheticCallable()
|
||||
|
|
||||
c0 order by b, i, s
|
||||
)
|
||||
}
|
||||
|
||||
private newtype TDataFlowCallable =
|
||||
TSrcCallable(Callable c) or
|
||||
TSummarizedCallable(SummarizedCallable c) or
|
||||
@@ -448,28 +433,10 @@ class DataFlowCallable extends TDataFlowCallable {
|
||||
result = this.asSummarizedCallable().getLocation() or
|
||||
result = this.asFieldScope().getLocation()
|
||||
}
|
||||
|
||||
/** Gets a best-effort total ordering. */
|
||||
int totalorder() {
|
||||
this =
|
||||
rank[result](DataFlowCallable c, int b, int i |
|
||||
b = 0 and idOf_member(c.asCallable(), i)
|
||||
or
|
||||
b = 1 and i = summarizedCallableId(c.asSummarizedCallable())
|
||||
or
|
||||
b = 2 and idOf_member(c.asFieldScope(), i)
|
||||
|
|
||||
c order by b, i
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
class DataFlowExpr = Expr;
|
||||
|
||||
private predicate id_call(Call x, Call y) { x = y }
|
||||
|
||||
private predicate idOf_call(Call x, int y) = equivalenceRelation(id_call/2)(x, y)
|
||||
|
||||
private newtype TDataFlowCall =
|
||||
TCall(Call c) or
|
||||
TSummaryCall(SummarizedCallable c, FlowSummaryImpl::Private::SummaryNode receiver) {
|
||||
@@ -502,19 +469,6 @@ class DataFlowCall extends TDataFlowCall {
|
||||
) {
|
||||
this.getLocation().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
|
||||
}
|
||||
|
||||
/** Gets a best-effort total ordering. */
|
||||
int totalorder() {
|
||||
this =
|
||||
rank[result](DataFlowCall c, int b, int i |
|
||||
b = 0 and idOf_call(c.asCall(), i)
|
||||
or
|
||||
b = 1 and // not guaranteed to be total
|
||||
exists(SummarizedCallable sc | c = TSummaryCall(sc, _) and i = summarizedCallableId(sc))
|
||||
|
|
||||
c order by b, i
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/** A source call, that is, a `Call`. */
|
||||
@@ -549,16 +503,10 @@ class SummaryCall extends DataFlowCall, TSummaryCall {
|
||||
override Location getLocation() { result = c.getLocation() }
|
||||
}
|
||||
|
||||
private predicate id(BasicBlock x, BasicBlock y) { x = y }
|
||||
|
||||
private predicate idOf(BasicBlock x, int y) = equivalenceRelation(id/2)(x, y)
|
||||
|
||||
class NodeRegion instanceof BasicBlock {
|
||||
string toString() { result = "NodeRegion" }
|
||||
|
||||
predicate contains(Node n) { n.asExpr().getBasicBlock() = this }
|
||||
|
||||
int totalOrder() { idOf(this, result) }
|
||||
}
|
||||
|
||||
/** Holds if `e` is an expression that always has the same Boolean value `val`. */
|
||||
|
||||
@@ -344,16 +344,6 @@ abstract class DataFlowCallable extends TDataFlowCallable {
|
||||
|
||||
/** Gets the location of this dataflow callable. */
|
||||
abstract Location getLocation();
|
||||
|
||||
/** Gets a best-effort total ordering. */
|
||||
int totalorder() {
|
||||
this =
|
||||
rank[result](DataFlowCallable c, string file, int startline, int startcolumn |
|
||||
c.getLocation().hasLocationInfo(file, startline, startcolumn, _, _)
|
||||
|
|
||||
c order by file, startline, startcolumn
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/** A callable function. */
|
||||
@@ -1435,16 +1425,6 @@ abstract class DataFlowCall extends TDataFlowCall {
|
||||
) {
|
||||
this.getLocation().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
|
||||
}
|
||||
|
||||
/** Gets a best-effort total ordering. */
|
||||
int totalorder() {
|
||||
this =
|
||||
rank[result](DataFlowCall c, int startline, int startcolumn |
|
||||
c.hasLocationInfo(_, startline, startcolumn, _, _)
|
||||
|
|
||||
c order by startline, startcolumn
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/** A call found in the program source (as opposed to a synthesised call). */
|
||||
|
||||
@@ -1025,8 +1025,6 @@ class NodeRegion instanceof Unit {
|
||||
string toString() { result = "NodeRegion" }
|
||||
|
||||
predicate contains(Node n) { none() }
|
||||
|
||||
int totalOrder() { result = 1 }
|
||||
}
|
||||
|
||||
//--------
|
||||
|
||||
@@ -113,16 +113,6 @@ class DataFlowCallable extends TDataFlowCallable {
|
||||
this instanceof TLibraryCallable and
|
||||
result instanceof EmptyLocation
|
||||
}
|
||||
|
||||
/** Gets a best-effort total ordering. */
|
||||
int totalorder() {
|
||||
this =
|
||||
rank[result](DataFlowCallable c, string file, int startline, int startcolumn |
|
||||
c.getLocation().hasLocationInfo(file, startline, startcolumn, _, _)
|
||||
|
|
||||
c order by file, startline, startcolumn
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -154,16 +144,6 @@ abstract class DataFlowCall extends TDataFlowCall {
|
||||
) {
|
||||
this.getLocation().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
|
||||
}
|
||||
|
||||
/** Gets a best-effort total ordering. */
|
||||
int totalorder() {
|
||||
this =
|
||||
rank[result](DataFlowCall c, int startline, int startcolumn |
|
||||
c.hasLocationInfo(_, startline, startcolumn, _, _)
|
||||
|
|
||||
c order by startline, startcolumn
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -2183,8 +2183,6 @@ class NodeRegion instanceof Unit {
|
||||
string toString() { result = "NodeRegion" }
|
||||
|
||||
predicate contains(Node n) { none() }
|
||||
|
||||
int totalOrder() { result = 1 }
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -76,9 +76,6 @@ signature module InputSig<LocationSig Location> {
|
||||
Location getLocation();
|
||||
|
||||
DataFlowCallable getEnclosingCallable();
|
||||
|
||||
/** Gets a best-effort total ordering. */
|
||||
int totalorder();
|
||||
}
|
||||
|
||||
class DataFlowCallable {
|
||||
@@ -87,9 +84,6 @@ signature module InputSig<LocationSig Location> {
|
||||
|
||||
/** Gets the location of this callable. */
|
||||
Location getLocation();
|
||||
|
||||
/** Gets a best-effort total ordering. */
|
||||
int totalorder();
|
||||
}
|
||||
|
||||
class ReturnKind {
|
||||
@@ -266,8 +260,6 @@ signature module InputSig<LocationSig Location> {
|
||||
class NodeRegion {
|
||||
/** Holds if this region contains `n`. */
|
||||
predicate contains(Node n);
|
||||
|
||||
int totalOrder();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -4,7 +4,6 @@ private import codeql.util.Location
|
||||
private import codeql.util.Option
|
||||
private import codeql.util.Unit
|
||||
private import codeql.util.Option
|
||||
private import codeql.util.internal.MakeSets
|
||||
|
||||
module MakeImplCommon<LocationSig Location, InputSig<Location> Lang> {
|
||||
private import Lang
|
||||
@@ -502,24 +501,21 @@ module MakeImplCommon<LocationSig Location, InputSig<Location> Lang> {
|
||||
)
|
||||
}
|
||||
|
||||
private module CallSetsInput implements MkSetsInputSig {
|
||||
class Key = TCallEdge;
|
||||
|
||||
class Value = DataFlowCall;
|
||||
|
||||
DataFlowCall getAValue(TCallEdge ctxEdge) {
|
||||
exists(DataFlowCall ctx, DataFlowCallable c |
|
||||
ctxEdge = TMkCallEdge(ctx, c) and
|
||||
reducedViableImplInCallContext(result, c, ctx)
|
||||
)
|
||||
}
|
||||
|
||||
int totalorder(DataFlowCall e) { result = callOrder(e) }
|
||||
private DataFlowCall getACallWithReducedViableImpl(TCallEdge ctxEdge) {
|
||||
exists(DataFlowCall ctx, DataFlowCallable c |
|
||||
ctxEdge = TMkCallEdge(ctx, c) and
|
||||
reducedViableImplInCallContext(result, c, ctx)
|
||||
)
|
||||
}
|
||||
|
||||
private module CallSets = MakeSets<CallSetsInput>;
|
||||
private module CallSets =
|
||||
QlBuiltins::InternSets<TCallEdge, DataFlowCall, getACallWithReducedViableImpl/1>;
|
||||
|
||||
private module CallSetOption = Option<CallSets::ValueSet>;
|
||||
private class CallSet0 extends CallSets::Set {
|
||||
string toString() { result = "CallSet" }
|
||||
}
|
||||
|
||||
private module CallSetOption = Option<CallSet0>;
|
||||
|
||||
/**
|
||||
* A set of call sites for which dispatch is affected by the call context.
|
||||
@@ -528,26 +524,23 @@ module MakeImplCommon<LocationSig Location, InputSig<Location> Lang> {
|
||||
*/
|
||||
private class CallSet = CallSetOption::Option;
|
||||
|
||||
private module DispatchSetsInput implements MkSetsInputSig {
|
||||
class Key = TCallEdge;
|
||||
|
||||
class Value = TCallEdge;
|
||||
|
||||
TCallEdge getAValue(TCallEdge ctxEdge) {
|
||||
exists(DataFlowCall ctx, DataFlowCallable c, DataFlowCall call, DataFlowCallable tgt |
|
||||
ctxEdge = mkCallEdge(ctx, c) and
|
||||
result = mkCallEdge(call, tgt) and
|
||||
viableImplInCallContextExtIn(call, ctx) = tgt and
|
||||
reducedViableImplInCallContext(call, c, ctx)
|
||||
)
|
||||
}
|
||||
|
||||
int totalorder(TCallEdge e) { result = edgeOrder(e) }
|
||||
private TCallEdge getAReducedViableEdge(TCallEdge ctxEdge) {
|
||||
exists(DataFlowCall ctx, DataFlowCallable c, DataFlowCall call, DataFlowCallable tgt |
|
||||
ctxEdge = mkCallEdge(ctx, c) and
|
||||
result = mkCallEdge(call, tgt) and
|
||||
viableImplInCallContextExtIn(call, ctx) = tgt and
|
||||
reducedViableImplInCallContext(call, c, ctx)
|
||||
)
|
||||
}
|
||||
|
||||
private module DispatchSets = MakeSets<DispatchSetsInput>;
|
||||
private module DispatchSets =
|
||||
QlBuiltins::InternSets<TCallEdge, TCallEdge, getAReducedViableEdge/1>;
|
||||
|
||||
private module DispatchSetsOption = Option<DispatchSets::ValueSet>;
|
||||
private class DispatchSet0 extends DispatchSets::Set {
|
||||
string toString() { result = "DispatchSet" }
|
||||
}
|
||||
|
||||
private module DispatchSetsOption = Option<DispatchSet0>;
|
||||
|
||||
/**
|
||||
* A set of call edges that are allowed in the call context. This applies to
|
||||
@@ -561,7 +554,7 @@ module MakeImplCommon<LocationSig Location, InputSig<Location> Lang> {
|
||||
private class DispatchSet = DispatchSetsOption::Option;
|
||||
|
||||
private predicate relevantCtx(TCallEdge ctx) {
|
||||
exists(CallSets::getValueSet(ctx)) or exists(getUnreachableSet(ctx))
|
||||
exists(CallSets::getSet(ctx)) or exists(getUnreachableSet(ctx))
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
@@ -570,14 +563,14 @@ module MakeImplCommon<LocationSig Location, InputSig<Location> Lang> {
|
||||
) {
|
||||
relevantCtx(ctx) and
|
||||
(
|
||||
CallSets::getValueSet(ctx) = calls.asSome()
|
||||
CallSets::getSet(ctx) = calls.asSome()
|
||||
or
|
||||
not exists(CallSets::getValueSet(ctx)) and calls.isNone()
|
||||
not exists(CallSets::getSet(ctx)) and calls.isNone()
|
||||
) and
|
||||
(
|
||||
DispatchSets::getValueSet(ctx) = tgts.asSome()
|
||||
DispatchSets::getSet(ctx) = tgts.asSome()
|
||||
or
|
||||
not exists(DispatchSets::getValueSet(ctx)) and tgts.isNone()
|
||||
not exists(DispatchSets::getSet(ctx)) and tgts.isNone()
|
||||
) and
|
||||
(
|
||||
getUnreachableSet(ctx) = unreachable.asSome()
|
||||
@@ -1515,40 +1508,20 @@ module MakeImplCommon<LocationSig Location, InputSig<Location> Lang> {
|
||||
newtype TCallEdge =
|
||||
TMkCallEdge(DataFlowCall call, DataFlowCallable tgt) { viableCallableExt(call) = tgt }
|
||||
|
||||
cached
|
||||
int edgeOrder(TCallEdge edge) {
|
||||
edge =
|
||||
rank[result](TCallEdge e, DataFlowCall call, DataFlowCallable tgt |
|
||||
e = TMkCallEdge(call, tgt)
|
||||
|
|
||||
e order by call.totalorder(), tgt.totalorder()
|
||||
)
|
||||
private NodeRegion getAnUnreachableRegion(TCallEdge edge) {
|
||||
exists(DataFlowCall call, DataFlowCallable tgt |
|
||||
edge = mkCallEdge(call, tgt) and
|
||||
getNodeRegionEnclosingCallable(result) = tgt and
|
||||
isUnreachableInCallCached(result, call)
|
||||
)
|
||||
}
|
||||
|
||||
cached
|
||||
int callOrder(DataFlowCall call) { result = call.totalorder() }
|
||||
|
||||
private module UnreachableSetsInput implements MkSetsInputSig {
|
||||
class Key = TCallEdge;
|
||||
|
||||
class Value = NodeRegion;
|
||||
|
||||
NodeRegion getAValue(TCallEdge edge) {
|
||||
exists(DataFlowCall call, DataFlowCallable tgt |
|
||||
edge = mkCallEdge(call, tgt) and
|
||||
getNodeRegionEnclosingCallable(result) = tgt and
|
||||
isUnreachableInCallCached(result, call)
|
||||
)
|
||||
}
|
||||
|
||||
int totalorder(NodeRegion nr) { result = nr.totalOrder() }
|
||||
}
|
||||
|
||||
private module UnreachableSets = MakeSets<UnreachableSetsInput>;
|
||||
private module UnreachableSets =
|
||||
QlBuiltins::InternSets<TCallEdge, NodeRegion, getAnUnreachableRegion/1>;
|
||||
|
||||
/** A set of nodes that is unreachable in some call context. */
|
||||
cached
|
||||
class UnreachableSet instanceof UnreachableSets::ValueSet {
|
||||
class UnreachableSet instanceof UnreachableSets::Set {
|
||||
cached
|
||||
string toString() { result = "Unreachable" }
|
||||
|
||||
@@ -1562,7 +1535,7 @@ module MakeImplCommon<LocationSig Location, InputSig<Location> Lang> {
|
||||
}
|
||||
|
||||
cached
|
||||
UnreachableSet getUnreachableSet(TCallEdge edge) { result = UnreachableSets::getValueSet(edge) }
|
||||
UnreachableSet getUnreachableSet(TCallEdge edge) { result = UnreachableSets::getSet(edge) }
|
||||
|
||||
private module UnreachableSetOption = Option<UnreachableSet>;
|
||||
|
||||
@@ -1579,7 +1552,7 @@ module MakeImplCommon<LocationSig Location, InputSig<Location> Lang> {
|
||||
cached
|
||||
newtype TLocalFlowCallContext =
|
||||
TAnyLocalCall() or
|
||||
TSpecificLocalCall(UnreachableSets::ValueSet ns)
|
||||
TSpecificLocalCall(UnreachableSets::Set ns)
|
||||
|
||||
cached
|
||||
newtype TReturnKindExt =
|
||||
|
||||
@@ -1,104 +0,0 @@
|
||||
/**
|
||||
* INTERNAL: This module may be replaced without notice.
|
||||
*
|
||||
* Provides a module to create first-class representations of sets of values.
|
||||
*/
|
||||
|
||||
/** The input signature for `MakeSets`. */
|
||||
signature module MkSetsInputSig {
|
||||
class Key;
|
||||
|
||||
class Value;
|
||||
|
||||
Value getAValue(Key k);
|
||||
|
||||
int totalorder(Value v);
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a binary predicate `getAValue`, this module groups the `Value` column
|
||||
* by `Key` and constructs the corresponding sets of `Value`s as single entities.
|
||||
*
|
||||
* The output is a functional predicate, `getValueSet`, such that
|
||||
* `getValueSet(k).contains(v)` is equivalent to `v = getAValue(k)`, and a
|
||||
* class, `ValueSet`, that canonically represents a set of `Value`s. In
|
||||
* particular, if two keys `k1` and `k2` relate to the same set of values, then
|
||||
* `getValueSet(k1) = getValueSet(k2)`.
|
||||
*
|
||||
* If the given `totalorder` is not a total order, then the keys for which we
|
||||
* cannot order the values cannot be given a canonical representation, and
|
||||
* instead the key is simply reused as the set representation. This provides a
|
||||
* reasonable fallback where `getValueSet(k).contains(v)` remains equivalent to
|
||||
* `v = getAValue(k)`.
|
||||
*/
|
||||
module MakeSets<MkSetsInputSig Inp> {
|
||||
private import Inp
|
||||
|
||||
private int totalorderExt(Value v) {
|
||||
result = 0 and v = getAValue(_) and not exists(totalorder(v))
|
||||
or
|
||||
result = totalorder(v)
|
||||
}
|
||||
|
||||
private predicate rankedValue(Key k, Value v, int r) {
|
||||
v = rank[r](Value v0 | v0 = getAValue(k) | v0 order by totalorderExt(v0))
|
||||
}
|
||||
|
||||
private predicate unordered(Key k) {
|
||||
strictcount(int r | rankedValue(k, _, r)) != strictcount(getAValue(k))
|
||||
}
|
||||
|
||||
private int maxRank(Key k) { result = max(int r | rankedValue(k, _, r)) and not unordered(k) }
|
||||
|
||||
private newtype TValList =
|
||||
TValListNil() or
|
||||
TValListCons(Value head, int r, TValList tail) { hasValListCons(_, head, r, tail) } or
|
||||
TValListUnordered(Key k) { unordered(k) }
|
||||
|
||||
private predicate hasValListCons(Key k, Value head, int r, TValList tail) {
|
||||
rankedValue(k, head, r) and
|
||||
hasValList(k, r - 1, tail)
|
||||
}
|
||||
|
||||
private predicate hasValList(Key k, int r, TValList l) {
|
||||
exists(getAValue(k)) and r = 0 and l = TValListNil()
|
||||
or
|
||||
exists(Value head, TValList tail |
|
||||
l = TValListCons(head, r, tail) and
|
||||
hasValListCons(k, head, r, tail)
|
||||
)
|
||||
}
|
||||
|
||||
private predicate hasValueSet(Key k, TValList vs) {
|
||||
hasValList(k, maxRank(k), vs) or vs = TValListUnordered(k)
|
||||
}
|
||||
|
||||
/** A set of `Value`s. */
|
||||
class ValueSet extends TValList {
|
||||
ValueSet() { hasValueSet(_, this) }
|
||||
|
||||
string toString() {
|
||||
this instanceof TValListCons and result = "ValueSet"
|
||||
or
|
||||
this instanceof TValListUnordered and result = "ValueSetUnordered"
|
||||
}
|
||||
|
||||
private predicate sublist(TValListCons l) {
|
||||
this = l or
|
||||
this.sublist(TValListCons(_, _, l))
|
||||
}
|
||||
|
||||
/** Holds if this set contains `v`. */
|
||||
predicate contains(Value v) {
|
||||
this.sublist(TValListCons(v, _, _))
|
||||
or
|
||||
exists(Key k | this = TValListUnordered(k) and v = getAValue(k))
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the set of values such that `getValueSet(k).contains(v)` is equivalent
|
||||
* to `v = getAValue(k)`.
|
||||
*/
|
||||
ValueSet getValueSet(Key k) { hasValueSet(k, result) }
|
||||
}
|
||||
@@ -65,16 +65,6 @@ class DataFlowCallable extends TDataFlowCallable {
|
||||
Callable::TypeRange getUnderlyingCallable() {
|
||||
result = this.asSummarizedCallable() or result = this.asSourceCallable()
|
||||
}
|
||||
|
||||
/** Gets a best-effort total ordering. */
|
||||
int totalorder() {
|
||||
this =
|
||||
rank[result](DataFlowCallable c, string file, int startline, int startcolumn |
|
||||
c.getLocation().hasLocationInfo(file, startline, startcolumn, _, _)
|
||||
|
|
||||
c order by file, startline, startcolumn
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
cached
|
||||
@@ -130,16 +120,6 @@ class DataFlowCall extends TDataFlowCall {
|
||||
) {
|
||||
this.getLocation().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
|
||||
}
|
||||
|
||||
/** Gets a best-effort total ordering. */
|
||||
int totalorder() {
|
||||
this =
|
||||
rank[result](DataFlowCall c, int startline, int startcolumn |
|
||||
c.hasLocationInfo(_, startline, startcolumn, _, _)
|
||||
|
|
||||
c order by startline, startcolumn
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private class NormalCall extends DataFlowCall, TNormalCall {
|
||||
|
||||
@@ -1381,8 +1381,6 @@ class NodeRegion instanceof Unit {
|
||||
string toString() { result = "NodeRegion" }
|
||||
|
||||
predicate contains(Node n) { none() }
|
||||
|
||||
int totalOrder() { result = 1 }
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user