Dataflow: Switch local call contexts to use canonical representative.

This commit is contained in:
Anders Schack-Mulligen
2024-04-26 13:13:28 +02:00
parent 012e1b498d
commit 86e6d0b1e1
2 changed files with 36 additions and 11 deletions

View File

@@ -350,10 +350,7 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
pragma[nomagic]
private predicate isUnreachableInCall1(NodeEx n, LocalCallContextSpecificCall cc) {
exists(NodeRegion nr |
nr.contains(n.asNode()) and
isUnreachableInCallCached(nr, cc.getCall())
)
cc.unreachable(n.asNode())
}
/**

View File

@@ -3,6 +3,7 @@ private import codeql.typetracking.TypeTracking as Tt
private import codeql.util.Location
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
@@ -406,6 +407,27 @@ module MakeImplCommon<LocationSig Location, InputSig<Location> Lang> {
result = viableCallableLambda(call, _)
}
private newtype TCallEdge =
TMkCallEdge(DataFlowCall call, DataFlowCallable tgt) { viableCallableExt(call) = tgt }
private module UnreachableSetsInput implements MkSetsInp {
class Key = TCallEdge;
class Value = NodeRegion;
NodeRegion getAValue(TCallEdge edge) {
exists(DataFlowCall call, DataFlowCallable tgt |
edge = TMkCallEdge(call, tgt) and
getNodeRegionEnclosingCallable(result) = tgt and
isUnreachableInCallCached(result, call)
)
}
int totalorder(NodeRegion nr) { result = nr.totalOrder() }
}
private module UnreachableSets = MakeSets<UnreachableSetsInput>;
signature module CallContextSensitivityInputSig {
/** Holds if the edge is possibly needed in the direction `call` to `c`. */
predicate relevantCallEdgeIn(DataFlowCall call, DataFlowCallable c);
@@ -1254,7 +1276,7 @@ module MakeImplCommon<LocationSig Location, InputSig<Location> Lang> {
cached
newtype TLocalFlowCallContext =
TAnyLocalCall() or
TSpecificLocalCall(DataFlowCall call) { isUnreachableInCallCached(_, call) }
TSpecificLocalCall(UnreachableSets::ValueSet ns)
cached
newtype TReturnKindExt =
@@ -1814,15 +1836,18 @@ module MakeImplCommon<LocationSig Location, InputSig<Location> Lang> {
}
class LocalCallContextSpecificCall extends LocalCallContext, TSpecificLocalCall {
LocalCallContextSpecificCall() { this = TSpecificLocalCall(call) }
LocalCallContextSpecificCall() { this = TSpecificLocalCall(ns) }
DataFlowCall call;
UnreachableSets::ValueSet ns;
DataFlowCall getCall() { result = call }
override string toString() { result = "LocalCcCall" }
override string toString() { result = "LocalCcCall(" + call + ")" }
override predicate relevantFor(DataFlowCallable callable) {
exists(NodeRegion nr | ns.contains(nr) and callable = getNodeRegionEnclosingCallable(nr))
}
override predicate relevantFor(DataFlowCallable callable) { relevantLocalCCtx(call, callable) }
/** Holds if this call context makes `n` unreachable. */
predicate unreachable(Node n) { exists(NodeRegion nr | ns.contains(nr) and nr.contains(n)) }
}
private DataFlowCallable getNodeRegionEnclosingCallable(NodeRegion nr) {
@@ -1842,7 +1867,10 @@ module MakeImplCommon<LocationSig Location, InputSig<Location> Lang> {
LocalCallContext getLocalCallContext(CallContext ctx, DataFlowCallable callable) {
ctx.relevantFor(callable) and
if relevantLocalCCtx(ctx.(CallContextSpecificCall).getCall(), callable)
then result.(LocalCallContextSpecificCall).getCall() = ctx.(CallContextSpecificCall).getCall()
then
result =
TSpecificLocalCall(UnreachableSets::getValueSet(TMkCallEdge(ctx.(CallContextSpecificCall)
.getCall(), callable)))
else result instanceof LocalCallContextAny
}