Data flow: Sync files

This commit is contained in:
Tom Hvitved
2020-06-29 20:02:37 +02:00
parent 2d29fa1d15
commit 9ebf8d1d58
21 changed files with 1245 additions and 837 deletions

View File

@@ -1066,7 +1066,7 @@ private module LocalFlowBigStep {
* Holds if `node` can be the first node in a maximal subsequence of local * Holds if `node` can be the first node in a maximal subsequence of local
* flow steps in a dataflow path. * flow steps in a dataflow path.
*/ */
private predicate localFlowEntry(Node node, Configuration config) { predicate localFlowEntry(Node node, Configuration config) {
nodeCand2(node, config) and nodeCand2(node, config) and
( (
config.isSource(node) or config.isSource(node) or
@@ -1650,53 +1650,53 @@ private class AccessPathOption extends TAccessPathOption {
* Holds if `node` is reachable with access path `ap` from a source in * Holds if `node` is reachable with access path `ap` from a source in
* the configuration `config`. * the configuration `config`.
* *
* The Boolean `fromArg` records whether the node is reached through an * 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 in a call, and if so, `argAp` records the access path of that
* argument. * argument.
*/ */
private predicate flowFwd( private predicate flowFwd(
Node node, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Node node, CallContext cc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap,
Configuration config Configuration config
) { ) {
flowFwd0(node, fromArg, argAp, apf, ap, config) and flowFwd0(node, cc, argAp, apf, ap, config) and
flowCand(node, _, _, apf, config) flowCand(node, _, _, apf, config)
} }
private predicate flowFwd0( private predicate flowFwd0(
Node node, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Node node, CallContext cc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap,
Configuration config Configuration config
) { ) {
flowCand(node, _, _, _, config) and flowCand(node, _, _, _, config) and
config.isSource(node) and config.isSource(node) and
fromArg = false and cc instanceof CallContextAny and
argAp = TAccessPathNone() and argAp = TAccessPathNone() and
ap = TNil(getNodeType(node)) and ap = TNil(getNodeType(node)) and
apf = ap.(AccessPathNil).getFront() apf = ap.(AccessPathNil).getFront()
or or
flowCand(node, _, _, _, unbind(config)) and flowCand(node, _, _, _, unbind(config)) and
( (
exists(Node mid | exists(Node mid, LocalCallContext localCC |
flowFwd(mid, fromArg, argAp, apf, ap, config) and flowFwdLocalEntry(mid, cc, argAp, apf, ap, localCC, config) and
localFlowBigStep(mid, node, true, _, config, _) localFlowBigStep(mid, node, true, _, config, localCC)
) )
or or
exists(Node mid, AccessPathNil nil | exists(Node mid, AccessPathNil nil, LocalCallContext localCC |
flowFwd(mid, fromArg, argAp, _, nil, config) and flowFwdLocalEntry(mid, cc, argAp, _, nil, localCC, config) and
localFlowBigStep(mid, node, false, apf, config, _) and localFlowBigStep(mid, node, false, apf, config, localCC) and
apf = ap.(AccessPathNil).getFront() apf = ap.(AccessPathNil).getFront()
) )
or or
exists(Node mid | exists(Node mid |
flowFwd(mid, _, _, apf, ap, config) and flowFwd(mid, _, _, apf, ap, config) and
jumpStep(mid, node, config) and jumpStep(mid, node, config) and
fromArg = false and cc instanceof CallContextAny and
argAp = TAccessPathNone() argAp = TAccessPathNone()
) )
or or
exists(Node mid, AccessPathNil nil | exists(Node mid, AccessPathNil nil |
flowFwd(mid, _, _, _, nil, config) and flowFwd(mid, _, _, _, nil, config) and
additionalJumpStep(mid, node, config) and additionalJumpStep(mid, node, config) and
fromArg = false and cc instanceof CallContextAny and
argAp = TAccessPathNone() and argAp = TAccessPathNone() and
ap = TNil(getNodeType(node)) and ap = TNil(getNodeType(node)) and
apf = ap.(AccessPathNil).getFront() apf = ap.(AccessPathNil).getFront()
@@ -1704,40 +1704,51 @@ private predicate flowFwd0(
) )
or or
// store // store
exists(TypedContent tc | flowFwdStore(node, tc, pop(tc, ap), apf, fromArg, argAp, config)) exists(TypedContent tc | flowFwdStore(node, tc, pop(tc, ap), apf, cc, argAp, config))
or or
// read // read
exists(TypedContent tc | exists(TypedContent tc |
flowFwdRead(node, _, push(tc, ap), apf, fromArg, argAp, config) and flowFwdRead(node, _, push(tc, ap), apf, cc, argAp, config) and
flowFwdConsCand(tc, apf, ap, config) flowFwdConsCand(tc, apf, ap, config)
) )
or or
// flow into a callable // flow into a callable
flowFwdIn(_, node, _, _, apf, ap, config) and flowFwdIn(_, node, cc, _, _, apf, ap, config) and
fromArg = true and
if flowCand(node, true, _, apf, config) if flowCand(node, true, _, apf, config)
then argAp = TAccessPathSome(ap) then argAp = TAccessPathSome(ap)
else argAp = TAccessPathNone() else argAp = TAccessPathNone()
or or
// flow out of a callable // flow out of a callable
exists(DataFlowCall call | exists(DataFlowCall call |
flowFwdOut(call, node, fromArg, argAp, apf, ap, config) and exists(CallContextNoCall innercc, DataFlowCallable c |
fromArg = false flowFwdOut(call, node, innercc, c, argAp, apf, ap, config) and
if reducedViableImplInReturn(c, call) then cc = TReturn(c, call) else cc = TAnyCallContext()
)
or or
exists(AccessPath argAp0 | exists(AccessPath argAp0 |
flowFwdOutFromArg(call, node, argAp0, apf, ap, config) and flowFwdOutFromArg(call, node, argAp0, apf, ap, config) and
flowFwdIsEntered(call, fromArg, argAp, argAp0, config) flowFwdIsEntered(call, cc, argAp, argAp0, config)
) )
) )
} }
pragma[nomagic]
private predicate flowFwdLocalEntry(
Node node, CallContext cc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap,
LocalCallContext localCC, Configuration config
) {
flowFwd(node, cc, argAp, apf, ap, config) and
localFlowEntry(node, config) and
localCC = getLocalCallContext(cc, node.getEnclosingCallable())
}
pragma[nomagic] pragma[nomagic]
private predicate flowFwdStore( private predicate flowFwdStore(
Node node, TypedContent tc, AccessPath ap0, AccessPathFront apf, boolean fromArg, Node node, TypedContent tc, AccessPath ap0, AccessPathFront apf, CallContext cc,
AccessPathOption argAp, Configuration config AccessPathOption argAp, Configuration config
) { ) {
exists(Node mid, AccessPathFront apf0 | exists(Node mid, AccessPathFront apf0 |
flowFwd(mid, fromArg, argAp, apf0, ap0, config) and flowFwd(mid, cc, argAp, apf0, ap0, config) and
flowFwdStore0(mid, tc, node, apf0, apf, config) flowFwdStore0(mid, tc, node, apf0, apf, config)
) )
} }
@@ -1764,20 +1775,20 @@ private predicate flowFwdStore0(
pragma[nomagic] pragma[nomagic]
private predicate flowFwdRead0( private predicate flowFwdRead0(
Node node1, TypedContent tc, AccessPathFrontHead apf0, AccessPath ap0, Node node2, Node node1, TypedContent tc, AccessPathFrontHead apf0, AccessPath ap0, Node node2, CallContext cc,
boolean fromArg, AccessPathOption argAp, Configuration config AccessPathOption argAp, Configuration config
) { ) {
flowFwd(node1, fromArg, argAp, apf0, ap0, config) and flowFwd(node1, cc, argAp, apf0, ap0, config) and
readCandFwd(node1, tc, apf0, node2, config) readCandFwd(node1, tc, apf0, node2, config)
} }
pragma[nomagic] pragma[nomagic]
private predicate flowFwdRead( private predicate flowFwdRead(
Node node, AccessPathFrontHead apf0, AccessPath ap0, AccessPathFront apf, boolean fromArg, Node node, AccessPathFrontHead apf0, AccessPath ap0, AccessPathFront apf, CallContext cc,
AccessPathOption argAp, Configuration config AccessPathOption argAp, Configuration config
) { ) {
exists(Node mid, TypedContent tc | exists(Node mid, TypedContent tc |
flowFwdRead0(mid, tc, apf0, ap0, node, fromArg, argAp, config) and flowFwdRead0(mid, tc, apf0, ap0, node, cc, argAp, config) and
flowCand(node, _, _, apf, unbind(config)) and flowCand(node, _, _, apf, unbind(config)) and
flowCandConsCand(tc, apf, unbind(config)) flowCandConsCand(tc, apf, unbind(config))
) )
@@ -1795,13 +1806,16 @@ private predicate flowFwdConsCand(
pragma[nomagic] pragma[nomagic]
private predicate flowFwdIn( private predicate flowFwdIn(
DataFlowCall call, ParameterNode p, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, DataFlowCall call, ParameterNode p, CallContext innercc, CallContext outercc,
AccessPath ap, Configuration config AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config
) { ) {
exists(ArgumentNode arg, boolean allowsFieldFlow | exists(ArgumentNode arg, boolean allowsFieldFlow, DataFlowCallable c |
flowFwd(arg, fromArg, argAp, apf, ap, config) and flowFwd(arg, outercc, argAp, apf, ap, config) and
flowIntoCallNodeCand2(call, arg, p, allowsFieldFlow, config) and flowIntoCallNodeCand2(call, arg, p, allowsFieldFlow, config) and
flowCand(p, _, _, _, unbind(config)) 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 ap instanceof AccessPathNil or allowsFieldFlow = true
) )
@@ -1809,13 +1823,19 @@ private predicate flowFwdIn(
pragma[nomagic] pragma[nomagic]
private predicate flowFwdOut( private predicate flowFwdOut(
DataFlowCall call, Node node, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, DataFlowCall call, Node node, CallContext innercc, DataFlowCallable innerc,
AccessPath ap, Configuration config AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config
) { ) {
exists(ReturnNodeExt ret, boolean allowsFieldFlow | exists(ReturnNodeExt ret, boolean allowsFieldFlow |
flowFwd(ret, fromArg, argAp, apf, ap, config) and flowFwd(ret, innercc, argAp, apf, ap, config) and
flowOutOfCallNodeCand2(call, ret, node, allowsFieldFlow, config) and flowOutOfCallNodeCand2(call, ret, node, allowsFieldFlow, config) and
flowCand(node, _, _, _, unbind(config)) innerc = ret.getEnclosingCallable() and
flowCand(node, _, _, _, unbind(config)) and
(
resolveReturn(innercc, innerc, call)
or
innercc.(CallContextCall).matchesCall(call)
)
| |
ap instanceof AccessPathNil or allowsFieldFlow = true ap instanceof AccessPathNil or allowsFieldFlow = true
) )
@@ -1826,7 +1846,7 @@ private predicate flowFwdOutFromArg(
DataFlowCall call, Node node, AccessPath argAp, AccessPathFront apf, AccessPath ap, DataFlowCall call, Node node, AccessPath argAp, AccessPathFront apf, AccessPath ap,
Configuration config Configuration config
) { ) {
flowFwdOut(call, node, true, TAccessPathSome(argAp), apf, ap, config) flowFwdOut(call, node, any(CallContextCall ccc), _, TAccessPathSome(argAp), apf, ap, config)
} }
/** /**
@@ -1834,10 +1854,10 @@ private predicate flowFwdOutFromArg(
*/ */
pragma[nomagic] pragma[nomagic]
private predicate flowFwdIsEntered( private predicate flowFwdIsEntered(
DataFlowCall call, boolean fromArg, AccessPathOption argAp, AccessPath ap, Configuration config DataFlowCall call, CallContext cc, AccessPathOption argAp, AccessPath ap, Configuration config
) { ) {
exists(ParameterNode p, AccessPathFront apf | exists(ParameterNode p, AccessPathFront apf |
flowFwdIn(call, p, fromArg, argAp, apf, ap, config) and flowFwdIn(call, p, _, cc, argAp, apf, ap, config) and
flowCand(p, true, TAccessPathFrontSome(_), apf, config) flowCand(p, true, TAccessPathFrontSome(_), apf, config)
) )
} }
@@ -1920,7 +1940,7 @@ private predicate flow0(
// flow out of a callable // flow out of a callable
flowOut(_, node, _, _, ap, config) and flowOut(_, node, _, _, ap, config) and
toReturn = true and toReturn = true and
if flowFwd(node, true, TAccessPathSome(_), _, ap, config) if flowFwd(node, any(CallContextCall ccc), TAccessPathSome(_), _, ap, config)
then returnAp = TAccessPathSome(ap) then returnAp = TAccessPathSome(ap)
else returnAp = TAccessPathNone() else returnAp = TAccessPathNone()
} }
@@ -2006,9 +2026,10 @@ private predicate flowIsReturned(
DataFlowCall call, boolean toReturn, AccessPathOption returnAp, AccessPath ap, DataFlowCall call, boolean toReturn, AccessPathOption returnAp, AccessPath ap,
Configuration config Configuration config
) { ) {
exists(ReturnNodeExt ret | exists(ReturnNodeExt ret, CallContextCall ccc |
flowOut(call, ret, toReturn, returnAp, ap, config) and flowOut(call, ret, toReturn, returnAp, ap, config) and
flowFwd(ret, true, TAccessPathSome(_), _, ap, config) flowFwd(ret, ccc, TAccessPathSome(_), _, ap, config) and
ccc.matchesCall(call)
) )
} }
@@ -2031,7 +2052,7 @@ private newtype TSummaryCtx =
exists(ReturnNodeExt ret, Configuration config, AccessPath ap0 | exists(ReturnNodeExt ret, Configuration config, AccessPath ap0 |
parameterFlow(p, ap, ret.getEnclosingCallable(), config) and parameterFlow(p, ap, ret.getEnclosingCallable(), config) and
flow(ret, true, TAccessPathSome(_), ap0, config) and flow(ret, true, TAccessPathSome(_), ap0, config) and
flowFwd(ret, true, TAccessPathSome(ap), _, ap0, config) flowFwd(ret, any(CallContextCall ccc), TAccessPathSome(ap), _, ap0, config)
) )
} }
@@ -2352,7 +2373,7 @@ private predicate pathOutOfCallable0(
) { ) {
pos = getReturnPosition(mid.getNode()) and pos = getReturnPosition(mid.getNode()) and
innercc = mid.getCallContext() and innercc = mid.getCallContext() and
not innercc instanceof CallContextCall and innercc instanceof CallContextNoCall and
ap = mid.getAp() and ap = mid.getAp() and
config = mid.getConfiguration() config = mid.getConfiguration()
} }
@@ -2867,7 +2888,7 @@ private module FlowExploration {
) { ) {
pos = getReturnPosition(mid.getNode()) and pos = getReturnPosition(mid.getNode()) and
innercc = mid.getCallContext() and innercc = mid.getCallContext() and
not innercc instanceof CallContextCall and innercc instanceof CallContextNoCall and
ap = mid.getAp() and ap = mid.getAp() and
config = mid.getConfiguration() config = mid.getConfiguration()
} }

View File

@@ -1066,7 +1066,7 @@ private module LocalFlowBigStep {
* Holds if `node` can be the first node in a maximal subsequence of local * Holds if `node` can be the first node in a maximal subsequence of local
* flow steps in a dataflow path. * flow steps in a dataflow path.
*/ */
private predicate localFlowEntry(Node node, Configuration config) { predicate localFlowEntry(Node node, Configuration config) {
nodeCand2(node, config) and nodeCand2(node, config) and
( (
config.isSource(node) or config.isSource(node) or
@@ -1650,53 +1650,53 @@ private class AccessPathOption extends TAccessPathOption {
* Holds if `node` is reachable with access path `ap` from a source in * Holds if `node` is reachable with access path `ap` from a source in
* the configuration `config`. * the configuration `config`.
* *
* The Boolean `fromArg` records whether the node is reached through an * 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 in a call, and if so, `argAp` records the access path of that
* argument. * argument.
*/ */
private predicate flowFwd( private predicate flowFwd(
Node node, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Node node, CallContext cc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap,
Configuration config Configuration config
) { ) {
flowFwd0(node, fromArg, argAp, apf, ap, config) and flowFwd0(node, cc, argAp, apf, ap, config) and
flowCand(node, _, _, apf, config) flowCand(node, _, _, apf, config)
} }
private predicate flowFwd0( private predicate flowFwd0(
Node node, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Node node, CallContext cc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap,
Configuration config Configuration config
) { ) {
flowCand(node, _, _, _, config) and flowCand(node, _, _, _, config) and
config.isSource(node) and config.isSource(node) and
fromArg = false and cc instanceof CallContextAny and
argAp = TAccessPathNone() and argAp = TAccessPathNone() and
ap = TNil(getNodeType(node)) and ap = TNil(getNodeType(node)) and
apf = ap.(AccessPathNil).getFront() apf = ap.(AccessPathNil).getFront()
or or
flowCand(node, _, _, _, unbind(config)) and flowCand(node, _, _, _, unbind(config)) and
( (
exists(Node mid | exists(Node mid, LocalCallContext localCC |
flowFwd(mid, fromArg, argAp, apf, ap, config) and flowFwdLocalEntry(mid, cc, argAp, apf, ap, localCC, config) and
localFlowBigStep(mid, node, true, _, config, _) localFlowBigStep(mid, node, true, _, config, localCC)
) )
or or
exists(Node mid, AccessPathNil nil | exists(Node mid, AccessPathNil nil, LocalCallContext localCC |
flowFwd(mid, fromArg, argAp, _, nil, config) and flowFwdLocalEntry(mid, cc, argAp, _, nil, localCC, config) and
localFlowBigStep(mid, node, false, apf, config, _) and localFlowBigStep(mid, node, false, apf, config, localCC) and
apf = ap.(AccessPathNil).getFront() apf = ap.(AccessPathNil).getFront()
) )
or or
exists(Node mid | exists(Node mid |
flowFwd(mid, _, _, apf, ap, config) and flowFwd(mid, _, _, apf, ap, config) and
jumpStep(mid, node, config) and jumpStep(mid, node, config) and
fromArg = false and cc instanceof CallContextAny and
argAp = TAccessPathNone() argAp = TAccessPathNone()
) )
or or
exists(Node mid, AccessPathNil nil | exists(Node mid, AccessPathNil nil |
flowFwd(mid, _, _, _, nil, config) and flowFwd(mid, _, _, _, nil, config) and
additionalJumpStep(mid, node, config) and additionalJumpStep(mid, node, config) and
fromArg = false and cc instanceof CallContextAny and
argAp = TAccessPathNone() and argAp = TAccessPathNone() and
ap = TNil(getNodeType(node)) and ap = TNil(getNodeType(node)) and
apf = ap.(AccessPathNil).getFront() apf = ap.(AccessPathNil).getFront()
@@ -1704,40 +1704,51 @@ private predicate flowFwd0(
) )
or or
// store // store
exists(TypedContent tc | flowFwdStore(node, tc, pop(tc, ap), apf, fromArg, argAp, config)) exists(TypedContent tc | flowFwdStore(node, tc, pop(tc, ap), apf, cc, argAp, config))
or or
// read // read
exists(TypedContent tc | exists(TypedContent tc |
flowFwdRead(node, _, push(tc, ap), apf, fromArg, argAp, config) and flowFwdRead(node, _, push(tc, ap), apf, cc, argAp, config) and
flowFwdConsCand(tc, apf, ap, config) flowFwdConsCand(tc, apf, ap, config)
) )
or or
// flow into a callable // flow into a callable
flowFwdIn(_, node, _, _, apf, ap, config) and flowFwdIn(_, node, cc, _, _, apf, ap, config) and
fromArg = true and
if flowCand(node, true, _, apf, config) if flowCand(node, true, _, apf, config)
then argAp = TAccessPathSome(ap) then argAp = TAccessPathSome(ap)
else argAp = TAccessPathNone() else argAp = TAccessPathNone()
or or
// flow out of a callable // flow out of a callable
exists(DataFlowCall call | exists(DataFlowCall call |
flowFwdOut(call, node, fromArg, argAp, apf, ap, config) and exists(CallContextNoCall innercc, DataFlowCallable c |
fromArg = false flowFwdOut(call, node, innercc, c, argAp, apf, ap, config) and
if reducedViableImplInReturn(c, call) then cc = TReturn(c, call) else cc = TAnyCallContext()
)
or or
exists(AccessPath argAp0 | exists(AccessPath argAp0 |
flowFwdOutFromArg(call, node, argAp0, apf, ap, config) and flowFwdOutFromArg(call, node, argAp0, apf, ap, config) and
flowFwdIsEntered(call, fromArg, argAp, argAp0, config) flowFwdIsEntered(call, cc, argAp, argAp0, config)
) )
) )
} }
pragma[nomagic]
private predicate flowFwdLocalEntry(
Node node, CallContext cc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap,
LocalCallContext localCC, Configuration config
) {
flowFwd(node, cc, argAp, apf, ap, config) and
localFlowEntry(node, config) and
localCC = getLocalCallContext(cc, node.getEnclosingCallable())
}
pragma[nomagic] pragma[nomagic]
private predicate flowFwdStore( private predicate flowFwdStore(
Node node, TypedContent tc, AccessPath ap0, AccessPathFront apf, boolean fromArg, Node node, TypedContent tc, AccessPath ap0, AccessPathFront apf, CallContext cc,
AccessPathOption argAp, Configuration config AccessPathOption argAp, Configuration config
) { ) {
exists(Node mid, AccessPathFront apf0 | exists(Node mid, AccessPathFront apf0 |
flowFwd(mid, fromArg, argAp, apf0, ap0, config) and flowFwd(mid, cc, argAp, apf0, ap0, config) and
flowFwdStore0(mid, tc, node, apf0, apf, config) flowFwdStore0(mid, tc, node, apf0, apf, config)
) )
} }
@@ -1764,20 +1775,20 @@ private predicate flowFwdStore0(
pragma[nomagic] pragma[nomagic]
private predicate flowFwdRead0( private predicate flowFwdRead0(
Node node1, TypedContent tc, AccessPathFrontHead apf0, AccessPath ap0, Node node2, Node node1, TypedContent tc, AccessPathFrontHead apf0, AccessPath ap0, Node node2, CallContext cc,
boolean fromArg, AccessPathOption argAp, Configuration config AccessPathOption argAp, Configuration config
) { ) {
flowFwd(node1, fromArg, argAp, apf0, ap0, config) and flowFwd(node1, cc, argAp, apf0, ap0, config) and
readCandFwd(node1, tc, apf0, node2, config) readCandFwd(node1, tc, apf0, node2, config)
} }
pragma[nomagic] pragma[nomagic]
private predicate flowFwdRead( private predicate flowFwdRead(
Node node, AccessPathFrontHead apf0, AccessPath ap0, AccessPathFront apf, boolean fromArg, Node node, AccessPathFrontHead apf0, AccessPath ap0, AccessPathFront apf, CallContext cc,
AccessPathOption argAp, Configuration config AccessPathOption argAp, Configuration config
) { ) {
exists(Node mid, TypedContent tc | exists(Node mid, TypedContent tc |
flowFwdRead0(mid, tc, apf0, ap0, node, fromArg, argAp, config) and flowFwdRead0(mid, tc, apf0, ap0, node, cc, argAp, config) and
flowCand(node, _, _, apf, unbind(config)) and flowCand(node, _, _, apf, unbind(config)) and
flowCandConsCand(tc, apf, unbind(config)) flowCandConsCand(tc, apf, unbind(config))
) )
@@ -1795,13 +1806,16 @@ private predicate flowFwdConsCand(
pragma[nomagic] pragma[nomagic]
private predicate flowFwdIn( private predicate flowFwdIn(
DataFlowCall call, ParameterNode p, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, DataFlowCall call, ParameterNode p, CallContext innercc, CallContext outercc,
AccessPath ap, Configuration config AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config
) { ) {
exists(ArgumentNode arg, boolean allowsFieldFlow | exists(ArgumentNode arg, boolean allowsFieldFlow, DataFlowCallable c |
flowFwd(arg, fromArg, argAp, apf, ap, config) and flowFwd(arg, outercc, argAp, apf, ap, config) and
flowIntoCallNodeCand2(call, arg, p, allowsFieldFlow, config) and flowIntoCallNodeCand2(call, arg, p, allowsFieldFlow, config) and
flowCand(p, _, _, _, unbind(config)) 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 ap instanceof AccessPathNil or allowsFieldFlow = true
) )
@@ -1809,13 +1823,19 @@ private predicate flowFwdIn(
pragma[nomagic] pragma[nomagic]
private predicate flowFwdOut( private predicate flowFwdOut(
DataFlowCall call, Node node, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, DataFlowCall call, Node node, CallContext innercc, DataFlowCallable innerc,
AccessPath ap, Configuration config AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config
) { ) {
exists(ReturnNodeExt ret, boolean allowsFieldFlow | exists(ReturnNodeExt ret, boolean allowsFieldFlow |
flowFwd(ret, fromArg, argAp, apf, ap, config) and flowFwd(ret, innercc, argAp, apf, ap, config) and
flowOutOfCallNodeCand2(call, ret, node, allowsFieldFlow, config) and flowOutOfCallNodeCand2(call, ret, node, allowsFieldFlow, config) and
flowCand(node, _, _, _, unbind(config)) innerc = ret.getEnclosingCallable() and
flowCand(node, _, _, _, unbind(config)) and
(
resolveReturn(innercc, innerc, call)
or
innercc.(CallContextCall).matchesCall(call)
)
| |
ap instanceof AccessPathNil or allowsFieldFlow = true ap instanceof AccessPathNil or allowsFieldFlow = true
) )
@@ -1826,7 +1846,7 @@ private predicate flowFwdOutFromArg(
DataFlowCall call, Node node, AccessPath argAp, AccessPathFront apf, AccessPath ap, DataFlowCall call, Node node, AccessPath argAp, AccessPathFront apf, AccessPath ap,
Configuration config Configuration config
) { ) {
flowFwdOut(call, node, true, TAccessPathSome(argAp), apf, ap, config) flowFwdOut(call, node, any(CallContextCall ccc), _, TAccessPathSome(argAp), apf, ap, config)
} }
/** /**
@@ -1834,10 +1854,10 @@ private predicate flowFwdOutFromArg(
*/ */
pragma[nomagic] pragma[nomagic]
private predicate flowFwdIsEntered( private predicate flowFwdIsEntered(
DataFlowCall call, boolean fromArg, AccessPathOption argAp, AccessPath ap, Configuration config DataFlowCall call, CallContext cc, AccessPathOption argAp, AccessPath ap, Configuration config
) { ) {
exists(ParameterNode p, AccessPathFront apf | exists(ParameterNode p, AccessPathFront apf |
flowFwdIn(call, p, fromArg, argAp, apf, ap, config) and flowFwdIn(call, p, _, cc, argAp, apf, ap, config) and
flowCand(p, true, TAccessPathFrontSome(_), apf, config) flowCand(p, true, TAccessPathFrontSome(_), apf, config)
) )
} }
@@ -1920,7 +1940,7 @@ private predicate flow0(
// flow out of a callable // flow out of a callable
flowOut(_, node, _, _, ap, config) and flowOut(_, node, _, _, ap, config) and
toReturn = true and toReturn = true and
if flowFwd(node, true, TAccessPathSome(_), _, ap, config) if flowFwd(node, any(CallContextCall ccc), TAccessPathSome(_), _, ap, config)
then returnAp = TAccessPathSome(ap) then returnAp = TAccessPathSome(ap)
else returnAp = TAccessPathNone() else returnAp = TAccessPathNone()
} }
@@ -2006,9 +2026,10 @@ private predicate flowIsReturned(
DataFlowCall call, boolean toReturn, AccessPathOption returnAp, AccessPath ap, DataFlowCall call, boolean toReturn, AccessPathOption returnAp, AccessPath ap,
Configuration config Configuration config
) { ) {
exists(ReturnNodeExt ret | exists(ReturnNodeExt ret, CallContextCall ccc |
flowOut(call, ret, toReturn, returnAp, ap, config) and flowOut(call, ret, toReturn, returnAp, ap, config) and
flowFwd(ret, true, TAccessPathSome(_), _, ap, config) flowFwd(ret, ccc, TAccessPathSome(_), _, ap, config) and
ccc.matchesCall(call)
) )
} }
@@ -2031,7 +2052,7 @@ private newtype TSummaryCtx =
exists(ReturnNodeExt ret, Configuration config, AccessPath ap0 | exists(ReturnNodeExt ret, Configuration config, AccessPath ap0 |
parameterFlow(p, ap, ret.getEnclosingCallable(), config) and parameterFlow(p, ap, ret.getEnclosingCallable(), config) and
flow(ret, true, TAccessPathSome(_), ap0, config) and flow(ret, true, TAccessPathSome(_), ap0, config) and
flowFwd(ret, true, TAccessPathSome(ap), _, ap0, config) flowFwd(ret, any(CallContextCall ccc), TAccessPathSome(ap), _, ap0, config)
) )
} }
@@ -2352,7 +2373,7 @@ private predicate pathOutOfCallable0(
) { ) {
pos = getReturnPosition(mid.getNode()) and pos = getReturnPosition(mid.getNode()) and
innercc = mid.getCallContext() and innercc = mid.getCallContext() and
not innercc instanceof CallContextCall and innercc instanceof CallContextNoCall and
ap = mid.getAp() and ap = mid.getAp() and
config = mid.getConfiguration() config = mid.getConfiguration()
} }
@@ -2867,7 +2888,7 @@ private module FlowExploration {
) { ) {
pos = getReturnPosition(mid.getNode()) and pos = getReturnPosition(mid.getNode()) and
innercc = mid.getCallContext() and innercc = mid.getCallContext() and
not innercc instanceof CallContextCall and innercc instanceof CallContextNoCall and
ap = mid.getAp() and ap = mid.getAp() and
config = mid.getConfiguration() config = mid.getConfiguration()
} }

View File

@@ -1066,7 +1066,7 @@ private module LocalFlowBigStep {
* Holds if `node` can be the first node in a maximal subsequence of local * Holds if `node` can be the first node in a maximal subsequence of local
* flow steps in a dataflow path. * flow steps in a dataflow path.
*/ */
private predicate localFlowEntry(Node node, Configuration config) { predicate localFlowEntry(Node node, Configuration config) {
nodeCand2(node, config) and nodeCand2(node, config) and
( (
config.isSource(node) or config.isSource(node) or
@@ -1650,53 +1650,53 @@ private class AccessPathOption extends TAccessPathOption {
* Holds if `node` is reachable with access path `ap` from a source in * Holds if `node` is reachable with access path `ap` from a source in
* the configuration `config`. * the configuration `config`.
* *
* The Boolean `fromArg` records whether the node is reached through an * 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 in a call, and if so, `argAp` records the access path of that
* argument. * argument.
*/ */
private predicate flowFwd( private predicate flowFwd(
Node node, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Node node, CallContext cc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap,
Configuration config Configuration config
) { ) {
flowFwd0(node, fromArg, argAp, apf, ap, config) and flowFwd0(node, cc, argAp, apf, ap, config) and
flowCand(node, _, _, apf, config) flowCand(node, _, _, apf, config)
} }
private predicate flowFwd0( private predicate flowFwd0(
Node node, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Node node, CallContext cc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap,
Configuration config Configuration config
) { ) {
flowCand(node, _, _, _, config) and flowCand(node, _, _, _, config) and
config.isSource(node) and config.isSource(node) and
fromArg = false and cc instanceof CallContextAny and
argAp = TAccessPathNone() and argAp = TAccessPathNone() and
ap = TNil(getNodeType(node)) and ap = TNil(getNodeType(node)) and
apf = ap.(AccessPathNil).getFront() apf = ap.(AccessPathNil).getFront()
or or
flowCand(node, _, _, _, unbind(config)) and flowCand(node, _, _, _, unbind(config)) and
( (
exists(Node mid | exists(Node mid, LocalCallContext localCC |
flowFwd(mid, fromArg, argAp, apf, ap, config) and flowFwdLocalEntry(mid, cc, argAp, apf, ap, localCC, config) and
localFlowBigStep(mid, node, true, _, config, _) localFlowBigStep(mid, node, true, _, config, localCC)
) )
or or
exists(Node mid, AccessPathNil nil | exists(Node mid, AccessPathNil nil, LocalCallContext localCC |
flowFwd(mid, fromArg, argAp, _, nil, config) and flowFwdLocalEntry(mid, cc, argAp, _, nil, localCC, config) and
localFlowBigStep(mid, node, false, apf, config, _) and localFlowBigStep(mid, node, false, apf, config, localCC) and
apf = ap.(AccessPathNil).getFront() apf = ap.(AccessPathNil).getFront()
) )
or or
exists(Node mid | exists(Node mid |
flowFwd(mid, _, _, apf, ap, config) and flowFwd(mid, _, _, apf, ap, config) and
jumpStep(mid, node, config) and jumpStep(mid, node, config) and
fromArg = false and cc instanceof CallContextAny and
argAp = TAccessPathNone() argAp = TAccessPathNone()
) )
or or
exists(Node mid, AccessPathNil nil | exists(Node mid, AccessPathNil nil |
flowFwd(mid, _, _, _, nil, config) and flowFwd(mid, _, _, _, nil, config) and
additionalJumpStep(mid, node, config) and additionalJumpStep(mid, node, config) and
fromArg = false and cc instanceof CallContextAny and
argAp = TAccessPathNone() and argAp = TAccessPathNone() and
ap = TNil(getNodeType(node)) and ap = TNil(getNodeType(node)) and
apf = ap.(AccessPathNil).getFront() apf = ap.(AccessPathNil).getFront()
@@ -1704,40 +1704,51 @@ private predicate flowFwd0(
) )
or or
// store // store
exists(TypedContent tc | flowFwdStore(node, tc, pop(tc, ap), apf, fromArg, argAp, config)) exists(TypedContent tc | flowFwdStore(node, tc, pop(tc, ap), apf, cc, argAp, config))
or or
// read // read
exists(TypedContent tc | exists(TypedContent tc |
flowFwdRead(node, _, push(tc, ap), apf, fromArg, argAp, config) and flowFwdRead(node, _, push(tc, ap), apf, cc, argAp, config) and
flowFwdConsCand(tc, apf, ap, config) flowFwdConsCand(tc, apf, ap, config)
) )
or or
// flow into a callable // flow into a callable
flowFwdIn(_, node, _, _, apf, ap, config) and flowFwdIn(_, node, cc, _, _, apf, ap, config) and
fromArg = true and
if flowCand(node, true, _, apf, config) if flowCand(node, true, _, apf, config)
then argAp = TAccessPathSome(ap) then argAp = TAccessPathSome(ap)
else argAp = TAccessPathNone() else argAp = TAccessPathNone()
or or
// flow out of a callable // flow out of a callable
exists(DataFlowCall call | exists(DataFlowCall call |
flowFwdOut(call, node, fromArg, argAp, apf, ap, config) and exists(CallContextNoCall innercc, DataFlowCallable c |
fromArg = false flowFwdOut(call, node, innercc, c, argAp, apf, ap, config) and
if reducedViableImplInReturn(c, call) then cc = TReturn(c, call) else cc = TAnyCallContext()
)
or or
exists(AccessPath argAp0 | exists(AccessPath argAp0 |
flowFwdOutFromArg(call, node, argAp0, apf, ap, config) and flowFwdOutFromArg(call, node, argAp0, apf, ap, config) and
flowFwdIsEntered(call, fromArg, argAp, argAp0, config) flowFwdIsEntered(call, cc, argAp, argAp0, config)
) )
) )
} }
pragma[nomagic]
private predicate flowFwdLocalEntry(
Node node, CallContext cc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap,
LocalCallContext localCC, Configuration config
) {
flowFwd(node, cc, argAp, apf, ap, config) and
localFlowEntry(node, config) and
localCC = getLocalCallContext(cc, node.getEnclosingCallable())
}
pragma[nomagic] pragma[nomagic]
private predicate flowFwdStore( private predicate flowFwdStore(
Node node, TypedContent tc, AccessPath ap0, AccessPathFront apf, boolean fromArg, Node node, TypedContent tc, AccessPath ap0, AccessPathFront apf, CallContext cc,
AccessPathOption argAp, Configuration config AccessPathOption argAp, Configuration config
) { ) {
exists(Node mid, AccessPathFront apf0 | exists(Node mid, AccessPathFront apf0 |
flowFwd(mid, fromArg, argAp, apf0, ap0, config) and flowFwd(mid, cc, argAp, apf0, ap0, config) and
flowFwdStore0(mid, tc, node, apf0, apf, config) flowFwdStore0(mid, tc, node, apf0, apf, config)
) )
} }
@@ -1764,20 +1775,20 @@ private predicate flowFwdStore0(
pragma[nomagic] pragma[nomagic]
private predicate flowFwdRead0( private predicate flowFwdRead0(
Node node1, TypedContent tc, AccessPathFrontHead apf0, AccessPath ap0, Node node2, Node node1, TypedContent tc, AccessPathFrontHead apf0, AccessPath ap0, Node node2, CallContext cc,
boolean fromArg, AccessPathOption argAp, Configuration config AccessPathOption argAp, Configuration config
) { ) {
flowFwd(node1, fromArg, argAp, apf0, ap0, config) and flowFwd(node1, cc, argAp, apf0, ap0, config) and
readCandFwd(node1, tc, apf0, node2, config) readCandFwd(node1, tc, apf0, node2, config)
} }
pragma[nomagic] pragma[nomagic]
private predicate flowFwdRead( private predicate flowFwdRead(
Node node, AccessPathFrontHead apf0, AccessPath ap0, AccessPathFront apf, boolean fromArg, Node node, AccessPathFrontHead apf0, AccessPath ap0, AccessPathFront apf, CallContext cc,
AccessPathOption argAp, Configuration config AccessPathOption argAp, Configuration config
) { ) {
exists(Node mid, TypedContent tc | exists(Node mid, TypedContent tc |
flowFwdRead0(mid, tc, apf0, ap0, node, fromArg, argAp, config) and flowFwdRead0(mid, tc, apf0, ap0, node, cc, argAp, config) and
flowCand(node, _, _, apf, unbind(config)) and flowCand(node, _, _, apf, unbind(config)) and
flowCandConsCand(tc, apf, unbind(config)) flowCandConsCand(tc, apf, unbind(config))
) )
@@ -1795,13 +1806,16 @@ private predicate flowFwdConsCand(
pragma[nomagic] pragma[nomagic]
private predicate flowFwdIn( private predicate flowFwdIn(
DataFlowCall call, ParameterNode p, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, DataFlowCall call, ParameterNode p, CallContext innercc, CallContext outercc,
AccessPath ap, Configuration config AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config
) { ) {
exists(ArgumentNode arg, boolean allowsFieldFlow | exists(ArgumentNode arg, boolean allowsFieldFlow, DataFlowCallable c |
flowFwd(arg, fromArg, argAp, apf, ap, config) and flowFwd(arg, outercc, argAp, apf, ap, config) and
flowIntoCallNodeCand2(call, arg, p, allowsFieldFlow, config) and flowIntoCallNodeCand2(call, arg, p, allowsFieldFlow, config) and
flowCand(p, _, _, _, unbind(config)) 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 ap instanceof AccessPathNil or allowsFieldFlow = true
) )
@@ -1809,13 +1823,19 @@ private predicate flowFwdIn(
pragma[nomagic] pragma[nomagic]
private predicate flowFwdOut( private predicate flowFwdOut(
DataFlowCall call, Node node, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, DataFlowCall call, Node node, CallContext innercc, DataFlowCallable innerc,
AccessPath ap, Configuration config AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config
) { ) {
exists(ReturnNodeExt ret, boolean allowsFieldFlow | exists(ReturnNodeExt ret, boolean allowsFieldFlow |
flowFwd(ret, fromArg, argAp, apf, ap, config) and flowFwd(ret, innercc, argAp, apf, ap, config) and
flowOutOfCallNodeCand2(call, ret, node, allowsFieldFlow, config) and flowOutOfCallNodeCand2(call, ret, node, allowsFieldFlow, config) and
flowCand(node, _, _, _, unbind(config)) innerc = ret.getEnclosingCallable() and
flowCand(node, _, _, _, unbind(config)) and
(
resolveReturn(innercc, innerc, call)
or
innercc.(CallContextCall).matchesCall(call)
)
| |
ap instanceof AccessPathNil or allowsFieldFlow = true ap instanceof AccessPathNil or allowsFieldFlow = true
) )
@@ -1826,7 +1846,7 @@ private predicate flowFwdOutFromArg(
DataFlowCall call, Node node, AccessPath argAp, AccessPathFront apf, AccessPath ap, DataFlowCall call, Node node, AccessPath argAp, AccessPathFront apf, AccessPath ap,
Configuration config Configuration config
) { ) {
flowFwdOut(call, node, true, TAccessPathSome(argAp), apf, ap, config) flowFwdOut(call, node, any(CallContextCall ccc), _, TAccessPathSome(argAp), apf, ap, config)
} }
/** /**
@@ -1834,10 +1854,10 @@ private predicate flowFwdOutFromArg(
*/ */
pragma[nomagic] pragma[nomagic]
private predicate flowFwdIsEntered( private predicate flowFwdIsEntered(
DataFlowCall call, boolean fromArg, AccessPathOption argAp, AccessPath ap, Configuration config DataFlowCall call, CallContext cc, AccessPathOption argAp, AccessPath ap, Configuration config
) { ) {
exists(ParameterNode p, AccessPathFront apf | exists(ParameterNode p, AccessPathFront apf |
flowFwdIn(call, p, fromArg, argAp, apf, ap, config) and flowFwdIn(call, p, _, cc, argAp, apf, ap, config) and
flowCand(p, true, TAccessPathFrontSome(_), apf, config) flowCand(p, true, TAccessPathFrontSome(_), apf, config)
) )
} }
@@ -1920,7 +1940,7 @@ private predicate flow0(
// flow out of a callable // flow out of a callable
flowOut(_, node, _, _, ap, config) and flowOut(_, node, _, _, ap, config) and
toReturn = true and toReturn = true and
if flowFwd(node, true, TAccessPathSome(_), _, ap, config) if flowFwd(node, any(CallContextCall ccc), TAccessPathSome(_), _, ap, config)
then returnAp = TAccessPathSome(ap) then returnAp = TAccessPathSome(ap)
else returnAp = TAccessPathNone() else returnAp = TAccessPathNone()
} }
@@ -2006,9 +2026,10 @@ private predicate flowIsReturned(
DataFlowCall call, boolean toReturn, AccessPathOption returnAp, AccessPath ap, DataFlowCall call, boolean toReturn, AccessPathOption returnAp, AccessPath ap,
Configuration config Configuration config
) { ) {
exists(ReturnNodeExt ret | exists(ReturnNodeExt ret, CallContextCall ccc |
flowOut(call, ret, toReturn, returnAp, ap, config) and flowOut(call, ret, toReturn, returnAp, ap, config) and
flowFwd(ret, true, TAccessPathSome(_), _, ap, config) flowFwd(ret, ccc, TAccessPathSome(_), _, ap, config) and
ccc.matchesCall(call)
) )
} }
@@ -2031,7 +2052,7 @@ private newtype TSummaryCtx =
exists(ReturnNodeExt ret, Configuration config, AccessPath ap0 | exists(ReturnNodeExt ret, Configuration config, AccessPath ap0 |
parameterFlow(p, ap, ret.getEnclosingCallable(), config) and parameterFlow(p, ap, ret.getEnclosingCallable(), config) and
flow(ret, true, TAccessPathSome(_), ap0, config) and flow(ret, true, TAccessPathSome(_), ap0, config) and
flowFwd(ret, true, TAccessPathSome(ap), _, ap0, config) flowFwd(ret, any(CallContextCall ccc), TAccessPathSome(ap), _, ap0, config)
) )
} }
@@ -2352,7 +2373,7 @@ private predicate pathOutOfCallable0(
) { ) {
pos = getReturnPosition(mid.getNode()) and pos = getReturnPosition(mid.getNode()) and
innercc = mid.getCallContext() and innercc = mid.getCallContext() and
not innercc instanceof CallContextCall and innercc instanceof CallContextNoCall and
ap = mid.getAp() and ap = mid.getAp() and
config = mid.getConfiguration() config = mid.getConfiguration()
} }
@@ -2867,7 +2888,7 @@ private module FlowExploration {
) { ) {
pos = getReturnPosition(mid.getNode()) and pos = getReturnPosition(mid.getNode()) and
innercc = mid.getCallContext() and innercc = mid.getCallContext() and
not innercc instanceof CallContextCall and innercc instanceof CallContextNoCall and
ap = mid.getAp() and ap = mid.getAp() and
config = mid.getConfiguration() config = mid.getConfiguration()
} }

View File

@@ -1066,7 +1066,7 @@ private module LocalFlowBigStep {
* Holds if `node` can be the first node in a maximal subsequence of local * Holds if `node` can be the first node in a maximal subsequence of local
* flow steps in a dataflow path. * flow steps in a dataflow path.
*/ */
private predicate localFlowEntry(Node node, Configuration config) { predicate localFlowEntry(Node node, Configuration config) {
nodeCand2(node, config) and nodeCand2(node, config) and
( (
config.isSource(node) or config.isSource(node) or
@@ -1650,53 +1650,53 @@ private class AccessPathOption extends TAccessPathOption {
* Holds if `node` is reachable with access path `ap` from a source in * Holds if `node` is reachable with access path `ap` from a source in
* the configuration `config`. * the configuration `config`.
* *
* The Boolean `fromArg` records whether the node is reached through an * 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 in a call, and if so, `argAp` records the access path of that
* argument. * argument.
*/ */
private predicate flowFwd( private predicate flowFwd(
Node node, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Node node, CallContext cc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap,
Configuration config Configuration config
) { ) {
flowFwd0(node, fromArg, argAp, apf, ap, config) and flowFwd0(node, cc, argAp, apf, ap, config) and
flowCand(node, _, _, apf, config) flowCand(node, _, _, apf, config)
} }
private predicate flowFwd0( private predicate flowFwd0(
Node node, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Node node, CallContext cc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap,
Configuration config Configuration config
) { ) {
flowCand(node, _, _, _, config) and flowCand(node, _, _, _, config) and
config.isSource(node) and config.isSource(node) and
fromArg = false and cc instanceof CallContextAny and
argAp = TAccessPathNone() and argAp = TAccessPathNone() and
ap = TNil(getNodeType(node)) and ap = TNil(getNodeType(node)) and
apf = ap.(AccessPathNil).getFront() apf = ap.(AccessPathNil).getFront()
or or
flowCand(node, _, _, _, unbind(config)) and flowCand(node, _, _, _, unbind(config)) and
( (
exists(Node mid | exists(Node mid, LocalCallContext localCC |
flowFwd(mid, fromArg, argAp, apf, ap, config) and flowFwdLocalEntry(mid, cc, argAp, apf, ap, localCC, config) and
localFlowBigStep(mid, node, true, _, config, _) localFlowBigStep(mid, node, true, _, config, localCC)
) )
or or
exists(Node mid, AccessPathNil nil | exists(Node mid, AccessPathNil nil, LocalCallContext localCC |
flowFwd(mid, fromArg, argAp, _, nil, config) and flowFwdLocalEntry(mid, cc, argAp, _, nil, localCC, config) and
localFlowBigStep(mid, node, false, apf, config, _) and localFlowBigStep(mid, node, false, apf, config, localCC) and
apf = ap.(AccessPathNil).getFront() apf = ap.(AccessPathNil).getFront()
) )
or or
exists(Node mid | exists(Node mid |
flowFwd(mid, _, _, apf, ap, config) and flowFwd(mid, _, _, apf, ap, config) and
jumpStep(mid, node, config) and jumpStep(mid, node, config) and
fromArg = false and cc instanceof CallContextAny and
argAp = TAccessPathNone() argAp = TAccessPathNone()
) )
or or
exists(Node mid, AccessPathNil nil | exists(Node mid, AccessPathNil nil |
flowFwd(mid, _, _, _, nil, config) and flowFwd(mid, _, _, _, nil, config) and
additionalJumpStep(mid, node, config) and additionalJumpStep(mid, node, config) and
fromArg = false and cc instanceof CallContextAny and
argAp = TAccessPathNone() and argAp = TAccessPathNone() and
ap = TNil(getNodeType(node)) and ap = TNil(getNodeType(node)) and
apf = ap.(AccessPathNil).getFront() apf = ap.(AccessPathNil).getFront()
@@ -1704,40 +1704,51 @@ private predicate flowFwd0(
) )
or or
// store // store
exists(TypedContent tc | flowFwdStore(node, tc, pop(tc, ap), apf, fromArg, argAp, config)) exists(TypedContent tc | flowFwdStore(node, tc, pop(tc, ap), apf, cc, argAp, config))
or or
// read // read
exists(TypedContent tc | exists(TypedContent tc |
flowFwdRead(node, _, push(tc, ap), apf, fromArg, argAp, config) and flowFwdRead(node, _, push(tc, ap), apf, cc, argAp, config) and
flowFwdConsCand(tc, apf, ap, config) flowFwdConsCand(tc, apf, ap, config)
) )
or or
// flow into a callable // flow into a callable
flowFwdIn(_, node, _, _, apf, ap, config) and flowFwdIn(_, node, cc, _, _, apf, ap, config) and
fromArg = true and
if flowCand(node, true, _, apf, config) if flowCand(node, true, _, apf, config)
then argAp = TAccessPathSome(ap) then argAp = TAccessPathSome(ap)
else argAp = TAccessPathNone() else argAp = TAccessPathNone()
or or
// flow out of a callable // flow out of a callable
exists(DataFlowCall call | exists(DataFlowCall call |
flowFwdOut(call, node, fromArg, argAp, apf, ap, config) and exists(CallContextNoCall innercc, DataFlowCallable c |
fromArg = false flowFwdOut(call, node, innercc, c, argAp, apf, ap, config) and
if reducedViableImplInReturn(c, call) then cc = TReturn(c, call) else cc = TAnyCallContext()
)
or or
exists(AccessPath argAp0 | exists(AccessPath argAp0 |
flowFwdOutFromArg(call, node, argAp0, apf, ap, config) and flowFwdOutFromArg(call, node, argAp0, apf, ap, config) and
flowFwdIsEntered(call, fromArg, argAp, argAp0, config) flowFwdIsEntered(call, cc, argAp, argAp0, config)
) )
) )
} }
pragma[nomagic]
private predicate flowFwdLocalEntry(
Node node, CallContext cc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap,
LocalCallContext localCC, Configuration config
) {
flowFwd(node, cc, argAp, apf, ap, config) and
localFlowEntry(node, config) and
localCC = getLocalCallContext(cc, node.getEnclosingCallable())
}
pragma[nomagic] pragma[nomagic]
private predicate flowFwdStore( private predicate flowFwdStore(
Node node, TypedContent tc, AccessPath ap0, AccessPathFront apf, boolean fromArg, Node node, TypedContent tc, AccessPath ap0, AccessPathFront apf, CallContext cc,
AccessPathOption argAp, Configuration config AccessPathOption argAp, Configuration config
) { ) {
exists(Node mid, AccessPathFront apf0 | exists(Node mid, AccessPathFront apf0 |
flowFwd(mid, fromArg, argAp, apf0, ap0, config) and flowFwd(mid, cc, argAp, apf0, ap0, config) and
flowFwdStore0(mid, tc, node, apf0, apf, config) flowFwdStore0(mid, tc, node, apf0, apf, config)
) )
} }
@@ -1764,20 +1775,20 @@ private predicate flowFwdStore0(
pragma[nomagic] pragma[nomagic]
private predicate flowFwdRead0( private predicate flowFwdRead0(
Node node1, TypedContent tc, AccessPathFrontHead apf0, AccessPath ap0, Node node2, Node node1, TypedContent tc, AccessPathFrontHead apf0, AccessPath ap0, Node node2, CallContext cc,
boolean fromArg, AccessPathOption argAp, Configuration config AccessPathOption argAp, Configuration config
) { ) {
flowFwd(node1, fromArg, argAp, apf0, ap0, config) and flowFwd(node1, cc, argAp, apf0, ap0, config) and
readCandFwd(node1, tc, apf0, node2, config) readCandFwd(node1, tc, apf0, node2, config)
} }
pragma[nomagic] pragma[nomagic]
private predicate flowFwdRead( private predicate flowFwdRead(
Node node, AccessPathFrontHead apf0, AccessPath ap0, AccessPathFront apf, boolean fromArg, Node node, AccessPathFrontHead apf0, AccessPath ap0, AccessPathFront apf, CallContext cc,
AccessPathOption argAp, Configuration config AccessPathOption argAp, Configuration config
) { ) {
exists(Node mid, TypedContent tc | exists(Node mid, TypedContent tc |
flowFwdRead0(mid, tc, apf0, ap0, node, fromArg, argAp, config) and flowFwdRead0(mid, tc, apf0, ap0, node, cc, argAp, config) and
flowCand(node, _, _, apf, unbind(config)) and flowCand(node, _, _, apf, unbind(config)) and
flowCandConsCand(tc, apf, unbind(config)) flowCandConsCand(tc, apf, unbind(config))
) )
@@ -1795,13 +1806,16 @@ private predicate flowFwdConsCand(
pragma[nomagic] pragma[nomagic]
private predicate flowFwdIn( private predicate flowFwdIn(
DataFlowCall call, ParameterNode p, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, DataFlowCall call, ParameterNode p, CallContext innercc, CallContext outercc,
AccessPath ap, Configuration config AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config
) { ) {
exists(ArgumentNode arg, boolean allowsFieldFlow | exists(ArgumentNode arg, boolean allowsFieldFlow, DataFlowCallable c |
flowFwd(arg, fromArg, argAp, apf, ap, config) and flowFwd(arg, outercc, argAp, apf, ap, config) and
flowIntoCallNodeCand2(call, arg, p, allowsFieldFlow, config) and flowIntoCallNodeCand2(call, arg, p, allowsFieldFlow, config) and
flowCand(p, _, _, _, unbind(config)) 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 ap instanceof AccessPathNil or allowsFieldFlow = true
) )
@@ -1809,13 +1823,19 @@ private predicate flowFwdIn(
pragma[nomagic] pragma[nomagic]
private predicate flowFwdOut( private predicate flowFwdOut(
DataFlowCall call, Node node, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, DataFlowCall call, Node node, CallContext innercc, DataFlowCallable innerc,
AccessPath ap, Configuration config AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config
) { ) {
exists(ReturnNodeExt ret, boolean allowsFieldFlow | exists(ReturnNodeExt ret, boolean allowsFieldFlow |
flowFwd(ret, fromArg, argAp, apf, ap, config) and flowFwd(ret, innercc, argAp, apf, ap, config) and
flowOutOfCallNodeCand2(call, ret, node, allowsFieldFlow, config) and flowOutOfCallNodeCand2(call, ret, node, allowsFieldFlow, config) and
flowCand(node, _, _, _, unbind(config)) innerc = ret.getEnclosingCallable() and
flowCand(node, _, _, _, unbind(config)) and
(
resolveReturn(innercc, innerc, call)
or
innercc.(CallContextCall).matchesCall(call)
)
| |
ap instanceof AccessPathNil or allowsFieldFlow = true ap instanceof AccessPathNil or allowsFieldFlow = true
) )
@@ -1826,7 +1846,7 @@ private predicate flowFwdOutFromArg(
DataFlowCall call, Node node, AccessPath argAp, AccessPathFront apf, AccessPath ap, DataFlowCall call, Node node, AccessPath argAp, AccessPathFront apf, AccessPath ap,
Configuration config Configuration config
) { ) {
flowFwdOut(call, node, true, TAccessPathSome(argAp), apf, ap, config) flowFwdOut(call, node, any(CallContextCall ccc), _, TAccessPathSome(argAp), apf, ap, config)
} }
/** /**
@@ -1834,10 +1854,10 @@ private predicate flowFwdOutFromArg(
*/ */
pragma[nomagic] pragma[nomagic]
private predicate flowFwdIsEntered( private predicate flowFwdIsEntered(
DataFlowCall call, boolean fromArg, AccessPathOption argAp, AccessPath ap, Configuration config DataFlowCall call, CallContext cc, AccessPathOption argAp, AccessPath ap, Configuration config
) { ) {
exists(ParameterNode p, AccessPathFront apf | exists(ParameterNode p, AccessPathFront apf |
flowFwdIn(call, p, fromArg, argAp, apf, ap, config) and flowFwdIn(call, p, _, cc, argAp, apf, ap, config) and
flowCand(p, true, TAccessPathFrontSome(_), apf, config) flowCand(p, true, TAccessPathFrontSome(_), apf, config)
) )
} }
@@ -1920,7 +1940,7 @@ private predicate flow0(
// flow out of a callable // flow out of a callable
flowOut(_, node, _, _, ap, config) and flowOut(_, node, _, _, ap, config) and
toReturn = true and toReturn = true and
if flowFwd(node, true, TAccessPathSome(_), _, ap, config) if flowFwd(node, any(CallContextCall ccc), TAccessPathSome(_), _, ap, config)
then returnAp = TAccessPathSome(ap) then returnAp = TAccessPathSome(ap)
else returnAp = TAccessPathNone() else returnAp = TAccessPathNone()
} }
@@ -2006,9 +2026,10 @@ private predicate flowIsReturned(
DataFlowCall call, boolean toReturn, AccessPathOption returnAp, AccessPath ap, DataFlowCall call, boolean toReturn, AccessPathOption returnAp, AccessPath ap,
Configuration config Configuration config
) { ) {
exists(ReturnNodeExt ret | exists(ReturnNodeExt ret, CallContextCall ccc |
flowOut(call, ret, toReturn, returnAp, ap, config) and flowOut(call, ret, toReturn, returnAp, ap, config) and
flowFwd(ret, true, TAccessPathSome(_), _, ap, config) flowFwd(ret, ccc, TAccessPathSome(_), _, ap, config) and
ccc.matchesCall(call)
) )
} }
@@ -2031,7 +2052,7 @@ private newtype TSummaryCtx =
exists(ReturnNodeExt ret, Configuration config, AccessPath ap0 | exists(ReturnNodeExt ret, Configuration config, AccessPath ap0 |
parameterFlow(p, ap, ret.getEnclosingCallable(), config) and parameterFlow(p, ap, ret.getEnclosingCallable(), config) and
flow(ret, true, TAccessPathSome(_), ap0, config) and flow(ret, true, TAccessPathSome(_), ap0, config) and
flowFwd(ret, true, TAccessPathSome(ap), _, ap0, config) flowFwd(ret, any(CallContextCall ccc), TAccessPathSome(ap), _, ap0, config)
) )
} }
@@ -2352,7 +2373,7 @@ private predicate pathOutOfCallable0(
) { ) {
pos = getReturnPosition(mid.getNode()) and pos = getReturnPosition(mid.getNode()) and
innercc = mid.getCallContext() and innercc = mid.getCallContext() and
not innercc instanceof CallContextCall and innercc instanceof CallContextNoCall and
ap = mid.getAp() and ap = mid.getAp() and
config = mid.getConfiguration() config = mid.getConfiguration()
} }
@@ -2867,7 +2888,7 @@ private module FlowExploration {
) { ) {
pos = getReturnPosition(mid.getNode()) and pos = getReturnPosition(mid.getNode()) and
innercc = mid.getCallContext() and innercc = mid.getCallContext() and
not innercc instanceof CallContextCall and innercc instanceof CallContextNoCall and
ap = mid.getAp() and ap = mid.getAp() and
config = mid.getConfiguration() config = mid.getConfiguration()
} }

View File

@@ -512,13 +512,19 @@ abstract class CallContext extends TCallContext {
abstract predicate relevantFor(DataFlowCallable callable); abstract predicate relevantFor(DataFlowCallable callable);
} }
class CallContextAny extends CallContext, TAnyCallContext { abstract class CallContextNoCall extends CallContext { }
class CallContextAny extends CallContextNoCall, TAnyCallContext {
override string toString() { result = "CcAny" } override string toString() { result = "CcAny" }
override predicate relevantFor(DataFlowCallable callable) { any() } override predicate relevantFor(DataFlowCallable callable) { any() }
} }
abstract class CallContextCall extends CallContext { } abstract class CallContextCall extends CallContext {
/** Holds if this call context may be `call`. */
bindingset[call]
abstract predicate matchesCall(DataFlowCall call);
}
class CallContextSpecificCall extends CallContextCall, TSpecificCall { class CallContextSpecificCall extends CallContextCall, TSpecificCall {
override string toString() { override string toString() {
@@ -529,6 +535,8 @@ class CallContextSpecificCall extends CallContextCall, TSpecificCall {
recordDataFlowCallSite(getCall(), callable) recordDataFlowCallSite(getCall(), callable)
} }
override predicate matchesCall(DataFlowCall call) { call = this.getCall() }
DataFlowCall getCall() { this = TSpecificCall(result) } DataFlowCall getCall() { this = TSpecificCall(result) }
} }
@@ -538,9 +546,11 @@ class CallContextSomeCall extends CallContextCall, TSomeCall {
override predicate relevantFor(DataFlowCallable callable) { override predicate relevantFor(DataFlowCallable callable) {
exists(ParameterNode p | p.getEnclosingCallable() = callable) exists(ParameterNode p | p.getEnclosingCallable() = callable)
} }
override predicate matchesCall(DataFlowCall call) { any() }
} }
class CallContextReturn extends CallContext, TReturn { class CallContextReturn extends CallContextNoCall, TReturn {
override string toString() { override string toString() {
exists(DataFlowCall call | this = TReturn(_, call) | result = "CcReturn(" + call + ")") exists(DataFlowCall call | this = TReturn(_, call) | result = "CcReturn(" + call + ")")
} }

View File

@@ -1066,7 +1066,7 @@ private module LocalFlowBigStep {
* Holds if `node` can be the first node in a maximal subsequence of local * Holds if `node` can be the first node in a maximal subsequence of local
* flow steps in a dataflow path. * flow steps in a dataflow path.
*/ */
private predicate localFlowEntry(Node node, Configuration config) { predicate localFlowEntry(Node node, Configuration config) {
nodeCand2(node, config) and nodeCand2(node, config) and
( (
config.isSource(node) or config.isSource(node) or
@@ -1650,53 +1650,53 @@ private class AccessPathOption extends TAccessPathOption {
* Holds if `node` is reachable with access path `ap` from a source in * Holds if `node` is reachable with access path `ap` from a source in
* the configuration `config`. * the configuration `config`.
* *
* The Boolean `fromArg` records whether the node is reached through an * 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 in a call, and if so, `argAp` records the access path of that
* argument. * argument.
*/ */
private predicate flowFwd( private predicate flowFwd(
Node node, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Node node, CallContext cc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap,
Configuration config Configuration config
) { ) {
flowFwd0(node, fromArg, argAp, apf, ap, config) and flowFwd0(node, cc, argAp, apf, ap, config) and
flowCand(node, _, _, apf, config) flowCand(node, _, _, apf, config)
} }
private predicate flowFwd0( private predicate flowFwd0(
Node node, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Node node, CallContext cc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap,
Configuration config Configuration config
) { ) {
flowCand(node, _, _, _, config) and flowCand(node, _, _, _, config) and
config.isSource(node) and config.isSource(node) and
fromArg = false and cc instanceof CallContextAny and
argAp = TAccessPathNone() and argAp = TAccessPathNone() and
ap = TNil(getNodeType(node)) and ap = TNil(getNodeType(node)) and
apf = ap.(AccessPathNil).getFront() apf = ap.(AccessPathNil).getFront()
or or
flowCand(node, _, _, _, unbind(config)) and flowCand(node, _, _, _, unbind(config)) and
( (
exists(Node mid | exists(Node mid, LocalCallContext localCC |
flowFwd(mid, fromArg, argAp, apf, ap, config) and flowFwdLocalEntry(mid, cc, argAp, apf, ap, localCC, config) and
localFlowBigStep(mid, node, true, _, config, _) localFlowBigStep(mid, node, true, _, config, localCC)
) )
or or
exists(Node mid, AccessPathNil nil | exists(Node mid, AccessPathNil nil, LocalCallContext localCC |
flowFwd(mid, fromArg, argAp, _, nil, config) and flowFwdLocalEntry(mid, cc, argAp, _, nil, localCC, config) and
localFlowBigStep(mid, node, false, apf, config, _) and localFlowBigStep(mid, node, false, apf, config, localCC) and
apf = ap.(AccessPathNil).getFront() apf = ap.(AccessPathNil).getFront()
) )
or or
exists(Node mid | exists(Node mid |
flowFwd(mid, _, _, apf, ap, config) and flowFwd(mid, _, _, apf, ap, config) and
jumpStep(mid, node, config) and jumpStep(mid, node, config) and
fromArg = false and cc instanceof CallContextAny and
argAp = TAccessPathNone() argAp = TAccessPathNone()
) )
or or
exists(Node mid, AccessPathNil nil | exists(Node mid, AccessPathNil nil |
flowFwd(mid, _, _, _, nil, config) and flowFwd(mid, _, _, _, nil, config) and
additionalJumpStep(mid, node, config) and additionalJumpStep(mid, node, config) and
fromArg = false and cc instanceof CallContextAny and
argAp = TAccessPathNone() and argAp = TAccessPathNone() and
ap = TNil(getNodeType(node)) and ap = TNil(getNodeType(node)) and
apf = ap.(AccessPathNil).getFront() apf = ap.(AccessPathNil).getFront()
@@ -1704,40 +1704,51 @@ private predicate flowFwd0(
) )
or or
// store // store
exists(TypedContent tc | flowFwdStore(node, tc, pop(tc, ap), apf, fromArg, argAp, config)) exists(TypedContent tc | flowFwdStore(node, tc, pop(tc, ap), apf, cc, argAp, config))
or or
// read // read
exists(TypedContent tc | exists(TypedContent tc |
flowFwdRead(node, _, push(tc, ap), apf, fromArg, argAp, config) and flowFwdRead(node, _, push(tc, ap), apf, cc, argAp, config) and
flowFwdConsCand(tc, apf, ap, config) flowFwdConsCand(tc, apf, ap, config)
) )
or or
// flow into a callable // flow into a callable
flowFwdIn(_, node, _, _, apf, ap, config) and flowFwdIn(_, node, cc, _, _, apf, ap, config) and
fromArg = true and
if flowCand(node, true, _, apf, config) if flowCand(node, true, _, apf, config)
then argAp = TAccessPathSome(ap) then argAp = TAccessPathSome(ap)
else argAp = TAccessPathNone() else argAp = TAccessPathNone()
or or
// flow out of a callable // flow out of a callable
exists(DataFlowCall call | exists(DataFlowCall call |
flowFwdOut(call, node, fromArg, argAp, apf, ap, config) and exists(CallContextNoCall innercc, DataFlowCallable c |
fromArg = false flowFwdOut(call, node, innercc, c, argAp, apf, ap, config) and
if reducedViableImplInReturn(c, call) then cc = TReturn(c, call) else cc = TAnyCallContext()
)
or or
exists(AccessPath argAp0 | exists(AccessPath argAp0 |
flowFwdOutFromArg(call, node, argAp0, apf, ap, config) and flowFwdOutFromArg(call, node, argAp0, apf, ap, config) and
flowFwdIsEntered(call, fromArg, argAp, argAp0, config) flowFwdIsEntered(call, cc, argAp, argAp0, config)
) )
) )
} }
pragma[nomagic]
private predicate flowFwdLocalEntry(
Node node, CallContext cc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap,
LocalCallContext localCC, Configuration config
) {
flowFwd(node, cc, argAp, apf, ap, config) and
localFlowEntry(node, config) and
localCC = getLocalCallContext(cc, node.getEnclosingCallable())
}
pragma[nomagic] pragma[nomagic]
private predicate flowFwdStore( private predicate flowFwdStore(
Node node, TypedContent tc, AccessPath ap0, AccessPathFront apf, boolean fromArg, Node node, TypedContent tc, AccessPath ap0, AccessPathFront apf, CallContext cc,
AccessPathOption argAp, Configuration config AccessPathOption argAp, Configuration config
) { ) {
exists(Node mid, AccessPathFront apf0 | exists(Node mid, AccessPathFront apf0 |
flowFwd(mid, fromArg, argAp, apf0, ap0, config) and flowFwd(mid, cc, argAp, apf0, ap0, config) and
flowFwdStore0(mid, tc, node, apf0, apf, config) flowFwdStore0(mid, tc, node, apf0, apf, config)
) )
} }
@@ -1764,20 +1775,20 @@ private predicate flowFwdStore0(
pragma[nomagic] pragma[nomagic]
private predicate flowFwdRead0( private predicate flowFwdRead0(
Node node1, TypedContent tc, AccessPathFrontHead apf0, AccessPath ap0, Node node2, Node node1, TypedContent tc, AccessPathFrontHead apf0, AccessPath ap0, Node node2, CallContext cc,
boolean fromArg, AccessPathOption argAp, Configuration config AccessPathOption argAp, Configuration config
) { ) {
flowFwd(node1, fromArg, argAp, apf0, ap0, config) and flowFwd(node1, cc, argAp, apf0, ap0, config) and
readCandFwd(node1, tc, apf0, node2, config) readCandFwd(node1, tc, apf0, node2, config)
} }
pragma[nomagic] pragma[nomagic]
private predicate flowFwdRead( private predicate flowFwdRead(
Node node, AccessPathFrontHead apf0, AccessPath ap0, AccessPathFront apf, boolean fromArg, Node node, AccessPathFrontHead apf0, AccessPath ap0, AccessPathFront apf, CallContext cc,
AccessPathOption argAp, Configuration config AccessPathOption argAp, Configuration config
) { ) {
exists(Node mid, TypedContent tc | exists(Node mid, TypedContent tc |
flowFwdRead0(mid, tc, apf0, ap0, node, fromArg, argAp, config) and flowFwdRead0(mid, tc, apf0, ap0, node, cc, argAp, config) and
flowCand(node, _, _, apf, unbind(config)) and flowCand(node, _, _, apf, unbind(config)) and
flowCandConsCand(tc, apf, unbind(config)) flowCandConsCand(tc, apf, unbind(config))
) )
@@ -1795,13 +1806,16 @@ private predicate flowFwdConsCand(
pragma[nomagic] pragma[nomagic]
private predicate flowFwdIn( private predicate flowFwdIn(
DataFlowCall call, ParameterNode p, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, DataFlowCall call, ParameterNode p, CallContext innercc, CallContext outercc,
AccessPath ap, Configuration config AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config
) { ) {
exists(ArgumentNode arg, boolean allowsFieldFlow | exists(ArgumentNode arg, boolean allowsFieldFlow, DataFlowCallable c |
flowFwd(arg, fromArg, argAp, apf, ap, config) and flowFwd(arg, outercc, argAp, apf, ap, config) and
flowIntoCallNodeCand2(call, arg, p, allowsFieldFlow, config) and flowIntoCallNodeCand2(call, arg, p, allowsFieldFlow, config) and
flowCand(p, _, _, _, unbind(config)) 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 ap instanceof AccessPathNil or allowsFieldFlow = true
) )
@@ -1809,13 +1823,19 @@ private predicate flowFwdIn(
pragma[nomagic] pragma[nomagic]
private predicate flowFwdOut( private predicate flowFwdOut(
DataFlowCall call, Node node, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, DataFlowCall call, Node node, CallContext innercc, DataFlowCallable innerc,
AccessPath ap, Configuration config AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config
) { ) {
exists(ReturnNodeExt ret, boolean allowsFieldFlow | exists(ReturnNodeExt ret, boolean allowsFieldFlow |
flowFwd(ret, fromArg, argAp, apf, ap, config) and flowFwd(ret, innercc, argAp, apf, ap, config) and
flowOutOfCallNodeCand2(call, ret, node, allowsFieldFlow, config) and flowOutOfCallNodeCand2(call, ret, node, allowsFieldFlow, config) and
flowCand(node, _, _, _, unbind(config)) innerc = ret.getEnclosingCallable() and
flowCand(node, _, _, _, unbind(config)) and
(
resolveReturn(innercc, innerc, call)
or
innercc.(CallContextCall).matchesCall(call)
)
| |
ap instanceof AccessPathNil or allowsFieldFlow = true ap instanceof AccessPathNil or allowsFieldFlow = true
) )
@@ -1826,7 +1846,7 @@ private predicate flowFwdOutFromArg(
DataFlowCall call, Node node, AccessPath argAp, AccessPathFront apf, AccessPath ap, DataFlowCall call, Node node, AccessPath argAp, AccessPathFront apf, AccessPath ap,
Configuration config Configuration config
) { ) {
flowFwdOut(call, node, true, TAccessPathSome(argAp), apf, ap, config) flowFwdOut(call, node, any(CallContextCall ccc), _, TAccessPathSome(argAp), apf, ap, config)
} }
/** /**
@@ -1834,10 +1854,10 @@ private predicate flowFwdOutFromArg(
*/ */
pragma[nomagic] pragma[nomagic]
private predicate flowFwdIsEntered( private predicate flowFwdIsEntered(
DataFlowCall call, boolean fromArg, AccessPathOption argAp, AccessPath ap, Configuration config DataFlowCall call, CallContext cc, AccessPathOption argAp, AccessPath ap, Configuration config
) { ) {
exists(ParameterNode p, AccessPathFront apf | exists(ParameterNode p, AccessPathFront apf |
flowFwdIn(call, p, fromArg, argAp, apf, ap, config) and flowFwdIn(call, p, _, cc, argAp, apf, ap, config) and
flowCand(p, true, TAccessPathFrontSome(_), apf, config) flowCand(p, true, TAccessPathFrontSome(_), apf, config)
) )
} }
@@ -1920,7 +1940,7 @@ private predicate flow0(
// flow out of a callable // flow out of a callable
flowOut(_, node, _, _, ap, config) and flowOut(_, node, _, _, ap, config) and
toReturn = true and toReturn = true and
if flowFwd(node, true, TAccessPathSome(_), _, ap, config) if flowFwd(node, any(CallContextCall ccc), TAccessPathSome(_), _, ap, config)
then returnAp = TAccessPathSome(ap) then returnAp = TAccessPathSome(ap)
else returnAp = TAccessPathNone() else returnAp = TAccessPathNone()
} }
@@ -2006,9 +2026,10 @@ private predicate flowIsReturned(
DataFlowCall call, boolean toReturn, AccessPathOption returnAp, AccessPath ap, DataFlowCall call, boolean toReturn, AccessPathOption returnAp, AccessPath ap,
Configuration config Configuration config
) { ) {
exists(ReturnNodeExt ret | exists(ReturnNodeExt ret, CallContextCall ccc |
flowOut(call, ret, toReturn, returnAp, ap, config) and flowOut(call, ret, toReturn, returnAp, ap, config) and
flowFwd(ret, true, TAccessPathSome(_), _, ap, config) flowFwd(ret, ccc, TAccessPathSome(_), _, ap, config) and
ccc.matchesCall(call)
) )
} }
@@ -2031,7 +2052,7 @@ private newtype TSummaryCtx =
exists(ReturnNodeExt ret, Configuration config, AccessPath ap0 | exists(ReturnNodeExt ret, Configuration config, AccessPath ap0 |
parameterFlow(p, ap, ret.getEnclosingCallable(), config) and parameterFlow(p, ap, ret.getEnclosingCallable(), config) and
flow(ret, true, TAccessPathSome(_), ap0, config) and flow(ret, true, TAccessPathSome(_), ap0, config) and
flowFwd(ret, true, TAccessPathSome(ap), _, ap0, config) flowFwd(ret, any(CallContextCall ccc), TAccessPathSome(ap), _, ap0, config)
) )
} }
@@ -2352,7 +2373,7 @@ private predicate pathOutOfCallable0(
) { ) {
pos = getReturnPosition(mid.getNode()) and pos = getReturnPosition(mid.getNode()) and
innercc = mid.getCallContext() and innercc = mid.getCallContext() and
not innercc instanceof CallContextCall and innercc instanceof CallContextNoCall and
ap = mid.getAp() and ap = mid.getAp() and
config = mid.getConfiguration() config = mid.getConfiguration()
} }
@@ -2867,7 +2888,7 @@ private module FlowExploration {
) { ) {
pos = getReturnPosition(mid.getNode()) and pos = getReturnPosition(mid.getNode()) and
innercc = mid.getCallContext() and innercc = mid.getCallContext() and
not innercc instanceof CallContextCall and innercc instanceof CallContextNoCall and
ap = mid.getAp() and ap = mid.getAp() and
config = mid.getConfiguration() config = mid.getConfiguration()
} }

View File

@@ -1066,7 +1066,7 @@ private module LocalFlowBigStep {
* Holds if `node` can be the first node in a maximal subsequence of local * Holds if `node` can be the first node in a maximal subsequence of local
* flow steps in a dataflow path. * flow steps in a dataflow path.
*/ */
private predicate localFlowEntry(Node node, Configuration config) { predicate localFlowEntry(Node node, Configuration config) {
nodeCand2(node, config) and nodeCand2(node, config) and
( (
config.isSource(node) or config.isSource(node) or
@@ -1650,53 +1650,53 @@ private class AccessPathOption extends TAccessPathOption {
* Holds if `node` is reachable with access path `ap` from a source in * Holds if `node` is reachable with access path `ap` from a source in
* the configuration `config`. * the configuration `config`.
* *
* The Boolean `fromArg` records whether the node is reached through an * 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 in a call, and if so, `argAp` records the access path of that
* argument. * argument.
*/ */
private predicate flowFwd( private predicate flowFwd(
Node node, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Node node, CallContext cc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap,
Configuration config Configuration config
) { ) {
flowFwd0(node, fromArg, argAp, apf, ap, config) and flowFwd0(node, cc, argAp, apf, ap, config) and
flowCand(node, _, _, apf, config) flowCand(node, _, _, apf, config)
} }
private predicate flowFwd0( private predicate flowFwd0(
Node node, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Node node, CallContext cc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap,
Configuration config Configuration config
) { ) {
flowCand(node, _, _, _, config) and flowCand(node, _, _, _, config) and
config.isSource(node) and config.isSource(node) and
fromArg = false and cc instanceof CallContextAny and
argAp = TAccessPathNone() and argAp = TAccessPathNone() and
ap = TNil(getNodeType(node)) and ap = TNil(getNodeType(node)) and
apf = ap.(AccessPathNil).getFront() apf = ap.(AccessPathNil).getFront()
or or
flowCand(node, _, _, _, unbind(config)) and flowCand(node, _, _, _, unbind(config)) and
( (
exists(Node mid | exists(Node mid, LocalCallContext localCC |
flowFwd(mid, fromArg, argAp, apf, ap, config) and flowFwdLocalEntry(mid, cc, argAp, apf, ap, localCC, config) and
localFlowBigStep(mid, node, true, _, config, _) localFlowBigStep(mid, node, true, _, config, localCC)
) )
or or
exists(Node mid, AccessPathNil nil | exists(Node mid, AccessPathNil nil, LocalCallContext localCC |
flowFwd(mid, fromArg, argAp, _, nil, config) and flowFwdLocalEntry(mid, cc, argAp, _, nil, localCC, config) and
localFlowBigStep(mid, node, false, apf, config, _) and localFlowBigStep(mid, node, false, apf, config, localCC) and
apf = ap.(AccessPathNil).getFront() apf = ap.(AccessPathNil).getFront()
) )
or or
exists(Node mid | exists(Node mid |
flowFwd(mid, _, _, apf, ap, config) and flowFwd(mid, _, _, apf, ap, config) and
jumpStep(mid, node, config) and jumpStep(mid, node, config) and
fromArg = false and cc instanceof CallContextAny and
argAp = TAccessPathNone() argAp = TAccessPathNone()
) )
or or
exists(Node mid, AccessPathNil nil | exists(Node mid, AccessPathNil nil |
flowFwd(mid, _, _, _, nil, config) and flowFwd(mid, _, _, _, nil, config) and
additionalJumpStep(mid, node, config) and additionalJumpStep(mid, node, config) and
fromArg = false and cc instanceof CallContextAny and
argAp = TAccessPathNone() and argAp = TAccessPathNone() and
ap = TNil(getNodeType(node)) and ap = TNil(getNodeType(node)) and
apf = ap.(AccessPathNil).getFront() apf = ap.(AccessPathNil).getFront()
@@ -1704,40 +1704,51 @@ private predicate flowFwd0(
) )
or or
// store // store
exists(TypedContent tc | flowFwdStore(node, tc, pop(tc, ap), apf, fromArg, argAp, config)) exists(TypedContent tc | flowFwdStore(node, tc, pop(tc, ap), apf, cc, argAp, config))
or or
// read // read
exists(TypedContent tc | exists(TypedContent tc |
flowFwdRead(node, _, push(tc, ap), apf, fromArg, argAp, config) and flowFwdRead(node, _, push(tc, ap), apf, cc, argAp, config) and
flowFwdConsCand(tc, apf, ap, config) flowFwdConsCand(tc, apf, ap, config)
) )
or or
// flow into a callable // flow into a callable
flowFwdIn(_, node, _, _, apf, ap, config) and flowFwdIn(_, node, cc, _, _, apf, ap, config) and
fromArg = true and
if flowCand(node, true, _, apf, config) if flowCand(node, true, _, apf, config)
then argAp = TAccessPathSome(ap) then argAp = TAccessPathSome(ap)
else argAp = TAccessPathNone() else argAp = TAccessPathNone()
or or
// flow out of a callable // flow out of a callable
exists(DataFlowCall call | exists(DataFlowCall call |
flowFwdOut(call, node, fromArg, argAp, apf, ap, config) and exists(CallContextNoCall innercc, DataFlowCallable c |
fromArg = false flowFwdOut(call, node, innercc, c, argAp, apf, ap, config) and
if reducedViableImplInReturn(c, call) then cc = TReturn(c, call) else cc = TAnyCallContext()
)
or or
exists(AccessPath argAp0 | exists(AccessPath argAp0 |
flowFwdOutFromArg(call, node, argAp0, apf, ap, config) and flowFwdOutFromArg(call, node, argAp0, apf, ap, config) and
flowFwdIsEntered(call, fromArg, argAp, argAp0, config) flowFwdIsEntered(call, cc, argAp, argAp0, config)
) )
) )
} }
pragma[nomagic]
private predicate flowFwdLocalEntry(
Node node, CallContext cc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap,
LocalCallContext localCC, Configuration config
) {
flowFwd(node, cc, argAp, apf, ap, config) and
localFlowEntry(node, config) and
localCC = getLocalCallContext(cc, node.getEnclosingCallable())
}
pragma[nomagic] pragma[nomagic]
private predicate flowFwdStore( private predicate flowFwdStore(
Node node, TypedContent tc, AccessPath ap0, AccessPathFront apf, boolean fromArg, Node node, TypedContent tc, AccessPath ap0, AccessPathFront apf, CallContext cc,
AccessPathOption argAp, Configuration config AccessPathOption argAp, Configuration config
) { ) {
exists(Node mid, AccessPathFront apf0 | exists(Node mid, AccessPathFront apf0 |
flowFwd(mid, fromArg, argAp, apf0, ap0, config) and flowFwd(mid, cc, argAp, apf0, ap0, config) and
flowFwdStore0(mid, tc, node, apf0, apf, config) flowFwdStore0(mid, tc, node, apf0, apf, config)
) )
} }
@@ -1764,20 +1775,20 @@ private predicate flowFwdStore0(
pragma[nomagic] pragma[nomagic]
private predicate flowFwdRead0( private predicate flowFwdRead0(
Node node1, TypedContent tc, AccessPathFrontHead apf0, AccessPath ap0, Node node2, Node node1, TypedContent tc, AccessPathFrontHead apf0, AccessPath ap0, Node node2, CallContext cc,
boolean fromArg, AccessPathOption argAp, Configuration config AccessPathOption argAp, Configuration config
) { ) {
flowFwd(node1, fromArg, argAp, apf0, ap0, config) and flowFwd(node1, cc, argAp, apf0, ap0, config) and
readCandFwd(node1, tc, apf0, node2, config) readCandFwd(node1, tc, apf0, node2, config)
} }
pragma[nomagic] pragma[nomagic]
private predicate flowFwdRead( private predicate flowFwdRead(
Node node, AccessPathFrontHead apf0, AccessPath ap0, AccessPathFront apf, boolean fromArg, Node node, AccessPathFrontHead apf0, AccessPath ap0, AccessPathFront apf, CallContext cc,
AccessPathOption argAp, Configuration config AccessPathOption argAp, Configuration config
) { ) {
exists(Node mid, TypedContent tc | exists(Node mid, TypedContent tc |
flowFwdRead0(mid, tc, apf0, ap0, node, fromArg, argAp, config) and flowFwdRead0(mid, tc, apf0, ap0, node, cc, argAp, config) and
flowCand(node, _, _, apf, unbind(config)) and flowCand(node, _, _, apf, unbind(config)) and
flowCandConsCand(tc, apf, unbind(config)) flowCandConsCand(tc, apf, unbind(config))
) )
@@ -1795,13 +1806,16 @@ private predicate flowFwdConsCand(
pragma[nomagic] pragma[nomagic]
private predicate flowFwdIn( private predicate flowFwdIn(
DataFlowCall call, ParameterNode p, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, DataFlowCall call, ParameterNode p, CallContext innercc, CallContext outercc,
AccessPath ap, Configuration config AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config
) { ) {
exists(ArgumentNode arg, boolean allowsFieldFlow | exists(ArgumentNode arg, boolean allowsFieldFlow, DataFlowCallable c |
flowFwd(arg, fromArg, argAp, apf, ap, config) and flowFwd(arg, outercc, argAp, apf, ap, config) and
flowIntoCallNodeCand2(call, arg, p, allowsFieldFlow, config) and flowIntoCallNodeCand2(call, arg, p, allowsFieldFlow, config) and
flowCand(p, _, _, _, unbind(config)) 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 ap instanceof AccessPathNil or allowsFieldFlow = true
) )
@@ -1809,13 +1823,19 @@ private predicate flowFwdIn(
pragma[nomagic] pragma[nomagic]
private predicate flowFwdOut( private predicate flowFwdOut(
DataFlowCall call, Node node, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, DataFlowCall call, Node node, CallContext innercc, DataFlowCallable innerc,
AccessPath ap, Configuration config AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config
) { ) {
exists(ReturnNodeExt ret, boolean allowsFieldFlow | exists(ReturnNodeExt ret, boolean allowsFieldFlow |
flowFwd(ret, fromArg, argAp, apf, ap, config) and flowFwd(ret, innercc, argAp, apf, ap, config) and
flowOutOfCallNodeCand2(call, ret, node, allowsFieldFlow, config) and flowOutOfCallNodeCand2(call, ret, node, allowsFieldFlow, config) and
flowCand(node, _, _, _, unbind(config)) innerc = ret.getEnclosingCallable() and
flowCand(node, _, _, _, unbind(config)) and
(
resolveReturn(innercc, innerc, call)
or
innercc.(CallContextCall).matchesCall(call)
)
| |
ap instanceof AccessPathNil or allowsFieldFlow = true ap instanceof AccessPathNil or allowsFieldFlow = true
) )
@@ -1826,7 +1846,7 @@ private predicate flowFwdOutFromArg(
DataFlowCall call, Node node, AccessPath argAp, AccessPathFront apf, AccessPath ap, DataFlowCall call, Node node, AccessPath argAp, AccessPathFront apf, AccessPath ap,
Configuration config Configuration config
) { ) {
flowFwdOut(call, node, true, TAccessPathSome(argAp), apf, ap, config) flowFwdOut(call, node, any(CallContextCall ccc), _, TAccessPathSome(argAp), apf, ap, config)
} }
/** /**
@@ -1834,10 +1854,10 @@ private predicate flowFwdOutFromArg(
*/ */
pragma[nomagic] pragma[nomagic]
private predicate flowFwdIsEntered( private predicate flowFwdIsEntered(
DataFlowCall call, boolean fromArg, AccessPathOption argAp, AccessPath ap, Configuration config DataFlowCall call, CallContext cc, AccessPathOption argAp, AccessPath ap, Configuration config
) { ) {
exists(ParameterNode p, AccessPathFront apf | exists(ParameterNode p, AccessPathFront apf |
flowFwdIn(call, p, fromArg, argAp, apf, ap, config) and flowFwdIn(call, p, _, cc, argAp, apf, ap, config) and
flowCand(p, true, TAccessPathFrontSome(_), apf, config) flowCand(p, true, TAccessPathFrontSome(_), apf, config)
) )
} }
@@ -1920,7 +1940,7 @@ private predicate flow0(
// flow out of a callable // flow out of a callable
flowOut(_, node, _, _, ap, config) and flowOut(_, node, _, _, ap, config) and
toReturn = true and toReturn = true and
if flowFwd(node, true, TAccessPathSome(_), _, ap, config) if flowFwd(node, any(CallContextCall ccc), TAccessPathSome(_), _, ap, config)
then returnAp = TAccessPathSome(ap) then returnAp = TAccessPathSome(ap)
else returnAp = TAccessPathNone() else returnAp = TAccessPathNone()
} }
@@ -2006,9 +2026,10 @@ private predicate flowIsReturned(
DataFlowCall call, boolean toReturn, AccessPathOption returnAp, AccessPath ap, DataFlowCall call, boolean toReturn, AccessPathOption returnAp, AccessPath ap,
Configuration config Configuration config
) { ) {
exists(ReturnNodeExt ret | exists(ReturnNodeExt ret, CallContextCall ccc |
flowOut(call, ret, toReturn, returnAp, ap, config) and flowOut(call, ret, toReturn, returnAp, ap, config) and
flowFwd(ret, true, TAccessPathSome(_), _, ap, config) flowFwd(ret, ccc, TAccessPathSome(_), _, ap, config) and
ccc.matchesCall(call)
) )
} }
@@ -2031,7 +2052,7 @@ private newtype TSummaryCtx =
exists(ReturnNodeExt ret, Configuration config, AccessPath ap0 | exists(ReturnNodeExt ret, Configuration config, AccessPath ap0 |
parameterFlow(p, ap, ret.getEnclosingCallable(), config) and parameterFlow(p, ap, ret.getEnclosingCallable(), config) and
flow(ret, true, TAccessPathSome(_), ap0, config) and flow(ret, true, TAccessPathSome(_), ap0, config) and
flowFwd(ret, true, TAccessPathSome(ap), _, ap0, config) flowFwd(ret, any(CallContextCall ccc), TAccessPathSome(ap), _, ap0, config)
) )
} }
@@ -2352,7 +2373,7 @@ private predicate pathOutOfCallable0(
) { ) {
pos = getReturnPosition(mid.getNode()) and pos = getReturnPosition(mid.getNode()) and
innercc = mid.getCallContext() and innercc = mid.getCallContext() and
not innercc instanceof CallContextCall and innercc instanceof CallContextNoCall and
ap = mid.getAp() and ap = mid.getAp() and
config = mid.getConfiguration() config = mid.getConfiguration()
} }
@@ -2867,7 +2888,7 @@ private module FlowExploration {
) { ) {
pos = getReturnPosition(mid.getNode()) and pos = getReturnPosition(mid.getNode()) and
innercc = mid.getCallContext() and innercc = mid.getCallContext() and
not innercc instanceof CallContextCall and innercc instanceof CallContextNoCall and
ap = mid.getAp() and ap = mid.getAp() and
config = mid.getConfiguration() config = mid.getConfiguration()
} }

View File

@@ -1066,7 +1066,7 @@ private module LocalFlowBigStep {
* Holds if `node` can be the first node in a maximal subsequence of local * Holds if `node` can be the first node in a maximal subsequence of local
* flow steps in a dataflow path. * flow steps in a dataflow path.
*/ */
private predicate localFlowEntry(Node node, Configuration config) { predicate localFlowEntry(Node node, Configuration config) {
nodeCand2(node, config) and nodeCand2(node, config) and
( (
config.isSource(node) or config.isSource(node) or
@@ -1650,53 +1650,53 @@ private class AccessPathOption extends TAccessPathOption {
* Holds if `node` is reachable with access path `ap` from a source in * Holds if `node` is reachable with access path `ap` from a source in
* the configuration `config`. * the configuration `config`.
* *
* The Boolean `fromArg` records whether the node is reached through an * 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 in a call, and if so, `argAp` records the access path of that
* argument. * argument.
*/ */
private predicate flowFwd( private predicate flowFwd(
Node node, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Node node, CallContext cc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap,
Configuration config Configuration config
) { ) {
flowFwd0(node, fromArg, argAp, apf, ap, config) and flowFwd0(node, cc, argAp, apf, ap, config) and
flowCand(node, _, _, apf, config) flowCand(node, _, _, apf, config)
} }
private predicate flowFwd0( private predicate flowFwd0(
Node node, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Node node, CallContext cc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap,
Configuration config Configuration config
) { ) {
flowCand(node, _, _, _, config) and flowCand(node, _, _, _, config) and
config.isSource(node) and config.isSource(node) and
fromArg = false and cc instanceof CallContextAny and
argAp = TAccessPathNone() and argAp = TAccessPathNone() and
ap = TNil(getNodeType(node)) and ap = TNil(getNodeType(node)) and
apf = ap.(AccessPathNil).getFront() apf = ap.(AccessPathNil).getFront()
or or
flowCand(node, _, _, _, unbind(config)) and flowCand(node, _, _, _, unbind(config)) and
( (
exists(Node mid | exists(Node mid, LocalCallContext localCC |
flowFwd(mid, fromArg, argAp, apf, ap, config) and flowFwdLocalEntry(mid, cc, argAp, apf, ap, localCC, config) and
localFlowBigStep(mid, node, true, _, config, _) localFlowBigStep(mid, node, true, _, config, localCC)
) )
or or
exists(Node mid, AccessPathNil nil | exists(Node mid, AccessPathNil nil, LocalCallContext localCC |
flowFwd(mid, fromArg, argAp, _, nil, config) and flowFwdLocalEntry(mid, cc, argAp, _, nil, localCC, config) and
localFlowBigStep(mid, node, false, apf, config, _) and localFlowBigStep(mid, node, false, apf, config, localCC) and
apf = ap.(AccessPathNil).getFront() apf = ap.(AccessPathNil).getFront()
) )
or or
exists(Node mid | exists(Node mid |
flowFwd(mid, _, _, apf, ap, config) and flowFwd(mid, _, _, apf, ap, config) and
jumpStep(mid, node, config) and jumpStep(mid, node, config) and
fromArg = false and cc instanceof CallContextAny and
argAp = TAccessPathNone() argAp = TAccessPathNone()
) )
or or
exists(Node mid, AccessPathNil nil | exists(Node mid, AccessPathNil nil |
flowFwd(mid, _, _, _, nil, config) and flowFwd(mid, _, _, _, nil, config) and
additionalJumpStep(mid, node, config) and additionalJumpStep(mid, node, config) and
fromArg = false and cc instanceof CallContextAny and
argAp = TAccessPathNone() and argAp = TAccessPathNone() and
ap = TNil(getNodeType(node)) and ap = TNil(getNodeType(node)) and
apf = ap.(AccessPathNil).getFront() apf = ap.(AccessPathNil).getFront()
@@ -1704,40 +1704,51 @@ private predicate flowFwd0(
) )
or or
// store // store
exists(TypedContent tc | flowFwdStore(node, tc, pop(tc, ap), apf, fromArg, argAp, config)) exists(TypedContent tc | flowFwdStore(node, tc, pop(tc, ap), apf, cc, argAp, config))
or or
// read // read
exists(TypedContent tc | exists(TypedContent tc |
flowFwdRead(node, _, push(tc, ap), apf, fromArg, argAp, config) and flowFwdRead(node, _, push(tc, ap), apf, cc, argAp, config) and
flowFwdConsCand(tc, apf, ap, config) flowFwdConsCand(tc, apf, ap, config)
) )
or or
// flow into a callable // flow into a callable
flowFwdIn(_, node, _, _, apf, ap, config) and flowFwdIn(_, node, cc, _, _, apf, ap, config) and
fromArg = true and
if flowCand(node, true, _, apf, config) if flowCand(node, true, _, apf, config)
then argAp = TAccessPathSome(ap) then argAp = TAccessPathSome(ap)
else argAp = TAccessPathNone() else argAp = TAccessPathNone()
or or
// flow out of a callable // flow out of a callable
exists(DataFlowCall call | exists(DataFlowCall call |
flowFwdOut(call, node, fromArg, argAp, apf, ap, config) and exists(CallContextNoCall innercc, DataFlowCallable c |
fromArg = false flowFwdOut(call, node, innercc, c, argAp, apf, ap, config) and
if reducedViableImplInReturn(c, call) then cc = TReturn(c, call) else cc = TAnyCallContext()
)
or or
exists(AccessPath argAp0 | exists(AccessPath argAp0 |
flowFwdOutFromArg(call, node, argAp0, apf, ap, config) and flowFwdOutFromArg(call, node, argAp0, apf, ap, config) and
flowFwdIsEntered(call, fromArg, argAp, argAp0, config) flowFwdIsEntered(call, cc, argAp, argAp0, config)
) )
) )
} }
pragma[nomagic]
private predicate flowFwdLocalEntry(
Node node, CallContext cc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap,
LocalCallContext localCC, Configuration config
) {
flowFwd(node, cc, argAp, apf, ap, config) and
localFlowEntry(node, config) and
localCC = getLocalCallContext(cc, node.getEnclosingCallable())
}
pragma[nomagic] pragma[nomagic]
private predicate flowFwdStore( private predicate flowFwdStore(
Node node, TypedContent tc, AccessPath ap0, AccessPathFront apf, boolean fromArg, Node node, TypedContent tc, AccessPath ap0, AccessPathFront apf, CallContext cc,
AccessPathOption argAp, Configuration config AccessPathOption argAp, Configuration config
) { ) {
exists(Node mid, AccessPathFront apf0 | exists(Node mid, AccessPathFront apf0 |
flowFwd(mid, fromArg, argAp, apf0, ap0, config) and flowFwd(mid, cc, argAp, apf0, ap0, config) and
flowFwdStore0(mid, tc, node, apf0, apf, config) flowFwdStore0(mid, tc, node, apf0, apf, config)
) )
} }
@@ -1764,20 +1775,20 @@ private predicate flowFwdStore0(
pragma[nomagic] pragma[nomagic]
private predicate flowFwdRead0( private predicate flowFwdRead0(
Node node1, TypedContent tc, AccessPathFrontHead apf0, AccessPath ap0, Node node2, Node node1, TypedContent tc, AccessPathFrontHead apf0, AccessPath ap0, Node node2, CallContext cc,
boolean fromArg, AccessPathOption argAp, Configuration config AccessPathOption argAp, Configuration config
) { ) {
flowFwd(node1, fromArg, argAp, apf0, ap0, config) and flowFwd(node1, cc, argAp, apf0, ap0, config) and
readCandFwd(node1, tc, apf0, node2, config) readCandFwd(node1, tc, apf0, node2, config)
} }
pragma[nomagic] pragma[nomagic]
private predicate flowFwdRead( private predicate flowFwdRead(
Node node, AccessPathFrontHead apf0, AccessPath ap0, AccessPathFront apf, boolean fromArg, Node node, AccessPathFrontHead apf0, AccessPath ap0, AccessPathFront apf, CallContext cc,
AccessPathOption argAp, Configuration config AccessPathOption argAp, Configuration config
) { ) {
exists(Node mid, TypedContent tc | exists(Node mid, TypedContent tc |
flowFwdRead0(mid, tc, apf0, ap0, node, fromArg, argAp, config) and flowFwdRead0(mid, tc, apf0, ap0, node, cc, argAp, config) and
flowCand(node, _, _, apf, unbind(config)) and flowCand(node, _, _, apf, unbind(config)) and
flowCandConsCand(tc, apf, unbind(config)) flowCandConsCand(tc, apf, unbind(config))
) )
@@ -1795,13 +1806,16 @@ private predicate flowFwdConsCand(
pragma[nomagic] pragma[nomagic]
private predicate flowFwdIn( private predicate flowFwdIn(
DataFlowCall call, ParameterNode p, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, DataFlowCall call, ParameterNode p, CallContext innercc, CallContext outercc,
AccessPath ap, Configuration config AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config
) { ) {
exists(ArgumentNode arg, boolean allowsFieldFlow | exists(ArgumentNode arg, boolean allowsFieldFlow, DataFlowCallable c |
flowFwd(arg, fromArg, argAp, apf, ap, config) and flowFwd(arg, outercc, argAp, apf, ap, config) and
flowIntoCallNodeCand2(call, arg, p, allowsFieldFlow, config) and flowIntoCallNodeCand2(call, arg, p, allowsFieldFlow, config) and
flowCand(p, _, _, _, unbind(config)) 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 ap instanceof AccessPathNil or allowsFieldFlow = true
) )
@@ -1809,13 +1823,19 @@ private predicate flowFwdIn(
pragma[nomagic] pragma[nomagic]
private predicate flowFwdOut( private predicate flowFwdOut(
DataFlowCall call, Node node, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, DataFlowCall call, Node node, CallContext innercc, DataFlowCallable innerc,
AccessPath ap, Configuration config AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config
) { ) {
exists(ReturnNodeExt ret, boolean allowsFieldFlow | exists(ReturnNodeExt ret, boolean allowsFieldFlow |
flowFwd(ret, fromArg, argAp, apf, ap, config) and flowFwd(ret, innercc, argAp, apf, ap, config) and
flowOutOfCallNodeCand2(call, ret, node, allowsFieldFlow, config) and flowOutOfCallNodeCand2(call, ret, node, allowsFieldFlow, config) and
flowCand(node, _, _, _, unbind(config)) innerc = ret.getEnclosingCallable() and
flowCand(node, _, _, _, unbind(config)) and
(
resolveReturn(innercc, innerc, call)
or
innercc.(CallContextCall).matchesCall(call)
)
| |
ap instanceof AccessPathNil or allowsFieldFlow = true ap instanceof AccessPathNil or allowsFieldFlow = true
) )
@@ -1826,7 +1846,7 @@ private predicate flowFwdOutFromArg(
DataFlowCall call, Node node, AccessPath argAp, AccessPathFront apf, AccessPath ap, DataFlowCall call, Node node, AccessPath argAp, AccessPathFront apf, AccessPath ap,
Configuration config Configuration config
) { ) {
flowFwdOut(call, node, true, TAccessPathSome(argAp), apf, ap, config) flowFwdOut(call, node, any(CallContextCall ccc), _, TAccessPathSome(argAp), apf, ap, config)
} }
/** /**
@@ -1834,10 +1854,10 @@ private predicate flowFwdOutFromArg(
*/ */
pragma[nomagic] pragma[nomagic]
private predicate flowFwdIsEntered( private predicate flowFwdIsEntered(
DataFlowCall call, boolean fromArg, AccessPathOption argAp, AccessPath ap, Configuration config DataFlowCall call, CallContext cc, AccessPathOption argAp, AccessPath ap, Configuration config
) { ) {
exists(ParameterNode p, AccessPathFront apf | exists(ParameterNode p, AccessPathFront apf |
flowFwdIn(call, p, fromArg, argAp, apf, ap, config) and flowFwdIn(call, p, _, cc, argAp, apf, ap, config) and
flowCand(p, true, TAccessPathFrontSome(_), apf, config) flowCand(p, true, TAccessPathFrontSome(_), apf, config)
) )
} }
@@ -1920,7 +1940,7 @@ private predicate flow0(
// flow out of a callable // flow out of a callable
flowOut(_, node, _, _, ap, config) and flowOut(_, node, _, _, ap, config) and
toReturn = true and toReturn = true and
if flowFwd(node, true, TAccessPathSome(_), _, ap, config) if flowFwd(node, any(CallContextCall ccc), TAccessPathSome(_), _, ap, config)
then returnAp = TAccessPathSome(ap) then returnAp = TAccessPathSome(ap)
else returnAp = TAccessPathNone() else returnAp = TAccessPathNone()
} }
@@ -2006,9 +2026,10 @@ private predicate flowIsReturned(
DataFlowCall call, boolean toReturn, AccessPathOption returnAp, AccessPath ap, DataFlowCall call, boolean toReturn, AccessPathOption returnAp, AccessPath ap,
Configuration config Configuration config
) { ) {
exists(ReturnNodeExt ret | exists(ReturnNodeExt ret, CallContextCall ccc |
flowOut(call, ret, toReturn, returnAp, ap, config) and flowOut(call, ret, toReturn, returnAp, ap, config) and
flowFwd(ret, true, TAccessPathSome(_), _, ap, config) flowFwd(ret, ccc, TAccessPathSome(_), _, ap, config) and
ccc.matchesCall(call)
) )
} }
@@ -2031,7 +2052,7 @@ private newtype TSummaryCtx =
exists(ReturnNodeExt ret, Configuration config, AccessPath ap0 | exists(ReturnNodeExt ret, Configuration config, AccessPath ap0 |
parameterFlow(p, ap, ret.getEnclosingCallable(), config) and parameterFlow(p, ap, ret.getEnclosingCallable(), config) and
flow(ret, true, TAccessPathSome(_), ap0, config) and flow(ret, true, TAccessPathSome(_), ap0, config) and
flowFwd(ret, true, TAccessPathSome(ap), _, ap0, config) flowFwd(ret, any(CallContextCall ccc), TAccessPathSome(ap), _, ap0, config)
) )
} }
@@ -2352,7 +2373,7 @@ private predicate pathOutOfCallable0(
) { ) {
pos = getReturnPosition(mid.getNode()) and pos = getReturnPosition(mid.getNode()) and
innercc = mid.getCallContext() and innercc = mid.getCallContext() and
not innercc instanceof CallContextCall and innercc instanceof CallContextNoCall and
ap = mid.getAp() and ap = mid.getAp() and
config = mid.getConfiguration() config = mid.getConfiguration()
} }
@@ -2867,7 +2888,7 @@ private module FlowExploration {
) { ) {
pos = getReturnPosition(mid.getNode()) and pos = getReturnPosition(mid.getNode()) and
innercc = mid.getCallContext() and innercc = mid.getCallContext() and
not innercc instanceof CallContextCall and innercc instanceof CallContextNoCall and
ap = mid.getAp() and ap = mid.getAp() and
config = mid.getConfiguration() config = mid.getConfiguration()
} }

View File

@@ -1066,7 +1066,7 @@ private module LocalFlowBigStep {
* Holds if `node` can be the first node in a maximal subsequence of local * Holds if `node` can be the first node in a maximal subsequence of local
* flow steps in a dataflow path. * flow steps in a dataflow path.
*/ */
private predicate localFlowEntry(Node node, Configuration config) { predicate localFlowEntry(Node node, Configuration config) {
nodeCand2(node, config) and nodeCand2(node, config) and
( (
config.isSource(node) or config.isSource(node) or
@@ -1650,53 +1650,53 @@ private class AccessPathOption extends TAccessPathOption {
* Holds if `node` is reachable with access path `ap` from a source in * Holds if `node` is reachable with access path `ap` from a source in
* the configuration `config`. * the configuration `config`.
* *
* The Boolean `fromArg` records whether the node is reached through an * 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 in a call, and if so, `argAp` records the access path of that
* argument. * argument.
*/ */
private predicate flowFwd( private predicate flowFwd(
Node node, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Node node, CallContext cc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap,
Configuration config Configuration config
) { ) {
flowFwd0(node, fromArg, argAp, apf, ap, config) and flowFwd0(node, cc, argAp, apf, ap, config) and
flowCand(node, _, _, apf, config) flowCand(node, _, _, apf, config)
} }
private predicate flowFwd0( private predicate flowFwd0(
Node node, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Node node, CallContext cc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap,
Configuration config Configuration config
) { ) {
flowCand(node, _, _, _, config) and flowCand(node, _, _, _, config) and
config.isSource(node) and config.isSource(node) and
fromArg = false and cc instanceof CallContextAny and
argAp = TAccessPathNone() and argAp = TAccessPathNone() and
ap = TNil(getNodeType(node)) and ap = TNil(getNodeType(node)) and
apf = ap.(AccessPathNil).getFront() apf = ap.(AccessPathNil).getFront()
or or
flowCand(node, _, _, _, unbind(config)) and flowCand(node, _, _, _, unbind(config)) and
( (
exists(Node mid | exists(Node mid, LocalCallContext localCC |
flowFwd(mid, fromArg, argAp, apf, ap, config) and flowFwdLocalEntry(mid, cc, argAp, apf, ap, localCC, config) and
localFlowBigStep(mid, node, true, _, config, _) localFlowBigStep(mid, node, true, _, config, localCC)
) )
or or
exists(Node mid, AccessPathNil nil | exists(Node mid, AccessPathNil nil, LocalCallContext localCC |
flowFwd(mid, fromArg, argAp, _, nil, config) and flowFwdLocalEntry(mid, cc, argAp, _, nil, localCC, config) and
localFlowBigStep(mid, node, false, apf, config, _) and localFlowBigStep(mid, node, false, apf, config, localCC) and
apf = ap.(AccessPathNil).getFront() apf = ap.(AccessPathNil).getFront()
) )
or or
exists(Node mid | exists(Node mid |
flowFwd(mid, _, _, apf, ap, config) and flowFwd(mid, _, _, apf, ap, config) and
jumpStep(mid, node, config) and jumpStep(mid, node, config) and
fromArg = false and cc instanceof CallContextAny and
argAp = TAccessPathNone() argAp = TAccessPathNone()
) )
or or
exists(Node mid, AccessPathNil nil | exists(Node mid, AccessPathNil nil |
flowFwd(mid, _, _, _, nil, config) and flowFwd(mid, _, _, _, nil, config) and
additionalJumpStep(mid, node, config) and additionalJumpStep(mid, node, config) and
fromArg = false and cc instanceof CallContextAny and
argAp = TAccessPathNone() and argAp = TAccessPathNone() and
ap = TNil(getNodeType(node)) and ap = TNil(getNodeType(node)) and
apf = ap.(AccessPathNil).getFront() apf = ap.(AccessPathNil).getFront()
@@ -1704,40 +1704,51 @@ private predicate flowFwd0(
) )
or or
// store // store
exists(TypedContent tc | flowFwdStore(node, tc, pop(tc, ap), apf, fromArg, argAp, config)) exists(TypedContent tc | flowFwdStore(node, tc, pop(tc, ap), apf, cc, argAp, config))
or or
// read // read
exists(TypedContent tc | exists(TypedContent tc |
flowFwdRead(node, _, push(tc, ap), apf, fromArg, argAp, config) and flowFwdRead(node, _, push(tc, ap), apf, cc, argAp, config) and
flowFwdConsCand(tc, apf, ap, config) flowFwdConsCand(tc, apf, ap, config)
) )
or or
// flow into a callable // flow into a callable
flowFwdIn(_, node, _, _, apf, ap, config) and flowFwdIn(_, node, cc, _, _, apf, ap, config) and
fromArg = true and
if flowCand(node, true, _, apf, config) if flowCand(node, true, _, apf, config)
then argAp = TAccessPathSome(ap) then argAp = TAccessPathSome(ap)
else argAp = TAccessPathNone() else argAp = TAccessPathNone()
or or
// flow out of a callable // flow out of a callable
exists(DataFlowCall call | exists(DataFlowCall call |
flowFwdOut(call, node, fromArg, argAp, apf, ap, config) and exists(CallContextNoCall innercc, DataFlowCallable c |
fromArg = false flowFwdOut(call, node, innercc, c, argAp, apf, ap, config) and
if reducedViableImplInReturn(c, call) then cc = TReturn(c, call) else cc = TAnyCallContext()
)
or or
exists(AccessPath argAp0 | exists(AccessPath argAp0 |
flowFwdOutFromArg(call, node, argAp0, apf, ap, config) and flowFwdOutFromArg(call, node, argAp0, apf, ap, config) and
flowFwdIsEntered(call, fromArg, argAp, argAp0, config) flowFwdIsEntered(call, cc, argAp, argAp0, config)
) )
) )
} }
pragma[nomagic]
private predicate flowFwdLocalEntry(
Node node, CallContext cc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap,
LocalCallContext localCC, Configuration config
) {
flowFwd(node, cc, argAp, apf, ap, config) and
localFlowEntry(node, config) and
localCC = getLocalCallContext(cc, node.getEnclosingCallable())
}
pragma[nomagic] pragma[nomagic]
private predicate flowFwdStore( private predicate flowFwdStore(
Node node, TypedContent tc, AccessPath ap0, AccessPathFront apf, boolean fromArg, Node node, TypedContent tc, AccessPath ap0, AccessPathFront apf, CallContext cc,
AccessPathOption argAp, Configuration config AccessPathOption argAp, Configuration config
) { ) {
exists(Node mid, AccessPathFront apf0 | exists(Node mid, AccessPathFront apf0 |
flowFwd(mid, fromArg, argAp, apf0, ap0, config) and flowFwd(mid, cc, argAp, apf0, ap0, config) and
flowFwdStore0(mid, tc, node, apf0, apf, config) flowFwdStore0(mid, tc, node, apf0, apf, config)
) )
} }
@@ -1764,20 +1775,20 @@ private predicate flowFwdStore0(
pragma[nomagic] pragma[nomagic]
private predicate flowFwdRead0( private predicate flowFwdRead0(
Node node1, TypedContent tc, AccessPathFrontHead apf0, AccessPath ap0, Node node2, Node node1, TypedContent tc, AccessPathFrontHead apf0, AccessPath ap0, Node node2, CallContext cc,
boolean fromArg, AccessPathOption argAp, Configuration config AccessPathOption argAp, Configuration config
) { ) {
flowFwd(node1, fromArg, argAp, apf0, ap0, config) and flowFwd(node1, cc, argAp, apf0, ap0, config) and
readCandFwd(node1, tc, apf0, node2, config) readCandFwd(node1, tc, apf0, node2, config)
} }
pragma[nomagic] pragma[nomagic]
private predicate flowFwdRead( private predicate flowFwdRead(
Node node, AccessPathFrontHead apf0, AccessPath ap0, AccessPathFront apf, boolean fromArg, Node node, AccessPathFrontHead apf0, AccessPath ap0, AccessPathFront apf, CallContext cc,
AccessPathOption argAp, Configuration config AccessPathOption argAp, Configuration config
) { ) {
exists(Node mid, TypedContent tc | exists(Node mid, TypedContent tc |
flowFwdRead0(mid, tc, apf0, ap0, node, fromArg, argAp, config) and flowFwdRead0(mid, tc, apf0, ap0, node, cc, argAp, config) and
flowCand(node, _, _, apf, unbind(config)) and flowCand(node, _, _, apf, unbind(config)) and
flowCandConsCand(tc, apf, unbind(config)) flowCandConsCand(tc, apf, unbind(config))
) )
@@ -1795,13 +1806,16 @@ private predicate flowFwdConsCand(
pragma[nomagic] pragma[nomagic]
private predicate flowFwdIn( private predicate flowFwdIn(
DataFlowCall call, ParameterNode p, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, DataFlowCall call, ParameterNode p, CallContext innercc, CallContext outercc,
AccessPath ap, Configuration config AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config
) { ) {
exists(ArgumentNode arg, boolean allowsFieldFlow | exists(ArgumentNode arg, boolean allowsFieldFlow, DataFlowCallable c |
flowFwd(arg, fromArg, argAp, apf, ap, config) and flowFwd(arg, outercc, argAp, apf, ap, config) and
flowIntoCallNodeCand2(call, arg, p, allowsFieldFlow, config) and flowIntoCallNodeCand2(call, arg, p, allowsFieldFlow, config) and
flowCand(p, _, _, _, unbind(config)) 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 ap instanceof AccessPathNil or allowsFieldFlow = true
) )
@@ -1809,13 +1823,19 @@ private predicate flowFwdIn(
pragma[nomagic] pragma[nomagic]
private predicate flowFwdOut( private predicate flowFwdOut(
DataFlowCall call, Node node, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, DataFlowCall call, Node node, CallContext innercc, DataFlowCallable innerc,
AccessPath ap, Configuration config AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config
) { ) {
exists(ReturnNodeExt ret, boolean allowsFieldFlow | exists(ReturnNodeExt ret, boolean allowsFieldFlow |
flowFwd(ret, fromArg, argAp, apf, ap, config) and flowFwd(ret, innercc, argAp, apf, ap, config) and
flowOutOfCallNodeCand2(call, ret, node, allowsFieldFlow, config) and flowOutOfCallNodeCand2(call, ret, node, allowsFieldFlow, config) and
flowCand(node, _, _, _, unbind(config)) innerc = ret.getEnclosingCallable() and
flowCand(node, _, _, _, unbind(config)) and
(
resolveReturn(innercc, innerc, call)
or
innercc.(CallContextCall).matchesCall(call)
)
| |
ap instanceof AccessPathNil or allowsFieldFlow = true ap instanceof AccessPathNil or allowsFieldFlow = true
) )
@@ -1826,7 +1846,7 @@ private predicate flowFwdOutFromArg(
DataFlowCall call, Node node, AccessPath argAp, AccessPathFront apf, AccessPath ap, DataFlowCall call, Node node, AccessPath argAp, AccessPathFront apf, AccessPath ap,
Configuration config Configuration config
) { ) {
flowFwdOut(call, node, true, TAccessPathSome(argAp), apf, ap, config) flowFwdOut(call, node, any(CallContextCall ccc), _, TAccessPathSome(argAp), apf, ap, config)
} }
/** /**
@@ -1834,10 +1854,10 @@ private predicate flowFwdOutFromArg(
*/ */
pragma[nomagic] pragma[nomagic]
private predicate flowFwdIsEntered( private predicate flowFwdIsEntered(
DataFlowCall call, boolean fromArg, AccessPathOption argAp, AccessPath ap, Configuration config DataFlowCall call, CallContext cc, AccessPathOption argAp, AccessPath ap, Configuration config
) { ) {
exists(ParameterNode p, AccessPathFront apf | exists(ParameterNode p, AccessPathFront apf |
flowFwdIn(call, p, fromArg, argAp, apf, ap, config) and flowFwdIn(call, p, _, cc, argAp, apf, ap, config) and
flowCand(p, true, TAccessPathFrontSome(_), apf, config) flowCand(p, true, TAccessPathFrontSome(_), apf, config)
) )
} }
@@ -1920,7 +1940,7 @@ private predicate flow0(
// flow out of a callable // flow out of a callable
flowOut(_, node, _, _, ap, config) and flowOut(_, node, _, _, ap, config) and
toReturn = true and toReturn = true and
if flowFwd(node, true, TAccessPathSome(_), _, ap, config) if flowFwd(node, any(CallContextCall ccc), TAccessPathSome(_), _, ap, config)
then returnAp = TAccessPathSome(ap) then returnAp = TAccessPathSome(ap)
else returnAp = TAccessPathNone() else returnAp = TAccessPathNone()
} }
@@ -2006,9 +2026,10 @@ private predicate flowIsReturned(
DataFlowCall call, boolean toReturn, AccessPathOption returnAp, AccessPath ap, DataFlowCall call, boolean toReturn, AccessPathOption returnAp, AccessPath ap,
Configuration config Configuration config
) { ) {
exists(ReturnNodeExt ret | exists(ReturnNodeExt ret, CallContextCall ccc |
flowOut(call, ret, toReturn, returnAp, ap, config) and flowOut(call, ret, toReturn, returnAp, ap, config) and
flowFwd(ret, true, TAccessPathSome(_), _, ap, config) flowFwd(ret, ccc, TAccessPathSome(_), _, ap, config) and
ccc.matchesCall(call)
) )
} }
@@ -2031,7 +2052,7 @@ private newtype TSummaryCtx =
exists(ReturnNodeExt ret, Configuration config, AccessPath ap0 | exists(ReturnNodeExt ret, Configuration config, AccessPath ap0 |
parameterFlow(p, ap, ret.getEnclosingCallable(), config) and parameterFlow(p, ap, ret.getEnclosingCallable(), config) and
flow(ret, true, TAccessPathSome(_), ap0, config) and flow(ret, true, TAccessPathSome(_), ap0, config) and
flowFwd(ret, true, TAccessPathSome(ap), _, ap0, config) flowFwd(ret, any(CallContextCall ccc), TAccessPathSome(ap), _, ap0, config)
) )
} }
@@ -2352,7 +2373,7 @@ private predicate pathOutOfCallable0(
) { ) {
pos = getReturnPosition(mid.getNode()) and pos = getReturnPosition(mid.getNode()) and
innercc = mid.getCallContext() and innercc = mid.getCallContext() and
not innercc instanceof CallContextCall and innercc instanceof CallContextNoCall and
ap = mid.getAp() and ap = mid.getAp() and
config = mid.getConfiguration() config = mid.getConfiguration()
} }
@@ -2867,7 +2888,7 @@ private module FlowExploration {
) { ) {
pos = getReturnPosition(mid.getNode()) and pos = getReturnPosition(mid.getNode()) and
innercc = mid.getCallContext() and innercc = mid.getCallContext() and
not innercc instanceof CallContextCall and innercc instanceof CallContextNoCall and
ap = mid.getAp() and ap = mid.getAp() and
config = mid.getConfiguration() config = mid.getConfiguration()
} }

View File

@@ -1066,7 +1066,7 @@ private module LocalFlowBigStep {
* Holds if `node` can be the first node in a maximal subsequence of local * Holds if `node` can be the first node in a maximal subsequence of local
* flow steps in a dataflow path. * flow steps in a dataflow path.
*/ */
private predicate localFlowEntry(Node node, Configuration config) { predicate localFlowEntry(Node node, Configuration config) {
nodeCand2(node, config) and nodeCand2(node, config) and
( (
config.isSource(node) or config.isSource(node) or
@@ -1650,53 +1650,53 @@ private class AccessPathOption extends TAccessPathOption {
* Holds if `node` is reachable with access path `ap` from a source in * Holds if `node` is reachable with access path `ap` from a source in
* the configuration `config`. * the configuration `config`.
* *
* The Boolean `fromArg` records whether the node is reached through an * 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 in a call, and if so, `argAp` records the access path of that
* argument. * argument.
*/ */
private predicate flowFwd( private predicate flowFwd(
Node node, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Node node, CallContext cc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap,
Configuration config Configuration config
) { ) {
flowFwd0(node, fromArg, argAp, apf, ap, config) and flowFwd0(node, cc, argAp, apf, ap, config) and
flowCand(node, _, _, apf, config) flowCand(node, _, _, apf, config)
} }
private predicate flowFwd0( private predicate flowFwd0(
Node node, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Node node, CallContext cc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap,
Configuration config Configuration config
) { ) {
flowCand(node, _, _, _, config) and flowCand(node, _, _, _, config) and
config.isSource(node) and config.isSource(node) and
fromArg = false and cc instanceof CallContextAny and
argAp = TAccessPathNone() and argAp = TAccessPathNone() and
ap = TNil(getNodeType(node)) and ap = TNil(getNodeType(node)) and
apf = ap.(AccessPathNil).getFront() apf = ap.(AccessPathNil).getFront()
or or
flowCand(node, _, _, _, unbind(config)) and flowCand(node, _, _, _, unbind(config)) and
( (
exists(Node mid | exists(Node mid, LocalCallContext localCC |
flowFwd(mid, fromArg, argAp, apf, ap, config) and flowFwdLocalEntry(mid, cc, argAp, apf, ap, localCC, config) and
localFlowBigStep(mid, node, true, _, config, _) localFlowBigStep(mid, node, true, _, config, localCC)
) )
or or
exists(Node mid, AccessPathNil nil | exists(Node mid, AccessPathNil nil, LocalCallContext localCC |
flowFwd(mid, fromArg, argAp, _, nil, config) and flowFwdLocalEntry(mid, cc, argAp, _, nil, localCC, config) and
localFlowBigStep(mid, node, false, apf, config, _) and localFlowBigStep(mid, node, false, apf, config, localCC) and
apf = ap.(AccessPathNil).getFront() apf = ap.(AccessPathNil).getFront()
) )
or or
exists(Node mid | exists(Node mid |
flowFwd(mid, _, _, apf, ap, config) and flowFwd(mid, _, _, apf, ap, config) and
jumpStep(mid, node, config) and jumpStep(mid, node, config) and
fromArg = false and cc instanceof CallContextAny and
argAp = TAccessPathNone() argAp = TAccessPathNone()
) )
or or
exists(Node mid, AccessPathNil nil | exists(Node mid, AccessPathNil nil |
flowFwd(mid, _, _, _, nil, config) and flowFwd(mid, _, _, _, nil, config) and
additionalJumpStep(mid, node, config) and additionalJumpStep(mid, node, config) and
fromArg = false and cc instanceof CallContextAny and
argAp = TAccessPathNone() and argAp = TAccessPathNone() and
ap = TNil(getNodeType(node)) and ap = TNil(getNodeType(node)) and
apf = ap.(AccessPathNil).getFront() apf = ap.(AccessPathNil).getFront()
@@ -1704,40 +1704,51 @@ private predicate flowFwd0(
) )
or or
// store // store
exists(TypedContent tc | flowFwdStore(node, tc, pop(tc, ap), apf, fromArg, argAp, config)) exists(TypedContent tc | flowFwdStore(node, tc, pop(tc, ap), apf, cc, argAp, config))
or or
// read // read
exists(TypedContent tc | exists(TypedContent tc |
flowFwdRead(node, _, push(tc, ap), apf, fromArg, argAp, config) and flowFwdRead(node, _, push(tc, ap), apf, cc, argAp, config) and
flowFwdConsCand(tc, apf, ap, config) flowFwdConsCand(tc, apf, ap, config)
) )
or or
// flow into a callable // flow into a callable
flowFwdIn(_, node, _, _, apf, ap, config) and flowFwdIn(_, node, cc, _, _, apf, ap, config) and
fromArg = true and
if flowCand(node, true, _, apf, config) if flowCand(node, true, _, apf, config)
then argAp = TAccessPathSome(ap) then argAp = TAccessPathSome(ap)
else argAp = TAccessPathNone() else argAp = TAccessPathNone()
or or
// flow out of a callable // flow out of a callable
exists(DataFlowCall call | exists(DataFlowCall call |
flowFwdOut(call, node, fromArg, argAp, apf, ap, config) and exists(CallContextNoCall innercc, DataFlowCallable c |
fromArg = false flowFwdOut(call, node, innercc, c, argAp, apf, ap, config) and
if reducedViableImplInReturn(c, call) then cc = TReturn(c, call) else cc = TAnyCallContext()
)
or or
exists(AccessPath argAp0 | exists(AccessPath argAp0 |
flowFwdOutFromArg(call, node, argAp0, apf, ap, config) and flowFwdOutFromArg(call, node, argAp0, apf, ap, config) and
flowFwdIsEntered(call, fromArg, argAp, argAp0, config) flowFwdIsEntered(call, cc, argAp, argAp0, config)
) )
) )
} }
pragma[nomagic]
private predicate flowFwdLocalEntry(
Node node, CallContext cc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap,
LocalCallContext localCC, Configuration config
) {
flowFwd(node, cc, argAp, apf, ap, config) and
localFlowEntry(node, config) and
localCC = getLocalCallContext(cc, node.getEnclosingCallable())
}
pragma[nomagic] pragma[nomagic]
private predicate flowFwdStore( private predicate flowFwdStore(
Node node, TypedContent tc, AccessPath ap0, AccessPathFront apf, boolean fromArg, Node node, TypedContent tc, AccessPath ap0, AccessPathFront apf, CallContext cc,
AccessPathOption argAp, Configuration config AccessPathOption argAp, Configuration config
) { ) {
exists(Node mid, AccessPathFront apf0 | exists(Node mid, AccessPathFront apf0 |
flowFwd(mid, fromArg, argAp, apf0, ap0, config) and flowFwd(mid, cc, argAp, apf0, ap0, config) and
flowFwdStore0(mid, tc, node, apf0, apf, config) flowFwdStore0(mid, tc, node, apf0, apf, config)
) )
} }
@@ -1764,20 +1775,20 @@ private predicate flowFwdStore0(
pragma[nomagic] pragma[nomagic]
private predicate flowFwdRead0( private predicate flowFwdRead0(
Node node1, TypedContent tc, AccessPathFrontHead apf0, AccessPath ap0, Node node2, Node node1, TypedContent tc, AccessPathFrontHead apf0, AccessPath ap0, Node node2, CallContext cc,
boolean fromArg, AccessPathOption argAp, Configuration config AccessPathOption argAp, Configuration config
) { ) {
flowFwd(node1, fromArg, argAp, apf0, ap0, config) and flowFwd(node1, cc, argAp, apf0, ap0, config) and
readCandFwd(node1, tc, apf0, node2, config) readCandFwd(node1, tc, apf0, node2, config)
} }
pragma[nomagic] pragma[nomagic]
private predicate flowFwdRead( private predicate flowFwdRead(
Node node, AccessPathFrontHead apf0, AccessPath ap0, AccessPathFront apf, boolean fromArg, Node node, AccessPathFrontHead apf0, AccessPath ap0, AccessPathFront apf, CallContext cc,
AccessPathOption argAp, Configuration config AccessPathOption argAp, Configuration config
) { ) {
exists(Node mid, TypedContent tc | exists(Node mid, TypedContent tc |
flowFwdRead0(mid, tc, apf0, ap0, node, fromArg, argAp, config) and flowFwdRead0(mid, tc, apf0, ap0, node, cc, argAp, config) and
flowCand(node, _, _, apf, unbind(config)) and flowCand(node, _, _, apf, unbind(config)) and
flowCandConsCand(tc, apf, unbind(config)) flowCandConsCand(tc, apf, unbind(config))
) )
@@ -1795,13 +1806,16 @@ private predicate flowFwdConsCand(
pragma[nomagic] pragma[nomagic]
private predicate flowFwdIn( private predicate flowFwdIn(
DataFlowCall call, ParameterNode p, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, DataFlowCall call, ParameterNode p, CallContext innercc, CallContext outercc,
AccessPath ap, Configuration config AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config
) { ) {
exists(ArgumentNode arg, boolean allowsFieldFlow | exists(ArgumentNode arg, boolean allowsFieldFlow, DataFlowCallable c |
flowFwd(arg, fromArg, argAp, apf, ap, config) and flowFwd(arg, outercc, argAp, apf, ap, config) and
flowIntoCallNodeCand2(call, arg, p, allowsFieldFlow, config) and flowIntoCallNodeCand2(call, arg, p, allowsFieldFlow, config) and
flowCand(p, _, _, _, unbind(config)) 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 ap instanceof AccessPathNil or allowsFieldFlow = true
) )
@@ -1809,13 +1823,19 @@ private predicate flowFwdIn(
pragma[nomagic] pragma[nomagic]
private predicate flowFwdOut( private predicate flowFwdOut(
DataFlowCall call, Node node, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, DataFlowCall call, Node node, CallContext innercc, DataFlowCallable innerc,
AccessPath ap, Configuration config AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config
) { ) {
exists(ReturnNodeExt ret, boolean allowsFieldFlow | exists(ReturnNodeExt ret, boolean allowsFieldFlow |
flowFwd(ret, fromArg, argAp, apf, ap, config) and flowFwd(ret, innercc, argAp, apf, ap, config) and
flowOutOfCallNodeCand2(call, ret, node, allowsFieldFlow, config) and flowOutOfCallNodeCand2(call, ret, node, allowsFieldFlow, config) and
flowCand(node, _, _, _, unbind(config)) innerc = ret.getEnclosingCallable() and
flowCand(node, _, _, _, unbind(config)) and
(
resolveReturn(innercc, innerc, call)
or
innercc.(CallContextCall).matchesCall(call)
)
| |
ap instanceof AccessPathNil or allowsFieldFlow = true ap instanceof AccessPathNil or allowsFieldFlow = true
) )
@@ -1826,7 +1846,7 @@ private predicate flowFwdOutFromArg(
DataFlowCall call, Node node, AccessPath argAp, AccessPathFront apf, AccessPath ap, DataFlowCall call, Node node, AccessPath argAp, AccessPathFront apf, AccessPath ap,
Configuration config Configuration config
) { ) {
flowFwdOut(call, node, true, TAccessPathSome(argAp), apf, ap, config) flowFwdOut(call, node, any(CallContextCall ccc), _, TAccessPathSome(argAp), apf, ap, config)
} }
/** /**
@@ -1834,10 +1854,10 @@ private predicate flowFwdOutFromArg(
*/ */
pragma[nomagic] pragma[nomagic]
private predicate flowFwdIsEntered( private predicate flowFwdIsEntered(
DataFlowCall call, boolean fromArg, AccessPathOption argAp, AccessPath ap, Configuration config DataFlowCall call, CallContext cc, AccessPathOption argAp, AccessPath ap, Configuration config
) { ) {
exists(ParameterNode p, AccessPathFront apf | exists(ParameterNode p, AccessPathFront apf |
flowFwdIn(call, p, fromArg, argAp, apf, ap, config) and flowFwdIn(call, p, _, cc, argAp, apf, ap, config) and
flowCand(p, true, TAccessPathFrontSome(_), apf, config) flowCand(p, true, TAccessPathFrontSome(_), apf, config)
) )
} }
@@ -1920,7 +1940,7 @@ private predicate flow0(
// flow out of a callable // flow out of a callable
flowOut(_, node, _, _, ap, config) and flowOut(_, node, _, _, ap, config) and
toReturn = true and toReturn = true and
if flowFwd(node, true, TAccessPathSome(_), _, ap, config) if flowFwd(node, any(CallContextCall ccc), TAccessPathSome(_), _, ap, config)
then returnAp = TAccessPathSome(ap) then returnAp = TAccessPathSome(ap)
else returnAp = TAccessPathNone() else returnAp = TAccessPathNone()
} }
@@ -2006,9 +2026,10 @@ private predicate flowIsReturned(
DataFlowCall call, boolean toReturn, AccessPathOption returnAp, AccessPath ap, DataFlowCall call, boolean toReturn, AccessPathOption returnAp, AccessPath ap,
Configuration config Configuration config
) { ) {
exists(ReturnNodeExt ret | exists(ReturnNodeExt ret, CallContextCall ccc |
flowOut(call, ret, toReturn, returnAp, ap, config) and flowOut(call, ret, toReturn, returnAp, ap, config) and
flowFwd(ret, true, TAccessPathSome(_), _, ap, config) flowFwd(ret, ccc, TAccessPathSome(_), _, ap, config) and
ccc.matchesCall(call)
) )
} }
@@ -2031,7 +2052,7 @@ private newtype TSummaryCtx =
exists(ReturnNodeExt ret, Configuration config, AccessPath ap0 | exists(ReturnNodeExt ret, Configuration config, AccessPath ap0 |
parameterFlow(p, ap, ret.getEnclosingCallable(), config) and parameterFlow(p, ap, ret.getEnclosingCallable(), config) and
flow(ret, true, TAccessPathSome(_), ap0, config) and flow(ret, true, TAccessPathSome(_), ap0, config) and
flowFwd(ret, true, TAccessPathSome(ap), _, ap0, config) flowFwd(ret, any(CallContextCall ccc), TAccessPathSome(ap), _, ap0, config)
) )
} }
@@ -2352,7 +2373,7 @@ private predicate pathOutOfCallable0(
) { ) {
pos = getReturnPosition(mid.getNode()) and pos = getReturnPosition(mid.getNode()) and
innercc = mid.getCallContext() and innercc = mid.getCallContext() and
not innercc instanceof CallContextCall and innercc instanceof CallContextNoCall and
ap = mid.getAp() and ap = mid.getAp() and
config = mid.getConfiguration() config = mid.getConfiguration()
} }
@@ -2867,7 +2888,7 @@ private module FlowExploration {
) { ) {
pos = getReturnPosition(mid.getNode()) and pos = getReturnPosition(mid.getNode()) and
innercc = mid.getCallContext() and innercc = mid.getCallContext() and
not innercc instanceof CallContextCall and innercc instanceof CallContextNoCall and
ap = mid.getAp() and ap = mid.getAp() and
config = mid.getConfiguration() config = mid.getConfiguration()
} }

View File

@@ -512,13 +512,19 @@ abstract class CallContext extends TCallContext {
abstract predicate relevantFor(DataFlowCallable callable); abstract predicate relevantFor(DataFlowCallable callable);
} }
class CallContextAny extends CallContext, TAnyCallContext { abstract class CallContextNoCall extends CallContext { }
class CallContextAny extends CallContextNoCall, TAnyCallContext {
override string toString() { result = "CcAny" } override string toString() { result = "CcAny" }
override predicate relevantFor(DataFlowCallable callable) { any() } override predicate relevantFor(DataFlowCallable callable) { any() }
} }
abstract class CallContextCall extends CallContext { } abstract class CallContextCall extends CallContext {
/** Holds if this call context may be `call`. */
bindingset[call]
abstract predicate matchesCall(DataFlowCall call);
}
class CallContextSpecificCall extends CallContextCall, TSpecificCall { class CallContextSpecificCall extends CallContextCall, TSpecificCall {
override string toString() { override string toString() {
@@ -529,6 +535,8 @@ class CallContextSpecificCall extends CallContextCall, TSpecificCall {
recordDataFlowCallSite(getCall(), callable) recordDataFlowCallSite(getCall(), callable)
} }
override predicate matchesCall(DataFlowCall call) { call = this.getCall() }
DataFlowCall getCall() { this = TSpecificCall(result) } DataFlowCall getCall() { this = TSpecificCall(result) }
} }
@@ -538,9 +546,11 @@ class CallContextSomeCall extends CallContextCall, TSomeCall {
override predicate relevantFor(DataFlowCallable callable) { override predicate relevantFor(DataFlowCallable callable) {
exists(ParameterNode p | p.getEnclosingCallable() = callable) exists(ParameterNode p | p.getEnclosingCallable() = callable)
} }
override predicate matchesCall(DataFlowCall call) { any() }
} }
class CallContextReturn extends CallContext, TReturn { class CallContextReturn extends CallContextNoCall, TReturn {
override string toString() { override string toString() {
exists(DataFlowCall call | this = TReturn(_, call) | result = "CcReturn(" + call + ")") exists(DataFlowCall call | this = TReturn(_, call) | result = "CcReturn(" + call + ")")
} }

View File

@@ -1066,7 +1066,7 @@ private module LocalFlowBigStep {
* Holds if `node` can be the first node in a maximal subsequence of local * Holds if `node` can be the first node in a maximal subsequence of local
* flow steps in a dataflow path. * flow steps in a dataflow path.
*/ */
private predicate localFlowEntry(Node node, Configuration config) { predicate localFlowEntry(Node node, Configuration config) {
nodeCand2(node, config) and nodeCand2(node, config) and
( (
config.isSource(node) or config.isSource(node) or
@@ -1650,53 +1650,53 @@ private class AccessPathOption extends TAccessPathOption {
* Holds if `node` is reachable with access path `ap` from a source in * Holds if `node` is reachable with access path `ap` from a source in
* the configuration `config`. * the configuration `config`.
* *
* The Boolean `fromArg` records whether the node is reached through an * 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 in a call, and if so, `argAp` records the access path of that
* argument. * argument.
*/ */
private predicate flowFwd( private predicate flowFwd(
Node node, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Node node, CallContext cc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap,
Configuration config Configuration config
) { ) {
flowFwd0(node, fromArg, argAp, apf, ap, config) and flowFwd0(node, cc, argAp, apf, ap, config) and
flowCand(node, _, _, apf, config) flowCand(node, _, _, apf, config)
} }
private predicate flowFwd0( private predicate flowFwd0(
Node node, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Node node, CallContext cc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap,
Configuration config Configuration config
) { ) {
flowCand(node, _, _, _, config) and flowCand(node, _, _, _, config) and
config.isSource(node) and config.isSource(node) and
fromArg = false and cc instanceof CallContextAny and
argAp = TAccessPathNone() and argAp = TAccessPathNone() and
ap = TNil(getNodeType(node)) and ap = TNil(getNodeType(node)) and
apf = ap.(AccessPathNil).getFront() apf = ap.(AccessPathNil).getFront()
or or
flowCand(node, _, _, _, unbind(config)) and flowCand(node, _, _, _, unbind(config)) and
( (
exists(Node mid | exists(Node mid, LocalCallContext localCC |
flowFwd(mid, fromArg, argAp, apf, ap, config) and flowFwdLocalEntry(mid, cc, argAp, apf, ap, localCC, config) and
localFlowBigStep(mid, node, true, _, config, _) localFlowBigStep(mid, node, true, _, config, localCC)
) )
or or
exists(Node mid, AccessPathNil nil | exists(Node mid, AccessPathNil nil, LocalCallContext localCC |
flowFwd(mid, fromArg, argAp, _, nil, config) and flowFwdLocalEntry(mid, cc, argAp, _, nil, localCC, config) and
localFlowBigStep(mid, node, false, apf, config, _) and localFlowBigStep(mid, node, false, apf, config, localCC) and
apf = ap.(AccessPathNil).getFront() apf = ap.(AccessPathNil).getFront()
) )
or or
exists(Node mid | exists(Node mid |
flowFwd(mid, _, _, apf, ap, config) and flowFwd(mid, _, _, apf, ap, config) and
jumpStep(mid, node, config) and jumpStep(mid, node, config) and
fromArg = false and cc instanceof CallContextAny and
argAp = TAccessPathNone() argAp = TAccessPathNone()
) )
or or
exists(Node mid, AccessPathNil nil | exists(Node mid, AccessPathNil nil |
flowFwd(mid, _, _, _, nil, config) and flowFwd(mid, _, _, _, nil, config) and
additionalJumpStep(mid, node, config) and additionalJumpStep(mid, node, config) and
fromArg = false and cc instanceof CallContextAny and
argAp = TAccessPathNone() and argAp = TAccessPathNone() and
ap = TNil(getNodeType(node)) and ap = TNil(getNodeType(node)) and
apf = ap.(AccessPathNil).getFront() apf = ap.(AccessPathNil).getFront()
@@ -1704,40 +1704,51 @@ private predicate flowFwd0(
) )
or or
// store // store
exists(TypedContent tc | flowFwdStore(node, tc, pop(tc, ap), apf, fromArg, argAp, config)) exists(TypedContent tc | flowFwdStore(node, tc, pop(tc, ap), apf, cc, argAp, config))
or or
// read // read
exists(TypedContent tc | exists(TypedContent tc |
flowFwdRead(node, _, push(tc, ap), apf, fromArg, argAp, config) and flowFwdRead(node, _, push(tc, ap), apf, cc, argAp, config) and
flowFwdConsCand(tc, apf, ap, config) flowFwdConsCand(tc, apf, ap, config)
) )
or or
// flow into a callable // flow into a callable
flowFwdIn(_, node, _, _, apf, ap, config) and flowFwdIn(_, node, cc, _, _, apf, ap, config) and
fromArg = true and
if flowCand(node, true, _, apf, config) if flowCand(node, true, _, apf, config)
then argAp = TAccessPathSome(ap) then argAp = TAccessPathSome(ap)
else argAp = TAccessPathNone() else argAp = TAccessPathNone()
or or
// flow out of a callable // flow out of a callable
exists(DataFlowCall call | exists(DataFlowCall call |
flowFwdOut(call, node, fromArg, argAp, apf, ap, config) and exists(CallContextNoCall innercc, DataFlowCallable c |
fromArg = false flowFwdOut(call, node, innercc, c, argAp, apf, ap, config) and
if reducedViableImplInReturn(c, call) then cc = TReturn(c, call) else cc = TAnyCallContext()
)
or or
exists(AccessPath argAp0 | exists(AccessPath argAp0 |
flowFwdOutFromArg(call, node, argAp0, apf, ap, config) and flowFwdOutFromArg(call, node, argAp0, apf, ap, config) and
flowFwdIsEntered(call, fromArg, argAp, argAp0, config) flowFwdIsEntered(call, cc, argAp, argAp0, config)
) )
) )
} }
pragma[nomagic]
private predicate flowFwdLocalEntry(
Node node, CallContext cc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap,
LocalCallContext localCC, Configuration config
) {
flowFwd(node, cc, argAp, apf, ap, config) and
localFlowEntry(node, config) and
localCC = getLocalCallContext(cc, node.getEnclosingCallable())
}
pragma[nomagic] pragma[nomagic]
private predicate flowFwdStore( private predicate flowFwdStore(
Node node, TypedContent tc, AccessPath ap0, AccessPathFront apf, boolean fromArg, Node node, TypedContent tc, AccessPath ap0, AccessPathFront apf, CallContext cc,
AccessPathOption argAp, Configuration config AccessPathOption argAp, Configuration config
) { ) {
exists(Node mid, AccessPathFront apf0 | exists(Node mid, AccessPathFront apf0 |
flowFwd(mid, fromArg, argAp, apf0, ap0, config) and flowFwd(mid, cc, argAp, apf0, ap0, config) and
flowFwdStore0(mid, tc, node, apf0, apf, config) flowFwdStore0(mid, tc, node, apf0, apf, config)
) )
} }
@@ -1764,20 +1775,20 @@ private predicate flowFwdStore0(
pragma[nomagic] pragma[nomagic]
private predicate flowFwdRead0( private predicate flowFwdRead0(
Node node1, TypedContent tc, AccessPathFrontHead apf0, AccessPath ap0, Node node2, Node node1, TypedContent tc, AccessPathFrontHead apf0, AccessPath ap0, Node node2, CallContext cc,
boolean fromArg, AccessPathOption argAp, Configuration config AccessPathOption argAp, Configuration config
) { ) {
flowFwd(node1, fromArg, argAp, apf0, ap0, config) and flowFwd(node1, cc, argAp, apf0, ap0, config) and
readCandFwd(node1, tc, apf0, node2, config) readCandFwd(node1, tc, apf0, node2, config)
} }
pragma[nomagic] pragma[nomagic]
private predicate flowFwdRead( private predicate flowFwdRead(
Node node, AccessPathFrontHead apf0, AccessPath ap0, AccessPathFront apf, boolean fromArg, Node node, AccessPathFrontHead apf0, AccessPath ap0, AccessPathFront apf, CallContext cc,
AccessPathOption argAp, Configuration config AccessPathOption argAp, Configuration config
) { ) {
exists(Node mid, TypedContent tc | exists(Node mid, TypedContent tc |
flowFwdRead0(mid, tc, apf0, ap0, node, fromArg, argAp, config) and flowFwdRead0(mid, tc, apf0, ap0, node, cc, argAp, config) and
flowCand(node, _, _, apf, unbind(config)) and flowCand(node, _, _, apf, unbind(config)) and
flowCandConsCand(tc, apf, unbind(config)) flowCandConsCand(tc, apf, unbind(config))
) )
@@ -1795,13 +1806,16 @@ private predicate flowFwdConsCand(
pragma[nomagic] pragma[nomagic]
private predicate flowFwdIn( private predicate flowFwdIn(
DataFlowCall call, ParameterNode p, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, DataFlowCall call, ParameterNode p, CallContext innercc, CallContext outercc,
AccessPath ap, Configuration config AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config
) { ) {
exists(ArgumentNode arg, boolean allowsFieldFlow | exists(ArgumentNode arg, boolean allowsFieldFlow, DataFlowCallable c |
flowFwd(arg, fromArg, argAp, apf, ap, config) and flowFwd(arg, outercc, argAp, apf, ap, config) and
flowIntoCallNodeCand2(call, arg, p, allowsFieldFlow, config) and flowIntoCallNodeCand2(call, arg, p, allowsFieldFlow, config) and
flowCand(p, _, _, _, unbind(config)) 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 ap instanceof AccessPathNil or allowsFieldFlow = true
) )
@@ -1809,13 +1823,19 @@ private predicate flowFwdIn(
pragma[nomagic] pragma[nomagic]
private predicate flowFwdOut( private predicate flowFwdOut(
DataFlowCall call, Node node, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, DataFlowCall call, Node node, CallContext innercc, DataFlowCallable innerc,
AccessPath ap, Configuration config AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config
) { ) {
exists(ReturnNodeExt ret, boolean allowsFieldFlow | exists(ReturnNodeExt ret, boolean allowsFieldFlow |
flowFwd(ret, fromArg, argAp, apf, ap, config) and flowFwd(ret, innercc, argAp, apf, ap, config) and
flowOutOfCallNodeCand2(call, ret, node, allowsFieldFlow, config) and flowOutOfCallNodeCand2(call, ret, node, allowsFieldFlow, config) and
flowCand(node, _, _, _, unbind(config)) innerc = ret.getEnclosingCallable() and
flowCand(node, _, _, _, unbind(config)) and
(
resolveReturn(innercc, innerc, call)
or
innercc.(CallContextCall).matchesCall(call)
)
| |
ap instanceof AccessPathNil or allowsFieldFlow = true ap instanceof AccessPathNil or allowsFieldFlow = true
) )
@@ -1826,7 +1846,7 @@ private predicate flowFwdOutFromArg(
DataFlowCall call, Node node, AccessPath argAp, AccessPathFront apf, AccessPath ap, DataFlowCall call, Node node, AccessPath argAp, AccessPathFront apf, AccessPath ap,
Configuration config Configuration config
) { ) {
flowFwdOut(call, node, true, TAccessPathSome(argAp), apf, ap, config) flowFwdOut(call, node, any(CallContextCall ccc), _, TAccessPathSome(argAp), apf, ap, config)
} }
/** /**
@@ -1834,10 +1854,10 @@ private predicate flowFwdOutFromArg(
*/ */
pragma[nomagic] pragma[nomagic]
private predicate flowFwdIsEntered( private predicate flowFwdIsEntered(
DataFlowCall call, boolean fromArg, AccessPathOption argAp, AccessPath ap, Configuration config DataFlowCall call, CallContext cc, AccessPathOption argAp, AccessPath ap, Configuration config
) { ) {
exists(ParameterNode p, AccessPathFront apf | exists(ParameterNode p, AccessPathFront apf |
flowFwdIn(call, p, fromArg, argAp, apf, ap, config) and flowFwdIn(call, p, _, cc, argAp, apf, ap, config) and
flowCand(p, true, TAccessPathFrontSome(_), apf, config) flowCand(p, true, TAccessPathFrontSome(_), apf, config)
) )
} }
@@ -1920,7 +1940,7 @@ private predicate flow0(
// flow out of a callable // flow out of a callable
flowOut(_, node, _, _, ap, config) and flowOut(_, node, _, _, ap, config) and
toReturn = true and toReturn = true and
if flowFwd(node, true, TAccessPathSome(_), _, ap, config) if flowFwd(node, any(CallContextCall ccc), TAccessPathSome(_), _, ap, config)
then returnAp = TAccessPathSome(ap) then returnAp = TAccessPathSome(ap)
else returnAp = TAccessPathNone() else returnAp = TAccessPathNone()
} }
@@ -2006,9 +2026,10 @@ private predicate flowIsReturned(
DataFlowCall call, boolean toReturn, AccessPathOption returnAp, AccessPath ap, DataFlowCall call, boolean toReturn, AccessPathOption returnAp, AccessPath ap,
Configuration config Configuration config
) { ) {
exists(ReturnNodeExt ret | exists(ReturnNodeExt ret, CallContextCall ccc |
flowOut(call, ret, toReturn, returnAp, ap, config) and flowOut(call, ret, toReturn, returnAp, ap, config) and
flowFwd(ret, true, TAccessPathSome(_), _, ap, config) flowFwd(ret, ccc, TAccessPathSome(_), _, ap, config) and
ccc.matchesCall(call)
) )
} }
@@ -2031,7 +2052,7 @@ private newtype TSummaryCtx =
exists(ReturnNodeExt ret, Configuration config, AccessPath ap0 | exists(ReturnNodeExt ret, Configuration config, AccessPath ap0 |
parameterFlow(p, ap, ret.getEnclosingCallable(), config) and parameterFlow(p, ap, ret.getEnclosingCallable(), config) and
flow(ret, true, TAccessPathSome(_), ap0, config) and flow(ret, true, TAccessPathSome(_), ap0, config) and
flowFwd(ret, true, TAccessPathSome(ap), _, ap0, config) flowFwd(ret, any(CallContextCall ccc), TAccessPathSome(ap), _, ap0, config)
) )
} }
@@ -2352,7 +2373,7 @@ private predicate pathOutOfCallable0(
) { ) {
pos = getReturnPosition(mid.getNode()) and pos = getReturnPosition(mid.getNode()) and
innercc = mid.getCallContext() and innercc = mid.getCallContext() and
not innercc instanceof CallContextCall and innercc instanceof CallContextNoCall and
ap = mid.getAp() and ap = mid.getAp() and
config = mid.getConfiguration() config = mid.getConfiguration()
} }
@@ -2867,7 +2888,7 @@ private module FlowExploration {
) { ) {
pos = getReturnPosition(mid.getNode()) and pos = getReturnPosition(mid.getNode()) and
innercc = mid.getCallContext() and innercc = mid.getCallContext() and
not innercc instanceof CallContextCall and innercc instanceof CallContextNoCall and
ap = mid.getAp() and ap = mid.getAp() and
config = mid.getConfiguration() config = mid.getConfiguration()
} }

View File

@@ -1066,7 +1066,7 @@ private module LocalFlowBigStep {
* Holds if `node` can be the first node in a maximal subsequence of local * Holds if `node` can be the first node in a maximal subsequence of local
* flow steps in a dataflow path. * flow steps in a dataflow path.
*/ */
private predicate localFlowEntry(Node node, Configuration config) { predicate localFlowEntry(Node node, Configuration config) {
nodeCand2(node, config) and nodeCand2(node, config) and
( (
config.isSource(node) or config.isSource(node) or
@@ -1650,53 +1650,53 @@ private class AccessPathOption extends TAccessPathOption {
* Holds if `node` is reachable with access path `ap` from a source in * Holds if `node` is reachable with access path `ap` from a source in
* the configuration `config`. * the configuration `config`.
* *
* The Boolean `fromArg` records whether the node is reached through an * 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 in a call, and if so, `argAp` records the access path of that
* argument. * argument.
*/ */
private predicate flowFwd( private predicate flowFwd(
Node node, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Node node, CallContext cc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap,
Configuration config Configuration config
) { ) {
flowFwd0(node, fromArg, argAp, apf, ap, config) and flowFwd0(node, cc, argAp, apf, ap, config) and
flowCand(node, _, _, apf, config) flowCand(node, _, _, apf, config)
} }
private predicate flowFwd0( private predicate flowFwd0(
Node node, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Node node, CallContext cc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap,
Configuration config Configuration config
) { ) {
flowCand(node, _, _, _, config) and flowCand(node, _, _, _, config) and
config.isSource(node) and config.isSource(node) and
fromArg = false and cc instanceof CallContextAny and
argAp = TAccessPathNone() and argAp = TAccessPathNone() and
ap = TNil(getNodeType(node)) and ap = TNil(getNodeType(node)) and
apf = ap.(AccessPathNil).getFront() apf = ap.(AccessPathNil).getFront()
or or
flowCand(node, _, _, _, unbind(config)) and flowCand(node, _, _, _, unbind(config)) and
( (
exists(Node mid | exists(Node mid, LocalCallContext localCC |
flowFwd(mid, fromArg, argAp, apf, ap, config) and flowFwdLocalEntry(mid, cc, argAp, apf, ap, localCC, config) and
localFlowBigStep(mid, node, true, _, config, _) localFlowBigStep(mid, node, true, _, config, localCC)
) )
or or
exists(Node mid, AccessPathNil nil | exists(Node mid, AccessPathNil nil, LocalCallContext localCC |
flowFwd(mid, fromArg, argAp, _, nil, config) and flowFwdLocalEntry(mid, cc, argAp, _, nil, localCC, config) and
localFlowBigStep(mid, node, false, apf, config, _) and localFlowBigStep(mid, node, false, apf, config, localCC) and
apf = ap.(AccessPathNil).getFront() apf = ap.(AccessPathNil).getFront()
) )
or or
exists(Node mid | exists(Node mid |
flowFwd(mid, _, _, apf, ap, config) and flowFwd(mid, _, _, apf, ap, config) and
jumpStep(mid, node, config) and jumpStep(mid, node, config) and
fromArg = false and cc instanceof CallContextAny and
argAp = TAccessPathNone() argAp = TAccessPathNone()
) )
or or
exists(Node mid, AccessPathNil nil | exists(Node mid, AccessPathNil nil |
flowFwd(mid, _, _, _, nil, config) and flowFwd(mid, _, _, _, nil, config) and
additionalJumpStep(mid, node, config) and additionalJumpStep(mid, node, config) and
fromArg = false and cc instanceof CallContextAny and
argAp = TAccessPathNone() and argAp = TAccessPathNone() and
ap = TNil(getNodeType(node)) and ap = TNil(getNodeType(node)) and
apf = ap.(AccessPathNil).getFront() apf = ap.(AccessPathNil).getFront()
@@ -1704,40 +1704,51 @@ private predicate flowFwd0(
) )
or or
// store // store
exists(TypedContent tc | flowFwdStore(node, tc, pop(tc, ap), apf, fromArg, argAp, config)) exists(TypedContent tc | flowFwdStore(node, tc, pop(tc, ap), apf, cc, argAp, config))
or or
// read // read
exists(TypedContent tc | exists(TypedContent tc |
flowFwdRead(node, _, push(tc, ap), apf, fromArg, argAp, config) and flowFwdRead(node, _, push(tc, ap), apf, cc, argAp, config) and
flowFwdConsCand(tc, apf, ap, config) flowFwdConsCand(tc, apf, ap, config)
) )
or or
// flow into a callable // flow into a callable
flowFwdIn(_, node, _, _, apf, ap, config) and flowFwdIn(_, node, cc, _, _, apf, ap, config) and
fromArg = true and
if flowCand(node, true, _, apf, config) if flowCand(node, true, _, apf, config)
then argAp = TAccessPathSome(ap) then argAp = TAccessPathSome(ap)
else argAp = TAccessPathNone() else argAp = TAccessPathNone()
or or
// flow out of a callable // flow out of a callable
exists(DataFlowCall call | exists(DataFlowCall call |
flowFwdOut(call, node, fromArg, argAp, apf, ap, config) and exists(CallContextNoCall innercc, DataFlowCallable c |
fromArg = false flowFwdOut(call, node, innercc, c, argAp, apf, ap, config) and
if reducedViableImplInReturn(c, call) then cc = TReturn(c, call) else cc = TAnyCallContext()
)
or or
exists(AccessPath argAp0 | exists(AccessPath argAp0 |
flowFwdOutFromArg(call, node, argAp0, apf, ap, config) and flowFwdOutFromArg(call, node, argAp0, apf, ap, config) and
flowFwdIsEntered(call, fromArg, argAp, argAp0, config) flowFwdIsEntered(call, cc, argAp, argAp0, config)
) )
) )
} }
pragma[nomagic]
private predicate flowFwdLocalEntry(
Node node, CallContext cc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap,
LocalCallContext localCC, Configuration config
) {
flowFwd(node, cc, argAp, apf, ap, config) and
localFlowEntry(node, config) and
localCC = getLocalCallContext(cc, node.getEnclosingCallable())
}
pragma[nomagic] pragma[nomagic]
private predicate flowFwdStore( private predicate flowFwdStore(
Node node, TypedContent tc, AccessPath ap0, AccessPathFront apf, boolean fromArg, Node node, TypedContent tc, AccessPath ap0, AccessPathFront apf, CallContext cc,
AccessPathOption argAp, Configuration config AccessPathOption argAp, Configuration config
) { ) {
exists(Node mid, AccessPathFront apf0 | exists(Node mid, AccessPathFront apf0 |
flowFwd(mid, fromArg, argAp, apf0, ap0, config) and flowFwd(mid, cc, argAp, apf0, ap0, config) and
flowFwdStore0(mid, tc, node, apf0, apf, config) flowFwdStore0(mid, tc, node, apf0, apf, config)
) )
} }
@@ -1764,20 +1775,20 @@ private predicate flowFwdStore0(
pragma[nomagic] pragma[nomagic]
private predicate flowFwdRead0( private predicate flowFwdRead0(
Node node1, TypedContent tc, AccessPathFrontHead apf0, AccessPath ap0, Node node2, Node node1, TypedContent tc, AccessPathFrontHead apf0, AccessPath ap0, Node node2, CallContext cc,
boolean fromArg, AccessPathOption argAp, Configuration config AccessPathOption argAp, Configuration config
) { ) {
flowFwd(node1, fromArg, argAp, apf0, ap0, config) and flowFwd(node1, cc, argAp, apf0, ap0, config) and
readCandFwd(node1, tc, apf0, node2, config) readCandFwd(node1, tc, apf0, node2, config)
} }
pragma[nomagic] pragma[nomagic]
private predicate flowFwdRead( private predicate flowFwdRead(
Node node, AccessPathFrontHead apf0, AccessPath ap0, AccessPathFront apf, boolean fromArg, Node node, AccessPathFrontHead apf0, AccessPath ap0, AccessPathFront apf, CallContext cc,
AccessPathOption argAp, Configuration config AccessPathOption argAp, Configuration config
) { ) {
exists(Node mid, TypedContent tc | exists(Node mid, TypedContent tc |
flowFwdRead0(mid, tc, apf0, ap0, node, fromArg, argAp, config) and flowFwdRead0(mid, tc, apf0, ap0, node, cc, argAp, config) and
flowCand(node, _, _, apf, unbind(config)) and flowCand(node, _, _, apf, unbind(config)) and
flowCandConsCand(tc, apf, unbind(config)) flowCandConsCand(tc, apf, unbind(config))
) )
@@ -1795,13 +1806,16 @@ private predicate flowFwdConsCand(
pragma[nomagic] pragma[nomagic]
private predicate flowFwdIn( private predicate flowFwdIn(
DataFlowCall call, ParameterNode p, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, DataFlowCall call, ParameterNode p, CallContext innercc, CallContext outercc,
AccessPath ap, Configuration config AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config
) { ) {
exists(ArgumentNode arg, boolean allowsFieldFlow | exists(ArgumentNode arg, boolean allowsFieldFlow, DataFlowCallable c |
flowFwd(arg, fromArg, argAp, apf, ap, config) and flowFwd(arg, outercc, argAp, apf, ap, config) and
flowIntoCallNodeCand2(call, arg, p, allowsFieldFlow, config) and flowIntoCallNodeCand2(call, arg, p, allowsFieldFlow, config) and
flowCand(p, _, _, _, unbind(config)) 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 ap instanceof AccessPathNil or allowsFieldFlow = true
) )
@@ -1809,13 +1823,19 @@ private predicate flowFwdIn(
pragma[nomagic] pragma[nomagic]
private predicate flowFwdOut( private predicate flowFwdOut(
DataFlowCall call, Node node, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, DataFlowCall call, Node node, CallContext innercc, DataFlowCallable innerc,
AccessPath ap, Configuration config AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config
) { ) {
exists(ReturnNodeExt ret, boolean allowsFieldFlow | exists(ReturnNodeExt ret, boolean allowsFieldFlow |
flowFwd(ret, fromArg, argAp, apf, ap, config) and flowFwd(ret, innercc, argAp, apf, ap, config) and
flowOutOfCallNodeCand2(call, ret, node, allowsFieldFlow, config) and flowOutOfCallNodeCand2(call, ret, node, allowsFieldFlow, config) and
flowCand(node, _, _, _, unbind(config)) innerc = ret.getEnclosingCallable() and
flowCand(node, _, _, _, unbind(config)) and
(
resolveReturn(innercc, innerc, call)
or
innercc.(CallContextCall).matchesCall(call)
)
| |
ap instanceof AccessPathNil or allowsFieldFlow = true ap instanceof AccessPathNil or allowsFieldFlow = true
) )
@@ -1826,7 +1846,7 @@ private predicate flowFwdOutFromArg(
DataFlowCall call, Node node, AccessPath argAp, AccessPathFront apf, AccessPath ap, DataFlowCall call, Node node, AccessPath argAp, AccessPathFront apf, AccessPath ap,
Configuration config Configuration config
) { ) {
flowFwdOut(call, node, true, TAccessPathSome(argAp), apf, ap, config) flowFwdOut(call, node, any(CallContextCall ccc), _, TAccessPathSome(argAp), apf, ap, config)
} }
/** /**
@@ -1834,10 +1854,10 @@ private predicate flowFwdOutFromArg(
*/ */
pragma[nomagic] pragma[nomagic]
private predicate flowFwdIsEntered( private predicate flowFwdIsEntered(
DataFlowCall call, boolean fromArg, AccessPathOption argAp, AccessPath ap, Configuration config DataFlowCall call, CallContext cc, AccessPathOption argAp, AccessPath ap, Configuration config
) { ) {
exists(ParameterNode p, AccessPathFront apf | exists(ParameterNode p, AccessPathFront apf |
flowFwdIn(call, p, fromArg, argAp, apf, ap, config) and flowFwdIn(call, p, _, cc, argAp, apf, ap, config) and
flowCand(p, true, TAccessPathFrontSome(_), apf, config) flowCand(p, true, TAccessPathFrontSome(_), apf, config)
) )
} }
@@ -1920,7 +1940,7 @@ private predicate flow0(
// flow out of a callable // flow out of a callable
flowOut(_, node, _, _, ap, config) and flowOut(_, node, _, _, ap, config) and
toReturn = true and toReturn = true and
if flowFwd(node, true, TAccessPathSome(_), _, ap, config) if flowFwd(node, any(CallContextCall ccc), TAccessPathSome(_), _, ap, config)
then returnAp = TAccessPathSome(ap) then returnAp = TAccessPathSome(ap)
else returnAp = TAccessPathNone() else returnAp = TAccessPathNone()
} }
@@ -2006,9 +2026,10 @@ private predicate flowIsReturned(
DataFlowCall call, boolean toReturn, AccessPathOption returnAp, AccessPath ap, DataFlowCall call, boolean toReturn, AccessPathOption returnAp, AccessPath ap,
Configuration config Configuration config
) { ) {
exists(ReturnNodeExt ret | exists(ReturnNodeExt ret, CallContextCall ccc |
flowOut(call, ret, toReturn, returnAp, ap, config) and flowOut(call, ret, toReturn, returnAp, ap, config) and
flowFwd(ret, true, TAccessPathSome(_), _, ap, config) flowFwd(ret, ccc, TAccessPathSome(_), _, ap, config) and
ccc.matchesCall(call)
) )
} }
@@ -2031,7 +2052,7 @@ private newtype TSummaryCtx =
exists(ReturnNodeExt ret, Configuration config, AccessPath ap0 | exists(ReturnNodeExt ret, Configuration config, AccessPath ap0 |
parameterFlow(p, ap, ret.getEnclosingCallable(), config) and parameterFlow(p, ap, ret.getEnclosingCallable(), config) and
flow(ret, true, TAccessPathSome(_), ap0, config) and flow(ret, true, TAccessPathSome(_), ap0, config) and
flowFwd(ret, true, TAccessPathSome(ap), _, ap0, config) flowFwd(ret, any(CallContextCall ccc), TAccessPathSome(ap), _, ap0, config)
) )
} }
@@ -2352,7 +2373,7 @@ private predicate pathOutOfCallable0(
) { ) {
pos = getReturnPosition(mid.getNode()) and pos = getReturnPosition(mid.getNode()) and
innercc = mid.getCallContext() and innercc = mid.getCallContext() and
not innercc instanceof CallContextCall and innercc instanceof CallContextNoCall and
ap = mid.getAp() and ap = mid.getAp() and
config = mid.getConfiguration() config = mid.getConfiguration()
} }
@@ -2867,7 +2888,7 @@ private module FlowExploration {
) { ) {
pos = getReturnPosition(mid.getNode()) and pos = getReturnPosition(mid.getNode()) and
innercc = mid.getCallContext() and innercc = mid.getCallContext() and
not innercc instanceof CallContextCall and innercc instanceof CallContextNoCall and
ap = mid.getAp() and ap = mid.getAp() and
config = mid.getConfiguration() config = mid.getConfiguration()
} }

View File

@@ -1066,7 +1066,7 @@ private module LocalFlowBigStep {
* Holds if `node` can be the first node in a maximal subsequence of local * Holds if `node` can be the first node in a maximal subsequence of local
* flow steps in a dataflow path. * flow steps in a dataflow path.
*/ */
private predicate localFlowEntry(Node node, Configuration config) { predicate localFlowEntry(Node node, Configuration config) {
nodeCand2(node, config) and nodeCand2(node, config) and
( (
config.isSource(node) or config.isSource(node) or
@@ -1650,53 +1650,53 @@ private class AccessPathOption extends TAccessPathOption {
* Holds if `node` is reachable with access path `ap` from a source in * Holds if `node` is reachable with access path `ap` from a source in
* the configuration `config`. * the configuration `config`.
* *
* The Boolean `fromArg` records whether the node is reached through an * 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 in a call, and if so, `argAp` records the access path of that
* argument. * argument.
*/ */
private predicate flowFwd( private predicate flowFwd(
Node node, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Node node, CallContext cc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap,
Configuration config Configuration config
) { ) {
flowFwd0(node, fromArg, argAp, apf, ap, config) and flowFwd0(node, cc, argAp, apf, ap, config) and
flowCand(node, _, _, apf, config) flowCand(node, _, _, apf, config)
} }
private predicate flowFwd0( private predicate flowFwd0(
Node node, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Node node, CallContext cc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap,
Configuration config Configuration config
) { ) {
flowCand(node, _, _, _, config) and flowCand(node, _, _, _, config) and
config.isSource(node) and config.isSource(node) and
fromArg = false and cc instanceof CallContextAny and
argAp = TAccessPathNone() and argAp = TAccessPathNone() and
ap = TNil(getNodeType(node)) and ap = TNil(getNodeType(node)) and
apf = ap.(AccessPathNil).getFront() apf = ap.(AccessPathNil).getFront()
or or
flowCand(node, _, _, _, unbind(config)) and flowCand(node, _, _, _, unbind(config)) and
( (
exists(Node mid | exists(Node mid, LocalCallContext localCC |
flowFwd(mid, fromArg, argAp, apf, ap, config) and flowFwdLocalEntry(mid, cc, argAp, apf, ap, localCC, config) and
localFlowBigStep(mid, node, true, _, config, _) localFlowBigStep(mid, node, true, _, config, localCC)
) )
or or
exists(Node mid, AccessPathNil nil | exists(Node mid, AccessPathNil nil, LocalCallContext localCC |
flowFwd(mid, fromArg, argAp, _, nil, config) and flowFwdLocalEntry(mid, cc, argAp, _, nil, localCC, config) and
localFlowBigStep(mid, node, false, apf, config, _) and localFlowBigStep(mid, node, false, apf, config, localCC) and
apf = ap.(AccessPathNil).getFront() apf = ap.(AccessPathNil).getFront()
) )
or or
exists(Node mid | exists(Node mid |
flowFwd(mid, _, _, apf, ap, config) and flowFwd(mid, _, _, apf, ap, config) and
jumpStep(mid, node, config) and jumpStep(mid, node, config) and
fromArg = false and cc instanceof CallContextAny and
argAp = TAccessPathNone() argAp = TAccessPathNone()
) )
or or
exists(Node mid, AccessPathNil nil | exists(Node mid, AccessPathNil nil |
flowFwd(mid, _, _, _, nil, config) and flowFwd(mid, _, _, _, nil, config) and
additionalJumpStep(mid, node, config) and additionalJumpStep(mid, node, config) and
fromArg = false and cc instanceof CallContextAny and
argAp = TAccessPathNone() and argAp = TAccessPathNone() and
ap = TNil(getNodeType(node)) and ap = TNil(getNodeType(node)) and
apf = ap.(AccessPathNil).getFront() apf = ap.(AccessPathNil).getFront()
@@ -1704,40 +1704,51 @@ private predicate flowFwd0(
) )
or or
// store // store
exists(TypedContent tc | flowFwdStore(node, tc, pop(tc, ap), apf, fromArg, argAp, config)) exists(TypedContent tc | flowFwdStore(node, tc, pop(tc, ap), apf, cc, argAp, config))
or or
// read // read
exists(TypedContent tc | exists(TypedContent tc |
flowFwdRead(node, _, push(tc, ap), apf, fromArg, argAp, config) and flowFwdRead(node, _, push(tc, ap), apf, cc, argAp, config) and
flowFwdConsCand(tc, apf, ap, config) flowFwdConsCand(tc, apf, ap, config)
) )
or or
// flow into a callable // flow into a callable
flowFwdIn(_, node, _, _, apf, ap, config) and flowFwdIn(_, node, cc, _, _, apf, ap, config) and
fromArg = true and
if flowCand(node, true, _, apf, config) if flowCand(node, true, _, apf, config)
then argAp = TAccessPathSome(ap) then argAp = TAccessPathSome(ap)
else argAp = TAccessPathNone() else argAp = TAccessPathNone()
or or
// flow out of a callable // flow out of a callable
exists(DataFlowCall call | exists(DataFlowCall call |
flowFwdOut(call, node, fromArg, argAp, apf, ap, config) and exists(CallContextNoCall innercc, DataFlowCallable c |
fromArg = false flowFwdOut(call, node, innercc, c, argAp, apf, ap, config) and
if reducedViableImplInReturn(c, call) then cc = TReturn(c, call) else cc = TAnyCallContext()
)
or or
exists(AccessPath argAp0 | exists(AccessPath argAp0 |
flowFwdOutFromArg(call, node, argAp0, apf, ap, config) and flowFwdOutFromArg(call, node, argAp0, apf, ap, config) and
flowFwdIsEntered(call, fromArg, argAp, argAp0, config) flowFwdIsEntered(call, cc, argAp, argAp0, config)
) )
) )
} }
pragma[nomagic]
private predicate flowFwdLocalEntry(
Node node, CallContext cc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap,
LocalCallContext localCC, Configuration config
) {
flowFwd(node, cc, argAp, apf, ap, config) and
localFlowEntry(node, config) and
localCC = getLocalCallContext(cc, node.getEnclosingCallable())
}
pragma[nomagic] pragma[nomagic]
private predicate flowFwdStore( private predicate flowFwdStore(
Node node, TypedContent tc, AccessPath ap0, AccessPathFront apf, boolean fromArg, Node node, TypedContent tc, AccessPath ap0, AccessPathFront apf, CallContext cc,
AccessPathOption argAp, Configuration config AccessPathOption argAp, Configuration config
) { ) {
exists(Node mid, AccessPathFront apf0 | exists(Node mid, AccessPathFront apf0 |
flowFwd(mid, fromArg, argAp, apf0, ap0, config) and flowFwd(mid, cc, argAp, apf0, ap0, config) and
flowFwdStore0(mid, tc, node, apf0, apf, config) flowFwdStore0(mid, tc, node, apf0, apf, config)
) )
} }
@@ -1764,20 +1775,20 @@ private predicate flowFwdStore0(
pragma[nomagic] pragma[nomagic]
private predicate flowFwdRead0( private predicate flowFwdRead0(
Node node1, TypedContent tc, AccessPathFrontHead apf0, AccessPath ap0, Node node2, Node node1, TypedContent tc, AccessPathFrontHead apf0, AccessPath ap0, Node node2, CallContext cc,
boolean fromArg, AccessPathOption argAp, Configuration config AccessPathOption argAp, Configuration config
) { ) {
flowFwd(node1, fromArg, argAp, apf0, ap0, config) and flowFwd(node1, cc, argAp, apf0, ap0, config) and
readCandFwd(node1, tc, apf0, node2, config) readCandFwd(node1, tc, apf0, node2, config)
} }
pragma[nomagic] pragma[nomagic]
private predicate flowFwdRead( private predicate flowFwdRead(
Node node, AccessPathFrontHead apf0, AccessPath ap0, AccessPathFront apf, boolean fromArg, Node node, AccessPathFrontHead apf0, AccessPath ap0, AccessPathFront apf, CallContext cc,
AccessPathOption argAp, Configuration config AccessPathOption argAp, Configuration config
) { ) {
exists(Node mid, TypedContent tc | exists(Node mid, TypedContent tc |
flowFwdRead0(mid, tc, apf0, ap0, node, fromArg, argAp, config) and flowFwdRead0(mid, tc, apf0, ap0, node, cc, argAp, config) and
flowCand(node, _, _, apf, unbind(config)) and flowCand(node, _, _, apf, unbind(config)) and
flowCandConsCand(tc, apf, unbind(config)) flowCandConsCand(tc, apf, unbind(config))
) )
@@ -1795,13 +1806,16 @@ private predicate flowFwdConsCand(
pragma[nomagic] pragma[nomagic]
private predicate flowFwdIn( private predicate flowFwdIn(
DataFlowCall call, ParameterNode p, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, DataFlowCall call, ParameterNode p, CallContext innercc, CallContext outercc,
AccessPath ap, Configuration config AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config
) { ) {
exists(ArgumentNode arg, boolean allowsFieldFlow | exists(ArgumentNode arg, boolean allowsFieldFlow, DataFlowCallable c |
flowFwd(arg, fromArg, argAp, apf, ap, config) and flowFwd(arg, outercc, argAp, apf, ap, config) and
flowIntoCallNodeCand2(call, arg, p, allowsFieldFlow, config) and flowIntoCallNodeCand2(call, arg, p, allowsFieldFlow, config) and
flowCand(p, _, _, _, unbind(config)) 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 ap instanceof AccessPathNil or allowsFieldFlow = true
) )
@@ -1809,13 +1823,19 @@ private predicate flowFwdIn(
pragma[nomagic] pragma[nomagic]
private predicate flowFwdOut( private predicate flowFwdOut(
DataFlowCall call, Node node, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, DataFlowCall call, Node node, CallContext innercc, DataFlowCallable innerc,
AccessPath ap, Configuration config AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config
) { ) {
exists(ReturnNodeExt ret, boolean allowsFieldFlow | exists(ReturnNodeExt ret, boolean allowsFieldFlow |
flowFwd(ret, fromArg, argAp, apf, ap, config) and flowFwd(ret, innercc, argAp, apf, ap, config) and
flowOutOfCallNodeCand2(call, ret, node, allowsFieldFlow, config) and flowOutOfCallNodeCand2(call, ret, node, allowsFieldFlow, config) and
flowCand(node, _, _, _, unbind(config)) innerc = ret.getEnclosingCallable() and
flowCand(node, _, _, _, unbind(config)) and
(
resolveReturn(innercc, innerc, call)
or
innercc.(CallContextCall).matchesCall(call)
)
| |
ap instanceof AccessPathNil or allowsFieldFlow = true ap instanceof AccessPathNil or allowsFieldFlow = true
) )
@@ -1826,7 +1846,7 @@ private predicate flowFwdOutFromArg(
DataFlowCall call, Node node, AccessPath argAp, AccessPathFront apf, AccessPath ap, DataFlowCall call, Node node, AccessPath argAp, AccessPathFront apf, AccessPath ap,
Configuration config Configuration config
) { ) {
flowFwdOut(call, node, true, TAccessPathSome(argAp), apf, ap, config) flowFwdOut(call, node, any(CallContextCall ccc), _, TAccessPathSome(argAp), apf, ap, config)
} }
/** /**
@@ -1834,10 +1854,10 @@ private predicate flowFwdOutFromArg(
*/ */
pragma[nomagic] pragma[nomagic]
private predicate flowFwdIsEntered( private predicate flowFwdIsEntered(
DataFlowCall call, boolean fromArg, AccessPathOption argAp, AccessPath ap, Configuration config DataFlowCall call, CallContext cc, AccessPathOption argAp, AccessPath ap, Configuration config
) { ) {
exists(ParameterNode p, AccessPathFront apf | exists(ParameterNode p, AccessPathFront apf |
flowFwdIn(call, p, fromArg, argAp, apf, ap, config) and flowFwdIn(call, p, _, cc, argAp, apf, ap, config) and
flowCand(p, true, TAccessPathFrontSome(_), apf, config) flowCand(p, true, TAccessPathFrontSome(_), apf, config)
) )
} }
@@ -1920,7 +1940,7 @@ private predicate flow0(
// flow out of a callable // flow out of a callable
flowOut(_, node, _, _, ap, config) and flowOut(_, node, _, _, ap, config) and
toReturn = true and toReturn = true and
if flowFwd(node, true, TAccessPathSome(_), _, ap, config) if flowFwd(node, any(CallContextCall ccc), TAccessPathSome(_), _, ap, config)
then returnAp = TAccessPathSome(ap) then returnAp = TAccessPathSome(ap)
else returnAp = TAccessPathNone() else returnAp = TAccessPathNone()
} }
@@ -2006,9 +2026,10 @@ private predicate flowIsReturned(
DataFlowCall call, boolean toReturn, AccessPathOption returnAp, AccessPath ap, DataFlowCall call, boolean toReturn, AccessPathOption returnAp, AccessPath ap,
Configuration config Configuration config
) { ) {
exists(ReturnNodeExt ret | exists(ReturnNodeExt ret, CallContextCall ccc |
flowOut(call, ret, toReturn, returnAp, ap, config) and flowOut(call, ret, toReturn, returnAp, ap, config) and
flowFwd(ret, true, TAccessPathSome(_), _, ap, config) flowFwd(ret, ccc, TAccessPathSome(_), _, ap, config) and
ccc.matchesCall(call)
) )
} }
@@ -2031,7 +2052,7 @@ private newtype TSummaryCtx =
exists(ReturnNodeExt ret, Configuration config, AccessPath ap0 | exists(ReturnNodeExt ret, Configuration config, AccessPath ap0 |
parameterFlow(p, ap, ret.getEnclosingCallable(), config) and parameterFlow(p, ap, ret.getEnclosingCallable(), config) and
flow(ret, true, TAccessPathSome(_), ap0, config) and flow(ret, true, TAccessPathSome(_), ap0, config) and
flowFwd(ret, true, TAccessPathSome(ap), _, ap0, config) flowFwd(ret, any(CallContextCall ccc), TAccessPathSome(ap), _, ap0, config)
) )
} }
@@ -2352,7 +2373,7 @@ private predicate pathOutOfCallable0(
) { ) {
pos = getReturnPosition(mid.getNode()) and pos = getReturnPosition(mid.getNode()) and
innercc = mid.getCallContext() and innercc = mid.getCallContext() and
not innercc instanceof CallContextCall and innercc instanceof CallContextNoCall and
ap = mid.getAp() and ap = mid.getAp() and
config = mid.getConfiguration() config = mid.getConfiguration()
} }
@@ -2867,7 +2888,7 @@ private module FlowExploration {
) { ) {
pos = getReturnPosition(mid.getNode()) and pos = getReturnPosition(mid.getNode()) and
innercc = mid.getCallContext() and innercc = mid.getCallContext() and
not innercc instanceof CallContextCall and innercc instanceof CallContextNoCall and
ap = mid.getAp() and ap = mid.getAp() and
config = mid.getConfiguration() config = mid.getConfiguration()
} }

View File

@@ -1066,7 +1066,7 @@ private module LocalFlowBigStep {
* Holds if `node` can be the first node in a maximal subsequence of local * Holds if `node` can be the first node in a maximal subsequence of local
* flow steps in a dataflow path. * flow steps in a dataflow path.
*/ */
private predicate localFlowEntry(Node node, Configuration config) { predicate localFlowEntry(Node node, Configuration config) {
nodeCand2(node, config) and nodeCand2(node, config) and
( (
config.isSource(node) or config.isSource(node) or
@@ -1650,53 +1650,53 @@ private class AccessPathOption extends TAccessPathOption {
* Holds if `node` is reachable with access path `ap` from a source in * Holds if `node` is reachable with access path `ap` from a source in
* the configuration `config`. * the configuration `config`.
* *
* The Boolean `fromArg` records whether the node is reached through an * 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 in a call, and if so, `argAp` records the access path of that
* argument. * argument.
*/ */
private predicate flowFwd( private predicate flowFwd(
Node node, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Node node, CallContext cc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap,
Configuration config Configuration config
) { ) {
flowFwd0(node, fromArg, argAp, apf, ap, config) and flowFwd0(node, cc, argAp, apf, ap, config) and
flowCand(node, _, _, apf, config) flowCand(node, _, _, apf, config)
} }
private predicate flowFwd0( private predicate flowFwd0(
Node node, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Node node, CallContext cc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap,
Configuration config Configuration config
) { ) {
flowCand(node, _, _, _, config) and flowCand(node, _, _, _, config) and
config.isSource(node) and config.isSource(node) and
fromArg = false and cc instanceof CallContextAny and
argAp = TAccessPathNone() and argAp = TAccessPathNone() and
ap = TNil(getNodeType(node)) and ap = TNil(getNodeType(node)) and
apf = ap.(AccessPathNil).getFront() apf = ap.(AccessPathNil).getFront()
or or
flowCand(node, _, _, _, unbind(config)) and flowCand(node, _, _, _, unbind(config)) and
( (
exists(Node mid | exists(Node mid, LocalCallContext localCC |
flowFwd(mid, fromArg, argAp, apf, ap, config) and flowFwdLocalEntry(mid, cc, argAp, apf, ap, localCC, config) and
localFlowBigStep(mid, node, true, _, config, _) localFlowBigStep(mid, node, true, _, config, localCC)
) )
or or
exists(Node mid, AccessPathNil nil | exists(Node mid, AccessPathNil nil, LocalCallContext localCC |
flowFwd(mid, fromArg, argAp, _, nil, config) and flowFwdLocalEntry(mid, cc, argAp, _, nil, localCC, config) and
localFlowBigStep(mid, node, false, apf, config, _) and localFlowBigStep(mid, node, false, apf, config, localCC) and
apf = ap.(AccessPathNil).getFront() apf = ap.(AccessPathNil).getFront()
) )
or or
exists(Node mid | exists(Node mid |
flowFwd(mid, _, _, apf, ap, config) and flowFwd(mid, _, _, apf, ap, config) and
jumpStep(mid, node, config) and jumpStep(mid, node, config) and
fromArg = false and cc instanceof CallContextAny and
argAp = TAccessPathNone() argAp = TAccessPathNone()
) )
or or
exists(Node mid, AccessPathNil nil | exists(Node mid, AccessPathNil nil |
flowFwd(mid, _, _, _, nil, config) and flowFwd(mid, _, _, _, nil, config) and
additionalJumpStep(mid, node, config) and additionalJumpStep(mid, node, config) and
fromArg = false and cc instanceof CallContextAny and
argAp = TAccessPathNone() and argAp = TAccessPathNone() and
ap = TNil(getNodeType(node)) and ap = TNil(getNodeType(node)) and
apf = ap.(AccessPathNil).getFront() apf = ap.(AccessPathNil).getFront()
@@ -1704,40 +1704,51 @@ private predicate flowFwd0(
) )
or or
// store // store
exists(TypedContent tc | flowFwdStore(node, tc, pop(tc, ap), apf, fromArg, argAp, config)) exists(TypedContent tc | flowFwdStore(node, tc, pop(tc, ap), apf, cc, argAp, config))
or or
// read // read
exists(TypedContent tc | exists(TypedContent tc |
flowFwdRead(node, _, push(tc, ap), apf, fromArg, argAp, config) and flowFwdRead(node, _, push(tc, ap), apf, cc, argAp, config) and
flowFwdConsCand(tc, apf, ap, config) flowFwdConsCand(tc, apf, ap, config)
) )
or or
// flow into a callable // flow into a callable
flowFwdIn(_, node, _, _, apf, ap, config) and flowFwdIn(_, node, cc, _, _, apf, ap, config) and
fromArg = true and
if flowCand(node, true, _, apf, config) if flowCand(node, true, _, apf, config)
then argAp = TAccessPathSome(ap) then argAp = TAccessPathSome(ap)
else argAp = TAccessPathNone() else argAp = TAccessPathNone()
or or
// flow out of a callable // flow out of a callable
exists(DataFlowCall call | exists(DataFlowCall call |
flowFwdOut(call, node, fromArg, argAp, apf, ap, config) and exists(CallContextNoCall innercc, DataFlowCallable c |
fromArg = false flowFwdOut(call, node, innercc, c, argAp, apf, ap, config) and
if reducedViableImplInReturn(c, call) then cc = TReturn(c, call) else cc = TAnyCallContext()
)
or or
exists(AccessPath argAp0 | exists(AccessPath argAp0 |
flowFwdOutFromArg(call, node, argAp0, apf, ap, config) and flowFwdOutFromArg(call, node, argAp0, apf, ap, config) and
flowFwdIsEntered(call, fromArg, argAp, argAp0, config) flowFwdIsEntered(call, cc, argAp, argAp0, config)
) )
) )
} }
pragma[nomagic]
private predicate flowFwdLocalEntry(
Node node, CallContext cc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap,
LocalCallContext localCC, Configuration config
) {
flowFwd(node, cc, argAp, apf, ap, config) and
localFlowEntry(node, config) and
localCC = getLocalCallContext(cc, node.getEnclosingCallable())
}
pragma[nomagic] pragma[nomagic]
private predicate flowFwdStore( private predicate flowFwdStore(
Node node, TypedContent tc, AccessPath ap0, AccessPathFront apf, boolean fromArg, Node node, TypedContent tc, AccessPath ap0, AccessPathFront apf, CallContext cc,
AccessPathOption argAp, Configuration config AccessPathOption argAp, Configuration config
) { ) {
exists(Node mid, AccessPathFront apf0 | exists(Node mid, AccessPathFront apf0 |
flowFwd(mid, fromArg, argAp, apf0, ap0, config) and flowFwd(mid, cc, argAp, apf0, ap0, config) and
flowFwdStore0(mid, tc, node, apf0, apf, config) flowFwdStore0(mid, tc, node, apf0, apf, config)
) )
} }
@@ -1764,20 +1775,20 @@ private predicate flowFwdStore0(
pragma[nomagic] pragma[nomagic]
private predicate flowFwdRead0( private predicate flowFwdRead0(
Node node1, TypedContent tc, AccessPathFrontHead apf0, AccessPath ap0, Node node2, Node node1, TypedContent tc, AccessPathFrontHead apf0, AccessPath ap0, Node node2, CallContext cc,
boolean fromArg, AccessPathOption argAp, Configuration config AccessPathOption argAp, Configuration config
) { ) {
flowFwd(node1, fromArg, argAp, apf0, ap0, config) and flowFwd(node1, cc, argAp, apf0, ap0, config) and
readCandFwd(node1, tc, apf0, node2, config) readCandFwd(node1, tc, apf0, node2, config)
} }
pragma[nomagic] pragma[nomagic]
private predicate flowFwdRead( private predicate flowFwdRead(
Node node, AccessPathFrontHead apf0, AccessPath ap0, AccessPathFront apf, boolean fromArg, Node node, AccessPathFrontHead apf0, AccessPath ap0, AccessPathFront apf, CallContext cc,
AccessPathOption argAp, Configuration config AccessPathOption argAp, Configuration config
) { ) {
exists(Node mid, TypedContent tc | exists(Node mid, TypedContent tc |
flowFwdRead0(mid, tc, apf0, ap0, node, fromArg, argAp, config) and flowFwdRead0(mid, tc, apf0, ap0, node, cc, argAp, config) and
flowCand(node, _, _, apf, unbind(config)) and flowCand(node, _, _, apf, unbind(config)) and
flowCandConsCand(tc, apf, unbind(config)) flowCandConsCand(tc, apf, unbind(config))
) )
@@ -1795,13 +1806,16 @@ private predicate flowFwdConsCand(
pragma[nomagic] pragma[nomagic]
private predicate flowFwdIn( private predicate flowFwdIn(
DataFlowCall call, ParameterNode p, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, DataFlowCall call, ParameterNode p, CallContext innercc, CallContext outercc,
AccessPath ap, Configuration config AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config
) { ) {
exists(ArgumentNode arg, boolean allowsFieldFlow | exists(ArgumentNode arg, boolean allowsFieldFlow, DataFlowCallable c |
flowFwd(arg, fromArg, argAp, apf, ap, config) and flowFwd(arg, outercc, argAp, apf, ap, config) and
flowIntoCallNodeCand2(call, arg, p, allowsFieldFlow, config) and flowIntoCallNodeCand2(call, arg, p, allowsFieldFlow, config) and
flowCand(p, _, _, _, unbind(config)) 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 ap instanceof AccessPathNil or allowsFieldFlow = true
) )
@@ -1809,13 +1823,19 @@ private predicate flowFwdIn(
pragma[nomagic] pragma[nomagic]
private predicate flowFwdOut( private predicate flowFwdOut(
DataFlowCall call, Node node, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, DataFlowCall call, Node node, CallContext innercc, DataFlowCallable innerc,
AccessPath ap, Configuration config AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config
) { ) {
exists(ReturnNodeExt ret, boolean allowsFieldFlow | exists(ReturnNodeExt ret, boolean allowsFieldFlow |
flowFwd(ret, fromArg, argAp, apf, ap, config) and flowFwd(ret, innercc, argAp, apf, ap, config) and
flowOutOfCallNodeCand2(call, ret, node, allowsFieldFlow, config) and flowOutOfCallNodeCand2(call, ret, node, allowsFieldFlow, config) and
flowCand(node, _, _, _, unbind(config)) innerc = ret.getEnclosingCallable() and
flowCand(node, _, _, _, unbind(config)) and
(
resolveReturn(innercc, innerc, call)
or
innercc.(CallContextCall).matchesCall(call)
)
| |
ap instanceof AccessPathNil or allowsFieldFlow = true ap instanceof AccessPathNil or allowsFieldFlow = true
) )
@@ -1826,7 +1846,7 @@ private predicate flowFwdOutFromArg(
DataFlowCall call, Node node, AccessPath argAp, AccessPathFront apf, AccessPath ap, DataFlowCall call, Node node, AccessPath argAp, AccessPathFront apf, AccessPath ap,
Configuration config Configuration config
) { ) {
flowFwdOut(call, node, true, TAccessPathSome(argAp), apf, ap, config) flowFwdOut(call, node, any(CallContextCall ccc), _, TAccessPathSome(argAp), apf, ap, config)
} }
/** /**
@@ -1834,10 +1854,10 @@ private predicate flowFwdOutFromArg(
*/ */
pragma[nomagic] pragma[nomagic]
private predicate flowFwdIsEntered( private predicate flowFwdIsEntered(
DataFlowCall call, boolean fromArg, AccessPathOption argAp, AccessPath ap, Configuration config DataFlowCall call, CallContext cc, AccessPathOption argAp, AccessPath ap, Configuration config
) { ) {
exists(ParameterNode p, AccessPathFront apf | exists(ParameterNode p, AccessPathFront apf |
flowFwdIn(call, p, fromArg, argAp, apf, ap, config) and flowFwdIn(call, p, _, cc, argAp, apf, ap, config) and
flowCand(p, true, TAccessPathFrontSome(_), apf, config) flowCand(p, true, TAccessPathFrontSome(_), apf, config)
) )
} }
@@ -1920,7 +1940,7 @@ private predicate flow0(
// flow out of a callable // flow out of a callable
flowOut(_, node, _, _, ap, config) and flowOut(_, node, _, _, ap, config) and
toReturn = true and toReturn = true and
if flowFwd(node, true, TAccessPathSome(_), _, ap, config) if flowFwd(node, any(CallContextCall ccc), TAccessPathSome(_), _, ap, config)
then returnAp = TAccessPathSome(ap) then returnAp = TAccessPathSome(ap)
else returnAp = TAccessPathNone() else returnAp = TAccessPathNone()
} }
@@ -2006,9 +2026,10 @@ private predicate flowIsReturned(
DataFlowCall call, boolean toReturn, AccessPathOption returnAp, AccessPath ap, DataFlowCall call, boolean toReturn, AccessPathOption returnAp, AccessPath ap,
Configuration config Configuration config
) { ) {
exists(ReturnNodeExt ret | exists(ReturnNodeExt ret, CallContextCall ccc |
flowOut(call, ret, toReturn, returnAp, ap, config) and flowOut(call, ret, toReturn, returnAp, ap, config) and
flowFwd(ret, true, TAccessPathSome(_), _, ap, config) flowFwd(ret, ccc, TAccessPathSome(_), _, ap, config) and
ccc.matchesCall(call)
) )
} }
@@ -2031,7 +2052,7 @@ private newtype TSummaryCtx =
exists(ReturnNodeExt ret, Configuration config, AccessPath ap0 | exists(ReturnNodeExt ret, Configuration config, AccessPath ap0 |
parameterFlow(p, ap, ret.getEnclosingCallable(), config) and parameterFlow(p, ap, ret.getEnclosingCallable(), config) and
flow(ret, true, TAccessPathSome(_), ap0, config) and flow(ret, true, TAccessPathSome(_), ap0, config) and
flowFwd(ret, true, TAccessPathSome(ap), _, ap0, config) flowFwd(ret, any(CallContextCall ccc), TAccessPathSome(ap), _, ap0, config)
) )
} }
@@ -2352,7 +2373,7 @@ private predicate pathOutOfCallable0(
) { ) {
pos = getReturnPosition(mid.getNode()) and pos = getReturnPosition(mid.getNode()) and
innercc = mid.getCallContext() and innercc = mid.getCallContext() and
not innercc instanceof CallContextCall and innercc instanceof CallContextNoCall and
ap = mid.getAp() and ap = mid.getAp() and
config = mid.getConfiguration() config = mid.getConfiguration()
} }
@@ -2867,7 +2888,7 @@ private module FlowExploration {
) { ) {
pos = getReturnPosition(mid.getNode()) and pos = getReturnPosition(mid.getNode()) and
innercc = mid.getCallContext() and innercc = mid.getCallContext() and
not innercc instanceof CallContextCall and innercc instanceof CallContextNoCall and
ap = mid.getAp() and ap = mid.getAp() and
config = mid.getConfiguration() config = mid.getConfiguration()
} }

View File

@@ -1066,7 +1066,7 @@ private module LocalFlowBigStep {
* Holds if `node` can be the first node in a maximal subsequence of local * Holds if `node` can be the first node in a maximal subsequence of local
* flow steps in a dataflow path. * flow steps in a dataflow path.
*/ */
private predicate localFlowEntry(Node node, Configuration config) { predicate localFlowEntry(Node node, Configuration config) {
nodeCand2(node, config) and nodeCand2(node, config) and
( (
config.isSource(node) or config.isSource(node) or
@@ -1650,53 +1650,53 @@ private class AccessPathOption extends TAccessPathOption {
* Holds if `node` is reachable with access path `ap` from a source in * Holds if `node` is reachable with access path `ap` from a source in
* the configuration `config`. * the configuration `config`.
* *
* The Boolean `fromArg` records whether the node is reached through an * 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 in a call, and if so, `argAp` records the access path of that
* argument. * argument.
*/ */
private predicate flowFwd( private predicate flowFwd(
Node node, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Node node, CallContext cc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap,
Configuration config Configuration config
) { ) {
flowFwd0(node, fromArg, argAp, apf, ap, config) and flowFwd0(node, cc, argAp, apf, ap, config) and
flowCand(node, _, _, apf, config) flowCand(node, _, _, apf, config)
} }
private predicate flowFwd0( private predicate flowFwd0(
Node node, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Node node, CallContext cc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap,
Configuration config Configuration config
) { ) {
flowCand(node, _, _, _, config) and flowCand(node, _, _, _, config) and
config.isSource(node) and config.isSource(node) and
fromArg = false and cc instanceof CallContextAny and
argAp = TAccessPathNone() and argAp = TAccessPathNone() and
ap = TNil(getNodeType(node)) and ap = TNil(getNodeType(node)) and
apf = ap.(AccessPathNil).getFront() apf = ap.(AccessPathNil).getFront()
or or
flowCand(node, _, _, _, unbind(config)) and flowCand(node, _, _, _, unbind(config)) and
( (
exists(Node mid | exists(Node mid, LocalCallContext localCC |
flowFwd(mid, fromArg, argAp, apf, ap, config) and flowFwdLocalEntry(mid, cc, argAp, apf, ap, localCC, config) and
localFlowBigStep(mid, node, true, _, config, _) localFlowBigStep(mid, node, true, _, config, localCC)
) )
or or
exists(Node mid, AccessPathNil nil | exists(Node mid, AccessPathNil nil, LocalCallContext localCC |
flowFwd(mid, fromArg, argAp, _, nil, config) and flowFwdLocalEntry(mid, cc, argAp, _, nil, localCC, config) and
localFlowBigStep(mid, node, false, apf, config, _) and localFlowBigStep(mid, node, false, apf, config, localCC) and
apf = ap.(AccessPathNil).getFront() apf = ap.(AccessPathNil).getFront()
) )
or or
exists(Node mid | exists(Node mid |
flowFwd(mid, _, _, apf, ap, config) and flowFwd(mid, _, _, apf, ap, config) and
jumpStep(mid, node, config) and jumpStep(mid, node, config) and
fromArg = false and cc instanceof CallContextAny and
argAp = TAccessPathNone() argAp = TAccessPathNone()
) )
or or
exists(Node mid, AccessPathNil nil | exists(Node mid, AccessPathNil nil |
flowFwd(mid, _, _, _, nil, config) and flowFwd(mid, _, _, _, nil, config) and
additionalJumpStep(mid, node, config) and additionalJumpStep(mid, node, config) and
fromArg = false and cc instanceof CallContextAny and
argAp = TAccessPathNone() and argAp = TAccessPathNone() and
ap = TNil(getNodeType(node)) and ap = TNil(getNodeType(node)) and
apf = ap.(AccessPathNil).getFront() apf = ap.(AccessPathNil).getFront()
@@ -1704,40 +1704,51 @@ private predicate flowFwd0(
) )
or or
// store // store
exists(TypedContent tc | flowFwdStore(node, tc, pop(tc, ap), apf, fromArg, argAp, config)) exists(TypedContent tc | flowFwdStore(node, tc, pop(tc, ap), apf, cc, argAp, config))
or or
// read // read
exists(TypedContent tc | exists(TypedContent tc |
flowFwdRead(node, _, push(tc, ap), apf, fromArg, argAp, config) and flowFwdRead(node, _, push(tc, ap), apf, cc, argAp, config) and
flowFwdConsCand(tc, apf, ap, config) flowFwdConsCand(tc, apf, ap, config)
) )
or or
// flow into a callable // flow into a callable
flowFwdIn(_, node, _, _, apf, ap, config) and flowFwdIn(_, node, cc, _, _, apf, ap, config) and
fromArg = true and
if flowCand(node, true, _, apf, config) if flowCand(node, true, _, apf, config)
then argAp = TAccessPathSome(ap) then argAp = TAccessPathSome(ap)
else argAp = TAccessPathNone() else argAp = TAccessPathNone()
or or
// flow out of a callable // flow out of a callable
exists(DataFlowCall call | exists(DataFlowCall call |
flowFwdOut(call, node, fromArg, argAp, apf, ap, config) and exists(CallContextNoCall innercc, DataFlowCallable c |
fromArg = false flowFwdOut(call, node, innercc, c, argAp, apf, ap, config) and
if reducedViableImplInReturn(c, call) then cc = TReturn(c, call) else cc = TAnyCallContext()
)
or or
exists(AccessPath argAp0 | exists(AccessPath argAp0 |
flowFwdOutFromArg(call, node, argAp0, apf, ap, config) and flowFwdOutFromArg(call, node, argAp0, apf, ap, config) and
flowFwdIsEntered(call, fromArg, argAp, argAp0, config) flowFwdIsEntered(call, cc, argAp, argAp0, config)
) )
) )
} }
pragma[nomagic]
private predicate flowFwdLocalEntry(
Node node, CallContext cc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap,
LocalCallContext localCC, Configuration config
) {
flowFwd(node, cc, argAp, apf, ap, config) and
localFlowEntry(node, config) and
localCC = getLocalCallContext(cc, node.getEnclosingCallable())
}
pragma[nomagic] pragma[nomagic]
private predicate flowFwdStore( private predicate flowFwdStore(
Node node, TypedContent tc, AccessPath ap0, AccessPathFront apf, boolean fromArg, Node node, TypedContent tc, AccessPath ap0, AccessPathFront apf, CallContext cc,
AccessPathOption argAp, Configuration config AccessPathOption argAp, Configuration config
) { ) {
exists(Node mid, AccessPathFront apf0 | exists(Node mid, AccessPathFront apf0 |
flowFwd(mid, fromArg, argAp, apf0, ap0, config) and flowFwd(mid, cc, argAp, apf0, ap0, config) and
flowFwdStore0(mid, tc, node, apf0, apf, config) flowFwdStore0(mid, tc, node, apf0, apf, config)
) )
} }
@@ -1764,20 +1775,20 @@ private predicate flowFwdStore0(
pragma[nomagic] pragma[nomagic]
private predicate flowFwdRead0( private predicate flowFwdRead0(
Node node1, TypedContent tc, AccessPathFrontHead apf0, AccessPath ap0, Node node2, Node node1, TypedContent tc, AccessPathFrontHead apf0, AccessPath ap0, Node node2, CallContext cc,
boolean fromArg, AccessPathOption argAp, Configuration config AccessPathOption argAp, Configuration config
) { ) {
flowFwd(node1, fromArg, argAp, apf0, ap0, config) and flowFwd(node1, cc, argAp, apf0, ap0, config) and
readCandFwd(node1, tc, apf0, node2, config) readCandFwd(node1, tc, apf0, node2, config)
} }
pragma[nomagic] pragma[nomagic]
private predicate flowFwdRead( private predicate flowFwdRead(
Node node, AccessPathFrontHead apf0, AccessPath ap0, AccessPathFront apf, boolean fromArg, Node node, AccessPathFrontHead apf0, AccessPath ap0, AccessPathFront apf, CallContext cc,
AccessPathOption argAp, Configuration config AccessPathOption argAp, Configuration config
) { ) {
exists(Node mid, TypedContent tc | exists(Node mid, TypedContent tc |
flowFwdRead0(mid, tc, apf0, ap0, node, fromArg, argAp, config) and flowFwdRead0(mid, tc, apf0, ap0, node, cc, argAp, config) and
flowCand(node, _, _, apf, unbind(config)) and flowCand(node, _, _, apf, unbind(config)) and
flowCandConsCand(tc, apf, unbind(config)) flowCandConsCand(tc, apf, unbind(config))
) )
@@ -1795,13 +1806,16 @@ private predicate flowFwdConsCand(
pragma[nomagic] pragma[nomagic]
private predicate flowFwdIn( private predicate flowFwdIn(
DataFlowCall call, ParameterNode p, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, DataFlowCall call, ParameterNode p, CallContext innercc, CallContext outercc,
AccessPath ap, Configuration config AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config
) { ) {
exists(ArgumentNode arg, boolean allowsFieldFlow | exists(ArgumentNode arg, boolean allowsFieldFlow, DataFlowCallable c |
flowFwd(arg, fromArg, argAp, apf, ap, config) and flowFwd(arg, outercc, argAp, apf, ap, config) and
flowIntoCallNodeCand2(call, arg, p, allowsFieldFlow, config) and flowIntoCallNodeCand2(call, arg, p, allowsFieldFlow, config) and
flowCand(p, _, _, _, unbind(config)) 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 ap instanceof AccessPathNil or allowsFieldFlow = true
) )
@@ -1809,13 +1823,19 @@ private predicate flowFwdIn(
pragma[nomagic] pragma[nomagic]
private predicate flowFwdOut( private predicate flowFwdOut(
DataFlowCall call, Node node, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, DataFlowCall call, Node node, CallContext innercc, DataFlowCallable innerc,
AccessPath ap, Configuration config AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config
) { ) {
exists(ReturnNodeExt ret, boolean allowsFieldFlow | exists(ReturnNodeExt ret, boolean allowsFieldFlow |
flowFwd(ret, fromArg, argAp, apf, ap, config) and flowFwd(ret, innercc, argAp, apf, ap, config) and
flowOutOfCallNodeCand2(call, ret, node, allowsFieldFlow, config) and flowOutOfCallNodeCand2(call, ret, node, allowsFieldFlow, config) and
flowCand(node, _, _, _, unbind(config)) innerc = ret.getEnclosingCallable() and
flowCand(node, _, _, _, unbind(config)) and
(
resolveReturn(innercc, innerc, call)
or
innercc.(CallContextCall).matchesCall(call)
)
| |
ap instanceof AccessPathNil or allowsFieldFlow = true ap instanceof AccessPathNil or allowsFieldFlow = true
) )
@@ -1826,7 +1846,7 @@ private predicate flowFwdOutFromArg(
DataFlowCall call, Node node, AccessPath argAp, AccessPathFront apf, AccessPath ap, DataFlowCall call, Node node, AccessPath argAp, AccessPathFront apf, AccessPath ap,
Configuration config Configuration config
) { ) {
flowFwdOut(call, node, true, TAccessPathSome(argAp), apf, ap, config) flowFwdOut(call, node, any(CallContextCall ccc), _, TAccessPathSome(argAp), apf, ap, config)
} }
/** /**
@@ -1834,10 +1854,10 @@ private predicate flowFwdOutFromArg(
*/ */
pragma[nomagic] pragma[nomagic]
private predicate flowFwdIsEntered( private predicate flowFwdIsEntered(
DataFlowCall call, boolean fromArg, AccessPathOption argAp, AccessPath ap, Configuration config DataFlowCall call, CallContext cc, AccessPathOption argAp, AccessPath ap, Configuration config
) { ) {
exists(ParameterNode p, AccessPathFront apf | exists(ParameterNode p, AccessPathFront apf |
flowFwdIn(call, p, fromArg, argAp, apf, ap, config) and flowFwdIn(call, p, _, cc, argAp, apf, ap, config) and
flowCand(p, true, TAccessPathFrontSome(_), apf, config) flowCand(p, true, TAccessPathFrontSome(_), apf, config)
) )
} }
@@ -1920,7 +1940,7 @@ private predicate flow0(
// flow out of a callable // flow out of a callable
flowOut(_, node, _, _, ap, config) and flowOut(_, node, _, _, ap, config) and
toReturn = true and toReturn = true and
if flowFwd(node, true, TAccessPathSome(_), _, ap, config) if flowFwd(node, any(CallContextCall ccc), TAccessPathSome(_), _, ap, config)
then returnAp = TAccessPathSome(ap) then returnAp = TAccessPathSome(ap)
else returnAp = TAccessPathNone() else returnAp = TAccessPathNone()
} }
@@ -2006,9 +2026,10 @@ private predicate flowIsReturned(
DataFlowCall call, boolean toReturn, AccessPathOption returnAp, AccessPath ap, DataFlowCall call, boolean toReturn, AccessPathOption returnAp, AccessPath ap,
Configuration config Configuration config
) { ) {
exists(ReturnNodeExt ret | exists(ReturnNodeExt ret, CallContextCall ccc |
flowOut(call, ret, toReturn, returnAp, ap, config) and flowOut(call, ret, toReturn, returnAp, ap, config) and
flowFwd(ret, true, TAccessPathSome(_), _, ap, config) flowFwd(ret, ccc, TAccessPathSome(_), _, ap, config) and
ccc.matchesCall(call)
) )
} }
@@ -2031,7 +2052,7 @@ private newtype TSummaryCtx =
exists(ReturnNodeExt ret, Configuration config, AccessPath ap0 | exists(ReturnNodeExt ret, Configuration config, AccessPath ap0 |
parameterFlow(p, ap, ret.getEnclosingCallable(), config) and parameterFlow(p, ap, ret.getEnclosingCallable(), config) and
flow(ret, true, TAccessPathSome(_), ap0, config) and flow(ret, true, TAccessPathSome(_), ap0, config) and
flowFwd(ret, true, TAccessPathSome(ap), _, ap0, config) flowFwd(ret, any(CallContextCall ccc), TAccessPathSome(ap), _, ap0, config)
) )
} }
@@ -2352,7 +2373,7 @@ private predicate pathOutOfCallable0(
) { ) {
pos = getReturnPosition(mid.getNode()) and pos = getReturnPosition(mid.getNode()) and
innercc = mid.getCallContext() and innercc = mid.getCallContext() and
not innercc instanceof CallContextCall and innercc instanceof CallContextNoCall and
ap = mid.getAp() and ap = mid.getAp() and
config = mid.getConfiguration() config = mid.getConfiguration()
} }
@@ -2867,7 +2888,7 @@ private module FlowExploration {
) { ) {
pos = getReturnPosition(mid.getNode()) and pos = getReturnPosition(mid.getNode()) and
innercc = mid.getCallContext() and innercc = mid.getCallContext() and
not innercc instanceof CallContextCall and innercc instanceof CallContextNoCall and
ap = mid.getAp() and ap = mid.getAp() and
config = mid.getConfiguration() config = mid.getConfiguration()
} }

View File

@@ -1066,7 +1066,7 @@ private module LocalFlowBigStep {
* Holds if `node` can be the first node in a maximal subsequence of local * Holds if `node` can be the first node in a maximal subsequence of local
* flow steps in a dataflow path. * flow steps in a dataflow path.
*/ */
private predicate localFlowEntry(Node node, Configuration config) { predicate localFlowEntry(Node node, Configuration config) {
nodeCand2(node, config) and nodeCand2(node, config) and
( (
config.isSource(node) or config.isSource(node) or
@@ -1650,53 +1650,53 @@ private class AccessPathOption extends TAccessPathOption {
* Holds if `node` is reachable with access path `ap` from a source in * Holds if `node` is reachable with access path `ap` from a source in
* the configuration `config`. * the configuration `config`.
* *
* The Boolean `fromArg` records whether the node is reached through an * 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 in a call, and if so, `argAp` records the access path of that
* argument. * argument.
*/ */
private predicate flowFwd( private predicate flowFwd(
Node node, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Node node, CallContext cc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap,
Configuration config Configuration config
) { ) {
flowFwd0(node, fromArg, argAp, apf, ap, config) and flowFwd0(node, cc, argAp, apf, ap, config) and
flowCand(node, _, _, apf, config) flowCand(node, _, _, apf, config)
} }
private predicate flowFwd0( private predicate flowFwd0(
Node node, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Node node, CallContext cc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap,
Configuration config Configuration config
) { ) {
flowCand(node, _, _, _, config) and flowCand(node, _, _, _, config) and
config.isSource(node) and config.isSource(node) and
fromArg = false and cc instanceof CallContextAny and
argAp = TAccessPathNone() and argAp = TAccessPathNone() and
ap = TNil(getNodeType(node)) and ap = TNil(getNodeType(node)) and
apf = ap.(AccessPathNil).getFront() apf = ap.(AccessPathNil).getFront()
or or
flowCand(node, _, _, _, unbind(config)) and flowCand(node, _, _, _, unbind(config)) and
( (
exists(Node mid | exists(Node mid, LocalCallContext localCC |
flowFwd(mid, fromArg, argAp, apf, ap, config) and flowFwdLocalEntry(mid, cc, argAp, apf, ap, localCC, config) and
localFlowBigStep(mid, node, true, _, config, _) localFlowBigStep(mid, node, true, _, config, localCC)
) )
or or
exists(Node mid, AccessPathNil nil | exists(Node mid, AccessPathNil nil, LocalCallContext localCC |
flowFwd(mid, fromArg, argAp, _, nil, config) and flowFwdLocalEntry(mid, cc, argAp, _, nil, localCC, config) and
localFlowBigStep(mid, node, false, apf, config, _) and localFlowBigStep(mid, node, false, apf, config, localCC) and
apf = ap.(AccessPathNil).getFront() apf = ap.(AccessPathNil).getFront()
) )
or or
exists(Node mid | exists(Node mid |
flowFwd(mid, _, _, apf, ap, config) and flowFwd(mid, _, _, apf, ap, config) and
jumpStep(mid, node, config) and jumpStep(mid, node, config) and
fromArg = false and cc instanceof CallContextAny and
argAp = TAccessPathNone() argAp = TAccessPathNone()
) )
or or
exists(Node mid, AccessPathNil nil | exists(Node mid, AccessPathNil nil |
flowFwd(mid, _, _, _, nil, config) and flowFwd(mid, _, _, _, nil, config) and
additionalJumpStep(mid, node, config) and additionalJumpStep(mid, node, config) and
fromArg = false and cc instanceof CallContextAny and
argAp = TAccessPathNone() and argAp = TAccessPathNone() and
ap = TNil(getNodeType(node)) and ap = TNil(getNodeType(node)) and
apf = ap.(AccessPathNil).getFront() apf = ap.(AccessPathNil).getFront()
@@ -1704,40 +1704,51 @@ private predicate flowFwd0(
) )
or or
// store // store
exists(TypedContent tc | flowFwdStore(node, tc, pop(tc, ap), apf, fromArg, argAp, config)) exists(TypedContent tc | flowFwdStore(node, tc, pop(tc, ap), apf, cc, argAp, config))
or or
// read // read
exists(TypedContent tc | exists(TypedContent tc |
flowFwdRead(node, _, push(tc, ap), apf, fromArg, argAp, config) and flowFwdRead(node, _, push(tc, ap), apf, cc, argAp, config) and
flowFwdConsCand(tc, apf, ap, config) flowFwdConsCand(tc, apf, ap, config)
) )
or or
// flow into a callable // flow into a callable
flowFwdIn(_, node, _, _, apf, ap, config) and flowFwdIn(_, node, cc, _, _, apf, ap, config) and
fromArg = true and
if flowCand(node, true, _, apf, config) if flowCand(node, true, _, apf, config)
then argAp = TAccessPathSome(ap) then argAp = TAccessPathSome(ap)
else argAp = TAccessPathNone() else argAp = TAccessPathNone()
or or
// flow out of a callable // flow out of a callable
exists(DataFlowCall call | exists(DataFlowCall call |
flowFwdOut(call, node, fromArg, argAp, apf, ap, config) and exists(CallContextNoCall innercc, DataFlowCallable c |
fromArg = false flowFwdOut(call, node, innercc, c, argAp, apf, ap, config) and
if reducedViableImplInReturn(c, call) then cc = TReturn(c, call) else cc = TAnyCallContext()
)
or or
exists(AccessPath argAp0 | exists(AccessPath argAp0 |
flowFwdOutFromArg(call, node, argAp0, apf, ap, config) and flowFwdOutFromArg(call, node, argAp0, apf, ap, config) and
flowFwdIsEntered(call, fromArg, argAp, argAp0, config) flowFwdIsEntered(call, cc, argAp, argAp0, config)
) )
) )
} }
pragma[nomagic]
private predicate flowFwdLocalEntry(
Node node, CallContext cc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap,
LocalCallContext localCC, Configuration config
) {
flowFwd(node, cc, argAp, apf, ap, config) and
localFlowEntry(node, config) and
localCC = getLocalCallContext(cc, node.getEnclosingCallable())
}
pragma[nomagic] pragma[nomagic]
private predicate flowFwdStore( private predicate flowFwdStore(
Node node, TypedContent tc, AccessPath ap0, AccessPathFront apf, boolean fromArg, Node node, TypedContent tc, AccessPath ap0, AccessPathFront apf, CallContext cc,
AccessPathOption argAp, Configuration config AccessPathOption argAp, Configuration config
) { ) {
exists(Node mid, AccessPathFront apf0 | exists(Node mid, AccessPathFront apf0 |
flowFwd(mid, fromArg, argAp, apf0, ap0, config) and flowFwd(mid, cc, argAp, apf0, ap0, config) and
flowFwdStore0(mid, tc, node, apf0, apf, config) flowFwdStore0(mid, tc, node, apf0, apf, config)
) )
} }
@@ -1764,20 +1775,20 @@ private predicate flowFwdStore0(
pragma[nomagic] pragma[nomagic]
private predicate flowFwdRead0( private predicate flowFwdRead0(
Node node1, TypedContent tc, AccessPathFrontHead apf0, AccessPath ap0, Node node2, Node node1, TypedContent tc, AccessPathFrontHead apf0, AccessPath ap0, Node node2, CallContext cc,
boolean fromArg, AccessPathOption argAp, Configuration config AccessPathOption argAp, Configuration config
) { ) {
flowFwd(node1, fromArg, argAp, apf0, ap0, config) and flowFwd(node1, cc, argAp, apf0, ap0, config) and
readCandFwd(node1, tc, apf0, node2, config) readCandFwd(node1, tc, apf0, node2, config)
} }
pragma[nomagic] pragma[nomagic]
private predicate flowFwdRead( private predicate flowFwdRead(
Node node, AccessPathFrontHead apf0, AccessPath ap0, AccessPathFront apf, boolean fromArg, Node node, AccessPathFrontHead apf0, AccessPath ap0, AccessPathFront apf, CallContext cc,
AccessPathOption argAp, Configuration config AccessPathOption argAp, Configuration config
) { ) {
exists(Node mid, TypedContent tc | exists(Node mid, TypedContent tc |
flowFwdRead0(mid, tc, apf0, ap0, node, fromArg, argAp, config) and flowFwdRead0(mid, tc, apf0, ap0, node, cc, argAp, config) and
flowCand(node, _, _, apf, unbind(config)) and flowCand(node, _, _, apf, unbind(config)) and
flowCandConsCand(tc, apf, unbind(config)) flowCandConsCand(tc, apf, unbind(config))
) )
@@ -1795,13 +1806,16 @@ private predicate flowFwdConsCand(
pragma[nomagic] pragma[nomagic]
private predicate flowFwdIn( private predicate flowFwdIn(
DataFlowCall call, ParameterNode p, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, DataFlowCall call, ParameterNode p, CallContext innercc, CallContext outercc,
AccessPath ap, Configuration config AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config
) { ) {
exists(ArgumentNode arg, boolean allowsFieldFlow | exists(ArgumentNode arg, boolean allowsFieldFlow, DataFlowCallable c |
flowFwd(arg, fromArg, argAp, apf, ap, config) and flowFwd(arg, outercc, argAp, apf, ap, config) and
flowIntoCallNodeCand2(call, arg, p, allowsFieldFlow, config) and flowIntoCallNodeCand2(call, arg, p, allowsFieldFlow, config) and
flowCand(p, _, _, _, unbind(config)) 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 ap instanceof AccessPathNil or allowsFieldFlow = true
) )
@@ -1809,13 +1823,19 @@ private predicate flowFwdIn(
pragma[nomagic] pragma[nomagic]
private predicate flowFwdOut( private predicate flowFwdOut(
DataFlowCall call, Node node, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, DataFlowCall call, Node node, CallContext innercc, DataFlowCallable innerc,
AccessPath ap, Configuration config AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config
) { ) {
exists(ReturnNodeExt ret, boolean allowsFieldFlow | exists(ReturnNodeExt ret, boolean allowsFieldFlow |
flowFwd(ret, fromArg, argAp, apf, ap, config) and flowFwd(ret, innercc, argAp, apf, ap, config) and
flowOutOfCallNodeCand2(call, ret, node, allowsFieldFlow, config) and flowOutOfCallNodeCand2(call, ret, node, allowsFieldFlow, config) and
flowCand(node, _, _, _, unbind(config)) innerc = ret.getEnclosingCallable() and
flowCand(node, _, _, _, unbind(config)) and
(
resolveReturn(innercc, innerc, call)
or
innercc.(CallContextCall).matchesCall(call)
)
| |
ap instanceof AccessPathNil or allowsFieldFlow = true ap instanceof AccessPathNil or allowsFieldFlow = true
) )
@@ -1826,7 +1846,7 @@ private predicate flowFwdOutFromArg(
DataFlowCall call, Node node, AccessPath argAp, AccessPathFront apf, AccessPath ap, DataFlowCall call, Node node, AccessPath argAp, AccessPathFront apf, AccessPath ap,
Configuration config Configuration config
) { ) {
flowFwdOut(call, node, true, TAccessPathSome(argAp), apf, ap, config) flowFwdOut(call, node, any(CallContextCall ccc), _, TAccessPathSome(argAp), apf, ap, config)
} }
/** /**
@@ -1834,10 +1854,10 @@ private predicate flowFwdOutFromArg(
*/ */
pragma[nomagic] pragma[nomagic]
private predicate flowFwdIsEntered( private predicate flowFwdIsEntered(
DataFlowCall call, boolean fromArg, AccessPathOption argAp, AccessPath ap, Configuration config DataFlowCall call, CallContext cc, AccessPathOption argAp, AccessPath ap, Configuration config
) { ) {
exists(ParameterNode p, AccessPathFront apf | exists(ParameterNode p, AccessPathFront apf |
flowFwdIn(call, p, fromArg, argAp, apf, ap, config) and flowFwdIn(call, p, _, cc, argAp, apf, ap, config) and
flowCand(p, true, TAccessPathFrontSome(_), apf, config) flowCand(p, true, TAccessPathFrontSome(_), apf, config)
) )
} }
@@ -1920,7 +1940,7 @@ private predicate flow0(
// flow out of a callable // flow out of a callable
flowOut(_, node, _, _, ap, config) and flowOut(_, node, _, _, ap, config) and
toReturn = true and toReturn = true and
if flowFwd(node, true, TAccessPathSome(_), _, ap, config) if flowFwd(node, any(CallContextCall ccc), TAccessPathSome(_), _, ap, config)
then returnAp = TAccessPathSome(ap) then returnAp = TAccessPathSome(ap)
else returnAp = TAccessPathNone() else returnAp = TAccessPathNone()
} }
@@ -2006,9 +2026,10 @@ private predicate flowIsReturned(
DataFlowCall call, boolean toReturn, AccessPathOption returnAp, AccessPath ap, DataFlowCall call, boolean toReturn, AccessPathOption returnAp, AccessPath ap,
Configuration config Configuration config
) { ) {
exists(ReturnNodeExt ret | exists(ReturnNodeExt ret, CallContextCall ccc |
flowOut(call, ret, toReturn, returnAp, ap, config) and flowOut(call, ret, toReturn, returnAp, ap, config) and
flowFwd(ret, true, TAccessPathSome(_), _, ap, config) flowFwd(ret, ccc, TAccessPathSome(_), _, ap, config) and
ccc.matchesCall(call)
) )
} }
@@ -2031,7 +2052,7 @@ private newtype TSummaryCtx =
exists(ReturnNodeExt ret, Configuration config, AccessPath ap0 | exists(ReturnNodeExt ret, Configuration config, AccessPath ap0 |
parameterFlow(p, ap, ret.getEnclosingCallable(), config) and parameterFlow(p, ap, ret.getEnclosingCallable(), config) and
flow(ret, true, TAccessPathSome(_), ap0, config) and flow(ret, true, TAccessPathSome(_), ap0, config) and
flowFwd(ret, true, TAccessPathSome(ap), _, ap0, config) flowFwd(ret, any(CallContextCall ccc), TAccessPathSome(ap), _, ap0, config)
) )
} }
@@ -2352,7 +2373,7 @@ private predicate pathOutOfCallable0(
) { ) {
pos = getReturnPosition(mid.getNode()) and pos = getReturnPosition(mid.getNode()) and
innercc = mid.getCallContext() and innercc = mid.getCallContext() and
not innercc instanceof CallContextCall and innercc instanceof CallContextNoCall and
ap = mid.getAp() and ap = mid.getAp() and
config = mid.getConfiguration() config = mid.getConfiguration()
} }
@@ -2867,7 +2888,7 @@ private module FlowExploration {
) { ) {
pos = getReturnPosition(mid.getNode()) and pos = getReturnPosition(mid.getNode()) and
innercc = mid.getCallContext() and innercc = mid.getCallContext() and
not innercc instanceof CallContextCall and innercc instanceof CallContextNoCall and
ap = mid.getAp() and ap = mid.getAp() and
config = mid.getConfiguration() config = mid.getConfiguration()
} }

View File

@@ -1066,7 +1066,7 @@ private module LocalFlowBigStep {
* Holds if `node` can be the first node in a maximal subsequence of local * Holds if `node` can be the first node in a maximal subsequence of local
* flow steps in a dataflow path. * flow steps in a dataflow path.
*/ */
private predicate localFlowEntry(Node node, Configuration config) { predicate localFlowEntry(Node node, Configuration config) {
nodeCand2(node, config) and nodeCand2(node, config) and
( (
config.isSource(node) or config.isSource(node) or
@@ -1650,53 +1650,53 @@ private class AccessPathOption extends TAccessPathOption {
* Holds if `node` is reachable with access path `ap` from a source in * Holds if `node` is reachable with access path `ap` from a source in
* the configuration `config`. * the configuration `config`.
* *
* The Boolean `fromArg` records whether the node is reached through an * 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 in a call, and if so, `argAp` records the access path of that
* argument. * argument.
*/ */
private predicate flowFwd( private predicate flowFwd(
Node node, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Node node, CallContext cc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap,
Configuration config Configuration config
) { ) {
flowFwd0(node, fromArg, argAp, apf, ap, config) and flowFwd0(node, cc, argAp, apf, ap, config) and
flowCand(node, _, _, apf, config) flowCand(node, _, _, apf, config)
} }
private predicate flowFwd0( private predicate flowFwd0(
Node node, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Node node, CallContext cc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap,
Configuration config Configuration config
) { ) {
flowCand(node, _, _, _, config) and flowCand(node, _, _, _, config) and
config.isSource(node) and config.isSource(node) and
fromArg = false and cc instanceof CallContextAny and
argAp = TAccessPathNone() and argAp = TAccessPathNone() and
ap = TNil(getNodeType(node)) and ap = TNil(getNodeType(node)) and
apf = ap.(AccessPathNil).getFront() apf = ap.(AccessPathNil).getFront()
or or
flowCand(node, _, _, _, unbind(config)) and flowCand(node, _, _, _, unbind(config)) and
( (
exists(Node mid | exists(Node mid, LocalCallContext localCC |
flowFwd(mid, fromArg, argAp, apf, ap, config) and flowFwdLocalEntry(mid, cc, argAp, apf, ap, localCC, config) and
localFlowBigStep(mid, node, true, _, config, _) localFlowBigStep(mid, node, true, _, config, localCC)
) )
or or
exists(Node mid, AccessPathNil nil | exists(Node mid, AccessPathNil nil, LocalCallContext localCC |
flowFwd(mid, fromArg, argAp, _, nil, config) and flowFwdLocalEntry(mid, cc, argAp, _, nil, localCC, config) and
localFlowBigStep(mid, node, false, apf, config, _) and localFlowBigStep(mid, node, false, apf, config, localCC) and
apf = ap.(AccessPathNil).getFront() apf = ap.(AccessPathNil).getFront()
) )
or or
exists(Node mid | exists(Node mid |
flowFwd(mid, _, _, apf, ap, config) and flowFwd(mid, _, _, apf, ap, config) and
jumpStep(mid, node, config) and jumpStep(mid, node, config) and
fromArg = false and cc instanceof CallContextAny and
argAp = TAccessPathNone() argAp = TAccessPathNone()
) )
or or
exists(Node mid, AccessPathNil nil | exists(Node mid, AccessPathNil nil |
flowFwd(mid, _, _, _, nil, config) and flowFwd(mid, _, _, _, nil, config) and
additionalJumpStep(mid, node, config) and additionalJumpStep(mid, node, config) and
fromArg = false and cc instanceof CallContextAny and
argAp = TAccessPathNone() and argAp = TAccessPathNone() and
ap = TNil(getNodeType(node)) and ap = TNil(getNodeType(node)) and
apf = ap.(AccessPathNil).getFront() apf = ap.(AccessPathNil).getFront()
@@ -1704,40 +1704,51 @@ private predicate flowFwd0(
) )
or or
// store // store
exists(TypedContent tc | flowFwdStore(node, tc, pop(tc, ap), apf, fromArg, argAp, config)) exists(TypedContent tc | flowFwdStore(node, tc, pop(tc, ap), apf, cc, argAp, config))
or or
// read // read
exists(TypedContent tc | exists(TypedContent tc |
flowFwdRead(node, _, push(tc, ap), apf, fromArg, argAp, config) and flowFwdRead(node, _, push(tc, ap), apf, cc, argAp, config) and
flowFwdConsCand(tc, apf, ap, config) flowFwdConsCand(tc, apf, ap, config)
) )
or or
// flow into a callable // flow into a callable
flowFwdIn(_, node, _, _, apf, ap, config) and flowFwdIn(_, node, cc, _, _, apf, ap, config) and
fromArg = true and
if flowCand(node, true, _, apf, config) if flowCand(node, true, _, apf, config)
then argAp = TAccessPathSome(ap) then argAp = TAccessPathSome(ap)
else argAp = TAccessPathNone() else argAp = TAccessPathNone()
or or
// flow out of a callable // flow out of a callable
exists(DataFlowCall call | exists(DataFlowCall call |
flowFwdOut(call, node, fromArg, argAp, apf, ap, config) and exists(CallContextNoCall innercc, DataFlowCallable c |
fromArg = false flowFwdOut(call, node, innercc, c, argAp, apf, ap, config) and
if reducedViableImplInReturn(c, call) then cc = TReturn(c, call) else cc = TAnyCallContext()
)
or or
exists(AccessPath argAp0 | exists(AccessPath argAp0 |
flowFwdOutFromArg(call, node, argAp0, apf, ap, config) and flowFwdOutFromArg(call, node, argAp0, apf, ap, config) and
flowFwdIsEntered(call, fromArg, argAp, argAp0, config) flowFwdIsEntered(call, cc, argAp, argAp0, config)
) )
) )
} }
pragma[nomagic]
private predicate flowFwdLocalEntry(
Node node, CallContext cc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap,
LocalCallContext localCC, Configuration config
) {
flowFwd(node, cc, argAp, apf, ap, config) and
localFlowEntry(node, config) and
localCC = getLocalCallContext(cc, node.getEnclosingCallable())
}
pragma[nomagic] pragma[nomagic]
private predicate flowFwdStore( private predicate flowFwdStore(
Node node, TypedContent tc, AccessPath ap0, AccessPathFront apf, boolean fromArg, Node node, TypedContent tc, AccessPath ap0, AccessPathFront apf, CallContext cc,
AccessPathOption argAp, Configuration config AccessPathOption argAp, Configuration config
) { ) {
exists(Node mid, AccessPathFront apf0 | exists(Node mid, AccessPathFront apf0 |
flowFwd(mid, fromArg, argAp, apf0, ap0, config) and flowFwd(mid, cc, argAp, apf0, ap0, config) and
flowFwdStore0(mid, tc, node, apf0, apf, config) flowFwdStore0(mid, tc, node, apf0, apf, config)
) )
} }
@@ -1764,20 +1775,20 @@ private predicate flowFwdStore0(
pragma[nomagic] pragma[nomagic]
private predicate flowFwdRead0( private predicate flowFwdRead0(
Node node1, TypedContent tc, AccessPathFrontHead apf0, AccessPath ap0, Node node2, Node node1, TypedContent tc, AccessPathFrontHead apf0, AccessPath ap0, Node node2, CallContext cc,
boolean fromArg, AccessPathOption argAp, Configuration config AccessPathOption argAp, Configuration config
) { ) {
flowFwd(node1, fromArg, argAp, apf0, ap0, config) and flowFwd(node1, cc, argAp, apf0, ap0, config) and
readCandFwd(node1, tc, apf0, node2, config) readCandFwd(node1, tc, apf0, node2, config)
} }
pragma[nomagic] pragma[nomagic]
private predicate flowFwdRead( private predicate flowFwdRead(
Node node, AccessPathFrontHead apf0, AccessPath ap0, AccessPathFront apf, boolean fromArg, Node node, AccessPathFrontHead apf0, AccessPath ap0, AccessPathFront apf, CallContext cc,
AccessPathOption argAp, Configuration config AccessPathOption argAp, Configuration config
) { ) {
exists(Node mid, TypedContent tc | exists(Node mid, TypedContent tc |
flowFwdRead0(mid, tc, apf0, ap0, node, fromArg, argAp, config) and flowFwdRead0(mid, tc, apf0, ap0, node, cc, argAp, config) and
flowCand(node, _, _, apf, unbind(config)) and flowCand(node, _, _, apf, unbind(config)) and
flowCandConsCand(tc, apf, unbind(config)) flowCandConsCand(tc, apf, unbind(config))
) )
@@ -1795,13 +1806,16 @@ private predicate flowFwdConsCand(
pragma[nomagic] pragma[nomagic]
private predicate flowFwdIn( private predicate flowFwdIn(
DataFlowCall call, ParameterNode p, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, DataFlowCall call, ParameterNode p, CallContext innercc, CallContext outercc,
AccessPath ap, Configuration config AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config
) { ) {
exists(ArgumentNode arg, boolean allowsFieldFlow | exists(ArgumentNode arg, boolean allowsFieldFlow, DataFlowCallable c |
flowFwd(arg, fromArg, argAp, apf, ap, config) and flowFwd(arg, outercc, argAp, apf, ap, config) and
flowIntoCallNodeCand2(call, arg, p, allowsFieldFlow, config) and flowIntoCallNodeCand2(call, arg, p, allowsFieldFlow, config) and
flowCand(p, _, _, _, unbind(config)) 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 ap instanceof AccessPathNil or allowsFieldFlow = true
) )
@@ -1809,13 +1823,19 @@ private predicate flowFwdIn(
pragma[nomagic] pragma[nomagic]
private predicate flowFwdOut( private predicate flowFwdOut(
DataFlowCall call, Node node, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, DataFlowCall call, Node node, CallContext innercc, DataFlowCallable innerc,
AccessPath ap, Configuration config AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config
) { ) {
exists(ReturnNodeExt ret, boolean allowsFieldFlow | exists(ReturnNodeExt ret, boolean allowsFieldFlow |
flowFwd(ret, fromArg, argAp, apf, ap, config) and flowFwd(ret, innercc, argAp, apf, ap, config) and
flowOutOfCallNodeCand2(call, ret, node, allowsFieldFlow, config) and flowOutOfCallNodeCand2(call, ret, node, allowsFieldFlow, config) and
flowCand(node, _, _, _, unbind(config)) innerc = ret.getEnclosingCallable() and
flowCand(node, _, _, _, unbind(config)) and
(
resolveReturn(innercc, innerc, call)
or
innercc.(CallContextCall).matchesCall(call)
)
| |
ap instanceof AccessPathNil or allowsFieldFlow = true ap instanceof AccessPathNil or allowsFieldFlow = true
) )
@@ -1826,7 +1846,7 @@ private predicate flowFwdOutFromArg(
DataFlowCall call, Node node, AccessPath argAp, AccessPathFront apf, AccessPath ap, DataFlowCall call, Node node, AccessPath argAp, AccessPathFront apf, AccessPath ap,
Configuration config Configuration config
) { ) {
flowFwdOut(call, node, true, TAccessPathSome(argAp), apf, ap, config) flowFwdOut(call, node, any(CallContextCall ccc), _, TAccessPathSome(argAp), apf, ap, config)
} }
/** /**
@@ -1834,10 +1854,10 @@ private predicate flowFwdOutFromArg(
*/ */
pragma[nomagic] pragma[nomagic]
private predicate flowFwdIsEntered( private predicate flowFwdIsEntered(
DataFlowCall call, boolean fromArg, AccessPathOption argAp, AccessPath ap, Configuration config DataFlowCall call, CallContext cc, AccessPathOption argAp, AccessPath ap, Configuration config
) { ) {
exists(ParameterNode p, AccessPathFront apf | exists(ParameterNode p, AccessPathFront apf |
flowFwdIn(call, p, fromArg, argAp, apf, ap, config) and flowFwdIn(call, p, _, cc, argAp, apf, ap, config) and
flowCand(p, true, TAccessPathFrontSome(_), apf, config) flowCand(p, true, TAccessPathFrontSome(_), apf, config)
) )
} }
@@ -1920,7 +1940,7 @@ private predicate flow0(
// flow out of a callable // flow out of a callable
flowOut(_, node, _, _, ap, config) and flowOut(_, node, _, _, ap, config) and
toReturn = true and toReturn = true and
if flowFwd(node, true, TAccessPathSome(_), _, ap, config) if flowFwd(node, any(CallContextCall ccc), TAccessPathSome(_), _, ap, config)
then returnAp = TAccessPathSome(ap) then returnAp = TAccessPathSome(ap)
else returnAp = TAccessPathNone() else returnAp = TAccessPathNone()
} }
@@ -2006,9 +2026,10 @@ private predicate flowIsReturned(
DataFlowCall call, boolean toReturn, AccessPathOption returnAp, AccessPath ap, DataFlowCall call, boolean toReturn, AccessPathOption returnAp, AccessPath ap,
Configuration config Configuration config
) { ) {
exists(ReturnNodeExt ret | exists(ReturnNodeExt ret, CallContextCall ccc |
flowOut(call, ret, toReturn, returnAp, ap, config) and flowOut(call, ret, toReturn, returnAp, ap, config) and
flowFwd(ret, true, TAccessPathSome(_), _, ap, config) flowFwd(ret, ccc, TAccessPathSome(_), _, ap, config) and
ccc.matchesCall(call)
) )
} }
@@ -2031,7 +2052,7 @@ private newtype TSummaryCtx =
exists(ReturnNodeExt ret, Configuration config, AccessPath ap0 | exists(ReturnNodeExt ret, Configuration config, AccessPath ap0 |
parameterFlow(p, ap, ret.getEnclosingCallable(), config) and parameterFlow(p, ap, ret.getEnclosingCallable(), config) and
flow(ret, true, TAccessPathSome(_), ap0, config) and flow(ret, true, TAccessPathSome(_), ap0, config) and
flowFwd(ret, true, TAccessPathSome(ap), _, ap0, config) flowFwd(ret, any(CallContextCall ccc), TAccessPathSome(ap), _, ap0, config)
) )
} }
@@ -2352,7 +2373,7 @@ private predicate pathOutOfCallable0(
) { ) {
pos = getReturnPosition(mid.getNode()) and pos = getReturnPosition(mid.getNode()) and
innercc = mid.getCallContext() and innercc = mid.getCallContext() and
not innercc instanceof CallContextCall and innercc instanceof CallContextNoCall and
ap = mid.getAp() and ap = mid.getAp() and
config = mid.getConfiguration() config = mid.getConfiguration()
} }
@@ -2867,7 +2888,7 @@ private module FlowExploration {
) { ) {
pos = getReturnPosition(mid.getNode()) and pos = getReturnPosition(mid.getNode()) and
innercc = mid.getCallContext() and innercc = mid.getCallContext() and
not innercc instanceof CallContextCall and innercc instanceof CallContextNoCall and
ap = mid.getAp() and ap = mid.getAp() and
config = mid.getConfiguration() config = mid.getConfiguration()
} }

View File

@@ -1066,7 +1066,7 @@ private module LocalFlowBigStep {
* Holds if `node` can be the first node in a maximal subsequence of local * Holds if `node` can be the first node in a maximal subsequence of local
* flow steps in a dataflow path. * flow steps in a dataflow path.
*/ */
private predicate localFlowEntry(Node node, Configuration config) { predicate localFlowEntry(Node node, Configuration config) {
nodeCand2(node, config) and nodeCand2(node, config) and
( (
config.isSource(node) or config.isSource(node) or
@@ -1650,53 +1650,53 @@ private class AccessPathOption extends TAccessPathOption {
* Holds if `node` is reachable with access path `ap` from a source in * Holds if `node` is reachable with access path `ap` from a source in
* the configuration `config`. * the configuration `config`.
* *
* The Boolean `fromArg` records whether the node is reached through an * 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 in a call, and if so, `argAp` records the access path of that
* argument. * argument.
*/ */
private predicate flowFwd( private predicate flowFwd(
Node node, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Node node, CallContext cc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap,
Configuration config Configuration config
) { ) {
flowFwd0(node, fromArg, argAp, apf, ap, config) and flowFwd0(node, cc, argAp, apf, ap, config) and
flowCand(node, _, _, apf, config) flowCand(node, _, _, apf, config)
} }
private predicate flowFwd0( private predicate flowFwd0(
Node node, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Node node, CallContext cc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap,
Configuration config Configuration config
) { ) {
flowCand(node, _, _, _, config) and flowCand(node, _, _, _, config) and
config.isSource(node) and config.isSource(node) and
fromArg = false and cc instanceof CallContextAny and
argAp = TAccessPathNone() and argAp = TAccessPathNone() and
ap = TNil(getNodeType(node)) and ap = TNil(getNodeType(node)) and
apf = ap.(AccessPathNil).getFront() apf = ap.(AccessPathNil).getFront()
or or
flowCand(node, _, _, _, unbind(config)) and flowCand(node, _, _, _, unbind(config)) and
( (
exists(Node mid | exists(Node mid, LocalCallContext localCC |
flowFwd(mid, fromArg, argAp, apf, ap, config) and flowFwdLocalEntry(mid, cc, argAp, apf, ap, localCC, config) and
localFlowBigStep(mid, node, true, _, config, _) localFlowBigStep(mid, node, true, _, config, localCC)
) )
or or
exists(Node mid, AccessPathNil nil | exists(Node mid, AccessPathNil nil, LocalCallContext localCC |
flowFwd(mid, fromArg, argAp, _, nil, config) and flowFwdLocalEntry(mid, cc, argAp, _, nil, localCC, config) and
localFlowBigStep(mid, node, false, apf, config, _) and localFlowBigStep(mid, node, false, apf, config, localCC) and
apf = ap.(AccessPathNil).getFront() apf = ap.(AccessPathNil).getFront()
) )
or or
exists(Node mid | exists(Node mid |
flowFwd(mid, _, _, apf, ap, config) and flowFwd(mid, _, _, apf, ap, config) and
jumpStep(mid, node, config) and jumpStep(mid, node, config) and
fromArg = false and cc instanceof CallContextAny and
argAp = TAccessPathNone() argAp = TAccessPathNone()
) )
or or
exists(Node mid, AccessPathNil nil | exists(Node mid, AccessPathNil nil |
flowFwd(mid, _, _, _, nil, config) and flowFwd(mid, _, _, _, nil, config) and
additionalJumpStep(mid, node, config) and additionalJumpStep(mid, node, config) and
fromArg = false and cc instanceof CallContextAny and
argAp = TAccessPathNone() and argAp = TAccessPathNone() and
ap = TNil(getNodeType(node)) and ap = TNil(getNodeType(node)) and
apf = ap.(AccessPathNil).getFront() apf = ap.(AccessPathNil).getFront()
@@ -1704,40 +1704,51 @@ private predicate flowFwd0(
) )
or or
// store // store
exists(TypedContent tc | flowFwdStore(node, tc, pop(tc, ap), apf, fromArg, argAp, config)) exists(TypedContent tc | flowFwdStore(node, tc, pop(tc, ap), apf, cc, argAp, config))
or or
// read // read
exists(TypedContent tc | exists(TypedContent tc |
flowFwdRead(node, _, push(tc, ap), apf, fromArg, argAp, config) and flowFwdRead(node, _, push(tc, ap), apf, cc, argAp, config) and
flowFwdConsCand(tc, apf, ap, config) flowFwdConsCand(tc, apf, ap, config)
) )
or or
// flow into a callable // flow into a callable
flowFwdIn(_, node, _, _, apf, ap, config) and flowFwdIn(_, node, cc, _, _, apf, ap, config) and
fromArg = true and
if flowCand(node, true, _, apf, config) if flowCand(node, true, _, apf, config)
then argAp = TAccessPathSome(ap) then argAp = TAccessPathSome(ap)
else argAp = TAccessPathNone() else argAp = TAccessPathNone()
or or
// flow out of a callable // flow out of a callable
exists(DataFlowCall call | exists(DataFlowCall call |
flowFwdOut(call, node, fromArg, argAp, apf, ap, config) and exists(CallContextNoCall innercc, DataFlowCallable c |
fromArg = false flowFwdOut(call, node, innercc, c, argAp, apf, ap, config) and
if reducedViableImplInReturn(c, call) then cc = TReturn(c, call) else cc = TAnyCallContext()
)
or or
exists(AccessPath argAp0 | exists(AccessPath argAp0 |
flowFwdOutFromArg(call, node, argAp0, apf, ap, config) and flowFwdOutFromArg(call, node, argAp0, apf, ap, config) and
flowFwdIsEntered(call, fromArg, argAp, argAp0, config) flowFwdIsEntered(call, cc, argAp, argAp0, config)
) )
) )
} }
pragma[nomagic]
private predicate flowFwdLocalEntry(
Node node, CallContext cc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap,
LocalCallContext localCC, Configuration config
) {
flowFwd(node, cc, argAp, apf, ap, config) and
localFlowEntry(node, config) and
localCC = getLocalCallContext(cc, node.getEnclosingCallable())
}
pragma[nomagic] pragma[nomagic]
private predicate flowFwdStore( private predicate flowFwdStore(
Node node, TypedContent tc, AccessPath ap0, AccessPathFront apf, boolean fromArg, Node node, TypedContent tc, AccessPath ap0, AccessPathFront apf, CallContext cc,
AccessPathOption argAp, Configuration config AccessPathOption argAp, Configuration config
) { ) {
exists(Node mid, AccessPathFront apf0 | exists(Node mid, AccessPathFront apf0 |
flowFwd(mid, fromArg, argAp, apf0, ap0, config) and flowFwd(mid, cc, argAp, apf0, ap0, config) and
flowFwdStore0(mid, tc, node, apf0, apf, config) flowFwdStore0(mid, tc, node, apf0, apf, config)
) )
} }
@@ -1764,20 +1775,20 @@ private predicate flowFwdStore0(
pragma[nomagic] pragma[nomagic]
private predicate flowFwdRead0( private predicate flowFwdRead0(
Node node1, TypedContent tc, AccessPathFrontHead apf0, AccessPath ap0, Node node2, Node node1, TypedContent tc, AccessPathFrontHead apf0, AccessPath ap0, Node node2, CallContext cc,
boolean fromArg, AccessPathOption argAp, Configuration config AccessPathOption argAp, Configuration config
) { ) {
flowFwd(node1, fromArg, argAp, apf0, ap0, config) and flowFwd(node1, cc, argAp, apf0, ap0, config) and
readCandFwd(node1, tc, apf0, node2, config) readCandFwd(node1, tc, apf0, node2, config)
} }
pragma[nomagic] pragma[nomagic]
private predicate flowFwdRead( private predicate flowFwdRead(
Node node, AccessPathFrontHead apf0, AccessPath ap0, AccessPathFront apf, boolean fromArg, Node node, AccessPathFrontHead apf0, AccessPath ap0, AccessPathFront apf, CallContext cc,
AccessPathOption argAp, Configuration config AccessPathOption argAp, Configuration config
) { ) {
exists(Node mid, TypedContent tc | exists(Node mid, TypedContent tc |
flowFwdRead0(mid, tc, apf0, ap0, node, fromArg, argAp, config) and flowFwdRead0(mid, tc, apf0, ap0, node, cc, argAp, config) and
flowCand(node, _, _, apf, unbind(config)) and flowCand(node, _, _, apf, unbind(config)) and
flowCandConsCand(tc, apf, unbind(config)) flowCandConsCand(tc, apf, unbind(config))
) )
@@ -1795,13 +1806,16 @@ private predicate flowFwdConsCand(
pragma[nomagic] pragma[nomagic]
private predicate flowFwdIn( private predicate flowFwdIn(
DataFlowCall call, ParameterNode p, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, DataFlowCall call, ParameterNode p, CallContext innercc, CallContext outercc,
AccessPath ap, Configuration config AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config
) { ) {
exists(ArgumentNode arg, boolean allowsFieldFlow | exists(ArgumentNode arg, boolean allowsFieldFlow, DataFlowCallable c |
flowFwd(arg, fromArg, argAp, apf, ap, config) and flowFwd(arg, outercc, argAp, apf, ap, config) and
flowIntoCallNodeCand2(call, arg, p, allowsFieldFlow, config) and flowIntoCallNodeCand2(call, arg, p, allowsFieldFlow, config) and
flowCand(p, _, _, _, unbind(config)) 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 ap instanceof AccessPathNil or allowsFieldFlow = true
) )
@@ -1809,13 +1823,19 @@ private predicate flowFwdIn(
pragma[nomagic] pragma[nomagic]
private predicate flowFwdOut( private predicate flowFwdOut(
DataFlowCall call, Node node, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, DataFlowCall call, Node node, CallContext innercc, DataFlowCallable innerc,
AccessPath ap, Configuration config AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config
) { ) {
exists(ReturnNodeExt ret, boolean allowsFieldFlow | exists(ReturnNodeExt ret, boolean allowsFieldFlow |
flowFwd(ret, fromArg, argAp, apf, ap, config) and flowFwd(ret, innercc, argAp, apf, ap, config) and
flowOutOfCallNodeCand2(call, ret, node, allowsFieldFlow, config) and flowOutOfCallNodeCand2(call, ret, node, allowsFieldFlow, config) and
flowCand(node, _, _, _, unbind(config)) innerc = ret.getEnclosingCallable() and
flowCand(node, _, _, _, unbind(config)) and
(
resolveReturn(innercc, innerc, call)
or
innercc.(CallContextCall).matchesCall(call)
)
| |
ap instanceof AccessPathNil or allowsFieldFlow = true ap instanceof AccessPathNil or allowsFieldFlow = true
) )
@@ -1826,7 +1846,7 @@ private predicate flowFwdOutFromArg(
DataFlowCall call, Node node, AccessPath argAp, AccessPathFront apf, AccessPath ap, DataFlowCall call, Node node, AccessPath argAp, AccessPathFront apf, AccessPath ap,
Configuration config Configuration config
) { ) {
flowFwdOut(call, node, true, TAccessPathSome(argAp), apf, ap, config) flowFwdOut(call, node, any(CallContextCall ccc), _, TAccessPathSome(argAp), apf, ap, config)
} }
/** /**
@@ -1834,10 +1854,10 @@ private predicate flowFwdOutFromArg(
*/ */
pragma[nomagic] pragma[nomagic]
private predicate flowFwdIsEntered( private predicate flowFwdIsEntered(
DataFlowCall call, boolean fromArg, AccessPathOption argAp, AccessPath ap, Configuration config DataFlowCall call, CallContext cc, AccessPathOption argAp, AccessPath ap, Configuration config
) { ) {
exists(ParameterNode p, AccessPathFront apf | exists(ParameterNode p, AccessPathFront apf |
flowFwdIn(call, p, fromArg, argAp, apf, ap, config) and flowFwdIn(call, p, _, cc, argAp, apf, ap, config) and
flowCand(p, true, TAccessPathFrontSome(_), apf, config) flowCand(p, true, TAccessPathFrontSome(_), apf, config)
) )
} }
@@ -1920,7 +1940,7 @@ private predicate flow0(
// flow out of a callable // flow out of a callable
flowOut(_, node, _, _, ap, config) and flowOut(_, node, _, _, ap, config) and
toReturn = true and toReturn = true and
if flowFwd(node, true, TAccessPathSome(_), _, ap, config) if flowFwd(node, any(CallContextCall ccc), TAccessPathSome(_), _, ap, config)
then returnAp = TAccessPathSome(ap) then returnAp = TAccessPathSome(ap)
else returnAp = TAccessPathNone() else returnAp = TAccessPathNone()
} }
@@ -2006,9 +2026,10 @@ private predicate flowIsReturned(
DataFlowCall call, boolean toReturn, AccessPathOption returnAp, AccessPath ap, DataFlowCall call, boolean toReturn, AccessPathOption returnAp, AccessPath ap,
Configuration config Configuration config
) { ) {
exists(ReturnNodeExt ret | exists(ReturnNodeExt ret, CallContextCall ccc |
flowOut(call, ret, toReturn, returnAp, ap, config) and flowOut(call, ret, toReturn, returnAp, ap, config) and
flowFwd(ret, true, TAccessPathSome(_), _, ap, config) flowFwd(ret, ccc, TAccessPathSome(_), _, ap, config) and
ccc.matchesCall(call)
) )
} }
@@ -2031,7 +2052,7 @@ private newtype TSummaryCtx =
exists(ReturnNodeExt ret, Configuration config, AccessPath ap0 | exists(ReturnNodeExt ret, Configuration config, AccessPath ap0 |
parameterFlow(p, ap, ret.getEnclosingCallable(), config) and parameterFlow(p, ap, ret.getEnclosingCallable(), config) and
flow(ret, true, TAccessPathSome(_), ap0, config) and flow(ret, true, TAccessPathSome(_), ap0, config) and
flowFwd(ret, true, TAccessPathSome(ap), _, ap0, config) flowFwd(ret, any(CallContextCall ccc), TAccessPathSome(ap), _, ap0, config)
) )
} }
@@ -2352,7 +2373,7 @@ private predicate pathOutOfCallable0(
) { ) {
pos = getReturnPosition(mid.getNode()) and pos = getReturnPosition(mid.getNode()) and
innercc = mid.getCallContext() and innercc = mid.getCallContext() and
not innercc instanceof CallContextCall and innercc instanceof CallContextNoCall and
ap = mid.getAp() and ap = mid.getAp() and
config = mid.getConfiguration() config = mid.getConfiguration()
} }
@@ -2867,7 +2888,7 @@ private module FlowExploration {
) { ) {
pos = getReturnPosition(mid.getNode()) and pos = getReturnPosition(mid.getNode()) and
innercc = mid.getCallContext() and innercc = mid.getCallContext() and
not innercc instanceof CallContextCall and innercc instanceof CallContextNoCall and
ap = mid.getAp() and ap = mid.getAp() and
config = mid.getConfiguration() config = mid.getConfiguration()
} }

View File

@@ -1066,7 +1066,7 @@ private module LocalFlowBigStep {
* Holds if `node` can be the first node in a maximal subsequence of local * Holds if `node` can be the first node in a maximal subsequence of local
* flow steps in a dataflow path. * flow steps in a dataflow path.
*/ */
private predicate localFlowEntry(Node node, Configuration config) { predicate localFlowEntry(Node node, Configuration config) {
nodeCand2(node, config) and nodeCand2(node, config) and
( (
config.isSource(node) or config.isSource(node) or
@@ -1650,53 +1650,53 @@ private class AccessPathOption extends TAccessPathOption {
* Holds if `node` is reachable with access path `ap` from a source in * Holds if `node` is reachable with access path `ap` from a source in
* the configuration `config`. * the configuration `config`.
* *
* The Boolean `fromArg` records whether the node is reached through an * 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 in a call, and if so, `argAp` records the access path of that
* argument. * argument.
*/ */
private predicate flowFwd( private predicate flowFwd(
Node node, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Node node, CallContext cc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap,
Configuration config Configuration config
) { ) {
flowFwd0(node, fromArg, argAp, apf, ap, config) and flowFwd0(node, cc, argAp, apf, ap, config) and
flowCand(node, _, _, apf, config) flowCand(node, _, _, apf, config)
} }
private predicate flowFwd0( private predicate flowFwd0(
Node node, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Node node, CallContext cc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap,
Configuration config Configuration config
) { ) {
flowCand(node, _, _, _, config) and flowCand(node, _, _, _, config) and
config.isSource(node) and config.isSource(node) and
fromArg = false and cc instanceof CallContextAny and
argAp = TAccessPathNone() and argAp = TAccessPathNone() and
ap = TNil(getNodeType(node)) and ap = TNil(getNodeType(node)) and
apf = ap.(AccessPathNil).getFront() apf = ap.(AccessPathNil).getFront()
or or
flowCand(node, _, _, _, unbind(config)) and flowCand(node, _, _, _, unbind(config)) and
( (
exists(Node mid | exists(Node mid, LocalCallContext localCC |
flowFwd(mid, fromArg, argAp, apf, ap, config) and flowFwdLocalEntry(mid, cc, argAp, apf, ap, localCC, config) and
localFlowBigStep(mid, node, true, _, config, _) localFlowBigStep(mid, node, true, _, config, localCC)
) )
or or
exists(Node mid, AccessPathNil nil | exists(Node mid, AccessPathNil nil, LocalCallContext localCC |
flowFwd(mid, fromArg, argAp, _, nil, config) and flowFwdLocalEntry(mid, cc, argAp, _, nil, localCC, config) and
localFlowBigStep(mid, node, false, apf, config, _) and localFlowBigStep(mid, node, false, apf, config, localCC) and
apf = ap.(AccessPathNil).getFront() apf = ap.(AccessPathNil).getFront()
) )
or or
exists(Node mid | exists(Node mid |
flowFwd(mid, _, _, apf, ap, config) and flowFwd(mid, _, _, apf, ap, config) and
jumpStep(mid, node, config) and jumpStep(mid, node, config) and
fromArg = false and cc instanceof CallContextAny and
argAp = TAccessPathNone() argAp = TAccessPathNone()
) )
or or
exists(Node mid, AccessPathNil nil | exists(Node mid, AccessPathNil nil |
flowFwd(mid, _, _, _, nil, config) and flowFwd(mid, _, _, _, nil, config) and
additionalJumpStep(mid, node, config) and additionalJumpStep(mid, node, config) and
fromArg = false and cc instanceof CallContextAny and
argAp = TAccessPathNone() and argAp = TAccessPathNone() and
ap = TNil(getNodeType(node)) and ap = TNil(getNodeType(node)) and
apf = ap.(AccessPathNil).getFront() apf = ap.(AccessPathNil).getFront()
@@ -1704,40 +1704,51 @@ private predicate flowFwd0(
) )
or or
// store // store
exists(TypedContent tc | flowFwdStore(node, tc, pop(tc, ap), apf, fromArg, argAp, config)) exists(TypedContent tc | flowFwdStore(node, tc, pop(tc, ap), apf, cc, argAp, config))
or or
// read // read
exists(TypedContent tc | exists(TypedContent tc |
flowFwdRead(node, _, push(tc, ap), apf, fromArg, argAp, config) and flowFwdRead(node, _, push(tc, ap), apf, cc, argAp, config) and
flowFwdConsCand(tc, apf, ap, config) flowFwdConsCand(tc, apf, ap, config)
) )
or or
// flow into a callable // flow into a callable
flowFwdIn(_, node, _, _, apf, ap, config) and flowFwdIn(_, node, cc, _, _, apf, ap, config) and
fromArg = true and
if flowCand(node, true, _, apf, config) if flowCand(node, true, _, apf, config)
then argAp = TAccessPathSome(ap) then argAp = TAccessPathSome(ap)
else argAp = TAccessPathNone() else argAp = TAccessPathNone()
or or
// flow out of a callable // flow out of a callable
exists(DataFlowCall call | exists(DataFlowCall call |
flowFwdOut(call, node, fromArg, argAp, apf, ap, config) and exists(CallContextNoCall innercc, DataFlowCallable c |
fromArg = false flowFwdOut(call, node, innercc, c, argAp, apf, ap, config) and
if reducedViableImplInReturn(c, call) then cc = TReturn(c, call) else cc = TAnyCallContext()
)
or or
exists(AccessPath argAp0 | exists(AccessPath argAp0 |
flowFwdOutFromArg(call, node, argAp0, apf, ap, config) and flowFwdOutFromArg(call, node, argAp0, apf, ap, config) and
flowFwdIsEntered(call, fromArg, argAp, argAp0, config) flowFwdIsEntered(call, cc, argAp, argAp0, config)
) )
) )
} }
pragma[nomagic]
private predicate flowFwdLocalEntry(
Node node, CallContext cc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap,
LocalCallContext localCC, Configuration config
) {
flowFwd(node, cc, argAp, apf, ap, config) and
localFlowEntry(node, config) and
localCC = getLocalCallContext(cc, node.getEnclosingCallable())
}
pragma[nomagic] pragma[nomagic]
private predicate flowFwdStore( private predicate flowFwdStore(
Node node, TypedContent tc, AccessPath ap0, AccessPathFront apf, boolean fromArg, Node node, TypedContent tc, AccessPath ap0, AccessPathFront apf, CallContext cc,
AccessPathOption argAp, Configuration config AccessPathOption argAp, Configuration config
) { ) {
exists(Node mid, AccessPathFront apf0 | exists(Node mid, AccessPathFront apf0 |
flowFwd(mid, fromArg, argAp, apf0, ap0, config) and flowFwd(mid, cc, argAp, apf0, ap0, config) and
flowFwdStore0(mid, tc, node, apf0, apf, config) flowFwdStore0(mid, tc, node, apf0, apf, config)
) )
} }
@@ -1764,20 +1775,20 @@ private predicate flowFwdStore0(
pragma[nomagic] pragma[nomagic]
private predicate flowFwdRead0( private predicate flowFwdRead0(
Node node1, TypedContent tc, AccessPathFrontHead apf0, AccessPath ap0, Node node2, Node node1, TypedContent tc, AccessPathFrontHead apf0, AccessPath ap0, Node node2, CallContext cc,
boolean fromArg, AccessPathOption argAp, Configuration config AccessPathOption argAp, Configuration config
) { ) {
flowFwd(node1, fromArg, argAp, apf0, ap0, config) and flowFwd(node1, cc, argAp, apf0, ap0, config) and
readCandFwd(node1, tc, apf0, node2, config) readCandFwd(node1, tc, apf0, node2, config)
} }
pragma[nomagic] pragma[nomagic]
private predicate flowFwdRead( private predicate flowFwdRead(
Node node, AccessPathFrontHead apf0, AccessPath ap0, AccessPathFront apf, boolean fromArg, Node node, AccessPathFrontHead apf0, AccessPath ap0, AccessPathFront apf, CallContext cc,
AccessPathOption argAp, Configuration config AccessPathOption argAp, Configuration config
) { ) {
exists(Node mid, TypedContent tc | exists(Node mid, TypedContent tc |
flowFwdRead0(mid, tc, apf0, ap0, node, fromArg, argAp, config) and flowFwdRead0(mid, tc, apf0, ap0, node, cc, argAp, config) and
flowCand(node, _, _, apf, unbind(config)) and flowCand(node, _, _, apf, unbind(config)) and
flowCandConsCand(tc, apf, unbind(config)) flowCandConsCand(tc, apf, unbind(config))
) )
@@ -1795,13 +1806,16 @@ private predicate flowFwdConsCand(
pragma[nomagic] pragma[nomagic]
private predicate flowFwdIn( private predicate flowFwdIn(
DataFlowCall call, ParameterNode p, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, DataFlowCall call, ParameterNode p, CallContext innercc, CallContext outercc,
AccessPath ap, Configuration config AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config
) { ) {
exists(ArgumentNode arg, boolean allowsFieldFlow | exists(ArgumentNode arg, boolean allowsFieldFlow, DataFlowCallable c |
flowFwd(arg, fromArg, argAp, apf, ap, config) and flowFwd(arg, outercc, argAp, apf, ap, config) and
flowIntoCallNodeCand2(call, arg, p, allowsFieldFlow, config) and flowIntoCallNodeCand2(call, arg, p, allowsFieldFlow, config) and
flowCand(p, _, _, _, unbind(config)) 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 ap instanceof AccessPathNil or allowsFieldFlow = true
) )
@@ -1809,13 +1823,19 @@ private predicate flowFwdIn(
pragma[nomagic] pragma[nomagic]
private predicate flowFwdOut( private predicate flowFwdOut(
DataFlowCall call, Node node, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, DataFlowCall call, Node node, CallContext innercc, DataFlowCallable innerc,
AccessPath ap, Configuration config AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config
) { ) {
exists(ReturnNodeExt ret, boolean allowsFieldFlow | exists(ReturnNodeExt ret, boolean allowsFieldFlow |
flowFwd(ret, fromArg, argAp, apf, ap, config) and flowFwd(ret, innercc, argAp, apf, ap, config) and
flowOutOfCallNodeCand2(call, ret, node, allowsFieldFlow, config) and flowOutOfCallNodeCand2(call, ret, node, allowsFieldFlow, config) and
flowCand(node, _, _, _, unbind(config)) innerc = ret.getEnclosingCallable() and
flowCand(node, _, _, _, unbind(config)) and
(
resolveReturn(innercc, innerc, call)
or
innercc.(CallContextCall).matchesCall(call)
)
| |
ap instanceof AccessPathNil or allowsFieldFlow = true ap instanceof AccessPathNil or allowsFieldFlow = true
) )
@@ -1826,7 +1846,7 @@ private predicate flowFwdOutFromArg(
DataFlowCall call, Node node, AccessPath argAp, AccessPathFront apf, AccessPath ap, DataFlowCall call, Node node, AccessPath argAp, AccessPathFront apf, AccessPath ap,
Configuration config Configuration config
) { ) {
flowFwdOut(call, node, true, TAccessPathSome(argAp), apf, ap, config) flowFwdOut(call, node, any(CallContextCall ccc), _, TAccessPathSome(argAp), apf, ap, config)
} }
/** /**
@@ -1834,10 +1854,10 @@ private predicate flowFwdOutFromArg(
*/ */
pragma[nomagic] pragma[nomagic]
private predicate flowFwdIsEntered( private predicate flowFwdIsEntered(
DataFlowCall call, boolean fromArg, AccessPathOption argAp, AccessPath ap, Configuration config DataFlowCall call, CallContext cc, AccessPathOption argAp, AccessPath ap, Configuration config
) { ) {
exists(ParameterNode p, AccessPathFront apf | exists(ParameterNode p, AccessPathFront apf |
flowFwdIn(call, p, fromArg, argAp, apf, ap, config) and flowFwdIn(call, p, _, cc, argAp, apf, ap, config) and
flowCand(p, true, TAccessPathFrontSome(_), apf, config) flowCand(p, true, TAccessPathFrontSome(_), apf, config)
) )
} }
@@ -1920,7 +1940,7 @@ private predicate flow0(
// flow out of a callable // flow out of a callable
flowOut(_, node, _, _, ap, config) and flowOut(_, node, _, _, ap, config) and
toReturn = true and toReturn = true and
if flowFwd(node, true, TAccessPathSome(_), _, ap, config) if flowFwd(node, any(CallContextCall ccc), TAccessPathSome(_), _, ap, config)
then returnAp = TAccessPathSome(ap) then returnAp = TAccessPathSome(ap)
else returnAp = TAccessPathNone() else returnAp = TAccessPathNone()
} }
@@ -2006,9 +2026,10 @@ private predicate flowIsReturned(
DataFlowCall call, boolean toReturn, AccessPathOption returnAp, AccessPath ap, DataFlowCall call, boolean toReturn, AccessPathOption returnAp, AccessPath ap,
Configuration config Configuration config
) { ) {
exists(ReturnNodeExt ret | exists(ReturnNodeExt ret, CallContextCall ccc |
flowOut(call, ret, toReturn, returnAp, ap, config) and flowOut(call, ret, toReturn, returnAp, ap, config) and
flowFwd(ret, true, TAccessPathSome(_), _, ap, config) flowFwd(ret, ccc, TAccessPathSome(_), _, ap, config) and
ccc.matchesCall(call)
) )
} }
@@ -2031,7 +2052,7 @@ private newtype TSummaryCtx =
exists(ReturnNodeExt ret, Configuration config, AccessPath ap0 | exists(ReturnNodeExt ret, Configuration config, AccessPath ap0 |
parameterFlow(p, ap, ret.getEnclosingCallable(), config) and parameterFlow(p, ap, ret.getEnclosingCallable(), config) and
flow(ret, true, TAccessPathSome(_), ap0, config) and flow(ret, true, TAccessPathSome(_), ap0, config) and
flowFwd(ret, true, TAccessPathSome(ap), _, ap0, config) flowFwd(ret, any(CallContextCall ccc), TAccessPathSome(ap), _, ap0, config)
) )
} }
@@ -2352,7 +2373,7 @@ private predicate pathOutOfCallable0(
) { ) {
pos = getReturnPosition(mid.getNode()) and pos = getReturnPosition(mid.getNode()) and
innercc = mid.getCallContext() and innercc = mid.getCallContext() and
not innercc instanceof CallContextCall and innercc instanceof CallContextNoCall and
ap = mid.getAp() and ap = mid.getAp() and
config = mid.getConfiguration() config = mid.getConfiguration()
} }
@@ -2867,7 +2888,7 @@ private module FlowExploration {
) { ) {
pos = getReturnPosition(mid.getNode()) and pos = getReturnPosition(mid.getNode()) and
innercc = mid.getCallContext() and innercc = mid.getCallContext() and
not innercc instanceof CallContextCall and innercc instanceof CallContextNoCall and
ap = mid.getAp() and ap = mid.getAp() and
config = mid.getConfiguration() config = mid.getConfiguration()
} }

View File

@@ -512,13 +512,19 @@ abstract class CallContext extends TCallContext {
abstract predicate relevantFor(DataFlowCallable callable); abstract predicate relevantFor(DataFlowCallable callable);
} }
class CallContextAny extends CallContext, TAnyCallContext { abstract class CallContextNoCall extends CallContext { }
class CallContextAny extends CallContextNoCall, TAnyCallContext {
override string toString() { result = "CcAny" } override string toString() { result = "CcAny" }
override predicate relevantFor(DataFlowCallable callable) { any() } override predicate relevantFor(DataFlowCallable callable) { any() }
} }
abstract class CallContextCall extends CallContext { } abstract class CallContextCall extends CallContext {
/** Holds if this call context may be `call`. */
bindingset[call]
abstract predicate matchesCall(DataFlowCall call);
}
class CallContextSpecificCall extends CallContextCall, TSpecificCall { class CallContextSpecificCall extends CallContextCall, TSpecificCall {
override string toString() { override string toString() {
@@ -529,6 +535,8 @@ class CallContextSpecificCall extends CallContextCall, TSpecificCall {
recordDataFlowCallSite(getCall(), callable) recordDataFlowCallSite(getCall(), callable)
} }
override predicate matchesCall(DataFlowCall call) { call = this.getCall() }
DataFlowCall getCall() { this = TSpecificCall(result) } DataFlowCall getCall() { this = TSpecificCall(result) }
} }
@@ -538,9 +546,11 @@ class CallContextSomeCall extends CallContextCall, TSomeCall {
override predicate relevantFor(DataFlowCallable callable) { override predicate relevantFor(DataFlowCallable callable) {
exists(ParameterNode p | p.getEnclosingCallable() = callable) exists(ParameterNode p | p.getEnclosingCallable() = callable)
} }
override predicate matchesCall(DataFlowCall call) { any() }
} }
class CallContextReturn extends CallContext, TReturn { class CallContextReturn extends CallContextNoCall, TReturn {
override string toString() { override string toString() {
exists(DataFlowCall call | this = TReturn(_, call) | result = "CcReturn(" + call + ")") exists(DataFlowCall call | this = TReturn(_, call) | result = "CcReturn(" + call + ")")
} }