mirror of
https://github.com/github/codeql.git
synced 2025-12-17 01:03:14 +01:00
Merge pull request #16979 from aschackmull/dataflow/internsets
Dataflow: Replace MakeSets with QlBuiltins::InternSets.
This commit is contained in:
@@ -239,17 +239,7 @@ class CastNode extends Node {
|
|||||||
CastNode() { none() } // stub implementation
|
CastNode() { none() } // stub implementation
|
||||||
}
|
}
|
||||||
|
|
||||||
class DataFlowCallable extends Function {
|
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 DataFlowExpr = Expr;
|
class DataFlowExpr = Expr;
|
||||||
|
|
||||||
@@ -269,24 +259,12 @@ class DataFlowCall extends Expr instanceof Call {
|
|||||||
|
|
||||||
/** Gets the enclosing callable of this call. */
|
/** Gets the enclosing callable of this call. */
|
||||||
DataFlowCallable getEnclosingCallable() { result = this.getEnclosingFunction() }
|
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 {
|
class NodeRegion instanceof Unit {
|
||||||
string toString() { result = "NodeRegion" }
|
string toString() { result = "NodeRegion" }
|
||||||
|
|
||||||
predicate contains(Node n) { none() }
|
predicate contains(Node n) { none() }
|
||||||
|
|
||||||
int totalOrder() { result = 1 }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
predicate isUnreachableInCall(NodeRegion nr, DataFlowCall call) { none() } // stub implementation
|
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.asSummarizedCallable() or // SummarizedCallable = Function (in CPP)
|
||||||
result = this.asSourceCallable()
|
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.
|
* Gets the location of this call.
|
||||||
*/
|
*/
|
||||||
Location getLocation() { none() }
|
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" }
|
string toString() { result = "NodeRegion" }
|
||||||
|
|
||||||
predicate contains(Node n) { this = n.getBasicBlock() }
|
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) {
|
predicate isUnreachableInCall(NodeRegion block, DataFlowCall call) {
|
||||||
|
|||||||
@@ -191,16 +191,6 @@ class DataFlowCallable extends TDataFlowCallable {
|
|||||||
or
|
or
|
||||||
result = this.asCapturedVariable().getLocation()
|
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. */
|
/** A call relevant for data flow. */
|
||||||
@@ -244,16 +234,6 @@ abstract class DataFlowCall extends TDataFlowCall {
|
|||||||
) {
|
) {
|
||||||
this.getLocation().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
|
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. */
|
/** A non-delegate C# call relevant for data flow. */
|
||||||
|
|||||||
@@ -2379,15 +2379,6 @@ class NodeRegion instanceof ControlFlow::BasicBlock {
|
|||||||
string toString() { result = "NodeRegion" }
|
string toString() { result = "NodeRegion" }
|
||||||
|
|
||||||
predicate contains(Node n) { this = n.getControlFlowNode().getBasicBlock() }
|
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 = this.asFileScope().getLocation() or
|
||||||
result = getCallableLocation(this.asSummarizedCallable())
|
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) {
|
private Location getCallableLocation(Callable c) {
|
||||||
@@ -361,16 +351,6 @@ class DataFlowCall extends Expr {
|
|||||||
|
|
||||||
/** Gets the location of this call. */
|
/** Gets the location of this call. */
|
||||||
Location getLocation() { result = super.getLocation() }
|
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`. */
|
/** 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" }
|
string toString() { result = "NodeRegion" }
|
||||||
|
|
||||||
predicate contains(Node n) { n.getBasicBlock() = this }
|
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 =
|
private newtype TDataFlowCallable =
|
||||||
TSrcCallable(Callable c) or
|
TSrcCallable(Callable c) or
|
||||||
TSummarizedCallable(SummarizedCallable c) or
|
TSummarizedCallable(SummarizedCallable c) or
|
||||||
@@ -448,28 +433,10 @@ class DataFlowCallable extends TDataFlowCallable {
|
|||||||
result = this.asSummarizedCallable().getLocation() or
|
result = this.asSummarizedCallable().getLocation() or
|
||||||
result = this.asFieldScope().getLocation()
|
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;
|
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 =
|
private newtype TDataFlowCall =
|
||||||
TCall(Call c) or
|
TCall(Call c) or
|
||||||
TSummaryCall(SummarizedCallable c, FlowSummaryImpl::Private::SummaryNode receiver) {
|
TSummaryCall(SummarizedCallable c, FlowSummaryImpl::Private::SummaryNode receiver) {
|
||||||
@@ -502,19 +469,6 @@ class DataFlowCall extends TDataFlowCall {
|
|||||||
) {
|
) {
|
||||||
this.getLocation().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
|
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`. */
|
/** A source call, that is, a `Call`. */
|
||||||
@@ -549,16 +503,10 @@ class SummaryCall extends DataFlowCall, TSummaryCall {
|
|||||||
override Location getLocation() { result = c.getLocation() }
|
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 {
|
class NodeRegion instanceof BasicBlock {
|
||||||
string toString() { result = "NodeRegion" }
|
string toString() { result = "NodeRegion" }
|
||||||
|
|
||||||
predicate contains(Node n) { n.asExpr().getBasicBlock() = this }
|
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`. */
|
/** 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. */
|
/** Gets the location of this dataflow callable. */
|
||||||
abstract Location getLocation();
|
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. */
|
/** A callable function. */
|
||||||
@@ -1435,16 +1425,6 @@ abstract class DataFlowCall extends TDataFlowCall {
|
|||||||
) {
|
) {
|
||||||
this.getLocation().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
|
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). */
|
/** 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" }
|
string toString() { result = "NodeRegion" }
|
||||||
|
|
||||||
predicate contains(Node n) { none() }
|
predicate contains(Node n) { none() }
|
||||||
|
|
||||||
int totalOrder() { result = 1 }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//--------
|
//--------
|
||||||
|
|||||||
@@ -113,16 +113,6 @@ class DataFlowCallable extends TDataFlowCallable {
|
|||||||
this instanceof TLibraryCallable and
|
this instanceof TLibraryCallable and
|
||||||
result instanceof EmptyLocation
|
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)
|
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" }
|
string toString() { result = "NodeRegion" }
|
||||||
|
|
||||||
predicate contains(Node n) { none() }
|
predicate contains(Node n) { none() }
|
||||||
|
|
||||||
int totalOrder() { result = 1 }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -76,9 +76,6 @@ signature module InputSig<LocationSig Location> {
|
|||||||
Location getLocation();
|
Location getLocation();
|
||||||
|
|
||||||
DataFlowCallable getEnclosingCallable();
|
DataFlowCallable getEnclosingCallable();
|
||||||
|
|
||||||
/** Gets a best-effort total ordering. */
|
|
||||||
int totalorder();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class DataFlowCallable {
|
class DataFlowCallable {
|
||||||
@@ -87,9 +84,6 @@ signature module InputSig<LocationSig Location> {
|
|||||||
|
|
||||||
/** Gets the location of this callable. */
|
/** Gets the location of this callable. */
|
||||||
Location getLocation();
|
Location getLocation();
|
||||||
|
|
||||||
/** Gets a best-effort total ordering. */
|
|
||||||
int totalorder();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class ReturnKind {
|
class ReturnKind {
|
||||||
@@ -266,8 +260,6 @@ signature module InputSig<LocationSig Location> {
|
|||||||
class NodeRegion {
|
class NodeRegion {
|
||||||
/** Holds if this region contains `n`. */
|
/** Holds if this region contains `n`. */
|
||||||
predicate contains(Node 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.Option
|
||||||
private import codeql.util.Unit
|
private import codeql.util.Unit
|
||||||
private import codeql.util.Option
|
private import codeql.util.Option
|
||||||
private import codeql.util.internal.MakeSets
|
|
||||||
|
|
||||||
module MakeImplCommon<LocationSig Location, InputSig<Location> Lang> {
|
module MakeImplCommon<LocationSig Location, InputSig<Location> Lang> {
|
||||||
private import Lang
|
private import Lang
|
||||||
@@ -502,24 +501,21 @@ module MakeImplCommon<LocationSig Location, InputSig<Location> Lang> {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private module CallSetsInput implements MkSetsInputSig {
|
private DataFlowCall getACallWithReducedViableImpl(TCallEdge ctxEdge) {
|
||||||
class Key = TCallEdge;
|
exists(DataFlowCall ctx, DataFlowCallable c |
|
||||||
|
ctxEdge = TMkCallEdge(ctx, c) and
|
||||||
class Value = DataFlowCall;
|
reducedViableImplInCallContext(result, c, ctx)
|
||||||
|
)
|
||||||
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 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.
|
* 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 class CallSet = CallSetOption::Option;
|
||||||
|
|
||||||
private module DispatchSetsInput implements MkSetsInputSig {
|
private TCallEdge getAReducedViableEdge(TCallEdge ctxEdge) {
|
||||||
class Key = TCallEdge;
|
exists(DataFlowCall ctx, DataFlowCallable c, DataFlowCall call, DataFlowCallable tgt |
|
||||||
|
ctxEdge = mkCallEdge(ctx, c) and
|
||||||
class Value = TCallEdge;
|
result = mkCallEdge(call, tgt) and
|
||||||
|
viableImplInCallContextExtIn(call, ctx) = tgt and
|
||||||
TCallEdge getAValue(TCallEdge ctxEdge) {
|
reducedViableImplInCallContext(call, c, ctx)
|
||||||
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 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
|
* 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 class DispatchSet = DispatchSetsOption::Option;
|
||||||
|
|
||||||
private predicate relevantCtx(TCallEdge ctx) {
|
private predicate relevantCtx(TCallEdge ctx) {
|
||||||
exists(CallSets::getValueSet(ctx)) or exists(getUnreachableSet(ctx))
|
exists(CallSets::getSet(ctx)) or exists(getUnreachableSet(ctx))
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
@@ -570,14 +563,14 @@ module MakeImplCommon<LocationSig Location, InputSig<Location> Lang> {
|
|||||||
) {
|
) {
|
||||||
relevantCtx(ctx) and
|
relevantCtx(ctx) and
|
||||||
(
|
(
|
||||||
CallSets::getValueSet(ctx) = calls.asSome()
|
CallSets::getSet(ctx) = calls.asSome()
|
||||||
or
|
or
|
||||||
not exists(CallSets::getValueSet(ctx)) and calls.isNone()
|
not exists(CallSets::getSet(ctx)) and calls.isNone()
|
||||||
) and
|
) and
|
||||||
(
|
(
|
||||||
DispatchSets::getValueSet(ctx) = tgts.asSome()
|
DispatchSets::getSet(ctx) = tgts.asSome()
|
||||||
or
|
or
|
||||||
not exists(DispatchSets::getValueSet(ctx)) and tgts.isNone()
|
not exists(DispatchSets::getSet(ctx)) and tgts.isNone()
|
||||||
) and
|
) and
|
||||||
(
|
(
|
||||||
getUnreachableSet(ctx) = unreachable.asSome()
|
getUnreachableSet(ctx) = unreachable.asSome()
|
||||||
@@ -1515,40 +1508,20 @@ module MakeImplCommon<LocationSig Location, InputSig<Location> Lang> {
|
|||||||
newtype TCallEdge =
|
newtype TCallEdge =
|
||||||
TMkCallEdge(DataFlowCall call, DataFlowCallable tgt) { viableCallableExt(call) = tgt }
|
TMkCallEdge(DataFlowCall call, DataFlowCallable tgt) { viableCallableExt(call) = tgt }
|
||||||
|
|
||||||
cached
|
private NodeRegion getAnUnreachableRegion(TCallEdge edge) {
|
||||||
int edgeOrder(TCallEdge edge) {
|
exists(DataFlowCall call, DataFlowCallable tgt |
|
||||||
edge =
|
edge = mkCallEdge(call, tgt) and
|
||||||
rank[result](TCallEdge e, DataFlowCall call, DataFlowCallable tgt |
|
getNodeRegionEnclosingCallable(result) = tgt and
|
||||||
e = TMkCallEdge(call, tgt)
|
isUnreachableInCallCached(result, call)
|
||||||
|
|
)
|
||||||
e order by call.totalorder(), tgt.totalorder()
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cached
|
private module UnreachableSets =
|
||||||
int callOrder(DataFlowCall call) { result = call.totalorder() }
|
QlBuiltins::InternSets<TCallEdge, NodeRegion, getAnUnreachableRegion/1>;
|
||||||
|
|
||||||
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>;
|
|
||||||
|
|
||||||
/** A set of nodes that is unreachable in some call context. */
|
/** A set of nodes that is unreachable in some call context. */
|
||||||
cached
|
cached
|
||||||
class UnreachableSet instanceof UnreachableSets::ValueSet {
|
class UnreachableSet instanceof UnreachableSets::Set {
|
||||||
cached
|
cached
|
||||||
string toString() { result = "Unreachable" }
|
string toString() { result = "Unreachable" }
|
||||||
|
|
||||||
@@ -1562,7 +1535,7 @@ module MakeImplCommon<LocationSig Location, InputSig<Location> Lang> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
cached
|
cached
|
||||||
UnreachableSet getUnreachableSet(TCallEdge edge) { result = UnreachableSets::getValueSet(edge) }
|
UnreachableSet getUnreachableSet(TCallEdge edge) { result = UnreachableSets::getSet(edge) }
|
||||||
|
|
||||||
private module UnreachableSetOption = Option<UnreachableSet>;
|
private module UnreachableSetOption = Option<UnreachableSet>;
|
||||||
|
|
||||||
@@ -1579,7 +1552,7 @@ module MakeImplCommon<LocationSig Location, InputSig<Location> Lang> {
|
|||||||
cached
|
cached
|
||||||
newtype TLocalFlowCallContext =
|
newtype TLocalFlowCallContext =
|
||||||
TAnyLocalCall() or
|
TAnyLocalCall() or
|
||||||
TSpecificLocalCall(UnreachableSets::ValueSet ns)
|
TSpecificLocalCall(UnreachableSets::Set ns)
|
||||||
|
|
||||||
cached
|
cached
|
||||||
newtype TReturnKindExt =
|
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() {
|
Callable::TypeRange getUnderlyingCallable() {
|
||||||
result = this.asSummarizedCallable() or result = this.asSourceCallable()
|
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
|
cached
|
||||||
@@ -130,16 +120,6 @@ class DataFlowCall extends TDataFlowCall {
|
|||||||
) {
|
) {
|
||||||
this.getLocation().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
|
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 {
|
private class NormalCall extends DataFlowCall, TNormalCall {
|
||||||
|
|||||||
@@ -1381,8 +1381,6 @@ class NodeRegion instanceof Unit {
|
|||||||
string toString() { result = "NodeRegion" }
|
string toString() { result = "NodeRegion" }
|
||||||
|
|
||||||
predicate contains(Node n) { none() }
|
predicate contains(Node n) { none() }
|
||||||
|
|
||||||
int totalOrder() { result = 1 }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Reference in New Issue
Block a user