Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
85 changes: 30 additions & 55 deletions cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl.qll
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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) {
Expand All @@ -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())
)
)
Expand All @@ -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();

Expand Down Expand Up @@ -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() }

Expand All @@ -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 }
Expand All @@ -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()
}
}

Expand Down Expand Up @@ -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 }

Expand All @@ -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())
}

Expand All @@ -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
)
Expand All @@ -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
}
}

Expand Down Expand Up @@ -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()
}

Expand Down Expand Up @@ -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()
}
Expand All @@ -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()
}

Expand Down Expand Up @@ -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()
)
}

Expand Down Expand Up @@ -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
)
Expand All @@ -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()))
)
Expand Down
Loading