mirror of
https://github.com/github/codeql.git
synced 2026-04-27 01:35:13 +02:00
Data flow: Rename AccessPath to AccessPathApprox
This commit is contained in:
@@ -1523,7 +1523,7 @@ private predicate flowCandIsReturned(
|
||||
)
|
||||
}
|
||||
|
||||
private newtype TAccessPath =
|
||||
private newtype TAccessPathApprox =
|
||||
TNil(DataFlowType t) or
|
||||
TConsNil(TypedContent tc, DataFlowType t) { flowCandConsCand(tc, TFrontNil(t), _) } or
|
||||
TConsCons(TypedContent tc1, TypedContent tc2, int len) {
|
||||
@@ -1531,13 +1531,13 @@ private newtype TAccessPath =
|
||||
}
|
||||
|
||||
/**
|
||||
* Conceptually a list of `TypedContent`s followed by a `Type`, but only the first two
|
||||
* elements of the list and its length are tracked. If data flows from a source to
|
||||
* a given node with a given `AccessPath`, this indicates the sequence of
|
||||
* dereference operations needed to get from the value in the node to the
|
||||
* tracked object. The final type indicates the type of the tracked object.
|
||||
* Conceptually a list of `TypedContent`s followed by a `DataFlowType`, but only
|
||||
* the first two elements of the list and its length are tracked. If data flows
|
||||
* from a source to a given node with a given `AccessPathApprox`, this indicates
|
||||
* the sequence of dereference operations needed to get from the value in the node
|
||||
* to the tracked object. The final type indicates the type of the tracked object.
|
||||
*/
|
||||
abstract private class AccessPath extends TAccessPath {
|
||||
abstract private class AccessPathApprox extends TAccessPathApprox {
|
||||
abstract string toString();
|
||||
|
||||
abstract TypedContent getHead();
|
||||
@@ -1551,13 +1551,13 @@ abstract private class AccessPath extends TAccessPath {
|
||||
/**
|
||||
* Holds if this access path has `head` at the front and may be followed by `tail`.
|
||||
*/
|
||||
abstract predicate pop(TypedContent head, AccessPath tail);
|
||||
abstract predicate pop(TypedContent head, AccessPathApprox tail);
|
||||
}
|
||||
|
||||
private class AccessPathNil extends AccessPath, TNil {
|
||||
private class AccessPathApproxNil extends AccessPathApprox, TNil {
|
||||
private DataFlowType t;
|
||||
|
||||
AccessPathNil() { this = TNil(t) }
|
||||
AccessPathApproxNil() { this = TNil(t) }
|
||||
|
||||
override string toString() { result = concat(": " + ppReprType(t)) }
|
||||
|
||||
@@ -1569,16 +1569,16 @@ private class AccessPathNil extends AccessPath, TNil {
|
||||
|
||||
override AccessPathFront getFront() { result = TFrontNil(t) }
|
||||
|
||||
override predicate pop(TypedContent head, AccessPath tail) { none() }
|
||||
override predicate pop(TypedContent head, AccessPathApprox tail) { none() }
|
||||
}
|
||||
|
||||
abstract private class AccessPathCons extends AccessPath { }
|
||||
abstract private class AccessPathApproxCons extends AccessPathApprox { }
|
||||
|
||||
private class AccessPathConsNil extends AccessPathCons, TConsNil {
|
||||
private class AccessPathApproxConsNil extends AccessPathApproxCons, TConsNil {
|
||||
private TypedContent tc;
|
||||
private DataFlowType t;
|
||||
|
||||
AccessPathConsNil() { this = TConsNil(tc, t) }
|
||||
AccessPathApproxConsNil() { this = TConsNil(tc, t) }
|
||||
|
||||
override string toString() {
|
||||
// The `concat` becomes "" if `ppReprType` has no result.
|
||||
@@ -1593,15 +1593,15 @@ private class AccessPathConsNil extends AccessPathCons, TConsNil {
|
||||
|
||||
override AccessPathFront getFront() { result = TFrontHead(tc) }
|
||||
|
||||
override predicate pop(TypedContent head, AccessPath tail) { head = tc and tail = TNil(t) }
|
||||
override predicate pop(TypedContent head, AccessPathApprox tail) { head = tc and tail = TNil(t) }
|
||||
}
|
||||
|
||||
private class AccessPathConsCons extends AccessPathCons, TConsCons {
|
||||
private class AccessPathApproxConsCons extends AccessPathApproxCons, TConsCons {
|
||||
private TypedContent tc1;
|
||||
private TypedContent tc2;
|
||||
private int len;
|
||||
|
||||
AccessPathConsCons() { this = TConsCons(tc1, tc2, len) }
|
||||
AccessPathApproxConsCons() { this = TConsCons(tc1, tc2, len) }
|
||||
|
||||
override string toString() {
|
||||
if len = 2
|
||||
@@ -1617,7 +1617,7 @@ private class AccessPathConsCons extends AccessPathCons, TConsCons {
|
||||
|
||||
override AccessPathFront getFront() { result = TFrontHead(tc1) }
|
||||
|
||||
override predicate pop(TypedContent head, AccessPath tail) {
|
||||
override predicate pop(TypedContent head, AccessPathApprox tail) {
|
||||
head = tc1 and
|
||||
(
|
||||
tail = TConsCons(tc2, _, len - 1)
|
||||
@@ -1629,126 +1629,126 @@ private class AccessPathConsCons extends AccessPathCons, TConsCons {
|
||||
}
|
||||
|
||||
/** Gets the access path obtained by popping `tc` from `ap`, if any. */
|
||||
private AccessPath pop(TypedContent tc, AccessPath ap) { ap.pop(tc, result) }
|
||||
private AccessPathApprox pop(TypedContent tc, AccessPathApprox apa) { apa.pop(tc, result) }
|
||||
|
||||
/** Gets the access path obtained by pushing `tc` onto `ap`. */
|
||||
private AccessPath push(TypedContent tc, AccessPath ap) { ap = pop(tc, result) }
|
||||
private AccessPathApprox push(TypedContent tc, AccessPathApprox apa) { apa = pop(tc, result) }
|
||||
|
||||
private newtype TAccessPathOption =
|
||||
TAccessPathNone() or
|
||||
TAccessPathSome(AccessPath ap)
|
||||
private newtype TAccessPathApproxOption =
|
||||
TAccessPathApproxNone() or
|
||||
TAccessPathApproxSome(AccessPathApprox apa)
|
||||
|
||||
private class AccessPathOption extends TAccessPathOption {
|
||||
private class AccessPathApproxOption extends TAccessPathApproxOption {
|
||||
string toString() {
|
||||
this = TAccessPathNone() and result = "<none>"
|
||||
this = TAccessPathApproxNone() and result = "<none>"
|
||||
or
|
||||
this = TAccessPathSome(any(AccessPath ap | result = ap.toString()))
|
||||
this = TAccessPathApproxSome(any(AccessPathApprox apa | result = apa.toString()))
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `node` is reachable with access path `ap` from a source in
|
||||
* the configuration `config`.
|
||||
* Holds if `node` is reachable with approximate access path `ap` from a source
|
||||
* in the configuration `config`.
|
||||
*
|
||||
* The call context `cc` records whether the node is reached through an
|
||||
* argument in a call, and if so, `argAp` records the access path of that
|
||||
* argument.
|
||||
* argument in a call, and if so, `argApa` records the approximate access path
|
||||
* of that argument.
|
||||
*/
|
||||
private predicate flowFwd(
|
||||
Node node, CallContext cc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap,
|
||||
Configuration config
|
||||
Node node, CallContext cc, AccessPathApproxOption argApa, AccessPathFront apf,
|
||||
AccessPathApprox apa, Configuration config
|
||||
) {
|
||||
flowFwd0(node, cc, argAp, apf, ap, config) and
|
||||
flowFwd0(node, cc, argApa, apf, apa, config) and
|
||||
flowCand(node, _, _, apf, config)
|
||||
}
|
||||
|
||||
private predicate flowFwd0(
|
||||
Node node, CallContext cc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap,
|
||||
Configuration config
|
||||
Node node, CallContext cc, AccessPathApproxOption argApa, AccessPathFront apf,
|
||||
AccessPathApprox apa, Configuration config
|
||||
) {
|
||||
flowCand(node, _, _, _, config) and
|
||||
config.isSource(node) and
|
||||
cc instanceof CallContextAny and
|
||||
argAp = TAccessPathNone() and
|
||||
ap = TNil(getNodeType(node)) and
|
||||
apf = ap.(AccessPathNil).getFront()
|
||||
argApa = TAccessPathApproxNone() and
|
||||
apa = TNil(getNodeType(node)) and
|
||||
apf = apa.(AccessPathApproxNil).getFront()
|
||||
or
|
||||
flowCand(node, _, _, _, unbind(config)) and
|
||||
(
|
||||
exists(Node mid, LocalCallContext localCC |
|
||||
flowFwdLocalEntry(mid, cc, argAp, apf, ap, localCC, config) and
|
||||
flowFwdLocalEntry(mid, cc, argApa, apf, apa, localCC, config) and
|
||||
localFlowBigStep(mid, node, true, _, config, localCC)
|
||||
)
|
||||
or
|
||||
exists(Node mid, AccessPathNil nil, LocalCallContext localCC |
|
||||
flowFwdLocalEntry(mid, cc, argAp, _, nil, localCC, config) and
|
||||
exists(Node mid, AccessPathApproxNil nil, LocalCallContext localCC |
|
||||
flowFwdLocalEntry(mid, cc, argApa, _, nil, localCC, config) and
|
||||
localFlowBigStep(mid, node, false, apf, config, localCC) and
|
||||
apf = ap.(AccessPathNil).getFront()
|
||||
apf = apa.(AccessPathApproxNil).getFront()
|
||||
)
|
||||
or
|
||||
exists(Node mid |
|
||||
flowFwd(mid, _, _, apf, ap, config) and
|
||||
flowFwd(mid, _, _, apf, apa, config) and
|
||||
jumpStep(mid, node, config) and
|
||||
cc instanceof CallContextAny and
|
||||
argAp = TAccessPathNone()
|
||||
argApa = TAccessPathApproxNone()
|
||||
)
|
||||
or
|
||||
exists(Node mid, AccessPathNil nil |
|
||||
exists(Node mid, AccessPathApproxNil nil |
|
||||
flowFwd(mid, _, _, _, nil, config) and
|
||||
additionalJumpStep(mid, node, config) and
|
||||
cc instanceof CallContextAny and
|
||||
argAp = TAccessPathNone() and
|
||||
ap = TNil(getNodeType(node)) and
|
||||
apf = ap.(AccessPathNil).getFront()
|
||||
argApa = TAccessPathApproxNone() and
|
||||
apa = TNil(getNodeType(node)) and
|
||||
apf = apa.(AccessPathApproxNil).getFront()
|
||||
)
|
||||
)
|
||||
or
|
||||
// store
|
||||
exists(TypedContent tc | flowFwdStore(node, tc, pop(tc, ap), apf, cc, argAp, config))
|
||||
exists(TypedContent tc | flowFwdStore(node, tc, pop(tc, apa), apf, cc, argApa, config))
|
||||
or
|
||||
// read
|
||||
exists(TypedContent tc |
|
||||
flowFwdRead(node, _, push(tc, ap), apf, cc, argAp, config) and
|
||||
flowFwdConsCand(tc, apf, ap, config)
|
||||
flowFwdRead(node, _, push(tc, apa), apf, cc, argApa, config) and
|
||||
flowFwdConsCand(tc, apf, apa, config)
|
||||
)
|
||||
or
|
||||
// flow into a callable
|
||||
flowFwdIn(_, node, _, cc, _, apf, ap, config) and
|
||||
flowFwdIn(_, node, _, cc, _, apf, apa, config) and
|
||||
if flowCand(node, true, _, apf, config)
|
||||
then argAp = TAccessPathSome(ap)
|
||||
else argAp = TAccessPathNone()
|
||||
then argApa = TAccessPathApproxSome(apa)
|
||||
else argApa = TAccessPathApproxNone()
|
||||
or
|
||||
// flow out of a callable
|
||||
exists(DataFlowCall call |
|
||||
exists(DataFlowCallable c |
|
||||
flowFwdOut(call, node, any(CallContextNoCall innercc), c, argAp, apf, ap, config) and
|
||||
flowFwdOut(call, node, any(CallContextNoCall innercc), c, argApa, apf, apa, config) and
|
||||
if reducedViableImplInReturn(c, call) then cc = TReturn(c, call) else cc = TAnyCallContext()
|
||||
)
|
||||
or
|
||||
exists(AccessPath argAp0 |
|
||||
flowFwdOutFromArg(call, node, argAp0, apf, ap, config) and
|
||||
flowFwdIsEntered(call, cc, argAp, argAp0, config)
|
||||
exists(AccessPathApprox argApa0 |
|
||||
flowFwdOutFromArg(call, node, argApa0, apf, apa, config) and
|
||||
flowFwdIsEntered(call, cc, argApa, argApa0, config)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate flowFwdLocalEntry(
|
||||
Node node, CallContext cc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap,
|
||||
LocalCallContext localCC, Configuration config
|
||||
Node node, CallContext cc, AccessPathApproxOption argApa, AccessPathFront apf,
|
||||
AccessPathApprox apa, LocalCallContext localCC, Configuration config
|
||||
) {
|
||||
flowFwd(node, cc, argAp, apf, ap, config) and
|
||||
flowFwd(node, cc, argApa, apf, apa, config) and
|
||||
localFlowEntry(node, config) and
|
||||
localCC = getLocalCallContext(cc, node.getEnclosingCallable())
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate flowFwdStore(
|
||||
Node node, TypedContent tc, AccessPath ap0, AccessPathFront apf, CallContext cc,
|
||||
AccessPathOption argAp, Configuration config
|
||||
Node node, TypedContent tc, AccessPathApprox apa0, AccessPathFront apf, CallContext cc,
|
||||
AccessPathApproxOption argApa, Configuration config
|
||||
) {
|
||||
exists(Node mid, AccessPathFront apf0 |
|
||||
flowFwd(mid, cc, argAp, apf0, ap0, config) and
|
||||
flowFwd(mid, cc, argApa, apf0, apa0, config) and
|
||||
flowFwdStore0(mid, tc, node, apf0, apf, config)
|
||||
)
|
||||
}
|
||||
@@ -1775,20 +1775,20 @@ private predicate flowFwdStore0(
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate flowFwdRead0(
|
||||
Node node1, TypedContent tc, AccessPathFrontHead apf0, AccessPath ap0, Node node2, CallContext cc,
|
||||
AccessPathOption argAp, Configuration config
|
||||
Node node1, TypedContent tc, AccessPathFrontHead apf0, AccessPathApprox apa0, Node node2,
|
||||
CallContext cc, AccessPathApproxOption argApa, Configuration config
|
||||
) {
|
||||
flowFwd(node1, cc, argAp, apf0, ap0, config) and
|
||||
flowFwd(node1, cc, argApa, apf0, apa0, config) and
|
||||
readCandFwd(node1, tc, apf0, node2, config)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate flowFwdRead(
|
||||
Node node, AccessPathFrontHead apf0, AccessPath ap0, AccessPathFront apf, CallContext cc,
|
||||
AccessPathOption argAp, Configuration config
|
||||
Node node, AccessPathFrontHead apf0, AccessPathApprox apa0, AccessPathFront apf, CallContext cc,
|
||||
AccessPathApproxOption argApa, Configuration config
|
||||
) {
|
||||
exists(Node mid, TypedContent tc |
|
||||
flowFwdRead0(mid, tc, apf0, ap0, node, cc, argAp, config) and
|
||||
flowFwdRead0(mid, tc, apf0, apa0, node, cc, argApa, config) and
|
||||
flowCand(node, _, _, apf, unbind(config)) and
|
||||
flowCandConsCand(tc, apf, unbind(config))
|
||||
)
|
||||
@@ -1796,10 +1796,10 @@ private predicate flowFwdRead(
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate flowFwdConsCand(
|
||||
TypedContent tc, AccessPathFront apf, AccessPath ap, Configuration config
|
||||
TypedContent tc, AccessPathFront apf, AccessPathApprox apa, Configuration config
|
||||
) {
|
||||
exists(Node n |
|
||||
flowFwd(n, _, _, apf, ap, config) and
|
||||
flowFwd(n, _, _, apf, apa, config) and
|
||||
flowFwdStore0(n, tc, _, apf, _, config)
|
||||
)
|
||||
}
|
||||
@@ -1807,27 +1807,27 @@ private predicate flowFwdConsCand(
|
||||
pragma[nomagic]
|
||||
private predicate flowFwdIn(
|
||||
DataFlowCall call, ParameterNode p, CallContext outercc, CallContext innercc,
|
||||
AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config
|
||||
AccessPathApproxOption argApa, AccessPathFront apf, AccessPathApprox apa, Configuration config
|
||||
) {
|
||||
exists(ArgumentNode arg, boolean allowsFieldFlow, DataFlowCallable c |
|
||||
flowFwd(arg, outercc, argAp, apf, ap, config) and
|
||||
flowFwd(arg, outercc, argApa, apf, apa, config) and
|
||||
flowIntoCallNodeCand2(call, arg, p, allowsFieldFlow, config) and
|
||||
c = p.getEnclosingCallable() and
|
||||
c = resolveCall(call, outercc) and
|
||||
flowCand(p, _, _, _, unbind(config)) and
|
||||
if recordDataFlowCallSite(call, c) then innercc = TSpecificCall(call) else innercc = TSomeCall()
|
||||
|
|
||||
ap instanceof AccessPathNil or allowsFieldFlow = true
|
||||
apa instanceof AccessPathApproxNil or allowsFieldFlow = true
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate flowFwdOut(
|
||||
DataFlowCall call, Node node, CallContext innercc, DataFlowCallable innerc,
|
||||
AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config
|
||||
AccessPathApproxOption argApa, AccessPathFront apf, AccessPathApprox apa, Configuration config
|
||||
) {
|
||||
exists(ReturnNodeExt ret, boolean allowsFieldFlow |
|
||||
flowFwd(ret, innercc, argAp, apf, ap, config) and
|
||||
flowFwd(ret, innercc, argApa, apf, apa, config) and
|
||||
flowOutOfCallNodeCand2(call, ret, node, allowsFieldFlow, config) and
|
||||
innerc = ret.getEnclosingCallable() and
|
||||
flowCand(node, _, _, _, unbind(config)) and
|
||||
@@ -1837,16 +1837,17 @@ private predicate flowFwdOut(
|
||||
innercc.(CallContextCall).matchesCall(call)
|
||||
)
|
||||
|
|
||||
ap instanceof AccessPathNil or allowsFieldFlow = true
|
||||
apa instanceof AccessPathApproxNil or allowsFieldFlow = true
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate flowFwdOutFromArg(
|
||||
DataFlowCall call, Node node, AccessPath argAp, AccessPathFront apf, AccessPath ap,
|
||||
DataFlowCall call, Node node, AccessPathApprox argApa, AccessPathFront apf, AccessPathApprox apa,
|
||||
Configuration config
|
||||
) {
|
||||
flowFwdOut(call, node, any(CallContextCall ccc), _, TAccessPathSome(argAp), apf, ap, config)
|
||||
flowFwdOut(call, node, any(CallContextCall ccc), _, TAccessPathApproxSome(argApa), apf, apa,
|
||||
config)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1854,168 +1855,174 @@ private predicate flowFwdOutFromArg(
|
||||
*/
|
||||
pragma[nomagic]
|
||||
private predicate flowFwdIsEntered(
|
||||
DataFlowCall call, CallContext cc, AccessPathOption argAp, AccessPath ap, Configuration config
|
||||
DataFlowCall call, CallContext cc, AccessPathApproxOption argApa, AccessPathApprox apa,
|
||||
Configuration config
|
||||
) {
|
||||
exists(ParameterNode p, AccessPathFront apf |
|
||||
flowFwdIn(call, p, cc, _, argAp, apf, ap, config) and
|
||||
flowFwdIn(call, p, cc, _, argApa, apf, apa, config) and
|
||||
flowCand(p, true, TAccessPathFrontSome(_), apf, config)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `node` with access path `ap` is part of a path from a source to
|
||||
* a sink in the configuration `config`.
|
||||
* Holds if `node` with approximate access path `ap` 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
|
||||
* the enclosing callable in order to reach a sink, and if so, `returnAp`
|
||||
* records the access path of the returned value.
|
||||
* the enclosing callable in order to reach a sink, and if so, `returnApa`
|
||||
* records the approximate access path of the returned value.
|
||||
*/
|
||||
private predicate flow(
|
||||
Node node, boolean toReturn, AccessPathOption returnAp, AccessPath ap, Configuration config
|
||||
Node node, boolean toReturn, AccessPathApproxOption returnApa, AccessPathApprox apa,
|
||||
Configuration config
|
||||
) {
|
||||
flow0(node, toReturn, returnAp, ap, config) and
|
||||
flowFwd(node, _, _, _, ap, config)
|
||||
flow0(node, toReturn, returnApa, apa, config) and
|
||||
flowFwd(node, _, _, _, apa, config)
|
||||
}
|
||||
|
||||
private predicate flow0(
|
||||
Node node, boolean toReturn, AccessPathOption returnAp, AccessPath ap, Configuration config
|
||||
Node node, boolean toReturn, AccessPathApproxOption returnApa, AccessPathApprox apa,
|
||||
Configuration config
|
||||
) {
|
||||
flowFwd(node, _, _, _, ap, config) and
|
||||
flowFwd(node, _, _, _, apa, config) and
|
||||
config.isSink(node) and
|
||||
toReturn = false and
|
||||
returnAp = TAccessPathNone() and
|
||||
ap instanceof AccessPathNil
|
||||
returnApa = TAccessPathApproxNone() and
|
||||
apa instanceof AccessPathApproxNil
|
||||
or
|
||||
exists(Node mid |
|
||||
localFlowBigStep(node, mid, true, _, config, _) and
|
||||
flow(mid, toReturn, returnAp, ap, config)
|
||||
flow(mid, toReturn, returnApa, apa, config)
|
||||
)
|
||||
or
|
||||
exists(Node mid, AccessPathNil nil |
|
||||
flowFwd(node, _, _, _, ap, config) and
|
||||
exists(Node mid, AccessPathApproxNil nil |
|
||||
flowFwd(node, _, _, _, apa, config) and
|
||||
localFlowBigStep(node, mid, false, _, config, _) and
|
||||
flow(mid, toReturn, returnAp, nil, config) and
|
||||
ap instanceof AccessPathNil
|
||||
flow(mid, toReturn, returnApa, nil, config) and
|
||||
apa instanceof AccessPathApproxNil
|
||||
)
|
||||
or
|
||||
exists(Node mid |
|
||||
jumpStep(node, mid, config) and
|
||||
flow(mid, _, _, ap, config) and
|
||||
flow(mid, _, _, apa, config) and
|
||||
toReturn = false and
|
||||
returnAp = TAccessPathNone()
|
||||
returnApa = TAccessPathApproxNone()
|
||||
)
|
||||
or
|
||||
exists(Node mid, AccessPathNil nil |
|
||||
flowFwd(node, _, _, _, ap, config) and
|
||||
exists(Node mid, AccessPathApproxNil nil |
|
||||
flowFwd(node, _, _, _, apa, config) and
|
||||
additionalJumpStep(node, mid, config) and
|
||||
flow(mid, _, _, nil, config) and
|
||||
toReturn = false and
|
||||
returnAp = TAccessPathNone() and
|
||||
ap instanceof AccessPathNil
|
||||
returnApa = TAccessPathApproxNone() and
|
||||
apa instanceof AccessPathApproxNil
|
||||
)
|
||||
or
|
||||
// store
|
||||
exists(TypedContent tc |
|
||||
flowStore(tc, node, toReturn, returnAp, ap, config) and
|
||||
flowConsCand(tc, ap, config)
|
||||
flowStore(tc, node, toReturn, returnApa, apa, config) and
|
||||
flowConsCand(tc, apa, config)
|
||||
)
|
||||
or
|
||||
// read
|
||||
exists(Node mid, AccessPath ap0 |
|
||||
readFlowFwd(node, _, mid, ap, ap0, config) and
|
||||
flow(mid, toReturn, returnAp, ap0, config)
|
||||
exists(Node mid, AccessPathApprox apa0 |
|
||||
readFlowFwd(node, _, mid, apa, apa0, config) and
|
||||
flow(mid, toReturn, returnApa, apa0, config)
|
||||
)
|
||||
or
|
||||
// flow into a callable
|
||||
exists(DataFlowCall call |
|
||||
flowIn(call, node, toReturn, returnAp, ap, config) and
|
||||
flowIn(call, node, toReturn, returnApa, apa, config) and
|
||||
toReturn = false
|
||||
or
|
||||
exists(AccessPath returnAp0 |
|
||||
flowInToReturn(call, node, returnAp0, ap, config) and
|
||||
flowIsReturned(call, toReturn, returnAp, returnAp0, config)
|
||||
exists(AccessPathApprox returnApa0 |
|
||||
flowInToReturn(call, node, returnApa0, apa, config) and
|
||||
flowIsReturned(call, toReturn, returnApa, returnApa0, config)
|
||||
)
|
||||
)
|
||||
or
|
||||
// flow out of a callable
|
||||
flowOut(_, node, _, _, ap, config) and
|
||||
flowOut(_, node, _, _, apa, config) and
|
||||
toReturn = true and
|
||||
if flowFwd(node, any(CallContextCall ccc), TAccessPathSome(_), _, ap, config)
|
||||
then returnAp = TAccessPathSome(ap)
|
||||
else returnAp = TAccessPathNone()
|
||||
if flowFwd(node, any(CallContextCall ccc), TAccessPathApproxSome(_), _, apa, config)
|
||||
then returnApa = TAccessPathApproxSome(apa)
|
||||
else returnApa = TAccessPathApproxNone()
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate storeFlowFwd(
|
||||
Node node1, TypedContent tc, Node node2, AccessPath ap, AccessPath ap0, Configuration config
|
||||
Node node1, TypedContent tc, Node node2, AccessPathApprox apa, AccessPathApprox apa0,
|
||||
Configuration config
|
||||
) {
|
||||
storeCand2(node1, tc, node2, _, config) and
|
||||
flowFwdStore(node2, tc, ap, _, _, _, config) and
|
||||
ap0 = push(tc, ap)
|
||||
flowFwdStore(node2, tc, apa, _, _, _, config) and
|
||||
apa0 = push(tc, apa)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate flowStore(
|
||||
TypedContent tc, Node node, boolean toReturn, AccessPathOption returnAp, AccessPath ap,
|
||||
Configuration config
|
||||
TypedContent tc, Node node, boolean toReturn, AccessPathApproxOption returnApa,
|
||||
AccessPathApprox apa, Configuration config
|
||||
) {
|
||||
exists(Node mid, AccessPath ap0 |
|
||||
storeFlowFwd(node, tc, mid, ap, ap0, config) and
|
||||
flow(mid, toReturn, returnAp, ap0, config)
|
||||
exists(Node mid, AccessPathApprox apa0 |
|
||||
storeFlowFwd(node, tc, mid, apa, apa0, config) and
|
||||
flow(mid, toReturn, returnApa, apa0, config)
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate readFlowFwd(
|
||||
Node node1, TypedContent tc, Node node2, AccessPath ap, AccessPath ap0, Configuration config
|
||||
Node node1, TypedContent tc, Node node2, AccessPathApprox apa, AccessPathApprox apa0,
|
||||
Configuration config
|
||||
) {
|
||||
exists(AccessPathFrontHead apf |
|
||||
readCandFwd(node1, tc, apf, node2, config) and
|
||||
flowFwdRead(node2, apf, ap, _, _, _, config) and
|
||||
ap0 = pop(tc, ap) and
|
||||
flowFwdConsCand(tc, _, ap0, unbind(config))
|
||||
flowFwdRead(node2, apf, apa, _, _, _, config) and
|
||||
apa0 = pop(tc, apa) and
|
||||
flowFwdConsCand(tc, _, apa0, unbind(config))
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate flowConsCand(TypedContent tc, AccessPath ap, Configuration config) {
|
||||
private predicate flowConsCand(TypedContent tc, AccessPathApprox apa, Configuration config) {
|
||||
exists(Node n, Node mid |
|
||||
flow(mid, _, _, ap, config) and
|
||||
readFlowFwd(n, tc, mid, _, ap, config)
|
||||
flow(mid, _, _, apa, config) and
|
||||
readFlowFwd(n, tc, mid, _, apa, config)
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate flowOut(
|
||||
DataFlowCall call, ReturnNodeExt ret, boolean toReturn, AccessPathOption returnAp, AccessPath ap,
|
||||
Configuration config
|
||||
DataFlowCall call, ReturnNodeExt ret, boolean toReturn, AccessPathApproxOption returnApa,
|
||||
AccessPathApprox apa, Configuration config
|
||||
) {
|
||||
exists(Node out, boolean allowsFieldFlow |
|
||||
flow(out, toReturn, returnAp, ap, config) and
|
||||
flow(out, toReturn, returnApa, apa, config) and
|
||||
flowOutOfCallNodeCand2(call, ret, out, allowsFieldFlow, config)
|
||||
|
|
||||
ap instanceof AccessPathNil or allowsFieldFlow = true
|
||||
apa instanceof AccessPathApproxNil or allowsFieldFlow = true
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate flowIn(
|
||||
DataFlowCall call, ArgumentNode arg, boolean toReturn, AccessPathOption returnAp, AccessPath ap,
|
||||
Configuration config
|
||||
DataFlowCall call, ArgumentNode arg, boolean toReturn, AccessPathApproxOption returnApa,
|
||||
AccessPathApprox apa, Configuration config
|
||||
) {
|
||||
exists(ParameterNode p, boolean allowsFieldFlow |
|
||||
flow(p, toReturn, returnAp, ap, config) and
|
||||
flow(p, toReturn, returnApa, apa, config) and
|
||||
flowIntoCallNodeCand2(call, arg, p, allowsFieldFlow, config)
|
||||
|
|
||||
ap instanceof AccessPathNil or allowsFieldFlow = true
|
||||
apa instanceof AccessPathApproxNil or allowsFieldFlow = true
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate flowInToReturn(
|
||||
DataFlowCall call, ArgumentNode arg, AccessPath returnAp, AccessPath ap, Configuration config
|
||||
DataFlowCall call, ArgumentNode arg, AccessPathApprox returnApa, AccessPathApprox apa,
|
||||
Configuration config
|
||||
) {
|
||||
flowIn(call, arg, true, TAccessPathSome(returnAp), ap, config)
|
||||
flowIn(call, arg, true, TAccessPathApproxSome(returnApa), apa, config)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2023,12 +2030,12 @@ private predicate flowInToReturn(
|
||||
*/
|
||||
pragma[nomagic]
|
||||
private predicate flowIsReturned(
|
||||
DataFlowCall call, boolean toReturn, AccessPathOption returnAp, AccessPath ap,
|
||||
DataFlowCall call, boolean toReturn, AccessPathApproxOption returnApa, AccessPathApprox apa,
|
||||
Configuration config
|
||||
) {
|
||||
exists(ReturnNodeExt ret, CallContextCall ccc |
|
||||
flowOut(call, ret, toReturn, returnAp, ap, config) and
|
||||
flowFwd(ret, ccc, TAccessPathSome(_), _, ap, config) and
|
||||
flowOut(call, ret, toReturn, returnApa, apa, config) and
|
||||
flowFwd(ret, ccc, TAccessPathApproxSome(_), _, apa, config) and
|
||||
ccc.matchesCall(call)
|
||||
)
|
||||
}
|
||||
@@ -2040,19 +2047,19 @@ private predicate flow(Node n, Configuration config) { flow(n, _, _, _, config)
|
||||
|
||||
pragma[noinline]
|
||||
private predicate parameterFlow(
|
||||
ParameterNode p, AccessPath ap, DataFlowCallable c, Configuration config
|
||||
ParameterNode p, AccessPathApprox apa, DataFlowCallable c, Configuration config
|
||||
) {
|
||||
flow(p, true, _, ap, config) and
|
||||
flow(p, true, _, apa, config) and
|
||||
c = p.getEnclosingCallable()
|
||||
}
|
||||
|
||||
private newtype TSummaryCtx =
|
||||
TSummaryCtxNone() or
|
||||
TSummaryCtxSome(ParameterNode p, AccessPath ap) {
|
||||
exists(ReturnNodeExt ret, Configuration config, AccessPath ap0 |
|
||||
parameterFlow(p, ap, ret.getEnclosingCallable(), config) and
|
||||
flow(ret, true, TAccessPathSome(_), ap0, config) and
|
||||
flowFwd(ret, any(CallContextCall ccc), TAccessPathSome(ap), _, ap0, config)
|
||||
TSummaryCtxSome(ParameterNode p, AccessPathApprox apa) {
|
||||
exists(ReturnNodeExt ret, Configuration config, AccessPathApprox apa0 |
|
||||
parameterFlow(p, apa, ret.getEnclosingCallable(), config) and
|
||||
flow(ret, true, TAccessPathApproxSome(_), apa0, config) and
|
||||
flowFwd(ret, any(CallContextCall ccc), TAccessPathApproxSome(apa), _, apa0, config)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -2074,13 +2081,13 @@ private class SummaryCtxNone extends SummaryCtx, TSummaryCtxNone {
|
||||
/** A summary context from which a flow summary can be generated. */
|
||||
private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
|
||||
private ParameterNode p;
|
||||
private AccessPath ap;
|
||||
private AccessPathApprox apa;
|
||||
|
||||
SummaryCtxSome() { this = TSummaryCtxSome(p, ap) }
|
||||
SummaryCtxSome() { this = TSummaryCtxSome(p, apa) }
|
||||
|
||||
int getParameterPos() { p.isParameterOf(_, result) }
|
||||
|
||||
override string toString() { result = p + ": " + ap }
|
||||
override string toString() { result = p + ": " + apa }
|
||||
|
||||
predicate hasLocationInfo(
|
||||
string filepath, int startline, int startcolumn, int endline, int endcolumn
|
||||
@@ -2090,19 +2097,19 @@ private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
|
||||
}
|
||||
|
||||
private newtype TPathNode =
|
||||
TPathNodeMid(Node node, CallContext cc, SummaryCtx sc, AccessPath ap, Configuration config) {
|
||||
TPathNodeMid(Node node, CallContext cc, SummaryCtx sc, AccessPathApprox apa, 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 = TNil(getNodeType(node))
|
||||
apa = TNil(getNodeType(node))
|
||||
or
|
||||
// ... or a step from an existing PathNode to another node.
|
||||
exists(PathNodeMid mid |
|
||||
pathStep(mid, node, cc, sc, ap) and
|
||||
pathStep(mid, node, cc, sc, apa) and
|
||||
config = mid.getConfiguration() and
|
||||
flow(node, _, _, ap, unbind(config))
|
||||
flow(node, _, _, apa, unbind(config))
|
||||
)
|
||||
} or
|
||||
TPathNodeSink(Node node, Configuration config) {
|
||||
@@ -2114,7 +2121,7 @@ private newtype TPathNode =
|
||||
or
|
||||
// ... or a sink that can be reached from a source
|
||||
exists(PathNodeMid mid |
|
||||
pathStep(mid, node, _, _, any(AccessPathNil nil)) and
|
||||
pathStep(mid, node, _, _, any(AccessPathApproxNil nil)) and
|
||||
config = unbind(mid.getConfiguration())
|
||||
)
|
||||
)
|
||||
@@ -2232,10 +2239,10 @@ private class PathNodeMid extends PathNodeImpl, TPathNodeMid {
|
||||
Node node;
|
||||
CallContext cc;
|
||||
SummaryCtx sc;
|
||||
AccessPath ap;
|
||||
AccessPathApprox apa;
|
||||
Configuration config;
|
||||
|
||||
PathNodeMid() { this = TPathNodeMid(node, cc, sc, ap, config) }
|
||||
PathNodeMid() { this = TPathNodeMid(node, cc, sc, apa, config) }
|
||||
|
||||
override Node getNode() { result = node }
|
||||
|
||||
@@ -2243,7 +2250,7 @@ private class PathNodeMid extends PathNodeImpl, TPathNodeMid {
|
||||
|
||||
SummaryCtx getSummaryCtx() { result = sc }
|
||||
|
||||
AccessPath getAp() { result = ap }
|
||||
AccessPathApprox getAp() { result = apa }
|
||||
|
||||
override Configuration getConfiguration() { result = config }
|
||||
|
||||
@@ -2260,7 +2267,7 @@ private class PathNodeMid extends PathNodeImpl, TPathNodeMid {
|
||||
exists(PathNodeMid mid, PathNodeSink sink |
|
||||
mid = getSuccMid() and
|
||||
mid.getNode() = sink.getNode() and
|
||||
mid.getAp() instanceof AccessPathNil and
|
||||
mid.getAp() instanceof AccessPathApproxNil and
|
||||
sink.getConfiguration() = unbind(mid.getConfiguration()) and
|
||||
result = sink
|
||||
)
|
||||
@@ -2270,7 +2277,7 @@ private class PathNodeMid extends PathNodeImpl, TPathNodeMid {
|
||||
config.isSource(node) and
|
||||
cc instanceof CallContextAny and
|
||||
sc instanceof SummaryCtxNone and
|
||||
ap instanceof AccessPathNil
|
||||
apa instanceof AccessPathApproxNil
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2298,44 +2305,46 @@ 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) {
|
||||
exists(AccessPath ap0, Node midnode, Configuration conf, LocalCallContext localCC |
|
||||
private predicate pathStep(
|
||||
PathNodeMid mid, Node node, CallContext cc, SummaryCtx sc, AccessPathApprox apa
|
||||
) {
|
||||
exists(AccessPathApprox apa0, Node midnode, Configuration conf, LocalCallContext localCC |
|
||||
midnode = mid.getNode() and
|
||||
conf = mid.getConfiguration() and
|
||||
cc = mid.getCallContext() and
|
||||
sc = mid.getSummaryCtx() and
|
||||
localCC = getLocalCallContext(cc, midnode.getEnclosingCallable()) and
|
||||
ap0 = mid.getAp()
|
||||
apa0 = mid.getAp()
|
||||
|
|
||||
localFlowBigStep(midnode, node, true, _, conf, localCC) and
|
||||
ap = ap0
|
||||
apa = apa0
|
||||
or
|
||||
localFlowBigStep(midnode, node, false, ap.getFront(), conf, localCC) and
|
||||
ap0 instanceof AccessPathNil
|
||||
localFlowBigStep(midnode, node, false, apa.getFront(), conf, localCC) and
|
||||
apa0 instanceof AccessPathApproxNil
|
||||
)
|
||||
or
|
||||
jumpStep(mid.getNode(), node, mid.getConfiguration()) and
|
||||
cc instanceof CallContextAny and
|
||||
sc instanceof SummaryCtxNone and
|
||||
ap = mid.getAp()
|
||||
apa = mid.getAp()
|
||||
or
|
||||
additionalJumpStep(mid.getNode(), node, mid.getConfiguration()) and
|
||||
cc instanceof CallContextAny and
|
||||
sc instanceof SummaryCtxNone and
|
||||
mid.getAp() instanceof AccessPathNil and
|
||||
ap = TNil(getNodeType(node))
|
||||
mid.getAp() instanceof AccessPathApproxNil and
|
||||
apa = TNil(getNodeType(node))
|
||||
or
|
||||
exists(TypedContent tc | pathStoreStep(mid, node, pop(tc, ap), tc, cc)) and
|
||||
exists(TypedContent tc | pathStoreStep(mid, node, pop(tc, apa), tc, cc)) and
|
||||
sc = mid.getSummaryCtx()
|
||||
or
|
||||
exists(TypedContent tc | pathReadStep(mid, node, push(tc, ap), tc, cc)) and
|
||||
exists(TypedContent tc | pathReadStep(mid, node, push(tc, apa), tc, cc)) and
|
||||
sc = mid.getSummaryCtx()
|
||||
or
|
||||
pathIntoCallable(mid, node, _, cc, sc, _) and ap = mid.getAp()
|
||||
pathIntoCallable(mid, node, _, cc, sc, _) and apa = mid.getAp()
|
||||
or
|
||||
pathOutOfCallable(mid, node, cc) and ap = mid.getAp() and sc instanceof SummaryCtxNone
|
||||
pathOutOfCallable(mid, node, cc) and apa = mid.getAp() and sc instanceof SummaryCtxNone
|
||||
or
|
||||
pathThroughCallable(mid, node, cc, ap) and sc = mid.getSummaryCtx()
|
||||
pathThroughCallable(mid, node, cc, apa) and sc = mid.getSummaryCtx()
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
@@ -2346,9 +2355,9 @@ private predicate readCand(Node node1, TypedContent tc, Node node2, Configuratio
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate pathReadStep(
|
||||
PathNodeMid mid, Node node, AccessPath ap0, TypedContent tc, CallContext cc
|
||||
PathNodeMid mid, Node node, AccessPathApprox apa0, TypedContent tc, CallContext cc
|
||||
) {
|
||||
ap0 = mid.getAp() and
|
||||
apa0 = mid.getAp() and
|
||||
readCand(mid.getNode(), tc, node, mid.getConfiguration()) and
|
||||
cc = mid.getCallContext()
|
||||
}
|
||||
@@ -2361,30 +2370,31 @@ private predicate storeCand(Node node1, TypedContent tc, Node node2, Configurati
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate pathStoreStep(
|
||||
PathNodeMid mid, Node node, AccessPath ap0, TypedContent tc, CallContext cc
|
||||
PathNodeMid mid, Node node, AccessPathApprox apa0, TypedContent tc, CallContext cc
|
||||
) {
|
||||
ap0 = mid.getAp() and
|
||||
apa0 = mid.getAp() and
|
||||
storeCand(mid.getNode(), tc, node, mid.getConfiguration()) and
|
||||
cc = mid.getCallContext()
|
||||
}
|
||||
|
||||
private predicate pathOutOfCallable0(
|
||||
PathNodeMid mid, ReturnPosition pos, CallContext innercc, AccessPath ap, Configuration config
|
||||
PathNodeMid mid, ReturnPosition pos, CallContext innercc, AccessPathApprox apa,
|
||||
Configuration config
|
||||
) {
|
||||
pos = getReturnPosition(mid.getNode()) and
|
||||
innercc = mid.getCallContext() and
|
||||
innercc instanceof CallContextNoCall and
|
||||
ap = mid.getAp() and
|
||||
apa = mid.getAp() and
|
||||
config = mid.getConfiguration()
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate pathOutOfCallable1(
|
||||
PathNodeMid mid, DataFlowCall call, ReturnKindExt kind, CallContext cc, AccessPath ap,
|
||||
PathNodeMid mid, DataFlowCall call, ReturnKindExt kind, CallContext cc, AccessPathApprox apa,
|
||||
Configuration config
|
||||
) {
|
||||
exists(ReturnPosition pos, DataFlowCallable c, CallContext innercc |
|
||||
pathOutOfCallable0(mid, pos, innercc, ap, config) and
|
||||
pathOutOfCallable0(mid, pos, innercc, apa, config) and
|
||||
c = pos.getCallable() and
|
||||
kind = pos.getKind() and
|
||||
resolveReturn(innercc, c, call)
|
||||
@@ -2395,10 +2405,10 @@ private predicate pathOutOfCallable1(
|
||||
|
||||
pragma[noinline]
|
||||
private Node getAnOutNodeFlow(
|
||||
ReturnKindExt kind, DataFlowCall call, AccessPath ap, Configuration config
|
||||
ReturnKindExt kind, DataFlowCall call, AccessPathApprox apa, Configuration config
|
||||
) {
|
||||
result = kind.getAnOutNode(call) and
|
||||
flow(result, _, _, ap, config)
|
||||
flow(result, _, _, apa, config)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2407,10 +2417,10 @@ private Node getAnOutNodeFlow(
|
||||
*/
|
||||
pragma[noinline]
|
||||
private predicate pathOutOfCallable(PathNodeMid mid, Node out, CallContext cc) {
|
||||
exists(ReturnKindExt kind, DataFlowCall call, AccessPath ap, Configuration config |
|
||||
pathOutOfCallable1(mid, call, kind, cc, ap, config)
|
||||
exists(ReturnKindExt kind, DataFlowCall call, AccessPathApprox apa, Configuration config |
|
||||
pathOutOfCallable1(mid, call, kind, cc, apa, config)
|
||||
|
|
||||
out = getAnOutNodeFlow(kind, call, ap, config)
|
||||
out = getAnOutNodeFlow(kind, call, apa, config)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -2419,22 +2429,22 @@ private predicate pathOutOfCallable(PathNodeMid mid, Node out, CallContext cc) {
|
||||
*/
|
||||
pragma[noinline]
|
||||
private predicate pathIntoArg(
|
||||
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap
|
||||
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPathApprox apa
|
||||
) {
|
||||
exists(ArgumentNode arg |
|
||||
arg = mid.getNode() and
|
||||
cc = mid.getCallContext() and
|
||||
arg.argumentOf(call, i) and
|
||||
ap = mid.getAp()
|
||||
apa = mid.getAp()
|
||||
)
|
||||
}
|
||||
|
||||
pragma[noinline]
|
||||
private predicate parameterCand(
|
||||
DataFlowCallable callable, int i, AccessPath ap, Configuration config
|
||||
DataFlowCallable callable, int i, AccessPathApprox apa, Configuration config
|
||||
) {
|
||||
exists(ParameterNode p |
|
||||
flow(p, _, _, ap, config) and
|
||||
flow(p, _, _, apa, config) and
|
||||
p.isParameterOf(callable, i)
|
||||
)
|
||||
}
|
||||
@@ -2442,11 +2452,11 @@ private predicate parameterCand(
|
||||
pragma[nomagic]
|
||||
private predicate pathIntoCallable0(
|
||||
PathNodeMid mid, DataFlowCallable callable, int i, CallContext outercc, DataFlowCall call,
|
||||
AccessPath ap
|
||||
AccessPathApprox apa
|
||||
) {
|
||||
pathIntoArg(mid, i, outercc, call, ap) and
|
||||
pathIntoArg(mid, i, outercc, call, apa) and
|
||||
callable = resolveCall(call, outercc) and
|
||||
parameterCand(callable, any(int j | j <= i and j >= i), ap, mid.getConfiguration())
|
||||
parameterCand(callable, any(int j | j <= i and j >= i), apa, mid.getConfiguration())
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2458,13 +2468,13 @@ private predicate pathIntoCallable(
|
||||
PathNodeMid mid, ParameterNode p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
|
||||
DataFlowCall call
|
||||
) {
|
||||
exists(int i, DataFlowCallable callable, AccessPath ap |
|
||||
pathIntoCallable0(mid, callable, i, outercc, call, ap) and
|
||||
exists(int i, DataFlowCallable callable, AccessPathApprox apa |
|
||||
pathIntoCallable0(mid, callable, i, outercc, call, apa) and
|
||||
p.isParameterOf(callable, i) and
|
||||
(
|
||||
sc = TSummaryCtxSome(p, ap)
|
||||
sc = TSummaryCtxSome(p, apa)
|
||||
or
|
||||
not exists(TSummaryCtxSome(p, ap)) and
|
||||
not exists(TSummaryCtxSome(p, apa)) and
|
||||
sc = TSummaryCtxNone()
|
||||
)
|
||||
|
|
||||
@@ -2477,7 +2487,8 @@ private predicate pathIntoCallable(
|
||||
/** Holds if data may flow from a parameter given by `sc` to a return of kind `kind`. */
|
||||
pragma[nomagic]
|
||||
private predicate paramFlowsThrough(
|
||||
ReturnKindExt kind, CallContextCall cc, SummaryCtxSome sc, AccessPath ap, Configuration config
|
||||
ReturnKindExt kind, CallContextCall cc, SummaryCtxSome sc, AccessPathApprox apa,
|
||||
Configuration config
|
||||
) {
|
||||
exists(PathNodeMid mid, ReturnNodeExt ret, int pos |
|
||||
mid.getNode() = ret and
|
||||
@@ -2485,7 +2496,7 @@ private predicate paramFlowsThrough(
|
||||
cc = mid.getCallContext() and
|
||||
sc = mid.getSummaryCtx() and
|
||||
config = mid.getConfiguration() and
|
||||
ap = mid.getAp() and
|
||||
apa = mid.getAp() and
|
||||
pos = sc.getParameterPos() and
|
||||
not kind.(ParamUpdateReturnKind).getPosition() = pos
|
||||
)
|
||||
@@ -2493,11 +2504,11 @@ private predicate paramFlowsThrough(
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate pathThroughCallable0(
|
||||
DataFlowCall call, PathNodeMid mid, ReturnKindExt kind, CallContext cc, AccessPath ap
|
||||
DataFlowCall call, PathNodeMid mid, ReturnKindExt kind, CallContext cc, AccessPathApprox apa
|
||||
) {
|
||||
exists(CallContext innercc, SummaryCtx sc |
|
||||
pathIntoCallable(mid, _, cc, innercc, sc, call) and
|
||||
paramFlowsThrough(kind, innercc, sc, ap, unbind(mid.getConfiguration()))
|
||||
paramFlowsThrough(kind, innercc, sc, apa, unbind(mid.getConfiguration()))
|
||||
)
|
||||
}
|
||||
|
||||
@@ -2506,10 +2517,12 @@ 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) {
|
||||
private predicate pathThroughCallable(
|
||||
PathNodeMid mid, Node out, CallContext cc, AccessPathApprox apa
|
||||
) {
|
||||
exists(DataFlowCall call, ReturnKindExt kind |
|
||||
pathThroughCallable0(call, mid, kind, cc, ap) and
|
||||
out = getAnOutNodeFlow(kind, call, ap, mid.getConfiguration())
|
||||
pathThroughCallable0(call, mid, kind, cc, apa) and
|
||||
out = getAnOutNodeFlow(kind, call, apa, mid.getConfiguration())
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user