From e70b6f7ed1eefb97670cbfb1c2b75abdb090e8e5 Mon Sep 17 00:00:00 2001 From: Anders Schack-Mulligen Date: Thu, 10 Sep 2020 16:30:24 +0200 Subject: [PATCH 1/5] Dataflow: Precalculate AccessPath to avoid massive recursion. --- java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl.qll b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl.qll index 04975b875b7b..c1097538d2b5 100644 --- a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl.qll +++ b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl.qll @@ -2098,7 +2098,7 @@ private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome { private newtype TAccessPath = TAccessPathNil(DataFlowType t) or - TAccessPathCons(TypedContent head, AccessPath tail) { pathStoreStep(_, _, tail, _, head, _) } + TAccessPathCons(TypedContent head, AccessPath tail) { flowConsCand(head, tail.getApprox(), _) } private newtype TPathNode = TPathNodeMid( From 59937f20c3367d6ec3fd45cda88261f182d3dcdc Mon Sep 17 00:00:00 2001 From: Anders Schack-Mulligen Date: Fri, 11 Sep 2020 10:54:24 +0200 Subject: [PATCH 2/5] Dataflow: Simplify SCC: remove some apa params. --- .../java/dataflow/internal/DataFlowImpl.qll | 64 ++++++------------- 1 file changed, 21 insertions(+), 43 deletions(-) diff --git a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl.qll b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl.qll index c1097538d2b5..dbe041b15ce8 100644 --- a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl.qll +++ b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl.qll @@ -2101,23 +2101,19 @@ private newtype TAccessPath = TAccessPathCons(TypedContent head, AccessPath tail) { flowConsCand(head, tail.getApprox(), _) } private newtype TPathNode = - TPathNodeMid( - Node node, CallContext cc, SummaryCtx sc, AccessPath ap, AccessPathApprox apa, - Configuration config - ) { + TPathNodeMid(Node node, CallContext cc, SummaryCtx sc, AccessPath ap, Configuration config) { // A PathNode is introduced by a source ... flow(node, config) and config.isSource(node) and cc instanceof CallContextAny and sc instanceof SummaryCtxNone and - ap = TAccessPathNil(getNodeType(node)) and - apa = TNil(getNodeType(node)) + ap = TAccessPathNil(getNodeType(node)) or // ... or a step from an existing PathNode to another node. exists(PathNodeMid mid | - pathStep(mid, node, cc, sc, ap, apa) and + pathStep(mid, node, cc, sc, ap) and config = mid.getConfiguration() and - flow(node, _, _, apa, unbind(config)) + flow(node, _, _, ap.getApprox(), unbind(config)) ) } or TPathNodeSink(Node node, Configuration config) { @@ -2129,7 +2125,7 @@ private newtype TPathNode = or // ... or a sink that can be reached from a source exists(PathNodeMid mid | - pathStep(mid, node, _, _, _, TNil(_)) and + pathStep(mid, node, _, _, TAccessPathNil(_)) and config = unbind(mid.getConfiguration()) ) ) @@ -2340,10 +2336,9 @@ private class PathNodeMid extends PathNodeImpl, TPathNodeMid { CallContext cc; SummaryCtx sc; AccessPath ap; - AccessPathApprox apa; Configuration config; - PathNodeMid() { this = TPathNodeMid(node, cc, sc, ap, apa, config) } + PathNodeMid() { this = TPathNodeMid(node, cc, sc, ap, config) } override Node getNode() { result = node } @@ -2353,13 +2348,10 @@ private class PathNodeMid extends PathNodeImpl, TPathNodeMid { AccessPath getAp() { result = ap } - AccessPathApprox getApa() { result = apa } - override Configuration getConfiguration() { result = config } private PathNodeMid getSuccMid() { - pathStep(this, result.getNode(), result.getCallContext(), result.getSummaryCtx(), - result.getAp(), _) and + pathStep(this, result.getNode(), result.getCallContext(), result.getSummaryCtx(), result.getAp()) and result.getConfiguration() = unbind(this.getConfiguration()) } @@ -2371,7 +2363,7 @@ private class PathNodeMid extends PathNodeImpl, TPathNodeMid { exists(PathNodeMid mid, PathNodeSink sink | mid = getSuccMid() and mid.getNode() = sink.getNode() and - mid.getApa() instanceof AccessPathApproxNil and + mid.getAp() instanceof AccessPathNil and sink.getConfiguration() = unbind(mid.getConfiguration()) and result = sink ) @@ -2381,7 +2373,7 @@ private class PathNodeMid extends PathNodeImpl, TPathNodeMid { config.isSource(node) and cc instanceof CallContextAny and sc instanceof SummaryCtxNone and - apa instanceof AccessPathApproxNil + ap instanceof AccessPathNil } } @@ -2409,33 +2401,22 @@ private class PathNodeSink extends PathNodeImpl, TPathNodeSink { * Holds if data may flow from `mid` to `node`. The last step in or out of * a callable is recorded by `cc`. */ -private predicate pathStep( - PathNodeMid mid, Node node, CallContext cc, SummaryCtx sc, AccessPath ap, AccessPathApprox apa -) { +private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, SummaryCtx sc, AccessPath ap) { pathStepSameAp(mid, node, cc, sc) and - ap = mid.getAp() and - apa = mid.getApa() + ap = mid.getAp() or exists(DataFlowType t | pathStepEmptyAp(mid, node, cc, sc, t) and - ap = TAccessPathNil(t) and - apa = TNil(t) + ap = TAccessPathNil(t) ) or - exists(TypedContent tc, AccessPathApprox apa0 | - pathStoreStep(mid, node, ap.pop(tc), apa0, tc, cc) and - // Same as `apa = ap.getApprox()`, but avoids mutual recursion - apa0 = apa.pop(tc) - ) and + exists(TypedContent tc | pathStoreStep(mid, node, ap.pop(tc), tc, cc)) and sc = mid.getSummaryCtx() or exists(TypedContent tc | pathReadStep(mid, node, ap.push(tc), tc, cc)) and - sc = mid.getSummaryCtx() and - // Here the approximation cannot be created from the approximation before - // the read, so we must use `getApprox()` - apa = ap.getApprox() + sc = mid.getSummaryCtx() or - pathThroughCallable(mid, node, cc, ap, apa) and + pathThroughCallable(mid, node, cc, ap) and sc = mid.getSummaryCtx() } @@ -2504,10 +2485,9 @@ private predicate storeCand(Node node1, TypedContent tc, Node node2, Configurati pragma[nomagic] private predicate pathStoreStep( - PathNodeMid mid, Node node, AccessPath ap0, AccessPathApprox apa0, TypedContent tc, CallContext cc + PathNodeMid mid, Node node, AccessPath ap0, TypedContent tc, CallContext cc ) { ap0 = mid.getAp() and - apa0 = mid.getApa() and storeCand(mid.getNode(), tc, node, mid.getConfiguration()) and cc = mid.getCallContext() } @@ -2519,7 +2499,7 @@ private predicate pathOutOfCallable0( pos = getReturnPosition(mid.getNode()) and innercc = mid.getCallContext() and innercc instanceof CallContextNoCall and - apa = mid.getApa() and + apa = mid.getAp().getApprox() and config = mid.getConfiguration() } @@ -2570,7 +2550,7 @@ private predicate pathIntoArg( cc = mid.getCallContext() and arg.argumentOf(call, i) and ap = mid.getAp() and - apa = mid.getApa() + apa = ap.getApprox() ) } @@ -2653,7 +2633,7 @@ private predicate paramFlowsThrough( sc = mid.getSummaryCtx() and config = mid.getConfiguration() and ap = mid.getAp() and - apa = mid.getApa() and + apa = ap.getApprox() and pos = sc.getParameterPos() and not kind.(ParamUpdateReturnKind).getPosition() = pos ) @@ -2675,10 +2655,8 @@ private predicate pathThroughCallable0( * The context `cc` is restored to its value prior to entering the callable. */ pragma[noinline] -private predicate pathThroughCallable( - PathNodeMid mid, Node out, CallContext cc, AccessPath ap, AccessPathApprox apa -) { - exists(DataFlowCall call, ReturnKindExt kind | +private predicate pathThroughCallable(PathNodeMid mid, Node out, CallContext cc, AccessPath ap) { + exists(DataFlowCall call, ReturnKindExt kind, AccessPathApprox apa | pathThroughCallable0(call, mid, kind, cc, ap, apa) and out = getAnOutNodeFlow(kind, call, apa, unbind(mid.getConfiguration())) ) From de22722705d2c4b17a914ac555d1d3bc01d5b870 Mon Sep 17 00:00:00 2001 From: Anders Schack-Mulligen Date: Thu, 17 Sep 2020 10:09:56 +0200 Subject: [PATCH 3/5] Dataflow: qldoc fix --- .../src/semmle/code/java/dataflow/internal/DataFlowImpl.qll | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl.qll b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl.qll index dbe041b15ce8..103f05d90c2e 100644 --- a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl.qll +++ b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl.qll @@ -1645,7 +1645,7 @@ private class AccessPathApproxOption extends TAccessPathApproxOption { } /** - * Holds if `node` is reachable with approximate access path `ap` from a source + * Holds if `node` is reachable with approximate access path `apa` from a source * in the configuration `config`. * * The call context `cc` records whether the node is reached through an @@ -1863,7 +1863,7 @@ private predicate flowFwdIsEntered( } /** - * Holds if `node` with approximate access path `ap` is part of a path from a + * Holds if `node` with approximate access path `apa` is part of a path from a * source to a sink in the configuration `config`. * * The Boolean `toReturn` records whether the node must be returned from From 264236a37497ce8b308c6554acfec81b3d8af816 Mon Sep 17 00:00:00 2001 From: Anders Schack-Mulligen Date: Thu, 17 Sep 2020 10:19:04 +0200 Subject: [PATCH 4/5] Dataflow: Remove inconsistent AccessPath.getType(). --- .../code/java/dataflow/internal/DataFlowImpl.qll | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl.qll b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl.qll index 103f05d90c2e..77e777126c7b 100644 --- a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl.qll +++ b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl.qll @@ -2138,9 +2138,6 @@ private newtype TPathNode = * tracked object. The final type indicates the type of the tracked object. */ abstract private class AccessPath extends TAccessPath { - /** Gets the type of this access path. */ - abstract DataFlowType getType(); - /** Gets the head of this access path, if any. */ abstract TypedContent getHead(); @@ -2174,7 +2171,7 @@ private class AccessPathNil extends AccessPath, TAccessPathNil { AccessPathNil() { this = TAccessPathNil(t) } - override DataFlowType getType() { result = t } + DataFlowType getType() { result = t } override TypedContent getHead() { none() } @@ -2195,8 +2192,6 @@ private class AccessPathCons extends AccessPath, TAccessPathCons { AccessPathCons() { this = TAccessPathCons(head, tail) } - override DataFlowType getType() { result = tail.getType() } - override TypedContent getHead() { result = head } override AccessPath getTail() { result = tail } @@ -2212,14 +2207,16 @@ private class AccessPathCons extends AccessPath, TAccessPathCons { override int length() { result = 1 + tail.length() } private string toStringImpl() { - tail = TAccessPathNil(_) and - result = head.toString() + exists(DataFlowType t | + tail = TAccessPathNil(t) and + result = head.toString() + "]" + concat(" : " + ppReprType(t)) + ) or result = head + ", " + tail.(AccessPathCons).toStringImpl() } override string toString() { - result = "[" + this.toStringImpl() + "]" + concat(" : " + ppReprType(this.getType())) + result = "[" + this.toStringImpl() } } From 8c9224520f875b52b0d227b5d887c3d367e0dffb Mon Sep 17 00:00:00 2001 From: Anders Schack-Mulligen Date: Thu, 17 Sep 2020 10:50:14 +0200 Subject: [PATCH 5/5] Sync. --- .../cpp/dataflow/internal/DataFlowImpl.qll | 85 +++++++------------ .../cpp/dataflow/internal/DataFlowImpl2.qll | 85 +++++++------------ .../cpp/dataflow/internal/DataFlowImpl3.qll | 85 +++++++------------ .../cpp/dataflow/internal/DataFlowImpl4.qll | 85 +++++++------------ .../dataflow/internal/DataFlowImplLocal.qll | 85 +++++++------------ .../cpp/ir/dataflow/internal/DataFlowImpl.qll | 85 +++++++------------ .../ir/dataflow/internal/DataFlowImpl2.qll | 85 +++++++------------ .../ir/dataflow/internal/DataFlowImpl3.qll | 85 +++++++------------ .../ir/dataflow/internal/DataFlowImpl4.qll | 85 +++++++------------ .../csharp/dataflow/internal/DataFlowImpl.qll | 85 +++++++------------ .../dataflow/internal/DataFlowImpl2.qll | 85 +++++++------------ .../dataflow/internal/DataFlowImpl3.qll | 85 +++++++------------ .../dataflow/internal/DataFlowImpl4.qll | 85 +++++++------------ .../dataflow/internal/DataFlowImpl5.qll | 85 +++++++------------ .../java/dataflow/internal/DataFlowImpl2.qll | 85 +++++++------------ .../java/dataflow/internal/DataFlowImpl3.qll | 85 +++++++------------ .../java/dataflow/internal/DataFlowImpl4.qll | 85 +++++++------------ .../java/dataflow/internal/DataFlowImpl5.qll | 85 +++++++------------ .../dataflow/internal/DataFlowImpl.qll | 85 +++++++------------ .../dataflow/internal/DataFlowImpl2.qll | 85 +++++++------------ 20 files changed, 600 insertions(+), 1100 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl.qll b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl.qll index 04975b875b7b..77e777126c7b 100644 --- a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl.qll +++ b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl.qll @@ -1645,7 +1645,7 @@ private class AccessPathApproxOption extends TAccessPathApproxOption { } /** - * Holds if `node` is reachable with approximate access path `ap` from a source + * Holds if `node` is reachable with approximate access path `apa` from a source * in the configuration `config`. * * The call context `cc` records whether the node is reached through an @@ -1863,7 +1863,7 @@ private predicate flowFwdIsEntered( } /** - * Holds if `node` with approximate access path `ap` is part of a path from a + * Holds if `node` with approximate access path `apa` is part of a path from a * source to a sink in the configuration `config`. * * The Boolean `toReturn` records whether the node must be returned from @@ -2098,26 +2098,22 @@ private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome { private newtype TAccessPath = TAccessPathNil(DataFlowType t) or - TAccessPathCons(TypedContent head, AccessPath tail) { pathStoreStep(_, _, tail, _, head, _) } + TAccessPathCons(TypedContent head, AccessPath tail) { flowConsCand(head, tail.getApprox(), _) } private newtype TPathNode = - TPathNodeMid( - Node node, CallContext cc, SummaryCtx sc, AccessPath ap, AccessPathApprox apa, - Configuration config - ) { + TPathNodeMid(Node node, CallContext cc, SummaryCtx sc, AccessPath ap, Configuration config) { // A PathNode is introduced by a source ... flow(node, config) and config.isSource(node) and cc instanceof CallContextAny and sc instanceof SummaryCtxNone and - ap = TAccessPathNil(getNodeType(node)) and - apa = TNil(getNodeType(node)) + ap = TAccessPathNil(getNodeType(node)) or // ... or a step from an existing PathNode to another node. exists(PathNodeMid mid | - pathStep(mid, node, cc, sc, ap, apa) and + pathStep(mid, node, cc, sc, ap) and config = mid.getConfiguration() and - flow(node, _, _, apa, unbind(config)) + flow(node, _, _, ap.getApprox(), unbind(config)) ) } or TPathNodeSink(Node node, Configuration config) { @@ -2129,7 +2125,7 @@ private newtype TPathNode = or // ... or a sink that can be reached from a source exists(PathNodeMid mid | - pathStep(mid, node, _, _, _, TNil(_)) and + pathStep(mid, node, _, _, TAccessPathNil(_)) and config = unbind(mid.getConfiguration()) ) ) @@ -2142,9 +2138,6 @@ private newtype TPathNode = * tracked object. The final type indicates the type of the tracked object. */ abstract private class AccessPath extends TAccessPath { - /** Gets the type of this access path. */ - abstract DataFlowType getType(); - /** Gets the head of this access path, if any. */ abstract TypedContent getHead(); @@ -2178,7 +2171,7 @@ private class AccessPathNil extends AccessPath, TAccessPathNil { AccessPathNil() { this = TAccessPathNil(t) } - override DataFlowType getType() { result = t } + DataFlowType getType() { result = t } override TypedContent getHead() { none() } @@ -2199,8 +2192,6 @@ private class AccessPathCons extends AccessPath, TAccessPathCons { AccessPathCons() { this = TAccessPathCons(head, tail) } - override DataFlowType getType() { result = tail.getType() } - override TypedContent getHead() { result = head } override AccessPath getTail() { result = tail } @@ -2216,14 +2207,16 @@ private class AccessPathCons extends AccessPath, TAccessPathCons { override int length() { result = 1 + tail.length() } private string toStringImpl() { - tail = TAccessPathNil(_) and - result = head.toString() + exists(DataFlowType t | + tail = TAccessPathNil(t) and + result = head.toString() + "]" + concat(" : " + ppReprType(t)) + ) or result = head + ", " + tail.(AccessPathCons).toStringImpl() } override string toString() { - result = "[" + this.toStringImpl() + "]" + concat(" : " + ppReprType(this.getType())) + result = "[" + this.toStringImpl() } } @@ -2340,10 +2333,9 @@ private class PathNodeMid extends PathNodeImpl, TPathNodeMid { CallContext cc; SummaryCtx sc; AccessPath ap; - AccessPathApprox apa; Configuration config; - PathNodeMid() { this = TPathNodeMid(node, cc, sc, ap, apa, config) } + PathNodeMid() { this = TPathNodeMid(node, cc, sc, ap, config) } override Node getNode() { result = node } @@ -2353,13 +2345,10 @@ private class PathNodeMid extends PathNodeImpl, TPathNodeMid { AccessPath getAp() { result = ap } - AccessPathApprox getApa() { result = apa } - override Configuration getConfiguration() { result = config } private PathNodeMid getSuccMid() { - pathStep(this, result.getNode(), result.getCallContext(), result.getSummaryCtx(), - result.getAp(), _) and + pathStep(this, result.getNode(), result.getCallContext(), result.getSummaryCtx(), result.getAp()) and result.getConfiguration() = unbind(this.getConfiguration()) } @@ -2371,7 +2360,7 @@ private class PathNodeMid extends PathNodeImpl, TPathNodeMid { exists(PathNodeMid mid, PathNodeSink sink | mid = getSuccMid() and mid.getNode() = sink.getNode() and - mid.getApa() instanceof AccessPathApproxNil and + mid.getAp() instanceof AccessPathNil and sink.getConfiguration() = unbind(mid.getConfiguration()) and result = sink ) @@ -2381,7 +2370,7 @@ private class PathNodeMid extends PathNodeImpl, TPathNodeMid { config.isSource(node) and cc instanceof CallContextAny and sc instanceof SummaryCtxNone and - apa instanceof AccessPathApproxNil + ap instanceof AccessPathNil } } @@ -2409,33 +2398,22 @@ private class PathNodeSink extends PathNodeImpl, TPathNodeSink { * Holds if data may flow from `mid` to `node`. The last step in or out of * a callable is recorded by `cc`. */ -private predicate pathStep( - PathNodeMid mid, Node node, CallContext cc, SummaryCtx sc, AccessPath ap, AccessPathApprox apa -) { +private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, SummaryCtx sc, AccessPath ap) { pathStepSameAp(mid, node, cc, sc) and - ap = mid.getAp() and - apa = mid.getApa() + ap = mid.getAp() or exists(DataFlowType t | pathStepEmptyAp(mid, node, cc, sc, t) and - ap = TAccessPathNil(t) and - apa = TNil(t) + ap = TAccessPathNil(t) ) or - exists(TypedContent tc, AccessPathApprox apa0 | - pathStoreStep(mid, node, ap.pop(tc), apa0, tc, cc) and - // Same as `apa = ap.getApprox()`, but avoids mutual recursion - apa0 = apa.pop(tc) - ) and + exists(TypedContent tc | pathStoreStep(mid, node, ap.pop(tc), tc, cc)) and sc = mid.getSummaryCtx() or exists(TypedContent tc | pathReadStep(mid, node, ap.push(tc), tc, cc)) and - sc = mid.getSummaryCtx() and - // Here the approximation cannot be created from the approximation before - // the read, so we must use `getApprox()` - apa = ap.getApprox() + sc = mid.getSummaryCtx() or - pathThroughCallable(mid, node, cc, ap, apa) and + pathThroughCallable(mid, node, cc, ap) and sc = mid.getSummaryCtx() } @@ -2504,10 +2482,9 @@ private predicate storeCand(Node node1, TypedContent tc, Node node2, Configurati pragma[nomagic] private predicate pathStoreStep( - PathNodeMid mid, Node node, AccessPath ap0, AccessPathApprox apa0, TypedContent tc, CallContext cc + PathNodeMid mid, Node node, AccessPath ap0, TypedContent tc, CallContext cc ) { ap0 = mid.getAp() and - apa0 = mid.getApa() and storeCand(mid.getNode(), tc, node, mid.getConfiguration()) and cc = mid.getCallContext() } @@ -2519,7 +2496,7 @@ private predicate pathOutOfCallable0( pos = getReturnPosition(mid.getNode()) and innercc = mid.getCallContext() and innercc instanceof CallContextNoCall and - apa = mid.getApa() and + apa = mid.getAp().getApprox() and config = mid.getConfiguration() } @@ -2570,7 +2547,7 @@ private predicate pathIntoArg( cc = mid.getCallContext() and arg.argumentOf(call, i) and ap = mid.getAp() and - apa = mid.getApa() + apa = ap.getApprox() ) } @@ -2653,7 +2630,7 @@ private predicate paramFlowsThrough( sc = mid.getSummaryCtx() and config = mid.getConfiguration() and ap = mid.getAp() and - apa = mid.getApa() and + apa = ap.getApprox() and pos = sc.getParameterPos() and not kind.(ParamUpdateReturnKind).getPosition() = pos ) @@ -2675,10 +2652,8 @@ private predicate pathThroughCallable0( * The context `cc` is restored to its value prior to entering the callable. */ pragma[noinline] -private predicate pathThroughCallable( - PathNodeMid mid, Node out, CallContext cc, AccessPath ap, AccessPathApprox apa -) { - exists(DataFlowCall call, ReturnKindExt kind | +private predicate pathThroughCallable(PathNodeMid mid, Node out, CallContext cc, AccessPath ap) { + exists(DataFlowCall call, ReturnKindExt kind, AccessPathApprox apa | pathThroughCallable0(call, mid, kind, cc, ap, apa) and out = getAnOutNodeFlow(kind, call, apa, unbind(mid.getConfiguration())) ) diff --git a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl2.qll b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl2.qll index 04975b875b7b..77e777126c7b 100644 --- a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl2.qll +++ b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl2.qll @@ -1645,7 +1645,7 @@ private class AccessPathApproxOption extends TAccessPathApproxOption { } /** - * Holds if `node` is reachable with approximate access path `ap` from a source + * Holds if `node` is reachable with approximate access path `apa` from a source * in the configuration `config`. * * The call context `cc` records whether the node is reached through an @@ -1863,7 +1863,7 @@ private predicate flowFwdIsEntered( } /** - * Holds if `node` with approximate access path `ap` is part of a path from a + * Holds if `node` with approximate access path `apa` is part of a path from a * source to a sink in the configuration `config`. * * The Boolean `toReturn` records whether the node must be returned from @@ -2098,26 +2098,22 @@ private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome { private newtype TAccessPath = TAccessPathNil(DataFlowType t) or - TAccessPathCons(TypedContent head, AccessPath tail) { pathStoreStep(_, _, tail, _, head, _) } + TAccessPathCons(TypedContent head, AccessPath tail) { flowConsCand(head, tail.getApprox(), _) } private newtype TPathNode = - TPathNodeMid( - Node node, CallContext cc, SummaryCtx sc, AccessPath ap, AccessPathApprox apa, - Configuration config - ) { + TPathNodeMid(Node node, CallContext cc, SummaryCtx sc, AccessPath ap, Configuration config) { // A PathNode is introduced by a source ... flow(node, config) and config.isSource(node) and cc instanceof CallContextAny and sc instanceof SummaryCtxNone and - ap = TAccessPathNil(getNodeType(node)) and - apa = TNil(getNodeType(node)) + ap = TAccessPathNil(getNodeType(node)) or // ... or a step from an existing PathNode to another node. exists(PathNodeMid mid | - pathStep(mid, node, cc, sc, ap, apa) and + pathStep(mid, node, cc, sc, ap) and config = mid.getConfiguration() and - flow(node, _, _, apa, unbind(config)) + flow(node, _, _, ap.getApprox(), unbind(config)) ) } or TPathNodeSink(Node node, Configuration config) { @@ -2129,7 +2125,7 @@ private newtype TPathNode = or // ... or a sink that can be reached from a source exists(PathNodeMid mid | - pathStep(mid, node, _, _, _, TNil(_)) and + pathStep(mid, node, _, _, TAccessPathNil(_)) and config = unbind(mid.getConfiguration()) ) ) @@ -2142,9 +2138,6 @@ private newtype TPathNode = * tracked object. The final type indicates the type of the tracked object. */ abstract private class AccessPath extends TAccessPath { - /** Gets the type of this access path. */ - abstract DataFlowType getType(); - /** Gets the head of this access path, if any. */ abstract TypedContent getHead(); @@ -2178,7 +2171,7 @@ private class AccessPathNil extends AccessPath, TAccessPathNil { AccessPathNil() { this = TAccessPathNil(t) } - override DataFlowType getType() { result = t } + DataFlowType getType() { result = t } override TypedContent getHead() { none() } @@ -2199,8 +2192,6 @@ private class AccessPathCons extends AccessPath, TAccessPathCons { AccessPathCons() { this = TAccessPathCons(head, tail) } - override DataFlowType getType() { result = tail.getType() } - override TypedContent getHead() { result = head } override AccessPath getTail() { result = tail } @@ -2216,14 +2207,16 @@ private class AccessPathCons extends AccessPath, TAccessPathCons { override int length() { result = 1 + tail.length() } private string toStringImpl() { - tail = TAccessPathNil(_) and - result = head.toString() + exists(DataFlowType t | + tail = TAccessPathNil(t) and + result = head.toString() + "]" + concat(" : " + ppReprType(t)) + ) or result = head + ", " + tail.(AccessPathCons).toStringImpl() } override string toString() { - result = "[" + this.toStringImpl() + "]" + concat(" : " + ppReprType(this.getType())) + result = "[" + this.toStringImpl() } } @@ -2340,10 +2333,9 @@ private class PathNodeMid extends PathNodeImpl, TPathNodeMid { CallContext cc; SummaryCtx sc; AccessPath ap; - AccessPathApprox apa; Configuration config; - PathNodeMid() { this = TPathNodeMid(node, cc, sc, ap, apa, config) } + PathNodeMid() { this = TPathNodeMid(node, cc, sc, ap, config) } override Node getNode() { result = node } @@ -2353,13 +2345,10 @@ private class PathNodeMid extends PathNodeImpl, TPathNodeMid { AccessPath getAp() { result = ap } - AccessPathApprox getApa() { result = apa } - override Configuration getConfiguration() { result = config } private PathNodeMid getSuccMid() { - pathStep(this, result.getNode(), result.getCallContext(), result.getSummaryCtx(), - result.getAp(), _) and + pathStep(this, result.getNode(), result.getCallContext(), result.getSummaryCtx(), result.getAp()) and result.getConfiguration() = unbind(this.getConfiguration()) } @@ -2371,7 +2360,7 @@ private class PathNodeMid extends PathNodeImpl, TPathNodeMid { exists(PathNodeMid mid, PathNodeSink sink | mid = getSuccMid() and mid.getNode() = sink.getNode() and - mid.getApa() instanceof AccessPathApproxNil and + mid.getAp() instanceof AccessPathNil and sink.getConfiguration() = unbind(mid.getConfiguration()) and result = sink ) @@ -2381,7 +2370,7 @@ private class PathNodeMid extends PathNodeImpl, TPathNodeMid { config.isSource(node) and cc instanceof CallContextAny and sc instanceof SummaryCtxNone and - apa instanceof AccessPathApproxNil + ap instanceof AccessPathNil } } @@ -2409,33 +2398,22 @@ private class PathNodeSink extends PathNodeImpl, TPathNodeSink { * Holds if data may flow from `mid` to `node`. The last step in or out of * a callable is recorded by `cc`. */ -private predicate pathStep( - PathNodeMid mid, Node node, CallContext cc, SummaryCtx sc, AccessPath ap, AccessPathApprox apa -) { +private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, SummaryCtx sc, AccessPath ap) { pathStepSameAp(mid, node, cc, sc) and - ap = mid.getAp() and - apa = mid.getApa() + ap = mid.getAp() or exists(DataFlowType t | pathStepEmptyAp(mid, node, cc, sc, t) and - ap = TAccessPathNil(t) and - apa = TNil(t) + ap = TAccessPathNil(t) ) or - exists(TypedContent tc, AccessPathApprox apa0 | - pathStoreStep(mid, node, ap.pop(tc), apa0, tc, cc) and - // Same as `apa = ap.getApprox()`, but avoids mutual recursion - apa0 = apa.pop(tc) - ) and + exists(TypedContent tc | pathStoreStep(mid, node, ap.pop(tc), tc, cc)) and sc = mid.getSummaryCtx() or exists(TypedContent tc | pathReadStep(mid, node, ap.push(tc), tc, cc)) and - sc = mid.getSummaryCtx() and - // Here the approximation cannot be created from the approximation before - // the read, so we must use `getApprox()` - apa = ap.getApprox() + sc = mid.getSummaryCtx() or - pathThroughCallable(mid, node, cc, ap, apa) and + pathThroughCallable(mid, node, cc, ap) and sc = mid.getSummaryCtx() } @@ -2504,10 +2482,9 @@ private predicate storeCand(Node node1, TypedContent tc, Node node2, Configurati pragma[nomagic] private predicate pathStoreStep( - PathNodeMid mid, Node node, AccessPath ap0, AccessPathApprox apa0, TypedContent tc, CallContext cc + PathNodeMid mid, Node node, AccessPath ap0, TypedContent tc, CallContext cc ) { ap0 = mid.getAp() and - apa0 = mid.getApa() and storeCand(mid.getNode(), tc, node, mid.getConfiguration()) and cc = mid.getCallContext() } @@ -2519,7 +2496,7 @@ private predicate pathOutOfCallable0( pos = getReturnPosition(mid.getNode()) and innercc = mid.getCallContext() and innercc instanceof CallContextNoCall and - apa = mid.getApa() and + apa = mid.getAp().getApprox() and config = mid.getConfiguration() } @@ -2570,7 +2547,7 @@ private predicate pathIntoArg( cc = mid.getCallContext() and arg.argumentOf(call, i) and ap = mid.getAp() and - apa = mid.getApa() + apa = ap.getApprox() ) } @@ -2653,7 +2630,7 @@ private predicate paramFlowsThrough( sc = mid.getSummaryCtx() and config = mid.getConfiguration() and ap = mid.getAp() and - apa = mid.getApa() and + apa = ap.getApprox() and pos = sc.getParameterPos() and not kind.(ParamUpdateReturnKind).getPosition() = pos ) @@ -2675,10 +2652,8 @@ private predicate pathThroughCallable0( * The context `cc` is restored to its value prior to entering the callable. */ pragma[noinline] -private predicate pathThroughCallable( - PathNodeMid mid, Node out, CallContext cc, AccessPath ap, AccessPathApprox apa -) { - exists(DataFlowCall call, ReturnKindExt kind | +private predicate pathThroughCallable(PathNodeMid mid, Node out, CallContext cc, AccessPath ap) { + exists(DataFlowCall call, ReturnKindExt kind, AccessPathApprox apa | pathThroughCallable0(call, mid, kind, cc, ap, apa) and out = getAnOutNodeFlow(kind, call, apa, unbind(mid.getConfiguration())) ) diff --git a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl3.qll b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl3.qll index 04975b875b7b..77e777126c7b 100644 --- a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl3.qll +++ b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl3.qll @@ -1645,7 +1645,7 @@ private class AccessPathApproxOption extends TAccessPathApproxOption { } /** - * Holds if `node` is reachable with approximate access path `ap` from a source + * Holds if `node` is reachable with approximate access path `apa` from a source * in the configuration `config`. * * The call context `cc` records whether the node is reached through an @@ -1863,7 +1863,7 @@ private predicate flowFwdIsEntered( } /** - * Holds if `node` with approximate access path `ap` is part of a path from a + * Holds if `node` with approximate access path `apa` is part of a path from a * source to a sink in the configuration `config`. * * The Boolean `toReturn` records whether the node must be returned from @@ -2098,26 +2098,22 @@ private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome { private newtype TAccessPath = TAccessPathNil(DataFlowType t) or - TAccessPathCons(TypedContent head, AccessPath tail) { pathStoreStep(_, _, tail, _, head, _) } + TAccessPathCons(TypedContent head, AccessPath tail) { flowConsCand(head, tail.getApprox(), _) } private newtype TPathNode = - TPathNodeMid( - Node node, CallContext cc, SummaryCtx sc, AccessPath ap, AccessPathApprox apa, - Configuration config - ) { + TPathNodeMid(Node node, CallContext cc, SummaryCtx sc, AccessPath ap, Configuration config) { // A PathNode is introduced by a source ... flow(node, config) and config.isSource(node) and cc instanceof CallContextAny and sc instanceof SummaryCtxNone and - ap = TAccessPathNil(getNodeType(node)) and - apa = TNil(getNodeType(node)) + ap = TAccessPathNil(getNodeType(node)) or // ... or a step from an existing PathNode to another node. exists(PathNodeMid mid | - pathStep(mid, node, cc, sc, ap, apa) and + pathStep(mid, node, cc, sc, ap) and config = mid.getConfiguration() and - flow(node, _, _, apa, unbind(config)) + flow(node, _, _, ap.getApprox(), unbind(config)) ) } or TPathNodeSink(Node node, Configuration config) { @@ -2129,7 +2125,7 @@ private newtype TPathNode = or // ... or a sink that can be reached from a source exists(PathNodeMid mid | - pathStep(mid, node, _, _, _, TNil(_)) and + pathStep(mid, node, _, _, TAccessPathNil(_)) and config = unbind(mid.getConfiguration()) ) ) @@ -2142,9 +2138,6 @@ private newtype TPathNode = * tracked object. The final type indicates the type of the tracked object. */ abstract private class AccessPath extends TAccessPath { - /** Gets the type of this access path. */ - abstract DataFlowType getType(); - /** Gets the head of this access path, if any. */ abstract TypedContent getHead(); @@ -2178,7 +2171,7 @@ private class AccessPathNil extends AccessPath, TAccessPathNil { AccessPathNil() { this = TAccessPathNil(t) } - override DataFlowType getType() { result = t } + DataFlowType getType() { result = t } override TypedContent getHead() { none() } @@ -2199,8 +2192,6 @@ private class AccessPathCons extends AccessPath, TAccessPathCons { AccessPathCons() { this = TAccessPathCons(head, tail) } - override DataFlowType getType() { result = tail.getType() } - override TypedContent getHead() { result = head } override AccessPath getTail() { result = tail } @@ -2216,14 +2207,16 @@ private class AccessPathCons extends AccessPath, TAccessPathCons { override int length() { result = 1 + tail.length() } private string toStringImpl() { - tail = TAccessPathNil(_) and - result = head.toString() + exists(DataFlowType t | + tail = TAccessPathNil(t) and + result = head.toString() + "]" + concat(" : " + ppReprType(t)) + ) or result = head + ", " + tail.(AccessPathCons).toStringImpl() } override string toString() { - result = "[" + this.toStringImpl() + "]" + concat(" : " + ppReprType(this.getType())) + result = "[" + this.toStringImpl() } } @@ -2340,10 +2333,9 @@ private class PathNodeMid extends PathNodeImpl, TPathNodeMid { CallContext cc; SummaryCtx sc; AccessPath ap; - AccessPathApprox apa; Configuration config; - PathNodeMid() { this = TPathNodeMid(node, cc, sc, ap, apa, config) } + PathNodeMid() { this = TPathNodeMid(node, cc, sc, ap, config) } override Node getNode() { result = node } @@ -2353,13 +2345,10 @@ private class PathNodeMid extends PathNodeImpl, TPathNodeMid { AccessPath getAp() { result = ap } - AccessPathApprox getApa() { result = apa } - override Configuration getConfiguration() { result = config } private PathNodeMid getSuccMid() { - pathStep(this, result.getNode(), result.getCallContext(), result.getSummaryCtx(), - result.getAp(), _) and + pathStep(this, result.getNode(), result.getCallContext(), result.getSummaryCtx(), result.getAp()) and result.getConfiguration() = unbind(this.getConfiguration()) } @@ -2371,7 +2360,7 @@ private class PathNodeMid extends PathNodeImpl, TPathNodeMid { exists(PathNodeMid mid, PathNodeSink sink | mid = getSuccMid() and mid.getNode() = sink.getNode() and - mid.getApa() instanceof AccessPathApproxNil and + mid.getAp() instanceof AccessPathNil and sink.getConfiguration() = unbind(mid.getConfiguration()) and result = sink ) @@ -2381,7 +2370,7 @@ private class PathNodeMid extends PathNodeImpl, TPathNodeMid { config.isSource(node) and cc instanceof CallContextAny and sc instanceof SummaryCtxNone and - apa instanceof AccessPathApproxNil + ap instanceof AccessPathNil } } @@ -2409,33 +2398,22 @@ private class PathNodeSink extends PathNodeImpl, TPathNodeSink { * Holds if data may flow from `mid` to `node`. The last step in or out of * a callable is recorded by `cc`. */ -private predicate pathStep( - PathNodeMid mid, Node node, CallContext cc, SummaryCtx sc, AccessPath ap, AccessPathApprox apa -) { +private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, SummaryCtx sc, AccessPath ap) { pathStepSameAp(mid, node, cc, sc) and - ap = mid.getAp() and - apa = mid.getApa() + ap = mid.getAp() or exists(DataFlowType t | pathStepEmptyAp(mid, node, cc, sc, t) and - ap = TAccessPathNil(t) and - apa = TNil(t) + ap = TAccessPathNil(t) ) or - exists(TypedContent tc, AccessPathApprox apa0 | - pathStoreStep(mid, node, ap.pop(tc), apa0, tc, cc) and - // Same as `apa = ap.getApprox()`, but avoids mutual recursion - apa0 = apa.pop(tc) - ) and + exists(TypedContent tc | pathStoreStep(mid, node, ap.pop(tc), tc, cc)) and sc = mid.getSummaryCtx() or exists(TypedContent tc | pathReadStep(mid, node, ap.push(tc), tc, cc)) and - sc = mid.getSummaryCtx() and - // Here the approximation cannot be created from the approximation before - // the read, so we must use `getApprox()` - apa = ap.getApprox() + sc = mid.getSummaryCtx() or - pathThroughCallable(mid, node, cc, ap, apa) and + pathThroughCallable(mid, node, cc, ap) and sc = mid.getSummaryCtx() } @@ -2504,10 +2482,9 @@ private predicate storeCand(Node node1, TypedContent tc, Node node2, Configurati pragma[nomagic] private predicate pathStoreStep( - PathNodeMid mid, Node node, AccessPath ap0, AccessPathApprox apa0, TypedContent tc, CallContext cc + PathNodeMid mid, Node node, AccessPath ap0, TypedContent tc, CallContext cc ) { ap0 = mid.getAp() and - apa0 = mid.getApa() and storeCand(mid.getNode(), tc, node, mid.getConfiguration()) and cc = mid.getCallContext() } @@ -2519,7 +2496,7 @@ private predicate pathOutOfCallable0( pos = getReturnPosition(mid.getNode()) and innercc = mid.getCallContext() and innercc instanceof CallContextNoCall and - apa = mid.getApa() and + apa = mid.getAp().getApprox() and config = mid.getConfiguration() } @@ -2570,7 +2547,7 @@ private predicate pathIntoArg( cc = mid.getCallContext() and arg.argumentOf(call, i) and ap = mid.getAp() and - apa = mid.getApa() + apa = ap.getApprox() ) } @@ -2653,7 +2630,7 @@ private predicate paramFlowsThrough( sc = mid.getSummaryCtx() and config = mid.getConfiguration() and ap = mid.getAp() and - apa = mid.getApa() and + apa = ap.getApprox() and pos = sc.getParameterPos() and not kind.(ParamUpdateReturnKind).getPosition() = pos ) @@ -2675,10 +2652,8 @@ private predicate pathThroughCallable0( * The context `cc` is restored to its value prior to entering the callable. */ pragma[noinline] -private predicate pathThroughCallable( - PathNodeMid mid, Node out, CallContext cc, AccessPath ap, AccessPathApprox apa -) { - exists(DataFlowCall call, ReturnKindExt kind | +private predicate pathThroughCallable(PathNodeMid mid, Node out, CallContext cc, AccessPath ap) { + exists(DataFlowCall call, ReturnKindExt kind, AccessPathApprox apa | pathThroughCallable0(call, mid, kind, cc, ap, apa) and out = getAnOutNodeFlow(kind, call, apa, unbind(mid.getConfiguration())) ) diff --git a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl4.qll b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl4.qll index 04975b875b7b..77e777126c7b 100644 --- a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl4.qll +++ b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl4.qll @@ -1645,7 +1645,7 @@ private class AccessPathApproxOption extends TAccessPathApproxOption { } /** - * Holds if `node` is reachable with approximate access path `ap` from a source + * Holds if `node` is reachable with approximate access path `apa` from a source * in the configuration `config`. * * The call context `cc` records whether the node is reached through an @@ -1863,7 +1863,7 @@ private predicate flowFwdIsEntered( } /** - * Holds if `node` with approximate access path `ap` is part of a path from a + * Holds if `node` with approximate access path `apa` is part of a path from a * source to a sink in the configuration `config`. * * The Boolean `toReturn` records whether the node must be returned from @@ -2098,26 +2098,22 @@ private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome { private newtype TAccessPath = TAccessPathNil(DataFlowType t) or - TAccessPathCons(TypedContent head, AccessPath tail) { pathStoreStep(_, _, tail, _, head, _) } + TAccessPathCons(TypedContent head, AccessPath tail) { flowConsCand(head, tail.getApprox(), _) } private newtype TPathNode = - TPathNodeMid( - Node node, CallContext cc, SummaryCtx sc, AccessPath ap, AccessPathApprox apa, - Configuration config - ) { + TPathNodeMid(Node node, CallContext cc, SummaryCtx sc, AccessPath ap, Configuration config) { // A PathNode is introduced by a source ... flow(node, config) and config.isSource(node) and cc instanceof CallContextAny and sc instanceof SummaryCtxNone and - ap = TAccessPathNil(getNodeType(node)) and - apa = TNil(getNodeType(node)) + ap = TAccessPathNil(getNodeType(node)) or // ... or a step from an existing PathNode to another node. exists(PathNodeMid mid | - pathStep(mid, node, cc, sc, ap, apa) and + pathStep(mid, node, cc, sc, ap) and config = mid.getConfiguration() and - flow(node, _, _, apa, unbind(config)) + flow(node, _, _, ap.getApprox(), unbind(config)) ) } or TPathNodeSink(Node node, Configuration config) { @@ -2129,7 +2125,7 @@ private newtype TPathNode = or // ... or a sink that can be reached from a source exists(PathNodeMid mid | - pathStep(mid, node, _, _, _, TNil(_)) and + pathStep(mid, node, _, _, TAccessPathNil(_)) and config = unbind(mid.getConfiguration()) ) ) @@ -2142,9 +2138,6 @@ private newtype TPathNode = * tracked object. The final type indicates the type of the tracked object. */ abstract private class AccessPath extends TAccessPath { - /** Gets the type of this access path. */ - abstract DataFlowType getType(); - /** Gets the head of this access path, if any. */ abstract TypedContent getHead(); @@ -2178,7 +2171,7 @@ private class AccessPathNil extends AccessPath, TAccessPathNil { AccessPathNil() { this = TAccessPathNil(t) } - override DataFlowType getType() { result = t } + DataFlowType getType() { result = t } override TypedContent getHead() { none() } @@ -2199,8 +2192,6 @@ private class AccessPathCons extends AccessPath, TAccessPathCons { AccessPathCons() { this = TAccessPathCons(head, tail) } - override DataFlowType getType() { result = tail.getType() } - override TypedContent getHead() { result = head } override AccessPath getTail() { result = tail } @@ -2216,14 +2207,16 @@ private class AccessPathCons extends AccessPath, TAccessPathCons { override int length() { result = 1 + tail.length() } private string toStringImpl() { - tail = TAccessPathNil(_) and - result = head.toString() + exists(DataFlowType t | + tail = TAccessPathNil(t) and + result = head.toString() + "]" + concat(" : " + ppReprType(t)) + ) or result = head + ", " + tail.(AccessPathCons).toStringImpl() } override string toString() { - result = "[" + this.toStringImpl() + "]" + concat(" : " + ppReprType(this.getType())) + result = "[" + this.toStringImpl() } } @@ -2340,10 +2333,9 @@ private class PathNodeMid extends PathNodeImpl, TPathNodeMid { CallContext cc; SummaryCtx sc; AccessPath ap; - AccessPathApprox apa; Configuration config; - PathNodeMid() { this = TPathNodeMid(node, cc, sc, ap, apa, config) } + PathNodeMid() { this = TPathNodeMid(node, cc, sc, ap, config) } override Node getNode() { result = node } @@ -2353,13 +2345,10 @@ private class PathNodeMid extends PathNodeImpl, TPathNodeMid { AccessPath getAp() { result = ap } - AccessPathApprox getApa() { result = apa } - override Configuration getConfiguration() { result = config } private PathNodeMid getSuccMid() { - pathStep(this, result.getNode(), result.getCallContext(), result.getSummaryCtx(), - result.getAp(), _) and + pathStep(this, result.getNode(), result.getCallContext(), result.getSummaryCtx(), result.getAp()) and result.getConfiguration() = unbind(this.getConfiguration()) } @@ -2371,7 +2360,7 @@ private class PathNodeMid extends PathNodeImpl, TPathNodeMid { exists(PathNodeMid mid, PathNodeSink sink | mid = getSuccMid() and mid.getNode() = sink.getNode() and - mid.getApa() instanceof AccessPathApproxNil and + mid.getAp() instanceof AccessPathNil and sink.getConfiguration() = unbind(mid.getConfiguration()) and result = sink ) @@ -2381,7 +2370,7 @@ private class PathNodeMid extends PathNodeImpl, TPathNodeMid { config.isSource(node) and cc instanceof CallContextAny and sc instanceof SummaryCtxNone and - apa instanceof AccessPathApproxNil + ap instanceof AccessPathNil } } @@ -2409,33 +2398,22 @@ private class PathNodeSink extends PathNodeImpl, TPathNodeSink { * Holds if data may flow from `mid` to `node`. The last step in or out of * a callable is recorded by `cc`. */ -private predicate pathStep( - PathNodeMid mid, Node node, CallContext cc, SummaryCtx sc, AccessPath ap, AccessPathApprox apa -) { +private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, SummaryCtx sc, AccessPath ap) { pathStepSameAp(mid, node, cc, sc) and - ap = mid.getAp() and - apa = mid.getApa() + ap = mid.getAp() or exists(DataFlowType t | pathStepEmptyAp(mid, node, cc, sc, t) and - ap = TAccessPathNil(t) and - apa = TNil(t) + ap = TAccessPathNil(t) ) or - exists(TypedContent tc, AccessPathApprox apa0 | - pathStoreStep(mid, node, ap.pop(tc), apa0, tc, cc) and - // Same as `apa = ap.getApprox()`, but avoids mutual recursion - apa0 = apa.pop(tc) - ) and + exists(TypedContent tc | pathStoreStep(mid, node, ap.pop(tc), tc, cc)) and sc = mid.getSummaryCtx() or exists(TypedContent tc | pathReadStep(mid, node, ap.push(tc), tc, cc)) and - sc = mid.getSummaryCtx() and - // Here the approximation cannot be created from the approximation before - // the read, so we must use `getApprox()` - apa = ap.getApprox() + sc = mid.getSummaryCtx() or - pathThroughCallable(mid, node, cc, ap, apa) and + pathThroughCallable(mid, node, cc, ap) and sc = mid.getSummaryCtx() } @@ -2504,10 +2482,9 @@ private predicate storeCand(Node node1, TypedContent tc, Node node2, Configurati pragma[nomagic] private predicate pathStoreStep( - PathNodeMid mid, Node node, AccessPath ap0, AccessPathApprox apa0, TypedContent tc, CallContext cc + PathNodeMid mid, Node node, AccessPath ap0, TypedContent tc, CallContext cc ) { ap0 = mid.getAp() and - apa0 = mid.getApa() and storeCand(mid.getNode(), tc, node, mid.getConfiguration()) and cc = mid.getCallContext() } @@ -2519,7 +2496,7 @@ private predicate pathOutOfCallable0( pos = getReturnPosition(mid.getNode()) and innercc = mid.getCallContext() and innercc instanceof CallContextNoCall and - apa = mid.getApa() and + apa = mid.getAp().getApprox() and config = mid.getConfiguration() } @@ -2570,7 +2547,7 @@ private predicate pathIntoArg( cc = mid.getCallContext() and arg.argumentOf(call, i) and ap = mid.getAp() and - apa = mid.getApa() + apa = ap.getApprox() ) } @@ -2653,7 +2630,7 @@ private predicate paramFlowsThrough( sc = mid.getSummaryCtx() and config = mid.getConfiguration() and ap = mid.getAp() and - apa = mid.getApa() and + apa = ap.getApprox() and pos = sc.getParameterPos() and not kind.(ParamUpdateReturnKind).getPosition() = pos ) @@ -2675,10 +2652,8 @@ private predicate pathThroughCallable0( * The context `cc` is restored to its value prior to entering the callable. */ pragma[noinline] -private predicate pathThroughCallable( - PathNodeMid mid, Node out, CallContext cc, AccessPath ap, AccessPathApprox apa -) { - exists(DataFlowCall call, ReturnKindExt kind | +private predicate pathThroughCallable(PathNodeMid mid, Node out, CallContext cc, AccessPath ap) { + exists(DataFlowCall call, ReturnKindExt kind, AccessPathApprox apa | pathThroughCallable0(call, mid, kind, cc, ap, apa) and out = getAnOutNodeFlow(kind, call, apa, unbind(mid.getConfiguration())) ) diff --git a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImplLocal.qll b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImplLocal.qll index 04975b875b7b..77e777126c7b 100644 --- a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImplLocal.qll +++ b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImplLocal.qll @@ -1645,7 +1645,7 @@ private class AccessPathApproxOption extends TAccessPathApproxOption { } /** - * Holds if `node` is reachable with approximate access path `ap` from a source + * Holds if `node` is reachable with approximate access path `apa` from a source * in the configuration `config`. * * The call context `cc` records whether the node is reached through an @@ -1863,7 +1863,7 @@ private predicate flowFwdIsEntered( } /** - * Holds if `node` with approximate access path `ap` is part of a path from a + * Holds if `node` with approximate access path `apa` is part of a path from a * source to a sink in the configuration `config`. * * The Boolean `toReturn` records whether the node must be returned from @@ -2098,26 +2098,22 @@ private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome { private newtype TAccessPath = TAccessPathNil(DataFlowType t) or - TAccessPathCons(TypedContent head, AccessPath tail) { pathStoreStep(_, _, tail, _, head, _) } + TAccessPathCons(TypedContent head, AccessPath tail) { flowConsCand(head, tail.getApprox(), _) } private newtype TPathNode = - TPathNodeMid( - Node node, CallContext cc, SummaryCtx sc, AccessPath ap, AccessPathApprox apa, - Configuration config - ) { + TPathNodeMid(Node node, CallContext cc, SummaryCtx sc, AccessPath ap, Configuration config) { // A PathNode is introduced by a source ... flow(node, config) and config.isSource(node) and cc instanceof CallContextAny and sc instanceof SummaryCtxNone and - ap = TAccessPathNil(getNodeType(node)) and - apa = TNil(getNodeType(node)) + ap = TAccessPathNil(getNodeType(node)) or // ... or a step from an existing PathNode to another node. exists(PathNodeMid mid | - pathStep(mid, node, cc, sc, ap, apa) and + pathStep(mid, node, cc, sc, ap) and config = mid.getConfiguration() and - flow(node, _, _, apa, unbind(config)) + flow(node, _, _, ap.getApprox(), unbind(config)) ) } or TPathNodeSink(Node node, Configuration config) { @@ -2129,7 +2125,7 @@ private newtype TPathNode = or // ... or a sink that can be reached from a source exists(PathNodeMid mid | - pathStep(mid, node, _, _, _, TNil(_)) and + pathStep(mid, node, _, _, TAccessPathNil(_)) and config = unbind(mid.getConfiguration()) ) ) @@ -2142,9 +2138,6 @@ private newtype TPathNode = * tracked object. The final type indicates the type of the tracked object. */ abstract private class AccessPath extends TAccessPath { - /** Gets the type of this access path. */ - abstract DataFlowType getType(); - /** Gets the head of this access path, if any. */ abstract TypedContent getHead(); @@ -2178,7 +2171,7 @@ private class AccessPathNil extends AccessPath, TAccessPathNil { AccessPathNil() { this = TAccessPathNil(t) } - override DataFlowType getType() { result = t } + DataFlowType getType() { result = t } override TypedContent getHead() { none() } @@ -2199,8 +2192,6 @@ private class AccessPathCons extends AccessPath, TAccessPathCons { AccessPathCons() { this = TAccessPathCons(head, tail) } - override DataFlowType getType() { result = tail.getType() } - override TypedContent getHead() { result = head } override AccessPath getTail() { result = tail } @@ -2216,14 +2207,16 @@ private class AccessPathCons extends AccessPath, TAccessPathCons { override int length() { result = 1 + tail.length() } private string toStringImpl() { - tail = TAccessPathNil(_) and - result = head.toString() + exists(DataFlowType t | + tail = TAccessPathNil(t) and + result = head.toString() + "]" + concat(" : " + ppReprType(t)) + ) or result = head + ", " + tail.(AccessPathCons).toStringImpl() } override string toString() { - result = "[" + this.toStringImpl() + "]" + concat(" : " + ppReprType(this.getType())) + result = "[" + this.toStringImpl() } } @@ -2340,10 +2333,9 @@ private class PathNodeMid extends PathNodeImpl, TPathNodeMid { CallContext cc; SummaryCtx sc; AccessPath ap; - AccessPathApprox apa; Configuration config; - PathNodeMid() { this = TPathNodeMid(node, cc, sc, ap, apa, config) } + PathNodeMid() { this = TPathNodeMid(node, cc, sc, ap, config) } override Node getNode() { result = node } @@ -2353,13 +2345,10 @@ private class PathNodeMid extends PathNodeImpl, TPathNodeMid { AccessPath getAp() { result = ap } - AccessPathApprox getApa() { result = apa } - override Configuration getConfiguration() { result = config } private PathNodeMid getSuccMid() { - pathStep(this, result.getNode(), result.getCallContext(), result.getSummaryCtx(), - result.getAp(), _) and + pathStep(this, result.getNode(), result.getCallContext(), result.getSummaryCtx(), result.getAp()) and result.getConfiguration() = unbind(this.getConfiguration()) } @@ -2371,7 +2360,7 @@ private class PathNodeMid extends PathNodeImpl, TPathNodeMid { exists(PathNodeMid mid, PathNodeSink sink | mid = getSuccMid() and mid.getNode() = sink.getNode() and - mid.getApa() instanceof AccessPathApproxNil and + mid.getAp() instanceof AccessPathNil and sink.getConfiguration() = unbind(mid.getConfiguration()) and result = sink ) @@ -2381,7 +2370,7 @@ private class PathNodeMid extends PathNodeImpl, TPathNodeMid { config.isSource(node) and cc instanceof CallContextAny and sc instanceof SummaryCtxNone and - apa instanceof AccessPathApproxNil + ap instanceof AccessPathNil } } @@ -2409,33 +2398,22 @@ private class PathNodeSink extends PathNodeImpl, TPathNodeSink { * Holds if data may flow from `mid` to `node`. The last step in or out of * a callable is recorded by `cc`. */ -private predicate pathStep( - PathNodeMid mid, Node node, CallContext cc, SummaryCtx sc, AccessPath ap, AccessPathApprox apa -) { +private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, SummaryCtx sc, AccessPath ap) { pathStepSameAp(mid, node, cc, sc) and - ap = mid.getAp() and - apa = mid.getApa() + ap = mid.getAp() or exists(DataFlowType t | pathStepEmptyAp(mid, node, cc, sc, t) and - ap = TAccessPathNil(t) and - apa = TNil(t) + ap = TAccessPathNil(t) ) or - exists(TypedContent tc, AccessPathApprox apa0 | - pathStoreStep(mid, node, ap.pop(tc), apa0, tc, cc) and - // Same as `apa = ap.getApprox()`, but avoids mutual recursion - apa0 = apa.pop(tc) - ) and + exists(TypedContent tc | pathStoreStep(mid, node, ap.pop(tc), tc, cc)) and sc = mid.getSummaryCtx() or exists(TypedContent tc | pathReadStep(mid, node, ap.push(tc), tc, cc)) and - sc = mid.getSummaryCtx() and - // Here the approximation cannot be created from the approximation before - // the read, so we must use `getApprox()` - apa = ap.getApprox() + sc = mid.getSummaryCtx() or - pathThroughCallable(mid, node, cc, ap, apa) and + pathThroughCallable(mid, node, cc, ap) and sc = mid.getSummaryCtx() } @@ -2504,10 +2482,9 @@ private predicate storeCand(Node node1, TypedContent tc, Node node2, Configurati pragma[nomagic] private predicate pathStoreStep( - PathNodeMid mid, Node node, AccessPath ap0, AccessPathApprox apa0, TypedContent tc, CallContext cc + PathNodeMid mid, Node node, AccessPath ap0, TypedContent tc, CallContext cc ) { ap0 = mid.getAp() and - apa0 = mid.getApa() and storeCand(mid.getNode(), tc, node, mid.getConfiguration()) and cc = mid.getCallContext() } @@ -2519,7 +2496,7 @@ private predicate pathOutOfCallable0( pos = getReturnPosition(mid.getNode()) and innercc = mid.getCallContext() and innercc instanceof CallContextNoCall and - apa = mid.getApa() and + apa = mid.getAp().getApprox() and config = mid.getConfiguration() } @@ -2570,7 +2547,7 @@ private predicate pathIntoArg( cc = mid.getCallContext() and arg.argumentOf(call, i) and ap = mid.getAp() and - apa = mid.getApa() + apa = ap.getApprox() ) } @@ -2653,7 +2630,7 @@ private predicate paramFlowsThrough( sc = mid.getSummaryCtx() and config = mid.getConfiguration() and ap = mid.getAp() and - apa = mid.getApa() and + apa = ap.getApprox() and pos = sc.getParameterPos() and not kind.(ParamUpdateReturnKind).getPosition() = pos ) @@ -2675,10 +2652,8 @@ private predicate pathThroughCallable0( * The context `cc` is restored to its value prior to entering the callable. */ pragma[noinline] -private predicate pathThroughCallable( - PathNodeMid mid, Node out, CallContext cc, AccessPath ap, AccessPathApprox apa -) { - exists(DataFlowCall call, ReturnKindExt kind | +private predicate pathThroughCallable(PathNodeMid mid, Node out, CallContext cc, AccessPath ap) { + exists(DataFlowCall call, ReturnKindExt kind, AccessPathApprox apa | pathThroughCallable0(call, mid, kind, cc, ap, apa) and out = getAnOutNodeFlow(kind, call, apa, unbind(mid.getConfiguration())) ) diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl.qll index 04975b875b7b..77e777126c7b 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl.qll @@ -1645,7 +1645,7 @@ private class AccessPathApproxOption extends TAccessPathApproxOption { } /** - * Holds if `node` is reachable with approximate access path `ap` from a source + * Holds if `node` is reachable with approximate access path `apa` from a source * in the configuration `config`. * * The call context `cc` records whether the node is reached through an @@ -1863,7 +1863,7 @@ private predicate flowFwdIsEntered( } /** - * Holds if `node` with approximate access path `ap` is part of a path from a + * Holds if `node` with approximate access path `apa` is part of a path from a * source to a sink in the configuration `config`. * * The Boolean `toReturn` records whether the node must be returned from @@ -2098,26 +2098,22 @@ private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome { private newtype TAccessPath = TAccessPathNil(DataFlowType t) or - TAccessPathCons(TypedContent head, AccessPath tail) { pathStoreStep(_, _, tail, _, head, _) } + TAccessPathCons(TypedContent head, AccessPath tail) { flowConsCand(head, tail.getApprox(), _) } private newtype TPathNode = - TPathNodeMid( - Node node, CallContext cc, SummaryCtx sc, AccessPath ap, AccessPathApprox apa, - Configuration config - ) { + TPathNodeMid(Node node, CallContext cc, SummaryCtx sc, AccessPath ap, Configuration config) { // A PathNode is introduced by a source ... flow(node, config) and config.isSource(node) and cc instanceof CallContextAny and sc instanceof SummaryCtxNone and - ap = TAccessPathNil(getNodeType(node)) and - apa = TNil(getNodeType(node)) + ap = TAccessPathNil(getNodeType(node)) or // ... or a step from an existing PathNode to another node. exists(PathNodeMid mid | - pathStep(mid, node, cc, sc, ap, apa) and + pathStep(mid, node, cc, sc, ap) and config = mid.getConfiguration() and - flow(node, _, _, apa, unbind(config)) + flow(node, _, _, ap.getApprox(), unbind(config)) ) } or TPathNodeSink(Node node, Configuration config) { @@ -2129,7 +2125,7 @@ private newtype TPathNode = or // ... or a sink that can be reached from a source exists(PathNodeMid mid | - pathStep(mid, node, _, _, _, TNil(_)) and + pathStep(mid, node, _, _, TAccessPathNil(_)) and config = unbind(mid.getConfiguration()) ) ) @@ -2142,9 +2138,6 @@ private newtype TPathNode = * tracked object. The final type indicates the type of the tracked object. */ abstract private class AccessPath extends TAccessPath { - /** Gets the type of this access path. */ - abstract DataFlowType getType(); - /** Gets the head of this access path, if any. */ abstract TypedContent getHead(); @@ -2178,7 +2171,7 @@ private class AccessPathNil extends AccessPath, TAccessPathNil { AccessPathNil() { this = TAccessPathNil(t) } - override DataFlowType getType() { result = t } + DataFlowType getType() { result = t } override TypedContent getHead() { none() } @@ -2199,8 +2192,6 @@ private class AccessPathCons extends AccessPath, TAccessPathCons { AccessPathCons() { this = TAccessPathCons(head, tail) } - override DataFlowType getType() { result = tail.getType() } - override TypedContent getHead() { result = head } override AccessPath getTail() { result = tail } @@ -2216,14 +2207,16 @@ private class AccessPathCons extends AccessPath, TAccessPathCons { override int length() { result = 1 + tail.length() } private string toStringImpl() { - tail = TAccessPathNil(_) and - result = head.toString() + exists(DataFlowType t | + tail = TAccessPathNil(t) and + result = head.toString() + "]" + concat(" : " + ppReprType(t)) + ) or result = head + ", " + tail.(AccessPathCons).toStringImpl() } override string toString() { - result = "[" + this.toStringImpl() + "]" + concat(" : " + ppReprType(this.getType())) + result = "[" + this.toStringImpl() } } @@ -2340,10 +2333,9 @@ private class PathNodeMid extends PathNodeImpl, TPathNodeMid { CallContext cc; SummaryCtx sc; AccessPath ap; - AccessPathApprox apa; Configuration config; - PathNodeMid() { this = TPathNodeMid(node, cc, sc, ap, apa, config) } + PathNodeMid() { this = TPathNodeMid(node, cc, sc, ap, config) } override Node getNode() { result = node } @@ -2353,13 +2345,10 @@ private class PathNodeMid extends PathNodeImpl, TPathNodeMid { AccessPath getAp() { result = ap } - AccessPathApprox getApa() { result = apa } - override Configuration getConfiguration() { result = config } private PathNodeMid getSuccMid() { - pathStep(this, result.getNode(), result.getCallContext(), result.getSummaryCtx(), - result.getAp(), _) and + pathStep(this, result.getNode(), result.getCallContext(), result.getSummaryCtx(), result.getAp()) and result.getConfiguration() = unbind(this.getConfiguration()) } @@ -2371,7 +2360,7 @@ private class PathNodeMid extends PathNodeImpl, TPathNodeMid { exists(PathNodeMid mid, PathNodeSink sink | mid = getSuccMid() and mid.getNode() = sink.getNode() and - mid.getApa() instanceof AccessPathApproxNil and + mid.getAp() instanceof AccessPathNil and sink.getConfiguration() = unbind(mid.getConfiguration()) and result = sink ) @@ -2381,7 +2370,7 @@ private class PathNodeMid extends PathNodeImpl, TPathNodeMid { config.isSource(node) and cc instanceof CallContextAny and sc instanceof SummaryCtxNone and - apa instanceof AccessPathApproxNil + ap instanceof AccessPathNil } } @@ -2409,33 +2398,22 @@ private class PathNodeSink extends PathNodeImpl, TPathNodeSink { * Holds if data may flow from `mid` to `node`. The last step in or out of * a callable is recorded by `cc`. */ -private predicate pathStep( - PathNodeMid mid, Node node, CallContext cc, SummaryCtx sc, AccessPath ap, AccessPathApprox apa -) { +private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, SummaryCtx sc, AccessPath ap) { pathStepSameAp(mid, node, cc, sc) and - ap = mid.getAp() and - apa = mid.getApa() + ap = mid.getAp() or exists(DataFlowType t | pathStepEmptyAp(mid, node, cc, sc, t) and - ap = TAccessPathNil(t) and - apa = TNil(t) + ap = TAccessPathNil(t) ) or - exists(TypedContent tc, AccessPathApprox apa0 | - pathStoreStep(mid, node, ap.pop(tc), apa0, tc, cc) and - // Same as `apa = ap.getApprox()`, but avoids mutual recursion - apa0 = apa.pop(tc) - ) and + exists(TypedContent tc | pathStoreStep(mid, node, ap.pop(tc), tc, cc)) and sc = mid.getSummaryCtx() or exists(TypedContent tc | pathReadStep(mid, node, ap.push(tc), tc, cc)) and - sc = mid.getSummaryCtx() and - // Here the approximation cannot be created from the approximation before - // the read, so we must use `getApprox()` - apa = ap.getApprox() + sc = mid.getSummaryCtx() or - pathThroughCallable(mid, node, cc, ap, apa) and + pathThroughCallable(mid, node, cc, ap) and sc = mid.getSummaryCtx() } @@ -2504,10 +2482,9 @@ private predicate storeCand(Node node1, TypedContent tc, Node node2, Configurati pragma[nomagic] private predicate pathStoreStep( - PathNodeMid mid, Node node, AccessPath ap0, AccessPathApprox apa0, TypedContent tc, CallContext cc + PathNodeMid mid, Node node, AccessPath ap0, TypedContent tc, CallContext cc ) { ap0 = mid.getAp() and - apa0 = mid.getApa() and storeCand(mid.getNode(), tc, node, mid.getConfiguration()) and cc = mid.getCallContext() } @@ -2519,7 +2496,7 @@ private predicate pathOutOfCallable0( pos = getReturnPosition(mid.getNode()) and innercc = mid.getCallContext() and innercc instanceof CallContextNoCall and - apa = mid.getApa() and + apa = mid.getAp().getApprox() and config = mid.getConfiguration() } @@ -2570,7 +2547,7 @@ private predicate pathIntoArg( cc = mid.getCallContext() and arg.argumentOf(call, i) and ap = mid.getAp() and - apa = mid.getApa() + apa = ap.getApprox() ) } @@ -2653,7 +2630,7 @@ private predicate paramFlowsThrough( sc = mid.getSummaryCtx() and config = mid.getConfiguration() and ap = mid.getAp() and - apa = mid.getApa() and + apa = ap.getApprox() and pos = sc.getParameterPos() and not kind.(ParamUpdateReturnKind).getPosition() = pos ) @@ -2675,10 +2652,8 @@ private predicate pathThroughCallable0( * The context `cc` is restored to its value prior to entering the callable. */ pragma[noinline] -private predicate pathThroughCallable( - PathNodeMid mid, Node out, CallContext cc, AccessPath ap, AccessPathApprox apa -) { - exists(DataFlowCall call, ReturnKindExt kind | +private predicate pathThroughCallable(PathNodeMid mid, Node out, CallContext cc, AccessPath ap) { + exists(DataFlowCall call, ReturnKindExt kind, AccessPathApprox apa | pathThroughCallable0(call, mid, kind, cc, ap, apa) and out = getAnOutNodeFlow(kind, call, apa, unbind(mid.getConfiguration())) ) diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl2.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl2.qll index 04975b875b7b..77e777126c7b 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl2.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl2.qll @@ -1645,7 +1645,7 @@ private class AccessPathApproxOption extends TAccessPathApproxOption { } /** - * Holds if `node` is reachable with approximate access path `ap` from a source + * Holds if `node` is reachable with approximate access path `apa` from a source * in the configuration `config`. * * The call context `cc` records whether the node is reached through an @@ -1863,7 +1863,7 @@ private predicate flowFwdIsEntered( } /** - * Holds if `node` with approximate access path `ap` is part of a path from a + * Holds if `node` with approximate access path `apa` is part of a path from a * source to a sink in the configuration `config`. * * The Boolean `toReturn` records whether the node must be returned from @@ -2098,26 +2098,22 @@ private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome { private newtype TAccessPath = TAccessPathNil(DataFlowType t) or - TAccessPathCons(TypedContent head, AccessPath tail) { pathStoreStep(_, _, tail, _, head, _) } + TAccessPathCons(TypedContent head, AccessPath tail) { flowConsCand(head, tail.getApprox(), _) } private newtype TPathNode = - TPathNodeMid( - Node node, CallContext cc, SummaryCtx sc, AccessPath ap, AccessPathApprox apa, - Configuration config - ) { + TPathNodeMid(Node node, CallContext cc, SummaryCtx sc, AccessPath ap, Configuration config) { // A PathNode is introduced by a source ... flow(node, config) and config.isSource(node) and cc instanceof CallContextAny and sc instanceof SummaryCtxNone and - ap = TAccessPathNil(getNodeType(node)) and - apa = TNil(getNodeType(node)) + ap = TAccessPathNil(getNodeType(node)) or // ... or a step from an existing PathNode to another node. exists(PathNodeMid mid | - pathStep(mid, node, cc, sc, ap, apa) and + pathStep(mid, node, cc, sc, ap) and config = mid.getConfiguration() and - flow(node, _, _, apa, unbind(config)) + flow(node, _, _, ap.getApprox(), unbind(config)) ) } or TPathNodeSink(Node node, Configuration config) { @@ -2129,7 +2125,7 @@ private newtype TPathNode = or // ... or a sink that can be reached from a source exists(PathNodeMid mid | - pathStep(mid, node, _, _, _, TNil(_)) and + pathStep(mid, node, _, _, TAccessPathNil(_)) and config = unbind(mid.getConfiguration()) ) ) @@ -2142,9 +2138,6 @@ private newtype TPathNode = * tracked object. The final type indicates the type of the tracked object. */ abstract private class AccessPath extends TAccessPath { - /** Gets the type of this access path. */ - abstract DataFlowType getType(); - /** Gets the head of this access path, if any. */ abstract TypedContent getHead(); @@ -2178,7 +2171,7 @@ private class AccessPathNil extends AccessPath, TAccessPathNil { AccessPathNil() { this = TAccessPathNil(t) } - override DataFlowType getType() { result = t } + DataFlowType getType() { result = t } override TypedContent getHead() { none() } @@ -2199,8 +2192,6 @@ private class AccessPathCons extends AccessPath, TAccessPathCons { AccessPathCons() { this = TAccessPathCons(head, tail) } - override DataFlowType getType() { result = tail.getType() } - override TypedContent getHead() { result = head } override AccessPath getTail() { result = tail } @@ -2216,14 +2207,16 @@ private class AccessPathCons extends AccessPath, TAccessPathCons { override int length() { result = 1 + tail.length() } private string toStringImpl() { - tail = TAccessPathNil(_) and - result = head.toString() + exists(DataFlowType t | + tail = TAccessPathNil(t) and + result = head.toString() + "]" + concat(" : " + ppReprType(t)) + ) or result = head + ", " + tail.(AccessPathCons).toStringImpl() } override string toString() { - result = "[" + this.toStringImpl() + "]" + concat(" : " + ppReprType(this.getType())) + result = "[" + this.toStringImpl() } } @@ -2340,10 +2333,9 @@ private class PathNodeMid extends PathNodeImpl, TPathNodeMid { CallContext cc; SummaryCtx sc; AccessPath ap; - AccessPathApprox apa; Configuration config; - PathNodeMid() { this = TPathNodeMid(node, cc, sc, ap, apa, config) } + PathNodeMid() { this = TPathNodeMid(node, cc, sc, ap, config) } override Node getNode() { result = node } @@ -2353,13 +2345,10 @@ private class PathNodeMid extends PathNodeImpl, TPathNodeMid { AccessPath getAp() { result = ap } - AccessPathApprox getApa() { result = apa } - override Configuration getConfiguration() { result = config } private PathNodeMid getSuccMid() { - pathStep(this, result.getNode(), result.getCallContext(), result.getSummaryCtx(), - result.getAp(), _) and + pathStep(this, result.getNode(), result.getCallContext(), result.getSummaryCtx(), result.getAp()) and result.getConfiguration() = unbind(this.getConfiguration()) } @@ -2371,7 +2360,7 @@ private class PathNodeMid extends PathNodeImpl, TPathNodeMid { exists(PathNodeMid mid, PathNodeSink sink | mid = getSuccMid() and mid.getNode() = sink.getNode() and - mid.getApa() instanceof AccessPathApproxNil and + mid.getAp() instanceof AccessPathNil and sink.getConfiguration() = unbind(mid.getConfiguration()) and result = sink ) @@ -2381,7 +2370,7 @@ private class PathNodeMid extends PathNodeImpl, TPathNodeMid { config.isSource(node) and cc instanceof CallContextAny and sc instanceof SummaryCtxNone and - apa instanceof AccessPathApproxNil + ap instanceof AccessPathNil } } @@ -2409,33 +2398,22 @@ private class PathNodeSink extends PathNodeImpl, TPathNodeSink { * Holds if data may flow from `mid` to `node`. The last step in or out of * a callable is recorded by `cc`. */ -private predicate pathStep( - PathNodeMid mid, Node node, CallContext cc, SummaryCtx sc, AccessPath ap, AccessPathApprox apa -) { +private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, SummaryCtx sc, AccessPath ap) { pathStepSameAp(mid, node, cc, sc) and - ap = mid.getAp() and - apa = mid.getApa() + ap = mid.getAp() or exists(DataFlowType t | pathStepEmptyAp(mid, node, cc, sc, t) and - ap = TAccessPathNil(t) and - apa = TNil(t) + ap = TAccessPathNil(t) ) or - exists(TypedContent tc, AccessPathApprox apa0 | - pathStoreStep(mid, node, ap.pop(tc), apa0, tc, cc) and - // Same as `apa = ap.getApprox()`, but avoids mutual recursion - apa0 = apa.pop(tc) - ) and + exists(TypedContent tc | pathStoreStep(mid, node, ap.pop(tc), tc, cc)) and sc = mid.getSummaryCtx() or exists(TypedContent tc | pathReadStep(mid, node, ap.push(tc), tc, cc)) and - sc = mid.getSummaryCtx() and - // Here the approximation cannot be created from the approximation before - // the read, so we must use `getApprox()` - apa = ap.getApprox() + sc = mid.getSummaryCtx() or - pathThroughCallable(mid, node, cc, ap, apa) and + pathThroughCallable(mid, node, cc, ap) and sc = mid.getSummaryCtx() } @@ -2504,10 +2482,9 @@ private predicate storeCand(Node node1, TypedContent tc, Node node2, Configurati pragma[nomagic] private predicate pathStoreStep( - PathNodeMid mid, Node node, AccessPath ap0, AccessPathApprox apa0, TypedContent tc, CallContext cc + PathNodeMid mid, Node node, AccessPath ap0, TypedContent tc, CallContext cc ) { ap0 = mid.getAp() and - apa0 = mid.getApa() and storeCand(mid.getNode(), tc, node, mid.getConfiguration()) and cc = mid.getCallContext() } @@ -2519,7 +2496,7 @@ private predicate pathOutOfCallable0( pos = getReturnPosition(mid.getNode()) and innercc = mid.getCallContext() and innercc instanceof CallContextNoCall and - apa = mid.getApa() and + apa = mid.getAp().getApprox() and config = mid.getConfiguration() } @@ -2570,7 +2547,7 @@ private predicate pathIntoArg( cc = mid.getCallContext() and arg.argumentOf(call, i) and ap = mid.getAp() and - apa = mid.getApa() + apa = ap.getApprox() ) } @@ -2653,7 +2630,7 @@ private predicate paramFlowsThrough( sc = mid.getSummaryCtx() and config = mid.getConfiguration() and ap = mid.getAp() and - apa = mid.getApa() and + apa = ap.getApprox() and pos = sc.getParameterPos() and not kind.(ParamUpdateReturnKind).getPosition() = pos ) @@ -2675,10 +2652,8 @@ private predicate pathThroughCallable0( * The context `cc` is restored to its value prior to entering the callable. */ pragma[noinline] -private predicate pathThroughCallable( - PathNodeMid mid, Node out, CallContext cc, AccessPath ap, AccessPathApprox apa -) { - exists(DataFlowCall call, ReturnKindExt kind | +private predicate pathThroughCallable(PathNodeMid mid, Node out, CallContext cc, AccessPath ap) { + exists(DataFlowCall call, ReturnKindExt kind, AccessPathApprox apa | pathThroughCallable0(call, mid, kind, cc, ap, apa) and out = getAnOutNodeFlow(kind, call, apa, unbind(mid.getConfiguration())) ) diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl3.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl3.qll index 04975b875b7b..77e777126c7b 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl3.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl3.qll @@ -1645,7 +1645,7 @@ private class AccessPathApproxOption extends TAccessPathApproxOption { } /** - * Holds if `node` is reachable with approximate access path `ap` from a source + * Holds if `node` is reachable with approximate access path `apa` from a source * in the configuration `config`. * * The call context `cc` records whether the node is reached through an @@ -1863,7 +1863,7 @@ private predicate flowFwdIsEntered( } /** - * Holds if `node` with approximate access path `ap` is part of a path from a + * Holds if `node` with approximate access path `apa` is part of a path from a * source to a sink in the configuration `config`. * * The Boolean `toReturn` records whether the node must be returned from @@ -2098,26 +2098,22 @@ private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome { private newtype TAccessPath = TAccessPathNil(DataFlowType t) or - TAccessPathCons(TypedContent head, AccessPath tail) { pathStoreStep(_, _, tail, _, head, _) } + TAccessPathCons(TypedContent head, AccessPath tail) { flowConsCand(head, tail.getApprox(), _) } private newtype TPathNode = - TPathNodeMid( - Node node, CallContext cc, SummaryCtx sc, AccessPath ap, AccessPathApprox apa, - Configuration config - ) { + TPathNodeMid(Node node, CallContext cc, SummaryCtx sc, AccessPath ap, Configuration config) { // A PathNode is introduced by a source ... flow(node, config) and config.isSource(node) and cc instanceof CallContextAny and sc instanceof SummaryCtxNone and - ap = TAccessPathNil(getNodeType(node)) and - apa = TNil(getNodeType(node)) + ap = TAccessPathNil(getNodeType(node)) or // ... or a step from an existing PathNode to another node. exists(PathNodeMid mid | - pathStep(mid, node, cc, sc, ap, apa) and + pathStep(mid, node, cc, sc, ap) and config = mid.getConfiguration() and - flow(node, _, _, apa, unbind(config)) + flow(node, _, _, ap.getApprox(), unbind(config)) ) } or TPathNodeSink(Node node, Configuration config) { @@ -2129,7 +2125,7 @@ private newtype TPathNode = or // ... or a sink that can be reached from a source exists(PathNodeMid mid | - pathStep(mid, node, _, _, _, TNil(_)) and + pathStep(mid, node, _, _, TAccessPathNil(_)) and config = unbind(mid.getConfiguration()) ) ) @@ -2142,9 +2138,6 @@ private newtype TPathNode = * tracked object. The final type indicates the type of the tracked object. */ abstract private class AccessPath extends TAccessPath { - /** Gets the type of this access path. */ - abstract DataFlowType getType(); - /** Gets the head of this access path, if any. */ abstract TypedContent getHead(); @@ -2178,7 +2171,7 @@ private class AccessPathNil extends AccessPath, TAccessPathNil { AccessPathNil() { this = TAccessPathNil(t) } - override DataFlowType getType() { result = t } + DataFlowType getType() { result = t } override TypedContent getHead() { none() } @@ -2199,8 +2192,6 @@ private class AccessPathCons extends AccessPath, TAccessPathCons { AccessPathCons() { this = TAccessPathCons(head, tail) } - override DataFlowType getType() { result = tail.getType() } - override TypedContent getHead() { result = head } override AccessPath getTail() { result = tail } @@ -2216,14 +2207,16 @@ private class AccessPathCons extends AccessPath, TAccessPathCons { override int length() { result = 1 + tail.length() } private string toStringImpl() { - tail = TAccessPathNil(_) and - result = head.toString() + exists(DataFlowType t | + tail = TAccessPathNil(t) and + result = head.toString() + "]" + concat(" : " + ppReprType(t)) + ) or result = head + ", " + tail.(AccessPathCons).toStringImpl() } override string toString() { - result = "[" + this.toStringImpl() + "]" + concat(" : " + ppReprType(this.getType())) + result = "[" + this.toStringImpl() } } @@ -2340,10 +2333,9 @@ private class PathNodeMid extends PathNodeImpl, TPathNodeMid { CallContext cc; SummaryCtx sc; AccessPath ap; - AccessPathApprox apa; Configuration config; - PathNodeMid() { this = TPathNodeMid(node, cc, sc, ap, apa, config) } + PathNodeMid() { this = TPathNodeMid(node, cc, sc, ap, config) } override Node getNode() { result = node } @@ -2353,13 +2345,10 @@ private class PathNodeMid extends PathNodeImpl, TPathNodeMid { AccessPath getAp() { result = ap } - AccessPathApprox getApa() { result = apa } - override Configuration getConfiguration() { result = config } private PathNodeMid getSuccMid() { - pathStep(this, result.getNode(), result.getCallContext(), result.getSummaryCtx(), - result.getAp(), _) and + pathStep(this, result.getNode(), result.getCallContext(), result.getSummaryCtx(), result.getAp()) and result.getConfiguration() = unbind(this.getConfiguration()) } @@ -2371,7 +2360,7 @@ private class PathNodeMid extends PathNodeImpl, TPathNodeMid { exists(PathNodeMid mid, PathNodeSink sink | mid = getSuccMid() and mid.getNode() = sink.getNode() and - mid.getApa() instanceof AccessPathApproxNil and + mid.getAp() instanceof AccessPathNil and sink.getConfiguration() = unbind(mid.getConfiguration()) and result = sink ) @@ -2381,7 +2370,7 @@ private class PathNodeMid extends PathNodeImpl, TPathNodeMid { config.isSource(node) and cc instanceof CallContextAny and sc instanceof SummaryCtxNone and - apa instanceof AccessPathApproxNil + ap instanceof AccessPathNil } } @@ -2409,33 +2398,22 @@ private class PathNodeSink extends PathNodeImpl, TPathNodeSink { * Holds if data may flow from `mid` to `node`. The last step in or out of * a callable is recorded by `cc`. */ -private predicate pathStep( - PathNodeMid mid, Node node, CallContext cc, SummaryCtx sc, AccessPath ap, AccessPathApprox apa -) { +private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, SummaryCtx sc, AccessPath ap) { pathStepSameAp(mid, node, cc, sc) and - ap = mid.getAp() and - apa = mid.getApa() + ap = mid.getAp() or exists(DataFlowType t | pathStepEmptyAp(mid, node, cc, sc, t) and - ap = TAccessPathNil(t) and - apa = TNil(t) + ap = TAccessPathNil(t) ) or - exists(TypedContent tc, AccessPathApprox apa0 | - pathStoreStep(mid, node, ap.pop(tc), apa0, tc, cc) and - // Same as `apa = ap.getApprox()`, but avoids mutual recursion - apa0 = apa.pop(tc) - ) and + exists(TypedContent tc | pathStoreStep(mid, node, ap.pop(tc), tc, cc)) and sc = mid.getSummaryCtx() or exists(TypedContent tc | pathReadStep(mid, node, ap.push(tc), tc, cc)) and - sc = mid.getSummaryCtx() and - // Here the approximation cannot be created from the approximation before - // the read, so we must use `getApprox()` - apa = ap.getApprox() + sc = mid.getSummaryCtx() or - pathThroughCallable(mid, node, cc, ap, apa) and + pathThroughCallable(mid, node, cc, ap) and sc = mid.getSummaryCtx() } @@ -2504,10 +2482,9 @@ private predicate storeCand(Node node1, TypedContent tc, Node node2, Configurati pragma[nomagic] private predicate pathStoreStep( - PathNodeMid mid, Node node, AccessPath ap0, AccessPathApprox apa0, TypedContent tc, CallContext cc + PathNodeMid mid, Node node, AccessPath ap0, TypedContent tc, CallContext cc ) { ap0 = mid.getAp() and - apa0 = mid.getApa() and storeCand(mid.getNode(), tc, node, mid.getConfiguration()) and cc = mid.getCallContext() } @@ -2519,7 +2496,7 @@ private predicate pathOutOfCallable0( pos = getReturnPosition(mid.getNode()) and innercc = mid.getCallContext() and innercc instanceof CallContextNoCall and - apa = mid.getApa() and + apa = mid.getAp().getApprox() and config = mid.getConfiguration() } @@ -2570,7 +2547,7 @@ private predicate pathIntoArg( cc = mid.getCallContext() and arg.argumentOf(call, i) and ap = mid.getAp() and - apa = mid.getApa() + apa = ap.getApprox() ) } @@ -2653,7 +2630,7 @@ private predicate paramFlowsThrough( sc = mid.getSummaryCtx() and config = mid.getConfiguration() and ap = mid.getAp() and - apa = mid.getApa() and + apa = ap.getApprox() and pos = sc.getParameterPos() and not kind.(ParamUpdateReturnKind).getPosition() = pos ) @@ -2675,10 +2652,8 @@ private predicate pathThroughCallable0( * The context `cc` is restored to its value prior to entering the callable. */ pragma[noinline] -private predicate pathThroughCallable( - PathNodeMid mid, Node out, CallContext cc, AccessPath ap, AccessPathApprox apa -) { - exists(DataFlowCall call, ReturnKindExt kind | +private predicate pathThroughCallable(PathNodeMid mid, Node out, CallContext cc, AccessPath ap) { + exists(DataFlowCall call, ReturnKindExt kind, AccessPathApprox apa | pathThroughCallable0(call, mid, kind, cc, ap, apa) and out = getAnOutNodeFlow(kind, call, apa, unbind(mid.getConfiguration())) ) diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl4.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl4.qll index 04975b875b7b..77e777126c7b 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl4.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl4.qll @@ -1645,7 +1645,7 @@ private class AccessPathApproxOption extends TAccessPathApproxOption { } /** - * Holds if `node` is reachable with approximate access path `ap` from a source + * Holds if `node` is reachable with approximate access path `apa` from a source * in the configuration `config`. * * The call context `cc` records whether the node is reached through an @@ -1863,7 +1863,7 @@ private predicate flowFwdIsEntered( } /** - * Holds if `node` with approximate access path `ap` is part of a path from a + * Holds if `node` with approximate access path `apa` is part of a path from a * source to a sink in the configuration `config`. * * The Boolean `toReturn` records whether the node must be returned from @@ -2098,26 +2098,22 @@ private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome { private newtype TAccessPath = TAccessPathNil(DataFlowType t) or - TAccessPathCons(TypedContent head, AccessPath tail) { pathStoreStep(_, _, tail, _, head, _) } + TAccessPathCons(TypedContent head, AccessPath tail) { flowConsCand(head, tail.getApprox(), _) } private newtype TPathNode = - TPathNodeMid( - Node node, CallContext cc, SummaryCtx sc, AccessPath ap, AccessPathApprox apa, - Configuration config - ) { + TPathNodeMid(Node node, CallContext cc, SummaryCtx sc, AccessPath ap, Configuration config) { // A PathNode is introduced by a source ... flow(node, config) and config.isSource(node) and cc instanceof CallContextAny and sc instanceof SummaryCtxNone and - ap = TAccessPathNil(getNodeType(node)) and - apa = TNil(getNodeType(node)) + ap = TAccessPathNil(getNodeType(node)) or // ... or a step from an existing PathNode to another node. exists(PathNodeMid mid | - pathStep(mid, node, cc, sc, ap, apa) and + pathStep(mid, node, cc, sc, ap) and config = mid.getConfiguration() and - flow(node, _, _, apa, unbind(config)) + flow(node, _, _, ap.getApprox(), unbind(config)) ) } or TPathNodeSink(Node node, Configuration config) { @@ -2129,7 +2125,7 @@ private newtype TPathNode = or // ... or a sink that can be reached from a source exists(PathNodeMid mid | - pathStep(mid, node, _, _, _, TNil(_)) and + pathStep(mid, node, _, _, TAccessPathNil(_)) and config = unbind(mid.getConfiguration()) ) ) @@ -2142,9 +2138,6 @@ private newtype TPathNode = * tracked object. The final type indicates the type of the tracked object. */ abstract private class AccessPath extends TAccessPath { - /** Gets the type of this access path. */ - abstract DataFlowType getType(); - /** Gets the head of this access path, if any. */ abstract TypedContent getHead(); @@ -2178,7 +2171,7 @@ private class AccessPathNil extends AccessPath, TAccessPathNil { AccessPathNil() { this = TAccessPathNil(t) } - override DataFlowType getType() { result = t } + DataFlowType getType() { result = t } override TypedContent getHead() { none() } @@ -2199,8 +2192,6 @@ private class AccessPathCons extends AccessPath, TAccessPathCons { AccessPathCons() { this = TAccessPathCons(head, tail) } - override DataFlowType getType() { result = tail.getType() } - override TypedContent getHead() { result = head } override AccessPath getTail() { result = tail } @@ -2216,14 +2207,16 @@ private class AccessPathCons extends AccessPath, TAccessPathCons { override int length() { result = 1 + tail.length() } private string toStringImpl() { - tail = TAccessPathNil(_) and - result = head.toString() + exists(DataFlowType t | + tail = TAccessPathNil(t) and + result = head.toString() + "]" + concat(" : " + ppReprType(t)) + ) or result = head + ", " + tail.(AccessPathCons).toStringImpl() } override string toString() { - result = "[" + this.toStringImpl() + "]" + concat(" : " + ppReprType(this.getType())) + result = "[" + this.toStringImpl() } } @@ -2340,10 +2333,9 @@ private class PathNodeMid extends PathNodeImpl, TPathNodeMid { CallContext cc; SummaryCtx sc; AccessPath ap; - AccessPathApprox apa; Configuration config; - PathNodeMid() { this = TPathNodeMid(node, cc, sc, ap, apa, config) } + PathNodeMid() { this = TPathNodeMid(node, cc, sc, ap, config) } override Node getNode() { result = node } @@ -2353,13 +2345,10 @@ private class PathNodeMid extends PathNodeImpl, TPathNodeMid { AccessPath getAp() { result = ap } - AccessPathApprox getApa() { result = apa } - override Configuration getConfiguration() { result = config } private PathNodeMid getSuccMid() { - pathStep(this, result.getNode(), result.getCallContext(), result.getSummaryCtx(), - result.getAp(), _) and + pathStep(this, result.getNode(), result.getCallContext(), result.getSummaryCtx(), result.getAp()) and result.getConfiguration() = unbind(this.getConfiguration()) } @@ -2371,7 +2360,7 @@ private class PathNodeMid extends PathNodeImpl, TPathNodeMid { exists(PathNodeMid mid, PathNodeSink sink | mid = getSuccMid() and mid.getNode() = sink.getNode() and - mid.getApa() instanceof AccessPathApproxNil and + mid.getAp() instanceof AccessPathNil and sink.getConfiguration() = unbind(mid.getConfiguration()) and result = sink ) @@ -2381,7 +2370,7 @@ private class PathNodeMid extends PathNodeImpl, TPathNodeMid { config.isSource(node) and cc instanceof CallContextAny and sc instanceof SummaryCtxNone and - apa instanceof AccessPathApproxNil + ap instanceof AccessPathNil } } @@ -2409,33 +2398,22 @@ private class PathNodeSink extends PathNodeImpl, TPathNodeSink { * Holds if data may flow from `mid` to `node`. The last step in or out of * a callable is recorded by `cc`. */ -private predicate pathStep( - PathNodeMid mid, Node node, CallContext cc, SummaryCtx sc, AccessPath ap, AccessPathApprox apa -) { +private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, SummaryCtx sc, AccessPath ap) { pathStepSameAp(mid, node, cc, sc) and - ap = mid.getAp() and - apa = mid.getApa() + ap = mid.getAp() or exists(DataFlowType t | pathStepEmptyAp(mid, node, cc, sc, t) and - ap = TAccessPathNil(t) and - apa = TNil(t) + ap = TAccessPathNil(t) ) or - exists(TypedContent tc, AccessPathApprox apa0 | - pathStoreStep(mid, node, ap.pop(tc), apa0, tc, cc) and - // Same as `apa = ap.getApprox()`, but avoids mutual recursion - apa0 = apa.pop(tc) - ) and + exists(TypedContent tc | pathStoreStep(mid, node, ap.pop(tc), tc, cc)) and sc = mid.getSummaryCtx() or exists(TypedContent tc | pathReadStep(mid, node, ap.push(tc), tc, cc)) and - sc = mid.getSummaryCtx() and - // Here the approximation cannot be created from the approximation before - // the read, so we must use `getApprox()` - apa = ap.getApprox() + sc = mid.getSummaryCtx() or - pathThroughCallable(mid, node, cc, ap, apa) and + pathThroughCallable(mid, node, cc, ap) and sc = mid.getSummaryCtx() } @@ -2504,10 +2482,9 @@ private predicate storeCand(Node node1, TypedContent tc, Node node2, Configurati pragma[nomagic] private predicate pathStoreStep( - PathNodeMid mid, Node node, AccessPath ap0, AccessPathApprox apa0, TypedContent tc, CallContext cc + PathNodeMid mid, Node node, AccessPath ap0, TypedContent tc, CallContext cc ) { ap0 = mid.getAp() and - apa0 = mid.getApa() and storeCand(mid.getNode(), tc, node, mid.getConfiguration()) and cc = mid.getCallContext() } @@ -2519,7 +2496,7 @@ private predicate pathOutOfCallable0( pos = getReturnPosition(mid.getNode()) and innercc = mid.getCallContext() and innercc instanceof CallContextNoCall and - apa = mid.getApa() and + apa = mid.getAp().getApprox() and config = mid.getConfiguration() } @@ -2570,7 +2547,7 @@ private predicate pathIntoArg( cc = mid.getCallContext() and arg.argumentOf(call, i) and ap = mid.getAp() and - apa = mid.getApa() + apa = ap.getApprox() ) } @@ -2653,7 +2630,7 @@ private predicate paramFlowsThrough( sc = mid.getSummaryCtx() and config = mid.getConfiguration() and ap = mid.getAp() and - apa = mid.getApa() and + apa = ap.getApprox() and pos = sc.getParameterPos() and not kind.(ParamUpdateReturnKind).getPosition() = pos ) @@ -2675,10 +2652,8 @@ private predicate pathThroughCallable0( * The context `cc` is restored to its value prior to entering the callable. */ pragma[noinline] -private predicate pathThroughCallable( - PathNodeMid mid, Node out, CallContext cc, AccessPath ap, AccessPathApprox apa -) { - exists(DataFlowCall call, ReturnKindExt kind | +private predicate pathThroughCallable(PathNodeMid mid, Node out, CallContext cc, AccessPath ap) { + exists(DataFlowCall call, ReturnKindExt kind, AccessPathApprox apa | pathThroughCallable0(call, mid, kind, cc, ap, apa) and out = getAnOutNodeFlow(kind, call, apa, unbind(mid.getConfiguration())) ) diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl.qll index 04975b875b7b..77e777126c7b 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl.qll @@ -1645,7 +1645,7 @@ private class AccessPathApproxOption extends TAccessPathApproxOption { } /** - * Holds if `node` is reachable with approximate access path `ap` from a source + * Holds if `node` is reachable with approximate access path `apa` from a source * in the configuration `config`. * * The call context `cc` records whether the node is reached through an @@ -1863,7 +1863,7 @@ private predicate flowFwdIsEntered( } /** - * Holds if `node` with approximate access path `ap` is part of a path from a + * Holds if `node` with approximate access path `apa` is part of a path from a * source to a sink in the configuration `config`. * * The Boolean `toReturn` records whether the node must be returned from @@ -2098,26 +2098,22 @@ private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome { private newtype TAccessPath = TAccessPathNil(DataFlowType t) or - TAccessPathCons(TypedContent head, AccessPath tail) { pathStoreStep(_, _, tail, _, head, _) } + TAccessPathCons(TypedContent head, AccessPath tail) { flowConsCand(head, tail.getApprox(), _) } private newtype TPathNode = - TPathNodeMid( - Node node, CallContext cc, SummaryCtx sc, AccessPath ap, AccessPathApprox apa, - Configuration config - ) { + TPathNodeMid(Node node, CallContext cc, SummaryCtx sc, AccessPath ap, Configuration config) { // A PathNode is introduced by a source ... flow(node, config) and config.isSource(node) and cc instanceof CallContextAny and sc instanceof SummaryCtxNone and - ap = TAccessPathNil(getNodeType(node)) and - apa = TNil(getNodeType(node)) + ap = TAccessPathNil(getNodeType(node)) or // ... or a step from an existing PathNode to another node. exists(PathNodeMid mid | - pathStep(mid, node, cc, sc, ap, apa) and + pathStep(mid, node, cc, sc, ap) and config = mid.getConfiguration() and - flow(node, _, _, apa, unbind(config)) + flow(node, _, _, ap.getApprox(), unbind(config)) ) } or TPathNodeSink(Node node, Configuration config) { @@ -2129,7 +2125,7 @@ private newtype TPathNode = or // ... or a sink that can be reached from a source exists(PathNodeMid mid | - pathStep(mid, node, _, _, _, TNil(_)) and + pathStep(mid, node, _, _, TAccessPathNil(_)) and config = unbind(mid.getConfiguration()) ) ) @@ -2142,9 +2138,6 @@ private newtype TPathNode = * tracked object. The final type indicates the type of the tracked object. */ abstract private class AccessPath extends TAccessPath { - /** Gets the type of this access path. */ - abstract DataFlowType getType(); - /** Gets the head of this access path, if any. */ abstract TypedContent getHead(); @@ -2178,7 +2171,7 @@ private class AccessPathNil extends AccessPath, TAccessPathNil { AccessPathNil() { this = TAccessPathNil(t) } - override DataFlowType getType() { result = t } + DataFlowType getType() { result = t } override TypedContent getHead() { none() } @@ -2199,8 +2192,6 @@ private class AccessPathCons extends AccessPath, TAccessPathCons { AccessPathCons() { this = TAccessPathCons(head, tail) } - override DataFlowType getType() { result = tail.getType() } - override TypedContent getHead() { result = head } override AccessPath getTail() { result = tail } @@ -2216,14 +2207,16 @@ private class AccessPathCons extends AccessPath, TAccessPathCons { override int length() { result = 1 + tail.length() } private string toStringImpl() { - tail = TAccessPathNil(_) and - result = head.toString() + exists(DataFlowType t | + tail = TAccessPathNil(t) and + result = head.toString() + "]" + concat(" : " + ppReprType(t)) + ) or result = head + ", " + tail.(AccessPathCons).toStringImpl() } override string toString() { - result = "[" + this.toStringImpl() + "]" + concat(" : " + ppReprType(this.getType())) + result = "[" + this.toStringImpl() } } @@ -2340,10 +2333,9 @@ private class PathNodeMid extends PathNodeImpl, TPathNodeMid { CallContext cc; SummaryCtx sc; AccessPath ap; - AccessPathApprox apa; Configuration config; - PathNodeMid() { this = TPathNodeMid(node, cc, sc, ap, apa, config) } + PathNodeMid() { this = TPathNodeMid(node, cc, sc, ap, config) } override Node getNode() { result = node } @@ -2353,13 +2345,10 @@ private class PathNodeMid extends PathNodeImpl, TPathNodeMid { AccessPath getAp() { result = ap } - AccessPathApprox getApa() { result = apa } - override Configuration getConfiguration() { result = config } private PathNodeMid getSuccMid() { - pathStep(this, result.getNode(), result.getCallContext(), result.getSummaryCtx(), - result.getAp(), _) and + pathStep(this, result.getNode(), result.getCallContext(), result.getSummaryCtx(), result.getAp()) and result.getConfiguration() = unbind(this.getConfiguration()) } @@ -2371,7 +2360,7 @@ private class PathNodeMid extends PathNodeImpl, TPathNodeMid { exists(PathNodeMid mid, PathNodeSink sink | mid = getSuccMid() and mid.getNode() = sink.getNode() and - mid.getApa() instanceof AccessPathApproxNil and + mid.getAp() instanceof AccessPathNil and sink.getConfiguration() = unbind(mid.getConfiguration()) and result = sink ) @@ -2381,7 +2370,7 @@ private class PathNodeMid extends PathNodeImpl, TPathNodeMid { config.isSource(node) and cc instanceof CallContextAny and sc instanceof SummaryCtxNone and - apa instanceof AccessPathApproxNil + ap instanceof AccessPathNil } } @@ -2409,33 +2398,22 @@ private class PathNodeSink extends PathNodeImpl, TPathNodeSink { * Holds if data may flow from `mid` to `node`. The last step in or out of * a callable is recorded by `cc`. */ -private predicate pathStep( - PathNodeMid mid, Node node, CallContext cc, SummaryCtx sc, AccessPath ap, AccessPathApprox apa -) { +private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, SummaryCtx sc, AccessPath ap) { pathStepSameAp(mid, node, cc, sc) and - ap = mid.getAp() and - apa = mid.getApa() + ap = mid.getAp() or exists(DataFlowType t | pathStepEmptyAp(mid, node, cc, sc, t) and - ap = TAccessPathNil(t) and - apa = TNil(t) + ap = TAccessPathNil(t) ) or - exists(TypedContent tc, AccessPathApprox apa0 | - pathStoreStep(mid, node, ap.pop(tc), apa0, tc, cc) and - // Same as `apa = ap.getApprox()`, but avoids mutual recursion - apa0 = apa.pop(tc) - ) and + exists(TypedContent tc | pathStoreStep(mid, node, ap.pop(tc), tc, cc)) and sc = mid.getSummaryCtx() or exists(TypedContent tc | pathReadStep(mid, node, ap.push(tc), tc, cc)) and - sc = mid.getSummaryCtx() and - // Here the approximation cannot be created from the approximation before - // the read, so we must use `getApprox()` - apa = ap.getApprox() + sc = mid.getSummaryCtx() or - pathThroughCallable(mid, node, cc, ap, apa) and + pathThroughCallable(mid, node, cc, ap) and sc = mid.getSummaryCtx() } @@ -2504,10 +2482,9 @@ private predicate storeCand(Node node1, TypedContent tc, Node node2, Configurati pragma[nomagic] private predicate pathStoreStep( - PathNodeMid mid, Node node, AccessPath ap0, AccessPathApprox apa0, TypedContent tc, CallContext cc + PathNodeMid mid, Node node, AccessPath ap0, TypedContent tc, CallContext cc ) { ap0 = mid.getAp() and - apa0 = mid.getApa() and storeCand(mid.getNode(), tc, node, mid.getConfiguration()) and cc = mid.getCallContext() } @@ -2519,7 +2496,7 @@ private predicate pathOutOfCallable0( pos = getReturnPosition(mid.getNode()) and innercc = mid.getCallContext() and innercc instanceof CallContextNoCall and - apa = mid.getApa() and + apa = mid.getAp().getApprox() and config = mid.getConfiguration() } @@ -2570,7 +2547,7 @@ private predicate pathIntoArg( cc = mid.getCallContext() and arg.argumentOf(call, i) and ap = mid.getAp() and - apa = mid.getApa() + apa = ap.getApprox() ) } @@ -2653,7 +2630,7 @@ private predicate paramFlowsThrough( sc = mid.getSummaryCtx() and config = mid.getConfiguration() and ap = mid.getAp() and - apa = mid.getApa() and + apa = ap.getApprox() and pos = sc.getParameterPos() and not kind.(ParamUpdateReturnKind).getPosition() = pos ) @@ -2675,10 +2652,8 @@ private predicate pathThroughCallable0( * The context `cc` is restored to its value prior to entering the callable. */ pragma[noinline] -private predicate pathThroughCallable( - PathNodeMid mid, Node out, CallContext cc, AccessPath ap, AccessPathApprox apa -) { - exists(DataFlowCall call, ReturnKindExt kind | +private predicate pathThroughCallable(PathNodeMid mid, Node out, CallContext cc, AccessPath ap) { + exists(DataFlowCall call, ReturnKindExt kind, AccessPathApprox apa | pathThroughCallable0(call, mid, kind, cc, ap, apa) and out = getAnOutNodeFlow(kind, call, apa, unbind(mid.getConfiguration())) ) diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl2.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl2.qll index 04975b875b7b..77e777126c7b 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl2.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl2.qll @@ -1645,7 +1645,7 @@ private class AccessPathApproxOption extends TAccessPathApproxOption { } /** - * Holds if `node` is reachable with approximate access path `ap` from a source + * Holds if `node` is reachable with approximate access path `apa` from a source * in the configuration `config`. * * The call context `cc` records whether the node is reached through an @@ -1863,7 +1863,7 @@ private predicate flowFwdIsEntered( } /** - * Holds if `node` with approximate access path `ap` is part of a path from a + * Holds if `node` with approximate access path `apa` is part of a path from a * source to a sink in the configuration `config`. * * The Boolean `toReturn` records whether the node must be returned from @@ -2098,26 +2098,22 @@ private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome { private newtype TAccessPath = TAccessPathNil(DataFlowType t) or - TAccessPathCons(TypedContent head, AccessPath tail) { pathStoreStep(_, _, tail, _, head, _) } + TAccessPathCons(TypedContent head, AccessPath tail) { flowConsCand(head, tail.getApprox(), _) } private newtype TPathNode = - TPathNodeMid( - Node node, CallContext cc, SummaryCtx sc, AccessPath ap, AccessPathApprox apa, - Configuration config - ) { + TPathNodeMid(Node node, CallContext cc, SummaryCtx sc, AccessPath ap, Configuration config) { // A PathNode is introduced by a source ... flow(node, config) and config.isSource(node) and cc instanceof CallContextAny and sc instanceof SummaryCtxNone and - ap = TAccessPathNil(getNodeType(node)) and - apa = TNil(getNodeType(node)) + ap = TAccessPathNil(getNodeType(node)) or // ... or a step from an existing PathNode to another node. exists(PathNodeMid mid | - pathStep(mid, node, cc, sc, ap, apa) and + pathStep(mid, node, cc, sc, ap) and config = mid.getConfiguration() and - flow(node, _, _, apa, unbind(config)) + flow(node, _, _, ap.getApprox(), unbind(config)) ) } or TPathNodeSink(Node node, Configuration config) { @@ -2129,7 +2125,7 @@ private newtype TPathNode = or // ... or a sink that can be reached from a source exists(PathNodeMid mid | - pathStep(mid, node, _, _, _, TNil(_)) and + pathStep(mid, node, _, _, TAccessPathNil(_)) and config = unbind(mid.getConfiguration()) ) ) @@ -2142,9 +2138,6 @@ private newtype TPathNode = * tracked object. The final type indicates the type of the tracked object. */ abstract private class AccessPath extends TAccessPath { - /** Gets the type of this access path. */ - abstract DataFlowType getType(); - /** Gets the head of this access path, if any. */ abstract TypedContent getHead(); @@ -2178,7 +2171,7 @@ private class AccessPathNil extends AccessPath, TAccessPathNil { AccessPathNil() { this = TAccessPathNil(t) } - override DataFlowType getType() { result = t } + DataFlowType getType() { result = t } override TypedContent getHead() { none() } @@ -2199,8 +2192,6 @@ private class AccessPathCons extends AccessPath, TAccessPathCons { AccessPathCons() { this = TAccessPathCons(head, tail) } - override DataFlowType getType() { result = tail.getType() } - override TypedContent getHead() { result = head } override AccessPath getTail() { result = tail } @@ -2216,14 +2207,16 @@ private class AccessPathCons extends AccessPath, TAccessPathCons { override int length() { result = 1 + tail.length() } private string toStringImpl() { - tail = TAccessPathNil(_) and - result = head.toString() + exists(DataFlowType t | + tail = TAccessPathNil(t) and + result = head.toString() + "]" + concat(" : " + ppReprType(t)) + ) or result = head + ", " + tail.(AccessPathCons).toStringImpl() } override string toString() { - result = "[" + this.toStringImpl() + "]" + concat(" : " + ppReprType(this.getType())) + result = "[" + this.toStringImpl() } } @@ -2340,10 +2333,9 @@ private class PathNodeMid extends PathNodeImpl, TPathNodeMid { CallContext cc; SummaryCtx sc; AccessPath ap; - AccessPathApprox apa; Configuration config; - PathNodeMid() { this = TPathNodeMid(node, cc, sc, ap, apa, config) } + PathNodeMid() { this = TPathNodeMid(node, cc, sc, ap, config) } override Node getNode() { result = node } @@ -2353,13 +2345,10 @@ private class PathNodeMid extends PathNodeImpl, TPathNodeMid { AccessPath getAp() { result = ap } - AccessPathApprox getApa() { result = apa } - override Configuration getConfiguration() { result = config } private PathNodeMid getSuccMid() { - pathStep(this, result.getNode(), result.getCallContext(), result.getSummaryCtx(), - result.getAp(), _) and + pathStep(this, result.getNode(), result.getCallContext(), result.getSummaryCtx(), result.getAp()) and result.getConfiguration() = unbind(this.getConfiguration()) } @@ -2371,7 +2360,7 @@ private class PathNodeMid extends PathNodeImpl, TPathNodeMid { exists(PathNodeMid mid, PathNodeSink sink | mid = getSuccMid() and mid.getNode() = sink.getNode() and - mid.getApa() instanceof AccessPathApproxNil and + mid.getAp() instanceof AccessPathNil and sink.getConfiguration() = unbind(mid.getConfiguration()) and result = sink ) @@ -2381,7 +2370,7 @@ private class PathNodeMid extends PathNodeImpl, TPathNodeMid { config.isSource(node) and cc instanceof CallContextAny and sc instanceof SummaryCtxNone and - apa instanceof AccessPathApproxNil + ap instanceof AccessPathNil } } @@ -2409,33 +2398,22 @@ private class PathNodeSink extends PathNodeImpl, TPathNodeSink { * Holds if data may flow from `mid` to `node`. The last step in or out of * a callable is recorded by `cc`. */ -private predicate pathStep( - PathNodeMid mid, Node node, CallContext cc, SummaryCtx sc, AccessPath ap, AccessPathApprox apa -) { +private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, SummaryCtx sc, AccessPath ap) { pathStepSameAp(mid, node, cc, sc) and - ap = mid.getAp() and - apa = mid.getApa() + ap = mid.getAp() or exists(DataFlowType t | pathStepEmptyAp(mid, node, cc, sc, t) and - ap = TAccessPathNil(t) and - apa = TNil(t) + ap = TAccessPathNil(t) ) or - exists(TypedContent tc, AccessPathApprox apa0 | - pathStoreStep(mid, node, ap.pop(tc), apa0, tc, cc) and - // Same as `apa = ap.getApprox()`, but avoids mutual recursion - apa0 = apa.pop(tc) - ) and + exists(TypedContent tc | pathStoreStep(mid, node, ap.pop(tc), tc, cc)) and sc = mid.getSummaryCtx() or exists(TypedContent tc | pathReadStep(mid, node, ap.push(tc), tc, cc)) and - sc = mid.getSummaryCtx() and - // Here the approximation cannot be created from the approximation before - // the read, so we must use `getApprox()` - apa = ap.getApprox() + sc = mid.getSummaryCtx() or - pathThroughCallable(mid, node, cc, ap, apa) and + pathThroughCallable(mid, node, cc, ap) and sc = mid.getSummaryCtx() } @@ -2504,10 +2482,9 @@ private predicate storeCand(Node node1, TypedContent tc, Node node2, Configurati pragma[nomagic] private predicate pathStoreStep( - PathNodeMid mid, Node node, AccessPath ap0, AccessPathApprox apa0, TypedContent tc, CallContext cc + PathNodeMid mid, Node node, AccessPath ap0, TypedContent tc, CallContext cc ) { ap0 = mid.getAp() and - apa0 = mid.getApa() and storeCand(mid.getNode(), tc, node, mid.getConfiguration()) and cc = mid.getCallContext() } @@ -2519,7 +2496,7 @@ private predicate pathOutOfCallable0( pos = getReturnPosition(mid.getNode()) and innercc = mid.getCallContext() and innercc instanceof CallContextNoCall and - apa = mid.getApa() and + apa = mid.getAp().getApprox() and config = mid.getConfiguration() } @@ -2570,7 +2547,7 @@ private predicate pathIntoArg( cc = mid.getCallContext() and arg.argumentOf(call, i) and ap = mid.getAp() and - apa = mid.getApa() + apa = ap.getApprox() ) } @@ -2653,7 +2630,7 @@ private predicate paramFlowsThrough( sc = mid.getSummaryCtx() and config = mid.getConfiguration() and ap = mid.getAp() and - apa = mid.getApa() and + apa = ap.getApprox() and pos = sc.getParameterPos() and not kind.(ParamUpdateReturnKind).getPosition() = pos ) @@ -2675,10 +2652,8 @@ private predicate pathThroughCallable0( * The context `cc` is restored to its value prior to entering the callable. */ pragma[noinline] -private predicate pathThroughCallable( - PathNodeMid mid, Node out, CallContext cc, AccessPath ap, AccessPathApprox apa -) { - exists(DataFlowCall call, ReturnKindExt kind | +private predicate pathThroughCallable(PathNodeMid mid, Node out, CallContext cc, AccessPath ap) { + exists(DataFlowCall call, ReturnKindExt kind, AccessPathApprox apa | pathThroughCallable0(call, mid, kind, cc, ap, apa) and out = getAnOutNodeFlow(kind, call, apa, unbind(mid.getConfiguration())) ) diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl3.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl3.qll index 04975b875b7b..77e777126c7b 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl3.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl3.qll @@ -1645,7 +1645,7 @@ private class AccessPathApproxOption extends TAccessPathApproxOption { } /** - * Holds if `node` is reachable with approximate access path `ap` from a source + * Holds if `node` is reachable with approximate access path `apa` from a source * in the configuration `config`. * * The call context `cc` records whether the node is reached through an @@ -1863,7 +1863,7 @@ private predicate flowFwdIsEntered( } /** - * Holds if `node` with approximate access path `ap` is part of a path from a + * Holds if `node` with approximate access path `apa` is part of a path from a * source to a sink in the configuration `config`. * * The Boolean `toReturn` records whether the node must be returned from @@ -2098,26 +2098,22 @@ private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome { private newtype TAccessPath = TAccessPathNil(DataFlowType t) or - TAccessPathCons(TypedContent head, AccessPath tail) { pathStoreStep(_, _, tail, _, head, _) } + TAccessPathCons(TypedContent head, AccessPath tail) { flowConsCand(head, tail.getApprox(), _) } private newtype TPathNode = - TPathNodeMid( - Node node, CallContext cc, SummaryCtx sc, AccessPath ap, AccessPathApprox apa, - Configuration config - ) { + TPathNodeMid(Node node, CallContext cc, SummaryCtx sc, AccessPath ap, Configuration config) { // A PathNode is introduced by a source ... flow(node, config) and config.isSource(node) and cc instanceof CallContextAny and sc instanceof SummaryCtxNone and - ap = TAccessPathNil(getNodeType(node)) and - apa = TNil(getNodeType(node)) + ap = TAccessPathNil(getNodeType(node)) or // ... or a step from an existing PathNode to another node. exists(PathNodeMid mid | - pathStep(mid, node, cc, sc, ap, apa) and + pathStep(mid, node, cc, sc, ap) and config = mid.getConfiguration() and - flow(node, _, _, apa, unbind(config)) + flow(node, _, _, ap.getApprox(), unbind(config)) ) } or TPathNodeSink(Node node, Configuration config) { @@ -2129,7 +2125,7 @@ private newtype TPathNode = or // ... or a sink that can be reached from a source exists(PathNodeMid mid | - pathStep(mid, node, _, _, _, TNil(_)) and + pathStep(mid, node, _, _, TAccessPathNil(_)) and config = unbind(mid.getConfiguration()) ) ) @@ -2142,9 +2138,6 @@ private newtype TPathNode = * tracked object. The final type indicates the type of the tracked object. */ abstract private class AccessPath extends TAccessPath { - /** Gets the type of this access path. */ - abstract DataFlowType getType(); - /** Gets the head of this access path, if any. */ abstract TypedContent getHead(); @@ -2178,7 +2171,7 @@ private class AccessPathNil extends AccessPath, TAccessPathNil { AccessPathNil() { this = TAccessPathNil(t) } - override DataFlowType getType() { result = t } + DataFlowType getType() { result = t } override TypedContent getHead() { none() } @@ -2199,8 +2192,6 @@ private class AccessPathCons extends AccessPath, TAccessPathCons { AccessPathCons() { this = TAccessPathCons(head, tail) } - override DataFlowType getType() { result = tail.getType() } - override TypedContent getHead() { result = head } override AccessPath getTail() { result = tail } @@ -2216,14 +2207,16 @@ private class AccessPathCons extends AccessPath, TAccessPathCons { override int length() { result = 1 + tail.length() } private string toStringImpl() { - tail = TAccessPathNil(_) and - result = head.toString() + exists(DataFlowType t | + tail = TAccessPathNil(t) and + result = head.toString() + "]" + concat(" : " + ppReprType(t)) + ) or result = head + ", " + tail.(AccessPathCons).toStringImpl() } override string toString() { - result = "[" + this.toStringImpl() + "]" + concat(" : " + ppReprType(this.getType())) + result = "[" + this.toStringImpl() } } @@ -2340,10 +2333,9 @@ private class PathNodeMid extends PathNodeImpl, TPathNodeMid { CallContext cc; SummaryCtx sc; AccessPath ap; - AccessPathApprox apa; Configuration config; - PathNodeMid() { this = TPathNodeMid(node, cc, sc, ap, apa, config) } + PathNodeMid() { this = TPathNodeMid(node, cc, sc, ap, config) } override Node getNode() { result = node } @@ -2353,13 +2345,10 @@ private class PathNodeMid extends PathNodeImpl, TPathNodeMid { AccessPath getAp() { result = ap } - AccessPathApprox getApa() { result = apa } - override Configuration getConfiguration() { result = config } private PathNodeMid getSuccMid() { - pathStep(this, result.getNode(), result.getCallContext(), result.getSummaryCtx(), - result.getAp(), _) and + pathStep(this, result.getNode(), result.getCallContext(), result.getSummaryCtx(), result.getAp()) and result.getConfiguration() = unbind(this.getConfiguration()) } @@ -2371,7 +2360,7 @@ private class PathNodeMid extends PathNodeImpl, TPathNodeMid { exists(PathNodeMid mid, PathNodeSink sink | mid = getSuccMid() and mid.getNode() = sink.getNode() and - mid.getApa() instanceof AccessPathApproxNil and + mid.getAp() instanceof AccessPathNil and sink.getConfiguration() = unbind(mid.getConfiguration()) and result = sink ) @@ -2381,7 +2370,7 @@ private class PathNodeMid extends PathNodeImpl, TPathNodeMid { config.isSource(node) and cc instanceof CallContextAny and sc instanceof SummaryCtxNone and - apa instanceof AccessPathApproxNil + ap instanceof AccessPathNil } } @@ -2409,33 +2398,22 @@ private class PathNodeSink extends PathNodeImpl, TPathNodeSink { * Holds if data may flow from `mid` to `node`. The last step in or out of * a callable is recorded by `cc`. */ -private predicate pathStep( - PathNodeMid mid, Node node, CallContext cc, SummaryCtx sc, AccessPath ap, AccessPathApprox apa -) { +private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, SummaryCtx sc, AccessPath ap) { pathStepSameAp(mid, node, cc, sc) and - ap = mid.getAp() and - apa = mid.getApa() + ap = mid.getAp() or exists(DataFlowType t | pathStepEmptyAp(mid, node, cc, sc, t) and - ap = TAccessPathNil(t) and - apa = TNil(t) + ap = TAccessPathNil(t) ) or - exists(TypedContent tc, AccessPathApprox apa0 | - pathStoreStep(mid, node, ap.pop(tc), apa0, tc, cc) and - // Same as `apa = ap.getApprox()`, but avoids mutual recursion - apa0 = apa.pop(tc) - ) and + exists(TypedContent tc | pathStoreStep(mid, node, ap.pop(tc), tc, cc)) and sc = mid.getSummaryCtx() or exists(TypedContent tc | pathReadStep(mid, node, ap.push(tc), tc, cc)) and - sc = mid.getSummaryCtx() and - // Here the approximation cannot be created from the approximation before - // the read, so we must use `getApprox()` - apa = ap.getApprox() + sc = mid.getSummaryCtx() or - pathThroughCallable(mid, node, cc, ap, apa) and + pathThroughCallable(mid, node, cc, ap) and sc = mid.getSummaryCtx() } @@ -2504,10 +2482,9 @@ private predicate storeCand(Node node1, TypedContent tc, Node node2, Configurati pragma[nomagic] private predicate pathStoreStep( - PathNodeMid mid, Node node, AccessPath ap0, AccessPathApprox apa0, TypedContent tc, CallContext cc + PathNodeMid mid, Node node, AccessPath ap0, TypedContent tc, CallContext cc ) { ap0 = mid.getAp() and - apa0 = mid.getApa() and storeCand(mid.getNode(), tc, node, mid.getConfiguration()) and cc = mid.getCallContext() } @@ -2519,7 +2496,7 @@ private predicate pathOutOfCallable0( pos = getReturnPosition(mid.getNode()) and innercc = mid.getCallContext() and innercc instanceof CallContextNoCall and - apa = mid.getApa() and + apa = mid.getAp().getApprox() and config = mid.getConfiguration() } @@ -2570,7 +2547,7 @@ private predicate pathIntoArg( cc = mid.getCallContext() and arg.argumentOf(call, i) and ap = mid.getAp() and - apa = mid.getApa() + apa = ap.getApprox() ) } @@ -2653,7 +2630,7 @@ private predicate paramFlowsThrough( sc = mid.getSummaryCtx() and config = mid.getConfiguration() and ap = mid.getAp() and - apa = mid.getApa() and + apa = ap.getApprox() and pos = sc.getParameterPos() and not kind.(ParamUpdateReturnKind).getPosition() = pos ) @@ -2675,10 +2652,8 @@ private predicate pathThroughCallable0( * The context `cc` is restored to its value prior to entering the callable. */ pragma[noinline] -private predicate pathThroughCallable( - PathNodeMid mid, Node out, CallContext cc, AccessPath ap, AccessPathApprox apa -) { - exists(DataFlowCall call, ReturnKindExt kind | +private predicate pathThroughCallable(PathNodeMid mid, Node out, CallContext cc, AccessPath ap) { + exists(DataFlowCall call, ReturnKindExt kind, AccessPathApprox apa | pathThroughCallable0(call, mid, kind, cc, ap, apa) and out = getAnOutNodeFlow(kind, call, apa, unbind(mid.getConfiguration())) ) diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl4.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl4.qll index 04975b875b7b..77e777126c7b 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl4.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl4.qll @@ -1645,7 +1645,7 @@ private class AccessPathApproxOption extends TAccessPathApproxOption { } /** - * Holds if `node` is reachable with approximate access path `ap` from a source + * Holds if `node` is reachable with approximate access path `apa` from a source * in the configuration `config`. * * The call context `cc` records whether the node is reached through an @@ -1863,7 +1863,7 @@ private predicate flowFwdIsEntered( } /** - * Holds if `node` with approximate access path `ap` is part of a path from a + * Holds if `node` with approximate access path `apa` is part of a path from a * source to a sink in the configuration `config`. * * The Boolean `toReturn` records whether the node must be returned from @@ -2098,26 +2098,22 @@ private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome { private newtype TAccessPath = TAccessPathNil(DataFlowType t) or - TAccessPathCons(TypedContent head, AccessPath tail) { pathStoreStep(_, _, tail, _, head, _) } + TAccessPathCons(TypedContent head, AccessPath tail) { flowConsCand(head, tail.getApprox(), _) } private newtype TPathNode = - TPathNodeMid( - Node node, CallContext cc, SummaryCtx sc, AccessPath ap, AccessPathApprox apa, - Configuration config - ) { + TPathNodeMid(Node node, CallContext cc, SummaryCtx sc, AccessPath ap, Configuration config) { // A PathNode is introduced by a source ... flow(node, config) and config.isSource(node) and cc instanceof CallContextAny and sc instanceof SummaryCtxNone and - ap = TAccessPathNil(getNodeType(node)) and - apa = TNil(getNodeType(node)) + ap = TAccessPathNil(getNodeType(node)) or // ... or a step from an existing PathNode to another node. exists(PathNodeMid mid | - pathStep(mid, node, cc, sc, ap, apa) and + pathStep(mid, node, cc, sc, ap) and config = mid.getConfiguration() and - flow(node, _, _, apa, unbind(config)) + flow(node, _, _, ap.getApprox(), unbind(config)) ) } or TPathNodeSink(Node node, Configuration config) { @@ -2129,7 +2125,7 @@ private newtype TPathNode = or // ... or a sink that can be reached from a source exists(PathNodeMid mid | - pathStep(mid, node, _, _, _, TNil(_)) and + pathStep(mid, node, _, _, TAccessPathNil(_)) and config = unbind(mid.getConfiguration()) ) ) @@ -2142,9 +2138,6 @@ private newtype TPathNode = * tracked object. The final type indicates the type of the tracked object. */ abstract private class AccessPath extends TAccessPath { - /** Gets the type of this access path. */ - abstract DataFlowType getType(); - /** Gets the head of this access path, if any. */ abstract TypedContent getHead(); @@ -2178,7 +2171,7 @@ private class AccessPathNil extends AccessPath, TAccessPathNil { AccessPathNil() { this = TAccessPathNil(t) } - override DataFlowType getType() { result = t } + DataFlowType getType() { result = t } override TypedContent getHead() { none() } @@ -2199,8 +2192,6 @@ private class AccessPathCons extends AccessPath, TAccessPathCons { AccessPathCons() { this = TAccessPathCons(head, tail) } - override DataFlowType getType() { result = tail.getType() } - override TypedContent getHead() { result = head } override AccessPath getTail() { result = tail } @@ -2216,14 +2207,16 @@ private class AccessPathCons extends AccessPath, TAccessPathCons { override int length() { result = 1 + tail.length() } private string toStringImpl() { - tail = TAccessPathNil(_) and - result = head.toString() + exists(DataFlowType t | + tail = TAccessPathNil(t) and + result = head.toString() + "]" + concat(" : " + ppReprType(t)) + ) or result = head + ", " + tail.(AccessPathCons).toStringImpl() } override string toString() { - result = "[" + this.toStringImpl() + "]" + concat(" : " + ppReprType(this.getType())) + result = "[" + this.toStringImpl() } } @@ -2340,10 +2333,9 @@ private class PathNodeMid extends PathNodeImpl, TPathNodeMid { CallContext cc; SummaryCtx sc; AccessPath ap; - AccessPathApprox apa; Configuration config; - PathNodeMid() { this = TPathNodeMid(node, cc, sc, ap, apa, config) } + PathNodeMid() { this = TPathNodeMid(node, cc, sc, ap, config) } override Node getNode() { result = node } @@ -2353,13 +2345,10 @@ private class PathNodeMid extends PathNodeImpl, TPathNodeMid { AccessPath getAp() { result = ap } - AccessPathApprox getApa() { result = apa } - override Configuration getConfiguration() { result = config } private PathNodeMid getSuccMid() { - pathStep(this, result.getNode(), result.getCallContext(), result.getSummaryCtx(), - result.getAp(), _) and + pathStep(this, result.getNode(), result.getCallContext(), result.getSummaryCtx(), result.getAp()) and result.getConfiguration() = unbind(this.getConfiguration()) } @@ -2371,7 +2360,7 @@ private class PathNodeMid extends PathNodeImpl, TPathNodeMid { exists(PathNodeMid mid, PathNodeSink sink | mid = getSuccMid() and mid.getNode() = sink.getNode() and - mid.getApa() instanceof AccessPathApproxNil and + mid.getAp() instanceof AccessPathNil and sink.getConfiguration() = unbind(mid.getConfiguration()) and result = sink ) @@ -2381,7 +2370,7 @@ private class PathNodeMid extends PathNodeImpl, TPathNodeMid { config.isSource(node) and cc instanceof CallContextAny and sc instanceof SummaryCtxNone and - apa instanceof AccessPathApproxNil + ap instanceof AccessPathNil } } @@ -2409,33 +2398,22 @@ private class PathNodeSink extends PathNodeImpl, TPathNodeSink { * Holds if data may flow from `mid` to `node`. The last step in or out of * a callable is recorded by `cc`. */ -private predicate pathStep( - PathNodeMid mid, Node node, CallContext cc, SummaryCtx sc, AccessPath ap, AccessPathApprox apa -) { +private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, SummaryCtx sc, AccessPath ap) { pathStepSameAp(mid, node, cc, sc) and - ap = mid.getAp() and - apa = mid.getApa() + ap = mid.getAp() or exists(DataFlowType t | pathStepEmptyAp(mid, node, cc, sc, t) and - ap = TAccessPathNil(t) and - apa = TNil(t) + ap = TAccessPathNil(t) ) or - exists(TypedContent tc, AccessPathApprox apa0 | - pathStoreStep(mid, node, ap.pop(tc), apa0, tc, cc) and - // Same as `apa = ap.getApprox()`, but avoids mutual recursion - apa0 = apa.pop(tc) - ) and + exists(TypedContent tc | pathStoreStep(mid, node, ap.pop(tc), tc, cc)) and sc = mid.getSummaryCtx() or exists(TypedContent tc | pathReadStep(mid, node, ap.push(tc), tc, cc)) and - sc = mid.getSummaryCtx() and - // Here the approximation cannot be created from the approximation before - // the read, so we must use `getApprox()` - apa = ap.getApprox() + sc = mid.getSummaryCtx() or - pathThroughCallable(mid, node, cc, ap, apa) and + pathThroughCallable(mid, node, cc, ap) and sc = mid.getSummaryCtx() } @@ -2504,10 +2482,9 @@ private predicate storeCand(Node node1, TypedContent tc, Node node2, Configurati pragma[nomagic] private predicate pathStoreStep( - PathNodeMid mid, Node node, AccessPath ap0, AccessPathApprox apa0, TypedContent tc, CallContext cc + PathNodeMid mid, Node node, AccessPath ap0, TypedContent tc, CallContext cc ) { ap0 = mid.getAp() and - apa0 = mid.getApa() and storeCand(mid.getNode(), tc, node, mid.getConfiguration()) and cc = mid.getCallContext() } @@ -2519,7 +2496,7 @@ private predicate pathOutOfCallable0( pos = getReturnPosition(mid.getNode()) and innercc = mid.getCallContext() and innercc instanceof CallContextNoCall and - apa = mid.getApa() and + apa = mid.getAp().getApprox() and config = mid.getConfiguration() } @@ -2570,7 +2547,7 @@ private predicate pathIntoArg( cc = mid.getCallContext() and arg.argumentOf(call, i) and ap = mid.getAp() and - apa = mid.getApa() + apa = ap.getApprox() ) } @@ -2653,7 +2630,7 @@ private predicate paramFlowsThrough( sc = mid.getSummaryCtx() and config = mid.getConfiguration() and ap = mid.getAp() and - apa = mid.getApa() and + apa = ap.getApprox() and pos = sc.getParameterPos() and not kind.(ParamUpdateReturnKind).getPosition() = pos ) @@ -2675,10 +2652,8 @@ private predicate pathThroughCallable0( * The context `cc` is restored to its value prior to entering the callable. */ pragma[noinline] -private predicate pathThroughCallable( - PathNodeMid mid, Node out, CallContext cc, AccessPath ap, AccessPathApprox apa -) { - exists(DataFlowCall call, ReturnKindExt kind | +private predicate pathThroughCallable(PathNodeMid mid, Node out, CallContext cc, AccessPath ap) { + exists(DataFlowCall call, ReturnKindExt kind, AccessPathApprox apa | pathThroughCallable0(call, mid, kind, cc, ap, apa) and out = getAnOutNodeFlow(kind, call, apa, unbind(mid.getConfiguration())) ) diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl5.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl5.qll index 04975b875b7b..77e777126c7b 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl5.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl5.qll @@ -1645,7 +1645,7 @@ private class AccessPathApproxOption extends TAccessPathApproxOption { } /** - * Holds if `node` is reachable with approximate access path `ap` from a source + * Holds if `node` is reachable with approximate access path `apa` from a source * in the configuration `config`. * * The call context `cc` records whether the node is reached through an @@ -1863,7 +1863,7 @@ private predicate flowFwdIsEntered( } /** - * Holds if `node` with approximate access path `ap` is part of a path from a + * Holds if `node` with approximate access path `apa` is part of a path from a * source to a sink in the configuration `config`. * * The Boolean `toReturn` records whether the node must be returned from @@ -2098,26 +2098,22 @@ private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome { private newtype TAccessPath = TAccessPathNil(DataFlowType t) or - TAccessPathCons(TypedContent head, AccessPath tail) { pathStoreStep(_, _, tail, _, head, _) } + TAccessPathCons(TypedContent head, AccessPath tail) { flowConsCand(head, tail.getApprox(), _) } private newtype TPathNode = - TPathNodeMid( - Node node, CallContext cc, SummaryCtx sc, AccessPath ap, AccessPathApprox apa, - Configuration config - ) { + TPathNodeMid(Node node, CallContext cc, SummaryCtx sc, AccessPath ap, Configuration config) { // A PathNode is introduced by a source ... flow(node, config) and config.isSource(node) and cc instanceof CallContextAny and sc instanceof SummaryCtxNone and - ap = TAccessPathNil(getNodeType(node)) and - apa = TNil(getNodeType(node)) + ap = TAccessPathNil(getNodeType(node)) or // ... or a step from an existing PathNode to another node. exists(PathNodeMid mid | - pathStep(mid, node, cc, sc, ap, apa) and + pathStep(mid, node, cc, sc, ap) and config = mid.getConfiguration() and - flow(node, _, _, apa, unbind(config)) + flow(node, _, _, ap.getApprox(), unbind(config)) ) } or TPathNodeSink(Node node, Configuration config) { @@ -2129,7 +2125,7 @@ private newtype TPathNode = or // ... or a sink that can be reached from a source exists(PathNodeMid mid | - pathStep(mid, node, _, _, _, TNil(_)) and + pathStep(mid, node, _, _, TAccessPathNil(_)) and config = unbind(mid.getConfiguration()) ) ) @@ -2142,9 +2138,6 @@ private newtype TPathNode = * tracked object. The final type indicates the type of the tracked object. */ abstract private class AccessPath extends TAccessPath { - /** Gets the type of this access path. */ - abstract DataFlowType getType(); - /** Gets the head of this access path, if any. */ abstract TypedContent getHead(); @@ -2178,7 +2171,7 @@ private class AccessPathNil extends AccessPath, TAccessPathNil { AccessPathNil() { this = TAccessPathNil(t) } - override DataFlowType getType() { result = t } + DataFlowType getType() { result = t } override TypedContent getHead() { none() } @@ -2199,8 +2192,6 @@ private class AccessPathCons extends AccessPath, TAccessPathCons { AccessPathCons() { this = TAccessPathCons(head, tail) } - override DataFlowType getType() { result = tail.getType() } - override TypedContent getHead() { result = head } override AccessPath getTail() { result = tail } @@ -2216,14 +2207,16 @@ private class AccessPathCons extends AccessPath, TAccessPathCons { override int length() { result = 1 + tail.length() } private string toStringImpl() { - tail = TAccessPathNil(_) and - result = head.toString() + exists(DataFlowType t | + tail = TAccessPathNil(t) and + result = head.toString() + "]" + concat(" : " + ppReprType(t)) + ) or result = head + ", " + tail.(AccessPathCons).toStringImpl() } override string toString() { - result = "[" + this.toStringImpl() + "]" + concat(" : " + ppReprType(this.getType())) + result = "[" + this.toStringImpl() } } @@ -2340,10 +2333,9 @@ private class PathNodeMid extends PathNodeImpl, TPathNodeMid { CallContext cc; SummaryCtx sc; AccessPath ap; - AccessPathApprox apa; Configuration config; - PathNodeMid() { this = TPathNodeMid(node, cc, sc, ap, apa, config) } + PathNodeMid() { this = TPathNodeMid(node, cc, sc, ap, config) } override Node getNode() { result = node } @@ -2353,13 +2345,10 @@ private class PathNodeMid extends PathNodeImpl, TPathNodeMid { AccessPath getAp() { result = ap } - AccessPathApprox getApa() { result = apa } - override Configuration getConfiguration() { result = config } private PathNodeMid getSuccMid() { - pathStep(this, result.getNode(), result.getCallContext(), result.getSummaryCtx(), - result.getAp(), _) and + pathStep(this, result.getNode(), result.getCallContext(), result.getSummaryCtx(), result.getAp()) and result.getConfiguration() = unbind(this.getConfiguration()) } @@ -2371,7 +2360,7 @@ private class PathNodeMid extends PathNodeImpl, TPathNodeMid { exists(PathNodeMid mid, PathNodeSink sink | mid = getSuccMid() and mid.getNode() = sink.getNode() and - mid.getApa() instanceof AccessPathApproxNil and + mid.getAp() instanceof AccessPathNil and sink.getConfiguration() = unbind(mid.getConfiguration()) and result = sink ) @@ -2381,7 +2370,7 @@ private class PathNodeMid extends PathNodeImpl, TPathNodeMid { config.isSource(node) and cc instanceof CallContextAny and sc instanceof SummaryCtxNone and - apa instanceof AccessPathApproxNil + ap instanceof AccessPathNil } } @@ -2409,33 +2398,22 @@ private class PathNodeSink extends PathNodeImpl, TPathNodeSink { * Holds if data may flow from `mid` to `node`. The last step in or out of * a callable is recorded by `cc`. */ -private predicate pathStep( - PathNodeMid mid, Node node, CallContext cc, SummaryCtx sc, AccessPath ap, AccessPathApprox apa -) { +private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, SummaryCtx sc, AccessPath ap) { pathStepSameAp(mid, node, cc, sc) and - ap = mid.getAp() and - apa = mid.getApa() + ap = mid.getAp() or exists(DataFlowType t | pathStepEmptyAp(mid, node, cc, sc, t) and - ap = TAccessPathNil(t) and - apa = TNil(t) + ap = TAccessPathNil(t) ) or - exists(TypedContent tc, AccessPathApprox apa0 | - pathStoreStep(mid, node, ap.pop(tc), apa0, tc, cc) and - // Same as `apa = ap.getApprox()`, but avoids mutual recursion - apa0 = apa.pop(tc) - ) and + exists(TypedContent tc | pathStoreStep(mid, node, ap.pop(tc), tc, cc)) and sc = mid.getSummaryCtx() or exists(TypedContent tc | pathReadStep(mid, node, ap.push(tc), tc, cc)) and - sc = mid.getSummaryCtx() and - // Here the approximation cannot be created from the approximation before - // the read, so we must use `getApprox()` - apa = ap.getApprox() + sc = mid.getSummaryCtx() or - pathThroughCallable(mid, node, cc, ap, apa) and + pathThroughCallable(mid, node, cc, ap) and sc = mid.getSummaryCtx() } @@ -2504,10 +2482,9 @@ private predicate storeCand(Node node1, TypedContent tc, Node node2, Configurati pragma[nomagic] private predicate pathStoreStep( - PathNodeMid mid, Node node, AccessPath ap0, AccessPathApprox apa0, TypedContent tc, CallContext cc + PathNodeMid mid, Node node, AccessPath ap0, TypedContent tc, CallContext cc ) { ap0 = mid.getAp() and - apa0 = mid.getApa() and storeCand(mid.getNode(), tc, node, mid.getConfiguration()) and cc = mid.getCallContext() } @@ -2519,7 +2496,7 @@ private predicate pathOutOfCallable0( pos = getReturnPosition(mid.getNode()) and innercc = mid.getCallContext() and innercc instanceof CallContextNoCall and - apa = mid.getApa() and + apa = mid.getAp().getApprox() and config = mid.getConfiguration() } @@ -2570,7 +2547,7 @@ private predicate pathIntoArg( cc = mid.getCallContext() and arg.argumentOf(call, i) and ap = mid.getAp() and - apa = mid.getApa() + apa = ap.getApprox() ) } @@ -2653,7 +2630,7 @@ private predicate paramFlowsThrough( sc = mid.getSummaryCtx() and config = mid.getConfiguration() and ap = mid.getAp() and - apa = mid.getApa() and + apa = ap.getApprox() and pos = sc.getParameterPos() and not kind.(ParamUpdateReturnKind).getPosition() = pos ) @@ -2675,10 +2652,8 @@ private predicate pathThroughCallable0( * The context `cc` is restored to its value prior to entering the callable. */ pragma[noinline] -private predicate pathThroughCallable( - PathNodeMid mid, Node out, CallContext cc, AccessPath ap, AccessPathApprox apa -) { - exists(DataFlowCall call, ReturnKindExt kind | +private predicate pathThroughCallable(PathNodeMid mid, Node out, CallContext cc, AccessPath ap) { + exists(DataFlowCall call, ReturnKindExt kind, AccessPathApprox apa | pathThroughCallable0(call, mid, kind, cc, ap, apa) and out = getAnOutNodeFlow(kind, call, apa, unbind(mid.getConfiguration())) ) diff --git a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl2.qll b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl2.qll index 04975b875b7b..77e777126c7b 100644 --- a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl2.qll +++ b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl2.qll @@ -1645,7 +1645,7 @@ private class AccessPathApproxOption extends TAccessPathApproxOption { } /** - * Holds if `node` is reachable with approximate access path `ap` from a source + * Holds if `node` is reachable with approximate access path `apa` from a source * in the configuration `config`. * * The call context `cc` records whether the node is reached through an @@ -1863,7 +1863,7 @@ private predicate flowFwdIsEntered( } /** - * Holds if `node` with approximate access path `ap` is part of a path from a + * Holds if `node` with approximate access path `apa` is part of a path from a * source to a sink in the configuration `config`. * * The Boolean `toReturn` records whether the node must be returned from @@ -2098,26 +2098,22 @@ private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome { private newtype TAccessPath = TAccessPathNil(DataFlowType t) or - TAccessPathCons(TypedContent head, AccessPath tail) { pathStoreStep(_, _, tail, _, head, _) } + TAccessPathCons(TypedContent head, AccessPath tail) { flowConsCand(head, tail.getApprox(), _) } private newtype TPathNode = - TPathNodeMid( - Node node, CallContext cc, SummaryCtx sc, AccessPath ap, AccessPathApprox apa, - Configuration config - ) { + TPathNodeMid(Node node, CallContext cc, SummaryCtx sc, AccessPath ap, Configuration config) { // A PathNode is introduced by a source ... flow(node, config) and config.isSource(node) and cc instanceof CallContextAny and sc instanceof SummaryCtxNone and - ap = TAccessPathNil(getNodeType(node)) and - apa = TNil(getNodeType(node)) + ap = TAccessPathNil(getNodeType(node)) or // ... or a step from an existing PathNode to another node. exists(PathNodeMid mid | - pathStep(mid, node, cc, sc, ap, apa) and + pathStep(mid, node, cc, sc, ap) and config = mid.getConfiguration() and - flow(node, _, _, apa, unbind(config)) + flow(node, _, _, ap.getApprox(), unbind(config)) ) } or TPathNodeSink(Node node, Configuration config) { @@ -2129,7 +2125,7 @@ private newtype TPathNode = or // ... or a sink that can be reached from a source exists(PathNodeMid mid | - pathStep(mid, node, _, _, _, TNil(_)) and + pathStep(mid, node, _, _, TAccessPathNil(_)) and config = unbind(mid.getConfiguration()) ) ) @@ -2142,9 +2138,6 @@ private newtype TPathNode = * tracked object. The final type indicates the type of the tracked object. */ abstract private class AccessPath extends TAccessPath { - /** Gets the type of this access path. */ - abstract DataFlowType getType(); - /** Gets the head of this access path, if any. */ abstract TypedContent getHead(); @@ -2178,7 +2171,7 @@ private class AccessPathNil extends AccessPath, TAccessPathNil { AccessPathNil() { this = TAccessPathNil(t) } - override DataFlowType getType() { result = t } + DataFlowType getType() { result = t } override TypedContent getHead() { none() } @@ -2199,8 +2192,6 @@ private class AccessPathCons extends AccessPath, TAccessPathCons { AccessPathCons() { this = TAccessPathCons(head, tail) } - override DataFlowType getType() { result = tail.getType() } - override TypedContent getHead() { result = head } override AccessPath getTail() { result = tail } @@ -2216,14 +2207,16 @@ private class AccessPathCons extends AccessPath, TAccessPathCons { override int length() { result = 1 + tail.length() } private string toStringImpl() { - tail = TAccessPathNil(_) and - result = head.toString() + exists(DataFlowType t | + tail = TAccessPathNil(t) and + result = head.toString() + "]" + concat(" : " + ppReprType(t)) + ) or result = head + ", " + tail.(AccessPathCons).toStringImpl() } override string toString() { - result = "[" + this.toStringImpl() + "]" + concat(" : " + ppReprType(this.getType())) + result = "[" + this.toStringImpl() } } @@ -2340,10 +2333,9 @@ private class PathNodeMid extends PathNodeImpl, TPathNodeMid { CallContext cc; SummaryCtx sc; AccessPath ap; - AccessPathApprox apa; Configuration config; - PathNodeMid() { this = TPathNodeMid(node, cc, sc, ap, apa, config) } + PathNodeMid() { this = TPathNodeMid(node, cc, sc, ap, config) } override Node getNode() { result = node } @@ -2353,13 +2345,10 @@ private class PathNodeMid extends PathNodeImpl, TPathNodeMid { AccessPath getAp() { result = ap } - AccessPathApprox getApa() { result = apa } - override Configuration getConfiguration() { result = config } private PathNodeMid getSuccMid() { - pathStep(this, result.getNode(), result.getCallContext(), result.getSummaryCtx(), - result.getAp(), _) and + pathStep(this, result.getNode(), result.getCallContext(), result.getSummaryCtx(), result.getAp()) and result.getConfiguration() = unbind(this.getConfiguration()) } @@ -2371,7 +2360,7 @@ private class PathNodeMid extends PathNodeImpl, TPathNodeMid { exists(PathNodeMid mid, PathNodeSink sink | mid = getSuccMid() and mid.getNode() = sink.getNode() and - mid.getApa() instanceof AccessPathApproxNil and + mid.getAp() instanceof AccessPathNil and sink.getConfiguration() = unbind(mid.getConfiguration()) and result = sink ) @@ -2381,7 +2370,7 @@ private class PathNodeMid extends PathNodeImpl, TPathNodeMid { config.isSource(node) and cc instanceof CallContextAny and sc instanceof SummaryCtxNone and - apa instanceof AccessPathApproxNil + ap instanceof AccessPathNil } } @@ -2409,33 +2398,22 @@ private class PathNodeSink extends PathNodeImpl, TPathNodeSink { * Holds if data may flow from `mid` to `node`. The last step in or out of * a callable is recorded by `cc`. */ -private predicate pathStep( - PathNodeMid mid, Node node, CallContext cc, SummaryCtx sc, AccessPath ap, AccessPathApprox apa -) { +private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, SummaryCtx sc, AccessPath ap) { pathStepSameAp(mid, node, cc, sc) and - ap = mid.getAp() and - apa = mid.getApa() + ap = mid.getAp() or exists(DataFlowType t | pathStepEmptyAp(mid, node, cc, sc, t) and - ap = TAccessPathNil(t) and - apa = TNil(t) + ap = TAccessPathNil(t) ) or - exists(TypedContent tc, AccessPathApprox apa0 | - pathStoreStep(mid, node, ap.pop(tc), apa0, tc, cc) and - // Same as `apa = ap.getApprox()`, but avoids mutual recursion - apa0 = apa.pop(tc) - ) and + exists(TypedContent tc | pathStoreStep(mid, node, ap.pop(tc), tc, cc)) and sc = mid.getSummaryCtx() or exists(TypedContent tc | pathReadStep(mid, node, ap.push(tc), tc, cc)) and - sc = mid.getSummaryCtx() and - // Here the approximation cannot be created from the approximation before - // the read, so we must use `getApprox()` - apa = ap.getApprox() + sc = mid.getSummaryCtx() or - pathThroughCallable(mid, node, cc, ap, apa) and + pathThroughCallable(mid, node, cc, ap) and sc = mid.getSummaryCtx() } @@ -2504,10 +2482,9 @@ private predicate storeCand(Node node1, TypedContent tc, Node node2, Configurati pragma[nomagic] private predicate pathStoreStep( - PathNodeMid mid, Node node, AccessPath ap0, AccessPathApprox apa0, TypedContent tc, CallContext cc + PathNodeMid mid, Node node, AccessPath ap0, TypedContent tc, CallContext cc ) { ap0 = mid.getAp() and - apa0 = mid.getApa() and storeCand(mid.getNode(), tc, node, mid.getConfiguration()) and cc = mid.getCallContext() } @@ -2519,7 +2496,7 @@ private predicate pathOutOfCallable0( pos = getReturnPosition(mid.getNode()) and innercc = mid.getCallContext() and innercc instanceof CallContextNoCall and - apa = mid.getApa() and + apa = mid.getAp().getApprox() and config = mid.getConfiguration() } @@ -2570,7 +2547,7 @@ private predicate pathIntoArg( cc = mid.getCallContext() and arg.argumentOf(call, i) and ap = mid.getAp() and - apa = mid.getApa() + apa = ap.getApprox() ) } @@ -2653,7 +2630,7 @@ private predicate paramFlowsThrough( sc = mid.getSummaryCtx() and config = mid.getConfiguration() and ap = mid.getAp() and - apa = mid.getApa() and + apa = ap.getApprox() and pos = sc.getParameterPos() and not kind.(ParamUpdateReturnKind).getPosition() = pos ) @@ -2675,10 +2652,8 @@ private predicate pathThroughCallable0( * The context `cc` is restored to its value prior to entering the callable. */ pragma[noinline] -private predicate pathThroughCallable( - PathNodeMid mid, Node out, CallContext cc, AccessPath ap, AccessPathApprox apa -) { - exists(DataFlowCall call, ReturnKindExt kind | +private predicate pathThroughCallable(PathNodeMid mid, Node out, CallContext cc, AccessPath ap) { + exists(DataFlowCall call, ReturnKindExt kind, AccessPathApprox apa | pathThroughCallable0(call, mid, kind, cc, ap, apa) and out = getAnOutNodeFlow(kind, call, apa, unbind(mid.getConfiguration())) ) diff --git a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl3.qll b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl3.qll index 04975b875b7b..77e777126c7b 100644 --- a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl3.qll +++ b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl3.qll @@ -1645,7 +1645,7 @@ private class AccessPathApproxOption extends TAccessPathApproxOption { } /** - * Holds if `node` is reachable with approximate access path `ap` from a source + * Holds if `node` is reachable with approximate access path `apa` from a source * in the configuration `config`. * * The call context `cc` records whether the node is reached through an @@ -1863,7 +1863,7 @@ private predicate flowFwdIsEntered( } /** - * Holds if `node` with approximate access path `ap` is part of a path from a + * Holds if `node` with approximate access path `apa` is part of a path from a * source to a sink in the configuration `config`. * * The Boolean `toReturn` records whether the node must be returned from @@ -2098,26 +2098,22 @@ private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome { private newtype TAccessPath = TAccessPathNil(DataFlowType t) or - TAccessPathCons(TypedContent head, AccessPath tail) { pathStoreStep(_, _, tail, _, head, _) } + TAccessPathCons(TypedContent head, AccessPath tail) { flowConsCand(head, tail.getApprox(), _) } private newtype TPathNode = - TPathNodeMid( - Node node, CallContext cc, SummaryCtx sc, AccessPath ap, AccessPathApprox apa, - Configuration config - ) { + TPathNodeMid(Node node, CallContext cc, SummaryCtx sc, AccessPath ap, Configuration config) { // A PathNode is introduced by a source ... flow(node, config) and config.isSource(node) and cc instanceof CallContextAny and sc instanceof SummaryCtxNone and - ap = TAccessPathNil(getNodeType(node)) and - apa = TNil(getNodeType(node)) + ap = TAccessPathNil(getNodeType(node)) or // ... or a step from an existing PathNode to another node. exists(PathNodeMid mid | - pathStep(mid, node, cc, sc, ap, apa) and + pathStep(mid, node, cc, sc, ap) and config = mid.getConfiguration() and - flow(node, _, _, apa, unbind(config)) + flow(node, _, _, ap.getApprox(), unbind(config)) ) } or TPathNodeSink(Node node, Configuration config) { @@ -2129,7 +2125,7 @@ private newtype TPathNode = or // ... or a sink that can be reached from a source exists(PathNodeMid mid | - pathStep(mid, node, _, _, _, TNil(_)) and + pathStep(mid, node, _, _, TAccessPathNil(_)) and config = unbind(mid.getConfiguration()) ) ) @@ -2142,9 +2138,6 @@ private newtype TPathNode = * tracked object. The final type indicates the type of the tracked object. */ abstract private class AccessPath extends TAccessPath { - /** Gets the type of this access path. */ - abstract DataFlowType getType(); - /** Gets the head of this access path, if any. */ abstract TypedContent getHead(); @@ -2178,7 +2171,7 @@ private class AccessPathNil extends AccessPath, TAccessPathNil { AccessPathNil() { this = TAccessPathNil(t) } - override DataFlowType getType() { result = t } + DataFlowType getType() { result = t } override TypedContent getHead() { none() } @@ -2199,8 +2192,6 @@ private class AccessPathCons extends AccessPath, TAccessPathCons { AccessPathCons() { this = TAccessPathCons(head, tail) } - override DataFlowType getType() { result = tail.getType() } - override TypedContent getHead() { result = head } override AccessPath getTail() { result = tail } @@ -2216,14 +2207,16 @@ private class AccessPathCons extends AccessPath, TAccessPathCons { override int length() { result = 1 + tail.length() } private string toStringImpl() { - tail = TAccessPathNil(_) and - result = head.toString() + exists(DataFlowType t | + tail = TAccessPathNil(t) and + result = head.toString() + "]" + concat(" : " + ppReprType(t)) + ) or result = head + ", " + tail.(AccessPathCons).toStringImpl() } override string toString() { - result = "[" + this.toStringImpl() + "]" + concat(" : " + ppReprType(this.getType())) + result = "[" + this.toStringImpl() } } @@ -2340,10 +2333,9 @@ private class PathNodeMid extends PathNodeImpl, TPathNodeMid { CallContext cc; SummaryCtx sc; AccessPath ap; - AccessPathApprox apa; Configuration config; - PathNodeMid() { this = TPathNodeMid(node, cc, sc, ap, apa, config) } + PathNodeMid() { this = TPathNodeMid(node, cc, sc, ap, config) } override Node getNode() { result = node } @@ -2353,13 +2345,10 @@ private class PathNodeMid extends PathNodeImpl, TPathNodeMid { AccessPath getAp() { result = ap } - AccessPathApprox getApa() { result = apa } - override Configuration getConfiguration() { result = config } private PathNodeMid getSuccMid() { - pathStep(this, result.getNode(), result.getCallContext(), result.getSummaryCtx(), - result.getAp(), _) and + pathStep(this, result.getNode(), result.getCallContext(), result.getSummaryCtx(), result.getAp()) and result.getConfiguration() = unbind(this.getConfiguration()) } @@ -2371,7 +2360,7 @@ private class PathNodeMid extends PathNodeImpl, TPathNodeMid { exists(PathNodeMid mid, PathNodeSink sink | mid = getSuccMid() and mid.getNode() = sink.getNode() and - mid.getApa() instanceof AccessPathApproxNil and + mid.getAp() instanceof AccessPathNil and sink.getConfiguration() = unbind(mid.getConfiguration()) and result = sink ) @@ -2381,7 +2370,7 @@ private class PathNodeMid extends PathNodeImpl, TPathNodeMid { config.isSource(node) and cc instanceof CallContextAny and sc instanceof SummaryCtxNone and - apa instanceof AccessPathApproxNil + ap instanceof AccessPathNil } } @@ -2409,33 +2398,22 @@ private class PathNodeSink extends PathNodeImpl, TPathNodeSink { * Holds if data may flow from `mid` to `node`. The last step in or out of * a callable is recorded by `cc`. */ -private predicate pathStep( - PathNodeMid mid, Node node, CallContext cc, SummaryCtx sc, AccessPath ap, AccessPathApprox apa -) { +private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, SummaryCtx sc, AccessPath ap) { pathStepSameAp(mid, node, cc, sc) and - ap = mid.getAp() and - apa = mid.getApa() + ap = mid.getAp() or exists(DataFlowType t | pathStepEmptyAp(mid, node, cc, sc, t) and - ap = TAccessPathNil(t) and - apa = TNil(t) + ap = TAccessPathNil(t) ) or - exists(TypedContent tc, AccessPathApprox apa0 | - pathStoreStep(mid, node, ap.pop(tc), apa0, tc, cc) and - // Same as `apa = ap.getApprox()`, but avoids mutual recursion - apa0 = apa.pop(tc) - ) and + exists(TypedContent tc | pathStoreStep(mid, node, ap.pop(tc), tc, cc)) and sc = mid.getSummaryCtx() or exists(TypedContent tc | pathReadStep(mid, node, ap.push(tc), tc, cc)) and - sc = mid.getSummaryCtx() and - // Here the approximation cannot be created from the approximation before - // the read, so we must use `getApprox()` - apa = ap.getApprox() + sc = mid.getSummaryCtx() or - pathThroughCallable(mid, node, cc, ap, apa) and + pathThroughCallable(mid, node, cc, ap) and sc = mid.getSummaryCtx() } @@ -2504,10 +2482,9 @@ private predicate storeCand(Node node1, TypedContent tc, Node node2, Configurati pragma[nomagic] private predicate pathStoreStep( - PathNodeMid mid, Node node, AccessPath ap0, AccessPathApprox apa0, TypedContent tc, CallContext cc + PathNodeMid mid, Node node, AccessPath ap0, TypedContent tc, CallContext cc ) { ap0 = mid.getAp() and - apa0 = mid.getApa() and storeCand(mid.getNode(), tc, node, mid.getConfiguration()) and cc = mid.getCallContext() } @@ -2519,7 +2496,7 @@ private predicate pathOutOfCallable0( pos = getReturnPosition(mid.getNode()) and innercc = mid.getCallContext() and innercc instanceof CallContextNoCall and - apa = mid.getApa() and + apa = mid.getAp().getApprox() and config = mid.getConfiguration() } @@ -2570,7 +2547,7 @@ private predicate pathIntoArg( cc = mid.getCallContext() and arg.argumentOf(call, i) and ap = mid.getAp() and - apa = mid.getApa() + apa = ap.getApprox() ) } @@ -2653,7 +2630,7 @@ private predicate paramFlowsThrough( sc = mid.getSummaryCtx() and config = mid.getConfiguration() and ap = mid.getAp() and - apa = mid.getApa() and + apa = ap.getApprox() and pos = sc.getParameterPos() and not kind.(ParamUpdateReturnKind).getPosition() = pos ) @@ -2675,10 +2652,8 @@ private predicate pathThroughCallable0( * The context `cc` is restored to its value prior to entering the callable. */ pragma[noinline] -private predicate pathThroughCallable( - PathNodeMid mid, Node out, CallContext cc, AccessPath ap, AccessPathApprox apa -) { - exists(DataFlowCall call, ReturnKindExt kind | +private predicate pathThroughCallable(PathNodeMid mid, Node out, CallContext cc, AccessPath ap) { + exists(DataFlowCall call, ReturnKindExt kind, AccessPathApprox apa | pathThroughCallable0(call, mid, kind, cc, ap, apa) and out = getAnOutNodeFlow(kind, call, apa, unbind(mid.getConfiguration())) ) diff --git a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl4.qll b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl4.qll index 04975b875b7b..77e777126c7b 100644 --- a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl4.qll +++ b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl4.qll @@ -1645,7 +1645,7 @@ private class AccessPathApproxOption extends TAccessPathApproxOption { } /** - * Holds if `node` is reachable with approximate access path `ap` from a source + * Holds if `node` is reachable with approximate access path `apa` from a source * in the configuration `config`. * * The call context `cc` records whether the node is reached through an @@ -1863,7 +1863,7 @@ private predicate flowFwdIsEntered( } /** - * Holds if `node` with approximate access path `ap` is part of a path from a + * Holds if `node` with approximate access path `apa` is part of a path from a * source to a sink in the configuration `config`. * * The Boolean `toReturn` records whether the node must be returned from @@ -2098,26 +2098,22 @@ private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome { private newtype TAccessPath = TAccessPathNil(DataFlowType t) or - TAccessPathCons(TypedContent head, AccessPath tail) { pathStoreStep(_, _, tail, _, head, _) } + TAccessPathCons(TypedContent head, AccessPath tail) { flowConsCand(head, tail.getApprox(), _) } private newtype TPathNode = - TPathNodeMid( - Node node, CallContext cc, SummaryCtx sc, AccessPath ap, AccessPathApprox apa, - Configuration config - ) { + TPathNodeMid(Node node, CallContext cc, SummaryCtx sc, AccessPath ap, Configuration config) { // A PathNode is introduced by a source ... flow(node, config) and config.isSource(node) and cc instanceof CallContextAny and sc instanceof SummaryCtxNone and - ap = TAccessPathNil(getNodeType(node)) and - apa = TNil(getNodeType(node)) + ap = TAccessPathNil(getNodeType(node)) or // ... or a step from an existing PathNode to another node. exists(PathNodeMid mid | - pathStep(mid, node, cc, sc, ap, apa) and + pathStep(mid, node, cc, sc, ap) and config = mid.getConfiguration() and - flow(node, _, _, apa, unbind(config)) + flow(node, _, _, ap.getApprox(), unbind(config)) ) } or TPathNodeSink(Node node, Configuration config) { @@ -2129,7 +2125,7 @@ private newtype TPathNode = or // ... or a sink that can be reached from a source exists(PathNodeMid mid | - pathStep(mid, node, _, _, _, TNil(_)) and + pathStep(mid, node, _, _, TAccessPathNil(_)) and config = unbind(mid.getConfiguration()) ) ) @@ -2142,9 +2138,6 @@ private newtype TPathNode = * tracked object. The final type indicates the type of the tracked object. */ abstract private class AccessPath extends TAccessPath { - /** Gets the type of this access path. */ - abstract DataFlowType getType(); - /** Gets the head of this access path, if any. */ abstract TypedContent getHead(); @@ -2178,7 +2171,7 @@ private class AccessPathNil extends AccessPath, TAccessPathNil { AccessPathNil() { this = TAccessPathNil(t) } - override DataFlowType getType() { result = t } + DataFlowType getType() { result = t } override TypedContent getHead() { none() } @@ -2199,8 +2192,6 @@ private class AccessPathCons extends AccessPath, TAccessPathCons { AccessPathCons() { this = TAccessPathCons(head, tail) } - override DataFlowType getType() { result = tail.getType() } - override TypedContent getHead() { result = head } override AccessPath getTail() { result = tail } @@ -2216,14 +2207,16 @@ private class AccessPathCons extends AccessPath, TAccessPathCons { override int length() { result = 1 + tail.length() } private string toStringImpl() { - tail = TAccessPathNil(_) and - result = head.toString() + exists(DataFlowType t | + tail = TAccessPathNil(t) and + result = head.toString() + "]" + concat(" : " + ppReprType(t)) + ) or result = head + ", " + tail.(AccessPathCons).toStringImpl() } override string toString() { - result = "[" + this.toStringImpl() + "]" + concat(" : " + ppReprType(this.getType())) + result = "[" + this.toStringImpl() } } @@ -2340,10 +2333,9 @@ private class PathNodeMid extends PathNodeImpl, TPathNodeMid { CallContext cc; SummaryCtx sc; AccessPath ap; - AccessPathApprox apa; Configuration config; - PathNodeMid() { this = TPathNodeMid(node, cc, sc, ap, apa, config) } + PathNodeMid() { this = TPathNodeMid(node, cc, sc, ap, config) } override Node getNode() { result = node } @@ -2353,13 +2345,10 @@ private class PathNodeMid extends PathNodeImpl, TPathNodeMid { AccessPath getAp() { result = ap } - AccessPathApprox getApa() { result = apa } - override Configuration getConfiguration() { result = config } private PathNodeMid getSuccMid() { - pathStep(this, result.getNode(), result.getCallContext(), result.getSummaryCtx(), - result.getAp(), _) and + pathStep(this, result.getNode(), result.getCallContext(), result.getSummaryCtx(), result.getAp()) and result.getConfiguration() = unbind(this.getConfiguration()) } @@ -2371,7 +2360,7 @@ private class PathNodeMid extends PathNodeImpl, TPathNodeMid { exists(PathNodeMid mid, PathNodeSink sink | mid = getSuccMid() and mid.getNode() = sink.getNode() and - mid.getApa() instanceof AccessPathApproxNil and + mid.getAp() instanceof AccessPathNil and sink.getConfiguration() = unbind(mid.getConfiguration()) and result = sink ) @@ -2381,7 +2370,7 @@ private class PathNodeMid extends PathNodeImpl, TPathNodeMid { config.isSource(node) and cc instanceof CallContextAny and sc instanceof SummaryCtxNone and - apa instanceof AccessPathApproxNil + ap instanceof AccessPathNil } } @@ -2409,33 +2398,22 @@ private class PathNodeSink extends PathNodeImpl, TPathNodeSink { * Holds if data may flow from `mid` to `node`. The last step in or out of * a callable is recorded by `cc`. */ -private predicate pathStep( - PathNodeMid mid, Node node, CallContext cc, SummaryCtx sc, AccessPath ap, AccessPathApprox apa -) { +private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, SummaryCtx sc, AccessPath ap) { pathStepSameAp(mid, node, cc, sc) and - ap = mid.getAp() and - apa = mid.getApa() + ap = mid.getAp() or exists(DataFlowType t | pathStepEmptyAp(mid, node, cc, sc, t) and - ap = TAccessPathNil(t) and - apa = TNil(t) + ap = TAccessPathNil(t) ) or - exists(TypedContent tc, AccessPathApprox apa0 | - pathStoreStep(mid, node, ap.pop(tc), apa0, tc, cc) and - // Same as `apa = ap.getApprox()`, but avoids mutual recursion - apa0 = apa.pop(tc) - ) and + exists(TypedContent tc | pathStoreStep(mid, node, ap.pop(tc), tc, cc)) and sc = mid.getSummaryCtx() or exists(TypedContent tc | pathReadStep(mid, node, ap.push(tc), tc, cc)) and - sc = mid.getSummaryCtx() and - // Here the approximation cannot be created from the approximation before - // the read, so we must use `getApprox()` - apa = ap.getApprox() + sc = mid.getSummaryCtx() or - pathThroughCallable(mid, node, cc, ap, apa) and + pathThroughCallable(mid, node, cc, ap) and sc = mid.getSummaryCtx() } @@ -2504,10 +2482,9 @@ private predicate storeCand(Node node1, TypedContent tc, Node node2, Configurati pragma[nomagic] private predicate pathStoreStep( - PathNodeMid mid, Node node, AccessPath ap0, AccessPathApprox apa0, TypedContent tc, CallContext cc + PathNodeMid mid, Node node, AccessPath ap0, TypedContent tc, CallContext cc ) { ap0 = mid.getAp() and - apa0 = mid.getApa() and storeCand(mid.getNode(), tc, node, mid.getConfiguration()) and cc = mid.getCallContext() } @@ -2519,7 +2496,7 @@ private predicate pathOutOfCallable0( pos = getReturnPosition(mid.getNode()) and innercc = mid.getCallContext() and innercc instanceof CallContextNoCall and - apa = mid.getApa() and + apa = mid.getAp().getApprox() and config = mid.getConfiguration() } @@ -2570,7 +2547,7 @@ private predicate pathIntoArg( cc = mid.getCallContext() and arg.argumentOf(call, i) and ap = mid.getAp() and - apa = mid.getApa() + apa = ap.getApprox() ) } @@ -2653,7 +2630,7 @@ private predicate paramFlowsThrough( sc = mid.getSummaryCtx() and config = mid.getConfiguration() and ap = mid.getAp() and - apa = mid.getApa() and + apa = ap.getApprox() and pos = sc.getParameterPos() and not kind.(ParamUpdateReturnKind).getPosition() = pos ) @@ -2675,10 +2652,8 @@ private predicate pathThroughCallable0( * The context `cc` is restored to its value prior to entering the callable. */ pragma[noinline] -private predicate pathThroughCallable( - PathNodeMid mid, Node out, CallContext cc, AccessPath ap, AccessPathApprox apa -) { - exists(DataFlowCall call, ReturnKindExt kind | +private predicate pathThroughCallable(PathNodeMid mid, Node out, CallContext cc, AccessPath ap) { + exists(DataFlowCall call, ReturnKindExt kind, AccessPathApprox apa | pathThroughCallable0(call, mid, kind, cc, ap, apa) and out = getAnOutNodeFlow(kind, call, apa, unbind(mid.getConfiguration())) ) diff --git a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl5.qll b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl5.qll index 04975b875b7b..77e777126c7b 100644 --- a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl5.qll +++ b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl5.qll @@ -1645,7 +1645,7 @@ private class AccessPathApproxOption extends TAccessPathApproxOption { } /** - * Holds if `node` is reachable with approximate access path `ap` from a source + * Holds if `node` is reachable with approximate access path `apa` from a source * in the configuration `config`. * * The call context `cc` records whether the node is reached through an @@ -1863,7 +1863,7 @@ private predicate flowFwdIsEntered( } /** - * Holds if `node` with approximate access path `ap` is part of a path from a + * Holds if `node` with approximate access path `apa` is part of a path from a * source to a sink in the configuration `config`. * * The Boolean `toReturn` records whether the node must be returned from @@ -2098,26 +2098,22 @@ private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome { private newtype TAccessPath = TAccessPathNil(DataFlowType t) or - TAccessPathCons(TypedContent head, AccessPath tail) { pathStoreStep(_, _, tail, _, head, _) } + TAccessPathCons(TypedContent head, AccessPath tail) { flowConsCand(head, tail.getApprox(), _) } private newtype TPathNode = - TPathNodeMid( - Node node, CallContext cc, SummaryCtx sc, AccessPath ap, AccessPathApprox apa, - Configuration config - ) { + TPathNodeMid(Node node, CallContext cc, SummaryCtx sc, AccessPath ap, Configuration config) { // A PathNode is introduced by a source ... flow(node, config) and config.isSource(node) and cc instanceof CallContextAny and sc instanceof SummaryCtxNone and - ap = TAccessPathNil(getNodeType(node)) and - apa = TNil(getNodeType(node)) + ap = TAccessPathNil(getNodeType(node)) or // ... or a step from an existing PathNode to another node. exists(PathNodeMid mid | - pathStep(mid, node, cc, sc, ap, apa) and + pathStep(mid, node, cc, sc, ap) and config = mid.getConfiguration() and - flow(node, _, _, apa, unbind(config)) + flow(node, _, _, ap.getApprox(), unbind(config)) ) } or TPathNodeSink(Node node, Configuration config) { @@ -2129,7 +2125,7 @@ private newtype TPathNode = or // ... or a sink that can be reached from a source exists(PathNodeMid mid | - pathStep(mid, node, _, _, _, TNil(_)) and + pathStep(mid, node, _, _, TAccessPathNil(_)) and config = unbind(mid.getConfiguration()) ) ) @@ -2142,9 +2138,6 @@ private newtype TPathNode = * tracked object. The final type indicates the type of the tracked object. */ abstract private class AccessPath extends TAccessPath { - /** Gets the type of this access path. */ - abstract DataFlowType getType(); - /** Gets the head of this access path, if any. */ abstract TypedContent getHead(); @@ -2178,7 +2171,7 @@ private class AccessPathNil extends AccessPath, TAccessPathNil { AccessPathNil() { this = TAccessPathNil(t) } - override DataFlowType getType() { result = t } + DataFlowType getType() { result = t } override TypedContent getHead() { none() } @@ -2199,8 +2192,6 @@ private class AccessPathCons extends AccessPath, TAccessPathCons { AccessPathCons() { this = TAccessPathCons(head, tail) } - override DataFlowType getType() { result = tail.getType() } - override TypedContent getHead() { result = head } override AccessPath getTail() { result = tail } @@ -2216,14 +2207,16 @@ private class AccessPathCons extends AccessPath, TAccessPathCons { override int length() { result = 1 + tail.length() } private string toStringImpl() { - tail = TAccessPathNil(_) and - result = head.toString() + exists(DataFlowType t | + tail = TAccessPathNil(t) and + result = head.toString() + "]" + concat(" : " + ppReprType(t)) + ) or result = head + ", " + tail.(AccessPathCons).toStringImpl() } override string toString() { - result = "[" + this.toStringImpl() + "]" + concat(" : " + ppReprType(this.getType())) + result = "[" + this.toStringImpl() } } @@ -2340,10 +2333,9 @@ private class PathNodeMid extends PathNodeImpl, TPathNodeMid { CallContext cc; SummaryCtx sc; AccessPath ap; - AccessPathApprox apa; Configuration config; - PathNodeMid() { this = TPathNodeMid(node, cc, sc, ap, apa, config) } + PathNodeMid() { this = TPathNodeMid(node, cc, sc, ap, config) } override Node getNode() { result = node } @@ -2353,13 +2345,10 @@ private class PathNodeMid extends PathNodeImpl, TPathNodeMid { AccessPath getAp() { result = ap } - AccessPathApprox getApa() { result = apa } - override Configuration getConfiguration() { result = config } private PathNodeMid getSuccMid() { - pathStep(this, result.getNode(), result.getCallContext(), result.getSummaryCtx(), - result.getAp(), _) and + pathStep(this, result.getNode(), result.getCallContext(), result.getSummaryCtx(), result.getAp()) and result.getConfiguration() = unbind(this.getConfiguration()) } @@ -2371,7 +2360,7 @@ private class PathNodeMid extends PathNodeImpl, TPathNodeMid { exists(PathNodeMid mid, PathNodeSink sink | mid = getSuccMid() and mid.getNode() = sink.getNode() and - mid.getApa() instanceof AccessPathApproxNil and + mid.getAp() instanceof AccessPathNil and sink.getConfiguration() = unbind(mid.getConfiguration()) and result = sink ) @@ -2381,7 +2370,7 @@ private class PathNodeMid extends PathNodeImpl, TPathNodeMid { config.isSource(node) and cc instanceof CallContextAny and sc instanceof SummaryCtxNone and - apa instanceof AccessPathApproxNil + ap instanceof AccessPathNil } } @@ -2409,33 +2398,22 @@ private class PathNodeSink extends PathNodeImpl, TPathNodeSink { * Holds if data may flow from `mid` to `node`. The last step in or out of * a callable is recorded by `cc`. */ -private predicate pathStep( - PathNodeMid mid, Node node, CallContext cc, SummaryCtx sc, AccessPath ap, AccessPathApprox apa -) { +private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, SummaryCtx sc, AccessPath ap) { pathStepSameAp(mid, node, cc, sc) and - ap = mid.getAp() and - apa = mid.getApa() + ap = mid.getAp() or exists(DataFlowType t | pathStepEmptyAp(mid, node, cc, sc, t) and - ap = TAccessPathNil(t) and - apa = TNil(t) + ap = TAccessPathNil(t) ) or - exists(TypedContent tc, AccessPathApprox apa0 | - pathStoreStep(mid, node, ap.pop(tc), apa0, tc, cc) and - // Same as `apa = ap.getApprox()`, but avoids mutual recursion - apa0 = apa.pop(tc) - ) and + exists(TypedContent tc | pathStoreStep(mid, node, ap.pop(tc), tc, cc)) and sc = mid.getSummaryCtx() or exists(TypedContent tc | pathReadStep(mid, node, ap.push(tc), tc, cc)) and - sc = mid.getSummaryCtx() and - // Here the approximation cannot be created from the approximation before - // the read, so we must use `getApprox()` - apa = ap.getApprox() + sc = mid.getSummaryCtx() or - pathThroughCallable(mid, node, cc, ap, apa) and + pathThroughCallable(mid, node, cc, ap) and sc = mid.getSummaryCtx() } @@ -2504,10 +2482,9 @@ private predicate storeCand(Node node1, TypedContent tc, Node node2, Configurati pragma[nomagic] private predicate pathStoreStep( - PathNodeMid mid, Node node, AccessPath ap0, AccessPathApprox apa0, TypedContent tc, CallContext cc + PathNodeMid mid, Node node, AccessPath ap0, TypedContent tc, CallContext cc ) { ap0 = mid.getAp() and - apa0 = mid.getApa() and storeCand(mid.getNode(), tc, node, mid.getConfiguration()) and cc = mid.getCallContext() } @@ -2519,7 +2496,7 @@ private predicate pathOutOfCallable0( pos = getReturnPosition(mid.getNode()) and innercc = mid.getCallContext() and innercc instanceof CallContextNoCall and - apa = mid.getApa() and + apa = mid.getAp().getApprox() and config = mid.getConfiguration() } @@ -2570,7 +2547,7 @@ private predicate pathIntoArg( cc = mid.getCallContext() and arg.argumentOf(call, i) and ap = mid.getAp() and - apa = mid.getApa() + apa = ap.getApprox() ) } @@ -2653,7 +2630,7 @@ private predicate paramFlowsThrough( sc = mid.getSummaryCtx() and config = mid.getConfiguration() and ap = mid.getAp() and - apa = mid.getApa() and + apa = ap.getApprox() and pos = sc.getParameterPos() and not kind.(ParamUpdateReturnKind).getPosition() = pos ) @@ -2675,10 +2652,8 @@ private predicate pathThroughCallable0( * The context `cc` is restored to its value prior to entering the callable. */ pragma[noinline] -private predicate pathThroughCallable( - PathNodeMid mid, Node out, CallContext cc, AccessPath ap, AccessPathApprox apa -) { - exists(DataFlowCall call, ReturnKindExt kind | +private predicate pathThroughCallable(PathNodeMid mid, Node out, CallContext cc, AccessPath ap) { + exists(DataFlowCall call, ReturnKindExt kind, AccessPathApprox apa | pathThroughCallable0(call, mid, kind, cc, ap, apa) and out = getAnOutNodeFlow(kind, call, apa, unbind(mid.getConfiguration())) ) diff --git a/python/ql/src/experimental/dataflow/internal/DataFlowImpl.qll b/python/ql/src/experimental/dataflow/internal/DataFlowImpl.qll index 04975b875b7b..77e777126c7b 100644 --- a/python/ql/src/experimental/dataflow/internal/DataFlowImpl.qll +++ b/python/ql/src/experimental/dataflow/internal/DataFlowImpl.qll @@ -1645,7 +1645,7 @@ private class AccessPathApproxOption extends TAccessPathApproxOption { } /** - * Holds if `node` is reachable with approximate access path `ap` from a source + * Holds if `node` is reachable with approximate access path `apa` from a source * in the configuration `config`. * * The call context `cc` records whether the node is reached through an @@ -1863,7 +1863,7 @@ private predicate flowFwdIsEntered( } /** - * Holds if `node` with approximate access path `ap` is part of a path from a + * Holds if `node` with approximate access path `apa` is part of a path from a * source to a sink in the configuration `config`. * * The Boolean `toReturn` records whether the node must be returned from @@ -2098,26 +2098,22 @@ private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome { private newtype TAccessPath = TAccessPathNil(DataFlowType t) or - TAccessPathCons(TypedContent head, AccessPath tail) { pathStoreStep(_, _, tail, _, head, _) } + TAccessPathCons(TypedContent head, AccessPath tail) { flowConsCand(head, tail.getApprox(), _) } private newtype TPathNode = - TPathNodeMid( - Node node, CallContext cc, SummaryCtx sc, AccessPath ap, AccessPathApprox apa, - Configuration config - ) { + TPathNodeMid(Node node, CallContext cc, SummaryCtx sc, AccessPath ap, Configuration config) { // A PathNode is introduced by a source ... flow(node, config) and config.isSource(node) and cc instanceof CallContextAny and sc instanceof SummaryCtxNone and - ap = TAccessPathNil(getNodeType(node)) and - apa = TNil(getNodeType(node)) + ap = TAccessPathNil(getNodeType(node)) or // ... or a step from an existing PathNode to another node. exists(PathNodeMid mid | - pathStep(mid, node, cc, sc, ap, apa) and + pathStep(mid, node, cc, sc, ap) and config = mid.getConfiguration() and - flow(node, _, _, apa, unbind(config)) + flow(node, _, _, ap.getApprox(), unbind(config)) ) } or TPathNodeSink(Node node, Configuration config) { @@ -2129,7 +2125,7 @@ private newtype TPathNode = or // ... or a sink that can be reached from a source exists(PathNodeMid mid | - pathStep(mid, node, _, _, _, TNil(_)) and + pathStep(mid, node, _, _, TAccessPathNil(_)) and config = unbind(mid.getConfiguration()) ) ) @@ -2142,9 +2138,6 @@ private newtype TPathNode = * tracked object. The final type indicates the type of the tracked object. */ abstract private class AccessPath extends TAccessPath { - /** Gets the type of this access path. */ - abstract DataFlowType getType(); - /** Gets the head of this access path, if any. */ abstract TypedContent getHead(); @@ -2178,7 +2171,7 @@ private class AccessPathNil extends AccessPath, TAccessPathNil { AccessPathNil() { this = TAccessPathNil(t) } - override DataFlowType getType() { result = t } + DataFlowType getType() { result = t } override TypedContent getHead() { none() } @@ -2199,8 +2192,6 @@ private class AccessPathCons extends AccessPath, TAccessPathCons { AccessPathCons() { this = TAccessPathCons(head, tail) } - override DataFlowType getType() { result = tail.getType() } - override TypedContent getHead() { result = head } override AccessPath getTail() { result = tail } @@ -2216,14 +2207,16 @@ private class AccessPathCons extends AccessPath, TAccessPathCons { override int length() { result = 1 + tail.length() } private string toStringImpl() { - tail = TAccessPathNil(_) and - result = head.toString() + exists(DataFlowType t | + tail = TAccessPathNil(t) and + result = head.toString() + "]" + concat(" : " + ppReprType(t)) + ) or result = head + ", " + tail.(AccessPathCons).toStringImpl() } override string toString() { - result = "[" + this.toStringImpl() + "]" + concat(" : " + ppReprType(this.getType())) + result = "[" + this.toStringImpl() } } @@ -2340,10 +2333,9 @@ private class PathNodeMid extends PathNodeImpl, TPathNodeMid { CallContext cc; SummaryCtx sc; AccessPath ap; - AccessPathApprox apa; Configuration config; - PathNodeMid() { this = TPathNodeMid(node, cc, sc, ap, apa, config) } + PathNodeMid() { this = TPathNodeMid(node, cc, sc, ap, config) } override Node getNode() { result = node } @@ -2353,13 +2345,10 @@ private class PathNodeMid extends PathNodeImpl, TPathNodeMid { AccessPath getAp() { result = ap } - AccessPathApprox getApa() { result = apa } - override Configuration getConfiguration() { result = config } private PathNodeMid getSuccMid() { - pathStep(this, result.getNode(), result.getCallContext(), result.getSummaryCtx(), - result.getAp(), _) and + pathStep(this, result.getNode(), result.getCallContext(), result.getSummaryCtx(), result.getAp()) and result.getConfiguration() = unbind(this.getConfiguration()) } @@ -2371,7 +2360,7 @@ private class PathNodeMid extends PathNodeImpl, TPathNodeMid { exists(PathNodeMid mid, PathNodeSink sink | mid = getSuccMid() and mid.getNode() = sink.getNode() and - mid.getApa() instanceof AccessPathApproxNil and + mid.getAp() instanceof AccessPathNil and sink.getConfiguration() = unbind(mid.getConfiguration()) and result = sink ) @@ -2381,7 +2370,7 @@ private class PathNodeMid extends PathNodeImpl, TPathNodeMid { config.isSource(node) and cc instanceof CallContextAny and sc instanceof SummaryCtxNone and - apa instanceof AccessPathApproxNil + ap instanceof AccessPathNil } } @@ -2409,33 +2398,22 @@ private class PathNodeSink extends PathNodeImpl, TPathNodeSink { * Holds if data may flow from `mid` to `node`. The last step in or out of * a callable is recorded by `cc`. */ -private predicate pathStep( - PathNodeMid mid, Node node, CallContext cc, SummaryCtx sc, AccessPath ap, AccessPathApprox apa -) { +private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, SummaryCtx sc, AccessPath ap) { pathStepSameAp(mid, node, cc, sc) and - ap = mid.getAp() and - apa = mid.getApa() + ap = mid.getAp() or exists(DataFlowType t | pathStepEmptyAp(mid, node, cc, sc, t) and - ap = TAccessPathNil(t) and - apa = TNil(t) + ap = TAccessPathNil(t) ) or - exists(TypedContent tc, AccessPathApprox apa0 | - pathStoreStep(mid, node, ap.pop(tc), apa0, tc, cc) and - // Same as `apa = ap.getApprox()`, but avoids mutual recursion - apa0 = apa.pop(tc) - ) and + exists(TypedContent tc | pathStoreStep(mid, node, ap.pop(tc), tc, cc)) and sc = mid.getSummaryCtx() or exists(TypedContent tc | pathReadStep(mid, node, ap.push(tc), tc, cc)) and - sc = mid.getSummaryCtx() and - // Here the approximation cannot be created from the approximation before - // the read, so we must use `getApprox()` - apa = ap.getApprox() + sc = mid.getSummaryCtx() or - pathThroughCallable(mid, node, cc, ap, apa) and + pathThroughCallable(mid, node, cc, ap) and sc = mid.getSummaryCtx() } @@ -2504,10 +2482,9 @@ private predicate storeCand(Node node1, TypedContent tc, Node node2, Configurati pragma[nomagic] private predicate pathStoreStep( - PathNodeMid mid, Node node, AccessPath ap0, AccessPathApprox apa0, TypedContent tc, CallContext cc + PathNodeMid mid, Node node, AccessPath ap0, TypedContent tc, CallContext cc ) { ap0 = mid.getAp() and - apa0 = mid.getApa() and storeCand(mid.getNode(), tc, node, mid.getConfiguration()) and cc = mid.getCallContext() } @@ -2519,7 +2496,7 @@ private predicate pathOutOfCallable0( pos = getReturnPosition(mid.getNode()) and innercc = mid.getCallContext() and innercc instanceof CallContextNoCall and - apa = mid.getApa() and + apa = mid.getAp().getApprox() and config = mid.getConfiguration() } @@ -2570,7 +2547,7 @@ private predicate pathIntoArg( cc = mid.getCallContext() and arg.argumentOf(call, i) and ap = mid.getAp() and - apa = mid.getApa() + apa = ap.getApprox() ) } @@ -2653,7 +2630,7 @@ private predicate paramFlowsThrough( sc = mid.getSummaryCtx() and config = mid.getConfiguration() and ap = mid.getAp() and - apa = mid.getApa() and + apa = ap.getApprox() and pos = sc.getParameterPos() and not kind.(ParamUpdateReturnKind).getPosition() = pos ) @@ -2675,10 +2652,8 @@ private predicate pathThroughCallable0( * The context `cc` is restored to its value prior to entering the callable. */ pragma[noinline] -private predicate pathThroughCallable( - PathNodeMid mid, Node out, CallContext cc, AccessPath ap, AccessPathApprox apa -) { - exists(DataFlowCall call, ReturnKindExt kind | +private predicate pathThroughCallable(PathNodeMid mid, Node out, CallContext cc, AccessPath ap) { + exists(DataFlowCall call, ReturnKindExt kind, AccessPathApprox apa | pathThroughCallable0(call, mid, kind, cc, ap, apa) and out = getAnOutNodeFlow(kind, call, apa, unbind(mid.getConfiguration())) ) diff --git a/python/ql/src/experimental/dataflow/internal/DataFlowImpl2.qll b/python/ql/src/experimental/dataflow/internal/DataFlowImpl2.qll index 04975b875b7b..77e777126c7b 100644 --- a/python/ql/src/experimental/dataflow/internal/DataFlowImpl2.qll +++ b/python/ql/src/experimental/dataflow/internal/DataFlowImpl2.qll @@ -1645,7 +1645,7 @@ private class AccessPathApproxOption extends TAccessPathApproxOption { } /** - * Holds if `node` is reachable with approximate access path `ap` from a source + * Holds if `node` is reachable with approximate access path `apa` from a source * in the configuration `config`. * * The call context `cc` records whether the node is reached through an @@ -1863,7 +1863,7 @@ private predicate flowFwdIsEntered( } /** - * Holds if `node` with approximate access path `ap` is part of a path from a + * Holds if `node` with approximate access path `apa` is part of a path from a * source to a sink in the configuration `config`. * * The Boolean `toReturn` records whether the node must be returned from @@ -2098,26 +2098,22 @@ private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome { private newtype TAccessPath = TAccessPathNil(DataFlowType t) or - TAccessPathCons(TypedContent head, AccessPath tail) { pathStoreStep(_, _, tail, _, head, _) } + TAccessPathCons(TypedContent head, AccessPath tail) { flowConsCand(head, tail.getApprox(), _) } private newtype TPathNode = - TPathNodeMid( - Node node, CallContext cc, SummaryCtx sc, AccessPath ap, AccessPathApprox apa, - Configuration config - ) { + TPathNodeMid(Node node, CallContext cc, SummaryCtx sc, AccessPath ap, Configuration config) { // A PathNode is introduced by a source ... flow(node, config) and config.isSource(node) and cc instanceof CallContextAny and sc instanceof SummaryCtxNone and - ap = TAccessPathNil(getNodeType(node)) and - apa = TNil(getNodeType(node)) + ap = TAccessPathNil(getNodeType(node)) or // ... or a step from an existing PathNode to another node. exists(PathNodeMid mid | - pathStep(mid, node, cc, sc, ap, apa) and + pathStep(mid, node, cc, sc, ap) and config = mid.getConfiguration() and - flow(node, _, _, apa, unbind(config)) + flow(node, _, _, ap.getApprox(), unbind(config)) ) } or TPathNodeSink(Node node, Configuration config) { @@ -2129,7 +2125,7 @@ private newtype TPathNode = or // ... or a sink that can be reached from a source exists(PathNodeMid mid | - pathStep(mid, node, _, _, _, TNil(_)) and + pathStep(mid, node, _, _, TAccessPathNil(_)) and config = unbind(mid.getConfiguration()) ) ) @@ -2142,9 +2138,6 @@ private newtype TPathNode = * tracked object. The final type indicates the type of the tracked object. */ abstract private class AccessPath extends TAccessPath { - /** Gets the type of this access path. */ - abstract DataFlowType getType(); - /** Gets the head of this access path, if any. */ abstract TypedContent getHead(); @@ -2178,7 +2171,7 @@ private class AccessPathNil extends AccessPath, TAccessPathNil { AccessPathNil() { this = TAccessPathNil(t) } - override DataFlowType getType() { result = t } + DataFlowType getType() { result = t } override TypedContent getHead() { none() } @@ -2199,8 +2192,6 @@ private class AccessPathCons extends AccessPath, TAccessPathCons { AccessPathCons() { this = TAccessPathCons(head, tail) } - override DataFlowType getType() { result = tail.getType() } - override TypedContent getHead() { result = head } override AccessPath getTail() { result = tail } @@ -2216,14 +2207,16 @@ private class AccessPathCons extends AccessPath, TAccessPathCons { override int length() { result = 1 + tail.length() } private string toStringImpl() { - tail = TAccessPathNil(_) and - result = head.toString() + exists(DataFlowType t | + tail = TAccessPathNil(t) and + result = head.toString() + "]" + concat(" : " + ppReprType(t)) + ) or result = head + ", " + tail.(AccessPathCons).toStringImpl() } override string toString() { - result = "[" + this.toStringImpl() + "]" + concat(" : " + ppReprType(this.getType())) + result = "[" + this.toStringImpl() } } @@ -2340,10 +2333,9 @@ private class PathNodeMid extends PathNodeImpl, TPathNodeMid { CallContext cc; SummaryCtx sc; AccessPath ap; - AccessPathApprox apa; Configuration config; - PathNodeMid() { this = TPathNodeMid(node, cc, sc, ap, apa, config) } + PathNodeMid() { this = TPathNodeMid(node, cc, sc, ap, config) } override Node getNode() { result = node } @@ -2353,13 +2345,10 @@ private class PathNodeMid extends PathNodeImpl, TPathNodeMid { AccessPath getAp() { result = ap } - AccessPathApprox getApa() { result = apa } - override Configuration getConfiguration() { result = config } private PathNodeMid getSuccMid() { - pathStep(this, result.getNode(), result.getCallContext(), result.getSummaryCtx(), - result.getAp(), _) and + pathStep(this, result.getNode(), result.getCallContext(), result.getSummaryCtx(), result.getAp()) and result.getConfiguration() = unbind(this.getConfiguration()) } @@ -2371,7 +2360,7 @@ private class PathNodeMid extends PathNodeImpl, TPathNodeMid { exists(PathNodeMid mid, PathNodeSink sink | mid = getSuccMid() and mid.getNode() = sink.getNode() and - mid.getApa() instanceof AccessPathApproxNil and + mid.getAp() instanceof AccessPathNil and sink.getConfiguration() = unbind(mid.getConfiguration()) and result = sink ) @@ -2381,7 +2370,7 @@ private class PathNodeMid extends PathNodeImpl, TPathNodeMid { config.isSource(node) and cc instanceof CallContextAny and sc instanceof SummaryCtxNone and - apa instanceof AccessPathApproxNil + ap instanceof AccessPathNil } } @@ -2409,33 +2398,22 @@ private class PathNodeSink extends PathNodeImpl, TPathNodeSink { * Holds if data may flow from `mid` to `node`. The last step in or out of * a callable is recorded by `cc`. */ -private predicate pathStep( - PathNodeMid mid, Node node, CallContext cc, SummaryCtx sc, AccessPath ap, AccessPathApprox apa -) { +private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, SummaryCtx sc, AccessPath ap) { pathStepSameAp(mid, node, cc, sc) and - ap = mid.getAp() and - apa = mid.getApa() + ap = mid.getAp() or exists(DataFlowType t | pathStepEmptyAp(mid, node, cc, sc, t) and - ap = TAccessPathNil(t) and - apa = TNil(t) + ap = TAccessPathNil(t) ) or - exists(TypedContent tc, AccessPathApprox apa0 | - pathStoreStep(mid, node, ap.pop(tc), apa0, tc, cc) and - // Same as `apa = ap.getApprox()`, but avoids mutual recursion - apa0 = apa.pop(tc) - ) and + exists(TypedContent tc | pathStoreStep(mid, node, ap.pop(tc), tc, cc)) and sc = mid.getSummaryCtx() or exists(TypedContent tc | pathReadStep(mid, node, ap.push(tc), tc, cc)) and - sc = mid.getSummaryCtx() and - // Here the approximation cannot be created from the approximation before - // the read, so we must use `getApprox()` - apa = ap.getApprox() + sc = mid.getSummaryCtx() or - pathThroughCallable(mid, node, cc, ap, apa) and + pathThroughCallable(mid, node, cc, ap) and sc = mid.getSummaryCtx() } @@ -2504,10 +2482,9 @@ private predicate storeCand(Node node1, TypedContent tc, Node node2, Configurati pragma[nomagic] private predicate pathStoreStep( - PathNodeMid mid, Node node, AccessPath ap0, AccessPathApprox apa0, TypedContent tc, CallContext cc + PathNodeMid mid, Node node, AccessPath ap0, TypedContent tc, CallContext cc ) { ap0 = mid.getAp() and - apa0 = mid.getApa() and storeCand(mid.getNode(), tc, node, mid.getConfiguration()) and cc = mid.getCallContext() } @@ -2519,7 +2496,7 @@ private predicate pathOutOfCallable0( pos = getReturnPosition(mid.getNode()) and innercc = mid.getCallContext() and innercc instanceof CallContextNoCall and - apa = mid.getApa() and + apa = mid.getAp().getApprox() and config = mid.getConfiguration() } @@ -2570,7 +2547,7 @@ private predicate pathIntoArg( cc = mid.getCallContext() and arg.argumentOf(call, i) and ap = mid.getAp() and - apa = mid.getApa() + apa = ap.getApprox() ) } @@ -2653,7 +2630,7 @@ private predicate paramFlowsThrough( sc = mid.getSummaryCtx() and config = mid.getConfiguration() and ap = mid.getAp() and - apa = mid.getApa() and + apa = ap.getApprox() and pos = sc.getParameterPos() and not kind.(ParamUpdateReturnKind).getPosition() = pos ) @@ -2675,10 +2652,8 @@ private predicate pathThroughCallable0( * The context `cc` is restored to its value prior to entering the callable. */ pragma[noinline] -private predicate pathThroughCallable( - PathNodeMid mid, Node out, CallContext cc, AccessPath ap, AccessPathApprox apa -) { - exists(DataFlowCall call, ReturnKindExt kind | +private predicate pathThroughCallable(PathNodeMid mid, Node out, CallContext cc, AccessPath ap) { + exists(DataFlowCall call, ReturnKindExt kind, AccessPathApprox apa | pathThroughCallable0(call, mid, kind, cc, ap, apa) and out = getAnOutNodeFlow(kind, call, apa, unbind(mid.getConfiguration())) )