Merge pull request #7232 from aschackmull/dataflow/perf

Data flow: Performance tuning
This commit is contained in:
Anders Schack-Mulligen
2021-11-25 15:01:01 +01:00
committed by GitHub
27 changed files with 3969 additions and 3888 deletions

View File

@@ -289,6 +289,7 @@ private predicate outBarrier(NodeEx node, Configuration config) {
)
}
pragma[nomagic]
private predicate fullBarrier(NodeEx node, Configuration config) {
exists(Node n | node.asNode() = n |
config.isBarrier(n)
@@ -307,11 +308,23 @@ private predicate fullBarrier(NodeEx node, Configuration config) {
}
pragma[nomagic]
private predicate sourceNode(NodeEx node, Configuration config) { config.isSource(node.asNode()) }
private predicate sourceNode(NodeEx node, Configuration config) {
config.isSource(node.asNode()) and
not fullBarrier(node, config)
}
pragma[nomagic]
private predicate sinkNode(NodeEx node, Configuration config) { config.isSink(node.asNode()) }
/** Provides the relevant barriers for a step from `node1` to `node2`. */
pragma[inline]
private predicate stepFilter(NodeEx node1, NodeEx node2, Configuration config) {
not outBarrier(node1, config) and
not inBarrier(node2, config) and
not fullBarrier(node1, config) and
not fullBarrier(node2, config)
}
/**
* Holds if data can flow in one local step from `node1` to `node2`.
*/
@@ -320,16 +333,14 @@ private predicate localFlowStep(NodeEx node1, NodeEx node2, Configuration config
node1.asNode() = n1 and
node2.asNode() = n2 and
simpleLocalFlowStepExt(n1, n2) and
not outBarrier(node1, config) and
not inBarrier(node2, config) and
not fullBarrier(node1, config) and
not fullBarrier(node2, config)
stepFilter(node1, node2, config)
)
or
exists(Node n |
config.allowImplicitRead(n, _) and
node1.asNode() = n and
node2.isImplicitReadNode(n, false)
node2.isImplicitReadNode(n, false) and
not fullBarrier(node1, config)
)
}
@@ -342,16 +353,14 @@ private predicate additionalLocalFlowStep(NodeEx node1, NodeEx node2, Configurat
node2.asNode() = n2 and
config.isAdditionalFlowStep(n1, n2) and
getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and
not outBarrier(node1, config) and
not inBarrier(node2, config) and
not fullBarrier(node1, config) and
not fullBarrier(node2, config)
stepFilter(node1, node2, config)
)
or
exists(Node n |
config.allowImplicitRead(n, _) and
node1.isImplicitReadNode(n, true) and
node2.asNode() = n
node2.asNode() = n and
not fullBarrier(node2, config)
)
}
@@ -363,10 +372,7 @@ private predicate jumpStep(NodeEx node1, NodeEx node2, Configuration config) {
node1.asNode() = n1 and
node2.asNode() = n2 and
jumpStepCached(n1, n2) and
not outBarrier(node1, config) and
not inBarrier(node2, config) and
not fullBarrier(node1, config) and
not fullBarrier(node2, config) and
stepFilter(node1, node2, config) and
not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext
)
}
@@ -380,16 +386,14 @@ private predicate additionalJumpStep(NodeEx node1, NodeEx node2, Configuration c
node2.asNode() = n2 and
config.isAdditionalFlowStep(n1, n2) and
getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and
not outBarrier(node1, config) and
not inBarrier(node2, config) and
not fullBarrier(node1, config) and
not fullBarrier(node2, config) and
stepFilter(node1, node2, config) and
not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext
)
}
private predicate read(NodeEx node1, Content c, NodeEx node2, Configuration config) {
read(node1.asNode(), c, node2.asNode())
read(node1.asNode(), c, node2.asNode()) and
stepFilter(node1, node2, config)
or
exists(Node n |
node2.isImplicitReadNode(n, true) and
@@ -402,7 +406,8 @@ private predicate store(
NodeEx node1, TypedContent tc, NodeEx node2, DataFlowType contentType, Configuration config
) {
store(node1.asNode(), tc, node2.asNode(), contentType) and
read(_, tc.getContent(), _, config)
read(_, tc.getContent(), _, config) and
stepFilter(node1, node2, config)
}
pragma[nomagic]
@@ -451,63 +456,59 @@ private module Stage1 {
* argument in a call.
*/
predicate fwdFlow(NodeEx node, Cc cc, Configuration config) {
not fullBarrier(node, config) and
(
sourceNode(node, config) and
if hasSourceCallCtx(config) then cc = true else cc = false
sourceNode(node, config) and
if hasSourceCallCtx(config) then cc = true else cc = false
or
exists(NodeEx mid |
fwdFlow(mid, cc, config) and
localFlowStep(mid, node, config)
)
or
exists(NodeEx mid |
fwdFlow(mid, cc, config) and
additionalLocalFlowStep(mid, node, config)
)
or
exists(NodeEx mid |
fwdFlow(mid, _, config) and
jumpStep(mid, node, config) and
cc = false
)
or
exists(NodeEx mid |
fwdFlow(mid, _, config) and
additionalJumpStep(mid, node, config) and
cc = false
)
or
// store
exists(NodeEx mid |
useFieldFlow(config) and
fwdFlow(mid, cc, config) and
store(mid, _, node, _, config)
)
or
// read
exists(Content c |
fwdFlowRead(c, node, cc, config) and
fwdFlowConsCand(c, config)
)
or
// flow into a callable
exists(NodeEx arg |
fwdFlow(arg, _, config) and
viableParamArgEx(_, node, arg) and
cc = true and
not fullBarrier(node, config)
)
or
// flow out of a callable
exists(DataFlowCall call |
fwdFlowOut(call, node, false, config) and
cc = false
or
exists(NodeEx mid |
fwdFlow(mid, cc, config) and
localFlowStep(mid, node, config)
)
or
exists(NodeEx mid |
fwdFlow(mid, cc, config) and
additionalLocalFlowStep(mid, node, config)
)
or
exists(NodeEx mid |
fwdFlow(mid, _, config) and
jumpStep(mid, node, config) and
cc = false
)
or
exists(NodeEx mid |
fwdFlow(mid, _, config) and
additionalJumpStep(mid, node, config) and
cc = false
)
or
// store
exists(NodeEx mid |
useFieldFlow(config) and
fwdFlow(mid, cc, config) and
store(mid, _, node, _, config) and
not outBarrier(mid, config)
)
or
// read
exists(Content c |
fwdFlowRead(c, node, cc, config) and
fwdFlowConsCand(c, config) and
not inBarrier(node, config)
)
or
// flow into a callable
exists(NodeEx arg |
fwdFlow(arg, _, config) and
viableParamArgEx(_, node, arg) and
cc = true
)
or
// flow out of a callable
exists(DataFlowCall call |
fwdFlowOut(call, node, false, config) and
cc = false
or
fwdFlowOutFromArg(call, node, config) and
fwdFlowIsEntered(call, cc, config)
)
fwdFlowOutFromArg(call, node, config) and
fwdFlowIsEntered(call, cc, config)
)
}
@@ -547,7 +548,8 @@ private module Stage1 {
private predicate fwdFlowOut(DataFlowCall call, NodeEx out, Cc cc, Configuration config) {
exists(ReturnPosition pos |
fwdFlowReturnPosition(pos, cc, config) and
viableReturnPosOutEx(call, pos, out)
viableReturnPosOutEx(call, pos, out) and
not fullBarrier(out, config)
)
}
@@ -773,6 +775,7 @@ private module Stage1 {
* Holds if flow may enter through `p` and reach a return node making `p` a
* candidate for the origin of a summary.
*/
pragma[nomagic]
predicate parameterMayFlowThrough(ParamNodeEx p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnKindExt kind |
throughFlowNodeCand(p, config) and
@@ -1019,12 +1022,14 @@ private module Stage2 {
pragma[nomagic]
private predicate flowThroughOutOfCall(
DataFlowCall call, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow, Configuration config
DataFlowCall call, CcCall ccc, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow,
Configuration config
) {
flowOutOfCall(call, ret, out, allowsFieldFlow, pragma[only_bind_into](config)) and
PrevStage::callMayFlowThroughRev(call, pragma[only_bind_into](config)) and
PrevStage::parameterMayFlowThrough(_, ret.getEnclosingCallable(), _,
pragma[only_bind_into](config))
pragma[only_bind_into](config)) and
ccc.matchesCall(call)
}
/**
@@ -1142,9 +1147,8 @@ private module Stage2 {
exists(ArgNodeEx arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc)
|
ap instanceof ApNil or allowsFieldFlow = true
innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc) and
if allowsFieldFlow = false then ap instanceof ApNil else any()
)
}
@@ -1159,9 +1163,8 @@ private module Stage2 {
fwdFlow(ret, innercc, argAp, ap, config) and
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
inner = ret.getEnclosingCallable() and
ccOut = getCallContextReturn(inner, call, innercc)
|
ap instanceof ApNil or allowsFieldFlow = true
ccOut = getCallContextReturn(inner, call, innercc) and
if allowsFieldFlow = false then ap instanceof ApNil else any()
)
}
@@ -1171,10 +1174,8 @@ private module Stage2 {
) {
exists(RetNodeEx ret, boolean allowsFieldFlow, CcCall ccc |
fwdFlow(ret, ccc, apSome(argAp), ap, config) and
flowThroughOutOfCall(call, ret, out, allowsFieldFlow, config) and
ccc.matchesCall(call)
|
ap instanceof ApNil or allowsFieldFlow = true
flowThroughOutOfCall(call, ccc, ret, out, allowsFieldFlow, config) and
if allowsFieldFlow = false then ap instanceof ApNil else any()
)
}
@@ -1230,6 +1231,11 @@ private module Stage2 {
callMayFlowThroughFwd(call, pragma[only_bind_into](config))
}
pragma[nomagic]
private predicate returnNodeMayFlowThrough(RetNodeEx ret, Ap ap, Configuration config) {
fwdFlow(ret, any(CcCall ccc), apSome(_), ap, config)
}
/**
* Holds if `node` with access path `ap` is part of a path from a source to a
* sink in the configuration `config`.
@@ -1306,7 +1312,7 @@ private module Stage2 {
// flow out of a callable
revFlowOut(_, node, _, _, ap, config) and
toReturn = true and
if fwdFlow(node, any(CcCall ccc), apSome(_), ap, config)
if returnNodeMayFlowThrough(node, ap, config)
then returnAp = apSome(ap)
else returnAp = apNone()
}
@@ -1341,9 +1347,8 @@ private module Stage2 {
) {
exists(NodeEx out, boolean allowsFieldFlow |
revFlow(out, toReturn, returnAp, ap, config) and
flowOutOfCall(call, ret, out, allowsFieldFlow, config)
|
ap instanceof ApNil or allowsFieldFlow = true
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
if allowsFieldFlow = false then ap instanceof ApNil else any()
)
}
@@ -1353,9 +1358,8 @@ private module Stage2 {
) {
exists(ParamNodeEx p, boolean allowsFieldFlow |
revFlow(p, false, returnAp, ap, config) and
flowIntoCall(_, arg, p, allowsFieldFlow, config)
|
ap instanceof ApNil or allowsFieldFlow = true
flowIntoCall(_, arg, p, allowsFieldFlow, config) and
if allowsFieldFlow = false then ap instanceof ApNil else any()
)
}
@@ -1365,9 +1369,8 @@ private module Stage2 {
) {
exists(ParamNodeEx p, boolean allowsFieldFlow |
revFlow(p, true, apSome(returnAp), ap, config) and
flowThroughIntoCall(call, arg, p, allowsFieldFlow, config)
|
ap instanceof ApNil or allowsFieldFlow = true
flowThroughIntoCall(call, arg, p, allowsFieldFlow, config) and
if allowsFieldFlow = false then ap instanceof ApNil else any()
)
}
@@ -1707,12 +1710,14 @@ private module Stage3 {
pragma[nomagic]
private predicate flowThroughOutOfCall(
DataFlowCall call, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow, Configuration config
DataFlowCall call, CcCall ccc, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow,
Configuration config
) {
flowOutOfCall(call, ret, out, allowsFieldFlow, pragma[only_bind_into](config)) and
PrevStage::callMayFlowThroughRev(call, pragma[only_bind_into](config)) and
PrevStage::parameterMayFlowThrough(_, ret.getEnclosingCallable(), _,
pragma[only_bind_into](config))
pragma[only_bind_into](config)) and
ccc.matchesCall(call)
}
/**
@@ -1837,9 +1842,8 @@ private module Stage3 {
exists(ArgNodeEx arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc)
|
ap instanceof ApNil or allowsFieldFlow = true
innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc) and
if allowsFieldFlow = false then ap instanceof ApNil else any()
)
}
@@ -1854,9 +1858,8 @@ private module Stage3 {
fwdFlow(ret, innercc, argAp, ap, config) and
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
inner = ret.getEnclosingCallable() and
ccOut = getCallContextReturn(inner, call, innercc)
|
ap instanceof ApNil or allowsFieldFlow = true
ccOut = getCallContextReturn(inner, call, innercc) and
if allowsFieldFlow = false then ap instanceof ApNil else any()
)
}
@@ -1866,10 +1869,8 @@ private module Stage3 {
) {
exists(RetNodeEx ret, boolean allowsFieldFlow, CcCall ccc |
fwdFlow(ret, ccc, apSome(argAp), ap, config) and
flowThroughOutOfCall(call, ret, out, allowsFieldFlow, config) and
ccc.matchesCall(call)
|
ap instanceof ApNil or allowsFieldFlow = true
flowThroughOutOfCall(call, ccc, ret, out, allowsFieldFlow, config) and
if allowsFieldFlow = false then ap instanceof ApNil else any()
)
}
@@ -1925,6 +1926,11 @@ private module Stage3 {
callMayFlowThroughFwd(call, pragma[only_bind_into](config))
}
pragma[nomagic]
private predicate returnNodeMayFlowThrough(RetNodeEx ret, Ap ap, Configuration config) {
fwdFlow(ret, any(CcCall ccc), apSome(_), ap, config)
}
/**
* Holds if `node` with access path `ap` is part of a path from a source to a
* sink in the configuration `config`.
@@ -2001,7 +2007,7 @@ private module Stage3 {
// flow out of a callable
revFlowOut(_, node, _, _, ap, config) and
toReturn = true and
if fwdFlow(node, any(CcCall ccc), apSome(_), ap, config)
if returnNodeMayFlowThrough(node, ap, config)
then returnAp = apSome(ap)
else returnAp = apNone()
}
@@ -2036,9 +2042,8 @@ private module Stage3 {
) {
exists(NodeEx out, boolean allowsFieldFlow |
revFlow(out, toReturn, returnAp, ap, config) and
flowOutOfCall(call, ret, out, allowsFieldFlow, config)
|
ap instanceof ApNil or allowsFieldFlow = true
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
if allowsFieldFlow = false then ap instanceof ApNil else any()
)
}
@@ -2048,9 +2053,8 @@ private module Stage3 {
) {
exists(ParamNodeEx p, boolean allowsFieldFlow |
revFlow(p, false, returnAp, ap, config) and
flowIntoCall(_, arg, p, allowsFieldFlow, config)
|
ap instanceof ApNil or allowsFieldFlow = true
flowIntoCall(_, arg, p, allowsFieldFlow, config) and
if allowsFieldFlow = false then ap instanceof ApNil else any()
)
}
@@ -2060,9 +2064,8 @@ private module Stage3 {
) {
exists(ParamNodeEx p, boolean allowsFieldFlow |
revFlow(p, true, apSome(returnAp), ap, config) and
flowThroughIntoCall(call, arg, p, allowsFieldFlow, config)
|
ap instanceof ApNil or allowsFieldFlow = true
flowThroughIntoCall(call, arg, p, allowsFieldFlow, config) and
if allowsFieldFlow = false then ap instanceof ApNil else any()
)
}
@@ -2473,12 +2476,14 @@ private module Stage4 {
pragma[nomagic]
private predicate flowThroughOutOfCall(
DataFlowCall call, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow, Configuration config
DataFlowCall call, CcCall ccc, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow,
Configuration config
) {
flowOutOfCall(call, ret, out, allowsFieldFlow, pragma[only_bind_into](config)) and
PrevStage::callMayFlowThroughRev(call, pragma[only_bind_into](config)) and
PrevStage::parameterMayFlowThrough(_, ret.getEnclosingCallable(), _,
pragma[only_bind_into](config))
pragma[only_bind_into](config)) and
ccc.matchesCall(call)
}
/**
@@ -2603,9 +2608,8 @@ private module Stage4 {
exists(ArgNodeEx arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc)
|
ap instanceof ApNil or allowsFieldFlow = true
innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc) and
if allowsFieldFlow = false then ap instanceof ApNil else any()
)
}
@@ -2620,9 +2624,8 @@ private module Stage4 {
fwdFlow(ret, innercc, argAp, ap, config) and
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
inner = ret.getEnclosingCallable() and
ccOut = getCallContextReturn(inner, call, innercc)
|
ap instanceof ApNil or allowsFieldFlow = true
ccOut = getCallContextReturn(inner, call, innercc) and
if allowsFieldFlow = false then ap instanceof ApNil else any()
)
}
@@ -2632,10 +2635,8 @@ private module Stage4 {
) {
exists(RetNodeEx ret, boolean allowsFieldFlow, CcCall ccc |
fwdFlow(ret, ccc, apSome(argAp), ap, config) and
flowThroughOutOfCall(call, ret, out, allowsFieldFlow, config) and
ccc.matchesCall(call)
|
ap instanceof ApNil or allowsFieldFlow = true
flowThroughOutOfCall(call, ccc, ret, out, allowsFieldFlow, config) and
if allowsFieldFlow = false then ap instanceof ApNil else any()
)
}
@@ -2691,6 +2692,11 @@ private module Stage4 {
callMayFlowThroughFwd(call, pragma[only_bind_into](config))
}
pragma[nomagic]
private predicate returnNodeMayFlowThrough(RetNodeEx ret, Ap ap, Configuration config) {
fwdFlow(ret, any(CcCall ccc), apSome(_), ap, config)
}
/**
* Holds if `node` with access path `ap` is part of a path from a source to a
* sink in the configuration `config`.
@@ -2767,7 +2773,7 @@ private module Stage4 {
// flow out of a callable
revFlowOut(_, node, _, _, ap, config) and
toReturn = true and
if fwdFlow(node, any(CcCall ccc), apSome(_), ap, config)
if returnNodeMayFlowThrough(node, ap, config)
then returnAp = apSome(ap)
else returnAp = apNone()
}
@@ -2802,9 +2808,8 @@ private module Stage4 {
) {
exists(NodeEx out, boolean allowsFieldFlow |
revFlow(out, toReturn, returnAp, ap, config) and
flowOutOfCall(call, ret, out, allowsFieldFlow, config)
|
ap instanceof ApNil or allowsFieldFlow = true
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
if allowsFieldFlow = false then ap instanceof ApNil else any()
)
}
@@ -2814,9 +2819,8 @@ private module Stage4 {
) {
exists(ParamNodeEx p, boolean allowsFieldFlow |
revFlow(p, false, returnAp, ap, config) and
flowIntoCall(_, arg, p, allowsFieldFlow, config)
|
ap instanceof ApNil or allowsFieldFlow = true
flowIntoCall(_, arg, p, allowsFieldFlow, config) and
if allowsFieldFlow = false then ap instanceof ApNil else any()
)
}
@@ -2826,9 +2830,8 @@ private module Stage4 {
) {
exists(ParamNodeEx p, boolean allowsFieldFlow |
revFlow(p, true, apSome(returnAp), ap, config) and
flowThroughIntoCall(call, arg, p, allowsFieldFlow, config)
|
ap instanceof ApNil or allowsFieldFlow = true
flowThroughIntoCall(call, arg, p, allowsFieldFlow, config) and
if allowsFieldFlow = false then ap instanceof ApNil else any()
)
}

View File

@@ -289,6 +289,7 @@ private predicate outBarrier(NodeEx node, Configuration config) {
)
}
pragma[nomagic]
private predicate fullBarrier(NodeEx node, Configuration config) {
exists(Node n | node.asNode() = n |
config.isBarrier(n)
@@ -307,11 +308,23 @@ private predicate fullBarrier(NodeEx node, Configuration config) {
}
pragma[nomagic]
private predicate sourceNode(NodeEx node, Configuration config) { config.isSource(node.asNode()) }
private predicate sourceNode(NodeEx node, Configuration config) {
config.isSource(node.asNode()) and
not fullBarrier(node, config)
}
pragma[nomagic]
private predicate sinkNode(NodeEx node, Configuration config) { config.isSink(node.asNode()) }
/** Provides the relevant barriers for a step from `node1` to `node2`. */
pragma[inline]
private predicate stepFilter(NodeEx node1, NodeEx node2, Configuration config) {
not outBarrier(node1, config) and
not inBarrier(node2, config) and
not fullBarrier(node1, config) and
not fullBarrier(node2, config)
}
/**
* Holds if data can flow in one local step from `node1` to `node2`.
*/
@@ -320,16 +333,14 @@ private predicate localFlowStep(NodeEx node1, NodeEx node2, Configuration config
node1.asNode() = n1 and
node2.asNode() = n2 and
simpleLocalFlowStepExt(n1, n2) and
not outBarrier(node1, config) and
not inBarrier(node2, config) and
not fullBarrier(node1, config) and
not fullBarrier(node2, config)
stepFilter(node1, node2, config)
)
or
exists(Node n |
config.allowImplicitRead(n, _) and
node1.asNode() = n and
node2.isImplicitReadNode(n, false)
node2.isImplicitReadNode(n, false) and
not fullBarrier(node1, config)
)
}
@@ -342,16 +353,14 @@ private predicate additionalLocalFlowStep(NodeEx node1, NodeEx node2, Configurat
node2.asNode() = n2 and
config.isAdditionalFlowStep(n1, n2) and
getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and
not outBarrier(node1, config) and
not inBarrier(node2, config) and
not fullBarrier(node1, config) and
not fullBarrier(node2, config)
stepFilter(node1, node2, config)
)
or
exists(Node n |
config.allowImplicitRead(n, _) and
node1.isImplicitReadNode(n, true) and
node2.asNode() = n
node2.asNode() = n and
not fullBarrier(node2, config)
)
}
@@ -363,10 +372,7 @@ private predicate jumpStep(NodeEx node1, NodeEx node2, Configuration config) {
node1.asNode() = n1 and
node2.asNode() = n2 and
jumpStepCached(n1, n2) and
not outBarrier(node1, config) and
not inBarrier(node2, config) and
not fullBarrier(node1, config) and
not fullBarrier(node2, config) and
stepFilter(node1, node2, config) and
not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext
)
}
@@ -380,16 +386,14 @@ private predicate additionalJumpStep(NodeEx node1, NodeEx node2, Configuration c
node2.asNode() = n2 and
config.isAdditionalFlowStep(n1, n2) and
getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and
not outBarrier(node1, config) and
not inBarrier(node2, config) and
not fullBarrier(node1, config) and
not fullBarrier(node2, config) and
stepFilter(node1, node2, config) and
not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext
)
}
private predicate read(NodeEx node1, Content c, NodeEx node2, Configuration config) {
read(node1.asNode(), c, node2.asNode())
read(node1.asNode(), c, node2.asNode()) and
stepFilter(node1, node2, config)
or
exists(Node n |
node2.isImplicitReadNode(n, true) and
@@ -402,7 +406,8 @@ private predicate store(
NodeEx node1, TypedContent tc, NodeEx node2, DataFlowType contentType, Configuration config
) {
store(node1.asNode(), tc, node2.asNode(), contentType) and
read(_, tc.getContent(), _, config)
read(_, tc.getContent(), _, config) and
stepFilter(node1, node2, config)
}
pragma[nomagic]
@@ -451,63 +456,59 @@ private module Stage1 {
* argument in a call.
*/
predicate fwdFlow(NodeEx node, Cc cc, Configuration config) {
not fullBarrier(node, config) and
(
sourceNode(node, config) and
if hasSourceCallCtx(config) then cc = true else cc = false
sourceNode(node, config) and
if hasSourceCallCtx(config) then cc = true else cc = false
or
exists(NodeEx mid |
fwdFlow(mid, cc, config) and
localFlowStep(mid, node, config)
)
or
exists(NodeEx mid |
fwdFlow(mid, cc, config) and
additionalLocalFlowStep(mid, node, config)
)
or
exists(NodeEx mid |
fwdFlow(mid, _, config) and
jumpStep(mid, node, config) and
cc = false
)
or
exists(NodeEx mid |
fwdFlow(mid, _, config) and
additionalJumpStep(mid, node, config) and
cc = false
)
or
// store
exists(NodeEx mid |
useFieldFlow(config) and
fwdFlow(mid, cc, config) and
store(mid, _, node, _, config)
)
or
// read
exists(Content c |
fwdFlowRead(c, node, cc, config) and
fwdFlowConsCand(c, config)
)
or
// flow into a callable
exists(NodeEx arg |
fwdFlow(arg, _, config) and
viableParamArgEx(_, node, arg) and
cc = true and
not fullBarrier(node, config)
)
or
// flow out of a callable
exists(DataFlowCall call |
fwdFlowOut(call, node, false, config) and
cc = false
or
exists(NodeEx mid |
fwdFlow(mid, cc, config) and
localFlowStep(mid, node, config)
)
or
exists(NodeEx mid |
fwdFlow(mid, cc, config) and
additionalLocalFlowStep(mid, node, config)
)
or
exists(NodeEx mid |
fwdFlow(mid, _, config) and
jumpStep(mid, node, config) and
cc = false
)
or
exists(NodeEx mid |
fwdFlow(mid, _, config) and
additionalJumpStep(mid, node, config) and
cc = false
)
or
// store
exists(NodeEx mid |
useFieldFlow(config) and
fwdFlow(mid, cc, config) and
store(mid, _, node, _, config) and
not outBarrier(mid, config)
)
or
// read
exists(Content c |
fwdFlowRead(c, node, cc, config) and
fwdFlowConsCand(c, config) and
not inBarrier(node, config)
)
or
// flow into a callable
exists(NodeEx arg |
fwdFlow(arg, _, config) and
viableParamArgEx(_, node, arg) and
cc = true
)
or
// flow out of a callable
exists(DataFlowCall call |
fwdFlowOut(call, node, false, config) and
cc = false
or
fwdFlowOutFromArg(call, node, config) and
fwdFlowIsEntered(call, cc, config)
)
fwdFlowOutFromArg(call, node, config) and
fwdFlowIsEntered(call, cc, config)
)
}
@@ -547,7 +548,8 @@ private module Stage1 {
private predicate fwdFlowOut(DataFlowCall call, NodeEx out, Cc cc, Configuration config) {
exists(ReturnPosition pos |
fwdFlowReturnPosition(pos, cc, config) and
viableReturnPosOutEx(call, pos, out)
viableReturnPosOutEx(call, pos, out) and
not fullBarrier(out, config)
)
}
@@ -773,6 +775,7 @@ private module Stage1 {
* Holds if flow may enter through `p` and reach a return node making `p` a
* candidate for the origin of a summary.
*/
pragma[nomagic]
predicate parameterMayFlowThrough(ParamNodeEx p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnKindExt kind |
throughFlowNodeCand(p, config) and
@@ -1019,12 +1022,14 @@ private module Stage2 {
pragma[nomagic]
private predicate flowThroughOutOfCall(
DataFlowCall call, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow, Configuration config
DataFlowCall call, CcCall ccc, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow,
Configuration config
) {
flowOutOfCall(call, ret, out, allowsFieldFlow, pragma[only_bind_into](config)) and
PrevStage::callMayFlowThroughRev(call, pragma[only_bind_into](config)) and
PrevStage::parameterMayFlowThrough(_, ret.getEnclosingCallable(), _,
pragma[only_bind_into](config))
pragma[only_bind_into](config)) and
ccc.matchesCall(call)
}
/**
@@ -1142,9 +1147,8 @@ private module Stage2 {
exists(ArgNodeEx arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc)
|
ap instanceof ApNil or allowsFieldFlow = true
innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc) and
if allowsFieldFlow = false then ap instanceof ApNil else any()
)
}
@@ -1159,9 +1163,8 @@ private module Stage2 {
fwdFlow(ret, innercc, argAp, ap, config) and
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
inner = ret.getEnclosingCallable() and
ccOut = getCallContextReturn(inner, call, innercc)
|
ap instanceof ApNil or allowsFieldFlow = true
ccOut = getCallContextReturn(inner, call, innercc) and
if allowsFieldFlow = false then ap instanceof ApNil else any()
)
}
@@ -1171,10 +1174,8 @@ private module Stage2 {
) {
exists(RetNodeEx ret, boolean allowsFieldFlow, CcCall ccc |
fwdFlow(ret, ccc, apSome(argAp), ap, config) and
flowThroughOutOfCall(call, ret, out, allowsFieldFlow, config) and
ccc.matchesCall(call)
|
ap instanceof ApNil or allowsFieldFlow = true
flowThroughOutOfCall(call, ccc, ret, out, allowsFieldFlow, config) and
if allowsFieldFlow = false then ap instanceof ApNil else any()
)
}
@@ -1230,6 +1231,11 @@ private module Stage2 {
callMayFlowThroughFwd(call, pragma[only_bind_into](config))
}
pragma[nomagic]
private predicate returnNodeMayFlowThrough(RetNodeEx ret, Ap ap, Configuration config) {
fwdFlow(ret, any(CcCall ccc), apSome(_), ap, config)
}
/**
* Holds if `node` with access path `ap` is part of a path from a source to a
* sink in the configuration `config`.
@@ -1306,7 +1312,7 @@ private module Stage2 {
// flow out of a callable
revFlowOut(_, node, _, _, ap, config) and
toReturn = true and
if fwdFlow(node, any(CcCall ccc), apSome(_), ap, config)
if returnNodeMayFlowThrough(node, ap, config)
then returnAp = apSome(ap)
else returnAp = apNone()
}
@@ -1341,9 +1347,8 @@ private module Stage2 {
) {
exists(NodeEx out, boolean allowsFieldFlow |
revFlow(out, toReturn, returnAp, ap, config) and
flowOutOfCall(call, ret, out, allowsFieldFlow, config)
|
ap instanceof ApNil or allowsFieldFlow = true
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
if allowsFieldFlow = false then ap instanceof ApNil else any()
)
}
@@ -1353,9 +1358,8 @@ private module Stage2 {
) {
exists(ParamNodeEx p, boolean allowsFieldFlow |
revFlow(p, false, returnAp, ap, config) and
flowIntoCall(_, arg, p, allowsFieldFlow, config)
|
ap instanceof ApNil or allowsFieldFlow = true
flowIntoCall(_, arg, p, allowsFieldFlow, config) and
if allowsFieldFlow = false then ap instanceof ApNil else any()
)
}
@@ -1365,9 +1369,8 @@ private module Stage2 {
) {
exists(ParamNodeEx p, boolean allowsFieldFlow |
revFlow(p, true, apSome(returnAp), ap, config) and
flowThroughIntoCall(call, arg, p, allowsFieldFlow, config)
|
ap instanceof ApNil or allowsFieldFlow = true
flowThroughIntoCall(call, arg, p, allowsFieldFlow, config) and
if allowsFieldFlow = false then ap instanceof ApNil else any()
)
}
@@ -1707,12 +1710,14 @@ private module Stage3 {
pragma[nomagic]
private predicate flowThroughOutOfCall(
DataFlowCall call, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow, Configuration config
DataFlowCall call, CcCall ccc, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow,
Configuration config
) {
flowOutOfCall(call, ret, out, allowsFieldFlow, pragma[only_bind_into](config)) and
PrevStage::callMayFlowThroughRev(call, pragma[only_bind_into](config)) and
PrevStage::parameterMayFlowThrough(_, ret.getEnclosingCallable(), _,
pragma[only_bind_into](config))
pragma[only_bind_into](config)) and
ccc.matchesCall(call)
}
/**
@@ -1837,9 +1842,8 @@ private module Stage3 {
exists(ArgNodeEx arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc)
|
ap instanceof ApNil or allowsFieldFlow = true
innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc) and
if allowsFieldFlow = false then ap instanceof ApNil else any()
)
}
@@ -1854,9 +1858,8 @@ private module Stage3 {
fwdFlow(ret, innercc, argAp, ap, config) and
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
inner = ret.getEnclosingCallable() and
ccOut = getCallContextReturn(inner, call, innercc)
|
ap instanceof ApNil or allowsFieldFlow = true
ccOut = getCallContextReturn(inner, call, innercc) and
if allowsFieldFlow = false then ap instanceof ApNil else any()
)
}
@@ -1866,10 +1869,8 @@ private module Stage3 {
) {
exists(RetNodeEx ret, boolean allowsFieldFlow, CcCall ccc |
fwdFlow(ret, ccc, apSome(argAp), ap, config) and
flowThroughOutOfCall(call, ret, out, allowsFieldFlow, config) and
ccc.matchesCall(call)
|
ap instanceof ApNil or allowsFieldFlow = true
flowThroughOutOfCall(call, ccc, ret, out, allowsFieldFlow, config) and
if allowsFieldFlow = false then ap instanceof ApNil else any()
)
}
@@ -1925,6 +1926,11 @@ private module Stage3 {
callMayFlowThroughFwd(call, pragma[only_bind_into](config))
}
pragma[nomagic]
private predicate returnNodeMayFlowThrough(RetNodeEx ret, Ap ap, Configuration config) {
fwdFlow(ret, any(CcCall ccc), apSome(_), ap, config)
}
/**
* Holds if `node` with access path `ap` is part of a path from a source to a
* sink in the configuration `config`.
@@ -2001,7 +2007,7 @@ private module Stage3 {
// flow out of a callable
revFlowOut(_, node, _, _, ap, config) and
toReturn = true and
if fwdFlow(node, any(CcCall ccc), apSome(_), ap, config)
if returnNodeMayFlowThrough(node, ap, config)
then returnAp = apSome(ap)
else returnAp = apNone()
}
@@ -2036,9 +2042,8 @@ private module Stage3 {
) {
exists(NodeEx out, boolean allowsFieldFlow |
revFlow(out, toReturn, returnAp, ap, config) and
flowOutOfCall(call, ret, out, allowsFieldFlow, config)
|
ap instanceof ApNil or allowsFieldFlow = true
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
if allowsFieldFlow = false then ap instanceof ApNil else any()
)
}
@@ -2048,9 +2053,8 @@ private module Stage3 {
) {
exists(ParamNodeEx p, boolean allowsFieldFlow |
revFlow(p, false, returnAp, ap, config) and
flowIntoCall(_, arg, p, allowsFieldFlow, config)
|
ap instanceof ApNil or allowsFieldFlow = true
flowIntoCall(_, arg, p, allowsFieldFlow, config) and
if allowsFieldFlow = false then ap instanceof ApNil else any()
)
}
@@ -2060,9 +2064,8 @@ private module Stage3 {
) {
exists(ParamNodeEx p, boolean allowsFieldFlow |
revFlow(p, true, apSome(returnAp), ap, config) and
flowThroughIntoCall(call, arg, p, allowsFieldFlow, config)
|
ap instanceof ApNil or allowsFieldFlow = true
flowThroughIntoCall(call, arg, p, allowsFieldFlow, config) and
if allowsFieldFlow = false then ap instanceof ApNil else any()
)
}
@@ -2473,12 +2476,14 @@ private module Stage4 {
pragma[nomagic]
private predicate flowThroughOutOfCall(
DataFlowCall call, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow, Configuration config
DataFlowCall call, CcCall ccc, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow,
Configuration config
) {
flowOutOfCall(call, ret, out, allowsFieldFlow, pragma[only_bind_into](config)) and
PrevStage::callMayFlowThroughRev(call, pragma[only_bind_into](config)) and
PrevStage::parameterMayFlowThrough(_, ret.getEnclosingCallable(), _,
pragma[only_bind_into](config))
pragma[only_bind_into](config)) and
ccc.matchesCall(call)
}
/**
@@ -2603,9 +2608,8 @@ private module Stage4 {
exists(ArgNodeEx arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc)
|
ap instanceof ApNil or allowsFieldFlow = true
innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc) and
if allowsFieldFlow = false then ap instanceof ApNil else any()
)
}
@@ -2620,9 +2624,8 @@ private module Stage4 {
fwdFlow(ret, innercc, argAp, ap, config) and
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
inner = ret.getEnclosingCallable() and
ccOut = getCallContextReturn(inner, call, innercc)
|
ap instanceof ApNil or allowsFieldFlow = true
ccOut = getCallContextReturn(inner, call, innercc) and
if allowsFieldFlow = false then ap instanceof ApNil else any()
)
}
@@ -2632,10 +2635,8 @@ private module Stage4 {
) {
exists(RetNodeEx ret, boolean allowsFieldFlow, CcCall ccc |
fwdFlow(ret, ccc, apSome(argAp), ap, config) and
flowThroughOutOfCall(call, ret, out, allowsFieldFlow, config) and
ccc.matchesCall(call)
|
ap instanceof ApNil or allowsFieldFlow = true
flowThroughOutOfCall(call, ccc, ret, out, allowsFieldFlow, config) and
if allowsFieldFlow = false then ap instanceof ApNil else any()
)
}
@@ -2691,6 +2692,11 @@ private module Stage4 {
callMayFlowThroughFwd(call, pragma[only_bind_into](config))
}
pragma[nomagic]
private predicate returnNodeMayFlowThrough(RetNodeEx ret, Ap ap, Configuration config) {
fwdFlow(ret, any(CcCall ccc), apSome(_), ap, config)
}
/**
* Holds if `node` with access path `ap` is part of a path from a source to a
* sink in the configuration `config`.
@@ -2767,7 +2773,7 @@ private module Stage4 {
// flow out of a callable
revFlowOut(_, node, _, _, ap, config) and
toReturn = true and
if fwdFlow(node, any(CcCall ccc), apSome(_), ap, config)
if returnNodeMayFlowThrough(node, ap, config)
then returnAp = apSome(ap)
else returnAp = apNone()
}
@@ -2802,9 +2808,8 @@ private module Stage4 {
) {
exists(NodeEx out, boolean allowsFieldFlow |
revFlow(out, toReturn, returnAp, ap, config) and
flowOutOfCall(call, ret, out, allowsFieldFlow, config)
|
ap instanceof ApNil or allowsFieldFlow = true
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
if allowsFieldFlow = false then ap instanceof ApNil else any()
)
}
@@ -2814,9 +2819,8 @@ private module Stage4 {
) {
exists(ParamNodeEx p, boolean allowsFieldFlow |
revFlow(p, false, returnAp, ap, config) and
flowIntoCall(_, arg, p, allowsFieldFlow, config)
|
ap instanceof ApNil or allowsFieldFlow = true
flowIntoCall(_, arg, p, allowsFieldFlow, config) and
if allowsFieldFlow = false then ap instanceof ApNil else any()
)
}
@@ -2826,9 +2830,8 @@ private module Stage4 {
) {
exists(ParamNodeEx p, boolean allowsFieldFlow |
revFlow(p, true, apSome(returnAp), ap, config) and
flowThroughIntoCall(call, arg, p, allowsFieldFlow, config)
|
ap instanceof ApNil or allowsFieldFlow = true
flowThroughIntoCall(call, arg, p, allowsFieldFlow, config) and
if allowsFieldFlow = false then ap instanceof ApNil else any()
)
}

View File

@@ -289,6 +289,7 @@ private predicate outBarrier(NodeEx node, Configuration config) {
)
}
pragma[nomagic]
private predicate fullBarrier(NodeEx node, Configuration config) {
exists(Node n | node.asNode() = n |
config.isBarrier(n)
@@ -307,11 +308,23 @@ private predicate fullBarrier(NodeEx node, Configuration config) {
}
pragma[nomagic]
private predicate sourceNode(NodeEx node, Configuration config) { config.isSource(node.asNode()) }
private predicate sourceNode(NodeEx node, Configuration config) {
config.isSource(node.asNode()) and
not fullBarrier(node, config)
}
pragma[nomagic]
private predicate sinkNode(NodeEx node, Configuration config) { config.isSink(node.asNode()) }
/** Provides the relevant barriers for a step from `node1` to `node2`. */
pragma[inline]
private predicate stepFilter(NodeEx node1, NodeEx node2, Configuration config) {
not outBarrier(node1, config) and
not inBarrier(node2, config) and
not fullBarrier(node1, config) and
not fullBarrier(node2, config)
}
/**
* Holds if data can flow in one local step from `node1` to `node2`.
*/
@@ -320,16 +333,14 @@ private predicate localFlowStep(NodeEx node1, NodeEx node2, Configuration config
node1.asNode() = n1 and
node2.asNode() = n2 and
simpleLocalFlowStepExt(n1, n2) and
not outBarrier(node1, config) and
not inBarrier(node2, config) and
not fullBarrier(node1, config) and
not fullBarrier(node2, config)
stepFilter(node1, node2, config)
)
or
exists(Node n |
config.allowImplicitRead(n, _) and
node1.asNode() = n and
node2.isImplicitReadNode(n, false)
node2.isImplicitReadNode(n, false) and
not fullBarrier(node1, config)
)
}
@@ -342,16 +353,14 @@ private predicate additionalLocalFlowStep(NodeEx node1, NodeEx node2, Configurat
node2.asNode() = n2 and
config.isAdditionalFlowStep(n1, n2) and
getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and
not outBarrier(node1, config) and
not inBarrier(node2, config) and
not fullBarrier(node1, config) and
not fullBarrier(node2, config)
stepFilter(node1, node2, config)
)
or
exists(Node n |
config.allowImplicitRead(n, _) and
node1.isImplicitReadNode(n, true) and
node2.asNode() = n
node2.asNode() = n and
not fullBarrier(node2, config)
)
}
@@ -363,10 +372,7 @@ private predicate jumpStep(NodeEx node1, NodeEx node2, Configuration config) {
node1.asNode() = n1 and
node2.asNode() = n2 and
jumpStepCached(n1, n2) and
not outBarrier(node1, config) and
not inBarrier(node2, config) and
not fullBarrier(node1, config) and
not fullBarrier(node2, config) and
stepFilter(node1, node2, config) and
not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext
)
}
@@ -380,16 +386,14 @@ private predicate additionalJumpStep(NodeEx node1, NodeEx node2, Configuration c
node2.asNode() = n2 and
config.isAdditionalFlowStep(n1, n2) and
getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and
not outBarrier(node1, config) and
not inBarrier(node2, config) and
not fullBarrier(node1, config) and
not fullBarrier(node2, config) and
stepFilter(node1, node2, config) and
not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext
)
}
private predicate read(NodeEx node1, Content c, NodeEx node2, Configuration config) {
read(node1.asNode(), c, node2.asNode())
read(node1.asNode(), c, node2.asNode()) and
stepFilter(node1, node2, config)
or
exists(Node n |
node2.isImplicitReadNode(n, true) and
@@ -402,7 +406,8 @@ private predicate store(
NodeEx node1, TypedContent tc, NodeEx node2, DataFlowType contentType, Configuration config
) {
store(node1.asNode(), tc, node2.asNode(), contentType) and
read(_, tc.getContent(), _, config)
read(_, tc.getContent(), _, config) and
stepFilter(node1, node2, config)
}
pragma[nomagic]
@@ -451,63 +456,59 @@ private module Stage1 {
* argument in a call.
*/
predicate fwdFlow(NodeEx node, Cc cc, Configuration config) {
not fullBarrier(node, config) and
(
sourceNode(node, config) and
if hasSourceCallCtx(config) then cc = true else cc = false
sourceNode(node, config) and
if hasSourceCallCtx(config) then cc = true else cc = false
or
exists(NodeEx mid |
fwdFlow(mid, cc, config) and
localFlowStep(mid, node, config)
)
or
exists(NodeEx mid |
fwdFlow(mid, cc, config) and
additionalLocalFlowStep(mid, node, config)
)
or
exists(NodeEx mid |
fwdFlow(mid, _, config) and
jumpStep(mid, node, config) and
cc = false
)
or
exists(NodeEx mid |
fwdFlow(mid, _, config) and
additionalJumpStep(mid, node, config) and
cc = false
)
or
// store
exists(NodeEx mid |
useFieldFlow(config) and
fwdFlow(mid, cc, config) and
store(mid, _, node, _, config)
)
or
// read
exists(Content c |
fwdFlowRead(c, node, cc, config) and
fwdFlowConsCand(c, config)
)
or
// flow into a callable
exists(NodeEx arg |
fwdFlow(arg, _, config) and
viableParamArgEx(_, node, arg) and
cc = true and
not fullBarrier(node, config)
)
or
// flow out of a callable
exists(DataFlowCall call |
fwdFlowOut(call, node, false, config) and
cc = false
or
exists(NodeEx mid |
fwdFlow(mid, cc, config) and
localFlowStep(mid, node, config)
)
or
exists(NodeEx mid |
fwdFlow(mid, cc, config) and
additionalLocalFlowStep(mid, node, config)
)
or
exists(NodeEx mid |
fwdFlow(mid, _, config) and
jumpStep(mid, node, config) and
cc = false
)
or
exists(NodeEx mid |
fwdFlow(mid, _, config) and
additionalJumpStep(mid, node, config) and
cc = false
)
or
// store
exists(NodeEx mid |
useFieldFlow(config) and
fwdFlow(mid, cc, config) and
store(mid, _, node, _, config) and
not outBarrier(mid, config)
)
or
// read
exists(Content c |
fwdFlowRead(c, node, cc, config) and
fwdFlowConsCand(c, config) and
not inBarrier(node, config)
)
or
// flow into a callable
exists(NodeEx arg |
fwdFlow(arg, _, config) and
viableParamArgEx(_, node, arg) and
cc = true
)
or
// flow out of a callable
exists(DataFlowCall call |
fwdFlowOut(call, node, false, config) and
cc = false
or
fwdFlowOutFromArg(call, node, config) and
fwdFlowIsEntered(call, cc, config)
)
fwdFlowOutFromArg(call, node, config) and
fwdFlowIsEntered(call, cc, config)
)
}
@@ -547,7 +548,8 @@ private module Stage1 {
private predicate fwdFlowOut(DataFlowCall call, NodeEx out, Cc cc, Configuration config) {
exists(ReturnPosition pos |
fwdFlowReturnPosition(pos, cc, config) and
viableReturnPosOutEx(call, pos, out)
viableReturnPosOutEx(call, pos, out) and
not fullBarrier(out, config)
)
}
@@ -773,6 +775,7 @@ private module Stage1 {
* Holds if flow may enter through `p` and reach a return node making `p` a
* candidate for the origin of a summary.
*/
pragma[nomagic]
predicate parameterMayFlowThrough(ParamNodeEx p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnKindExt kind |
throughFlowNodeCand(p, config) and
@@ -1019,12 +1022,14 @@ private module Stage2 {
pragma[nomagic]
private predicate flowThroughOutOfCall(
DataFlowCall call, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow, Configuration config
DataFlowCall call, CcCall ccc, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow,
Configuration config
) {
flowOutOfCall(call, ret, out, allowsFieldFlow, pragma[only_bind_into](config)) and
PrevStage::callMayFlowThroughRev(call, pragma[only_bind_into](config)) and
PrevStage::parameterMayFlowThrough(_, ret.getEnclosingCallable(), _,
pragma[only_bind_into](config))
pragma[only_bind_into](config)) and
ccc.matchesCall(call)
}
/**
@@ -1142,9 +1147,8 @@ private module Stage2 {
exists(ArgNodeEx arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc)
|
ap instanceof ApNil or allowsFieldFlow = true
innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc) and
if allowsFieldFlow = false then ap instanceof ApNil else any()
)
}
@@ -1159,9 +1163,8 @@ private module Stage2 {
fwdFlow(ret, innercc, argAp, ap, config) and
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
inner = ret.getEnclosingCallable() and
ccOut = getCallContextReturn(inner, call, innercc)
|
ap instanceof ApNil or allowsFieldFlow = true
ccOut = getCallContextReturn(inner, call, innercc) and
if allowsFieldFlow = false then ap instanceof ApNil else any()
)
}
@@ -1171,10 +1174,8 @@ private module Stage2 {
) {
exists(RetNodeEx ret, boolean allowsFieldFlow, CcCall ccc |
fwdFlow(ret, ccc, apSome(argAp), ap, config) and
flowThroughOutOfCall(call, ret, out, allowsFieldFlow, config) and
ccc.matchesCall(call)
|
ap instanceof ApNil or allowsFieldFlow = true
flowThroughOutOfCall(call, ccc, ret, out, allowsFieldFlow, config) and
if allowsFieldFlow = false then ap instanceof ApNil else any()
)
}
@@ -1230,6 +1231,11 @@ private module Stage2 {
callMayFlowThroughFwd(call, pragma[only_bind_into](config))
}
pragma[nomagic]
private predicate returnNodeMayFlowThrough(RetNodeEx ret, Ap ap, Configuration config) {
fwdFlow(ret, any(CcCall ccc), apSome(_), ap, config)
}
/**
* Holds if `node` with access path `ap` is part of a path from a source to a
* sink in the configuration `config`.
@@ -1306,7 +1312,7 @@ private module Stage2 {
// flow out of a callable
revFlowOut(_, node, _, _, ap, config) and
toReturn = true and
if fwdFlow(node, any(CcCall ccc), apSome(_), ap, config)
if returnNodeMayFlowThrough(node, ap, config)
then returnAp = apSome(ap)
else returnAp = apNone()
}
@@ -1341,9 +1347,8 @@ private module Stage2 {
) {
exists(NodeEx out, boolean allowsFieldFlow |
revFlow(out, toReturn, returnAp, ap, config) and
flowOutOfCall(call, ret, out, allowsFieldFlow, config)
|
ap instanceof ApNil or allowsFieldFlow = true
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
if allowsFieldFlow = false then ap instanceof ApNil else any()
)
}
@@ -1353,9 +1358,8 @@ private module Stage2 {
) {
exists(ParamNodeEx p, boolean allowsFieldFlow |
revFlow(p, false, returnAp, ap, config) and
flowIntoCall(_, arg, p, allowsFieldFlow, config)
|
ap instanceof ApNil or allowsFieldFlow = true
flowIntoCall(_, arg, p, allowsFieldFlow, config) and
if allowsFieldFlow = false then ap instanceof ApNil else any()
)
}
@@ -1365,9 +1369,8 @@ private module Stage2 {
) {
exists(ParamNodeEx p, boolean allowsFieldFlow |
revFlow(p, true, apSome(returnAp), ap, config) and
flowThroughIntoCall(call, arg, p, allowsFieldFlow, config)
|
ap instanceof ApNil or allowsFieldFlow = true
flowThroughIntoCall(call, arg, p, allowsFieldFlow, config) and
if allowsFieldFlow = false then ap instanceof ApNil else any()
)
}
@@ -1707,12 +1710,14 @@ private module Stage3 {
pragma[nomagic]
private predicate flowThroughOutOfCall(
DataFlowCall call, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow, Configuration config
DataFlowCall call, CcCall ccc, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow,
Configuration config
) {
flowOutOfCall(call, ret, out, allowsFieldFlow, pragma[only_bind_into](config)) and
PrevStage::callMayFlowThroughRev(call, pragma[only_bind_into](config)) and
PrevStage::parameterMayFlowThrough(_, ret.getEnclosingCallable(), _,
pragma[only_bind_into](config))
pragma[only_bind_into](config)) and
ccc.matchesCall(call)
}
/**
@@ -1837,9 +1842,8 @@ private module Stage3 {
exists(ArgNodeEx arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc)
|
ap instanceof ApNil or allowsFieldFlow = true
innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc) and
if allowsFieldFlow = false then ap instanceof ApNil else any()
)
}
@@ -1854,9 +1858,8 @@ private module Stage3 {
fwdFlow(ret, innercc, argAp, ap, config) and
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
inner = ret.getEnclosingCallable() and
ccOut = getCallContextReturn(inner, call, innercc)
|
ap instanceof ApNil or allowsFieldFlow = true
ccOut = getCallContextReturn(inner, call, innercc) and
if allowsFieldFlow = false then ap instanceof ApNil else any()
)
}
@@ -1866,10 +1869,8 @@ private module Stage3 {
) {
exists(RetNodeEx ret, boolean allowsFieldFlow, CcCall ccc |
fwdFlow(ret, ccc, apSome(argAp), ap, config) and
flowThroughOutOfCall(call, ret, out, allowsFieldFlow, config) and
ccc.matchesCall(call)
|
ap instanceof ApNil or allowsFieldFlow = true
flowThroughOutOfCall(call, ccc, ret, out, allowsFieldFlow, config) and
if allowsFieldFlow = false then ap instanceof ApNil else any()
)
}
@@ -1925,6 +1926,11 @@ private module Stage3 {
callMayFlowThroughFwd(call, pragma[only_bind_into](config))
}
pragma[nomagic]
private predicate returnNodeMayFlowThrough(RetNodeEx ret, Ap ap, Configuration config) {
fwdFlow(ret, any(CcCall ccc), apSome(_), ap, config)
}
/**
* Holds if `node` with access path `ap` is part of a path from a source to a
* sink in the configuration `config`.
@@ -2001,7 +2007,7 @@ private module Stage3 {
// flow out of a callable
revFlowOut(_, node, _, _, ap, config) and
toReturn = true and
if fwdFlow(node, any(CcCall ccc), apSome(_), ap, config)
if returnNodeMayFlowThrough(node, ap, config)
then returnAp = apSome(ap)
else returnAp = apNone()
}
@@ -2036,9 +2042,8 @@ private module Stage3 {
) {
exists(NodeEx out, boolean allowsFieldFlow |
revFlow(out, toReturn, returnAp, ap, config) and
flowOutOfCall(call, ret, out, allowsFieldFlow, config)
|
ap instanceof ApNil or allowsFieldFlow = true
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
if allowsFieldFlow = false then ap instanceof ApNil else any()
)
}
@@ -2048,9 +2053,8 @@ private module Stage3 {
) {
exists(ParamNodeEx p, boolean allowsFieldFlow |
revFlow(p, false, returnAp, ap, config) and
flowIntoCall(_, arg, p, allowsFieldFlow, config)
|
ap instanceof ApNil or allowsFieldFlow = true
flowIntoCall(_, arg, p, allowsFieldFlow, config) and
if allowsFieldFlow = false then ap instanceof ApNil else any()
)
}
@@ -2060,9 +2064,8 @@ private module Stage3 {
) {
exists(ParamNodeEx p, boolean allowsFieldFlow |
revFlow(p, true, apSome(returnAp), ap, config) and
flowThroughIntoCall(call, arg, p, allowsFieldFlow, config)
|
ap instanceof ApNil or allowsFieldFlow = true
flowThroughIntoCall(call, arg, p, allowsFieldFlow, config) and
if allowsFieldFlow = false then ap instanceof ApNil else any()
)
}
@@ -2473,12 +2476,14 @@ private module Stage4 {
pragma[nomagic]
private predicate flowThroughOutOfCall(
DataFlowCall call, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow, Configuration config
DataFlowCall call, CcCall ccc, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow,
Configuration config
) {
flowOutOfCall(call, ret, out, allowsFieldFlow, pragma[only_bind_into](config)) and
PrevStage::callMayFlowThroughRev(call, pragma[only_bind_into](config)) and
PrevStage::parameterMayFlowThrough(_, ret.getEnclosingCallable(), _,
pragma[only_bind_into](config))
pragma[only_bind_into](config)) and
ccc.matchesCall(call)
}
/**
@@ -2603,9 +2608,8 @@ private module Stage4 {
exists(ArgNodeEx arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc)
|
ap instanceof ApNil or allowsFieldFlow = true
innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc) and
if allowsFieldFlow = false then ap instanceof ApNil else any()
)
}
@@ -2620,9 +2624,8 @@ private module Stage4 {
fwdFlow(ret, innercc, argAp, ap, config) and
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
inner = ret.getEnclosingCallable() and
ccOut = getCallContextReturn(inner, call, innercc)
|
ap instanceof ApNil or allowsFieldFlow = true
ccOut = getCallContextReturn(inner, call, innercc) and
if allowsFieldFlow = false then ap instanceof ApNil else any()
)
}
@@ -2632,10 +2635,8 @@ private module Stage4 {
) {
exists(RetNodeEx ret, boolean allowsFieldFlow, CcCall ccc |
fwdFlow(ret, ccc, apSome(argAp), ap, config) and
flowThroughOutOfCall(call, ret, out, allowsFieldFlow, config) and
ccc.matchesCall(call)
|
ap instanceof ApNil or allowsFieldFlow = true
flowThroughOutOfCall(call, ccc, ret, out, allowsFieldFlow, config) and
if allowsFieldFlow = false then ap instanceof ApNil else any()
)
}
@@ -2691,6 +2692,11 @@ private module Stage4 {
callMayFlowThroughFwd(call, pragma[only_bind_into](config))
}
pragma[nomagic]
private predicate returnNodeMayFlowThrough(RetNodeEx ret, Ap ap, Configuration config) {
fwdFlow(ret, any(CcCall ccc), apSome(_), ap, config)
}
/**
* Holds if `node` with access path `ap` is part of a path from a source to a
* sink in the configuration `config`.
@@ -2767,7 +2773,7 @@ private module Stage4 {
// flow out of a callable
revFlowOut(_, node, _, _, ap, config) and
toReturn = true and
if fwdFlow(node, any(CcCall ccc), apSome(_), ap, config)
if returnNodeMayFlowThrough(node, ap, config)
then returnAp = apSome(ap)
else returnAp = apNone()
}
@@ -2802,9 +2808,8 @@ private module Stage4 {
) {
exists(NodeEx out, boolean allowsFieldFlow |
revFlow(out, toReturn, returnAp, ap, config) and
flowOutOfCall(call, ret, out, allowsFieldFlow, config)
|
ap instanceof ApNil or allowsFieldFlow = true
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
if allowsFieldFlow = false then ap instanceof ApNil else any()
)
}
@@ -2814,9 +2819,8 @@ private module Stage4 {
) {
exists(ParamNodeEx p, boolean allowsFieldFlow |
revFlow(p, false, returnAp, ap, config) and
flowIntoCall(_, arg, p, allowsFieldFlow, config)
|
ap instanceof ApNil or allowsFieldFlow = true
flowIntoCall(_, arg, p, allowsFieldFlow, config) and
if allowsFieldFlow = false then ap instanceof ApNil else any()
)
}
@@ -2826,9 +2830,8 @@ private module Stage4 {
) {
exists(ParamNodeEx p, boolean allowsFieldFlow |
revFlow(p, true, apSome(returnAp), ap, config) and
flowThroughIntoCall(call, arg, p, allowsFieldFlow, config)
|
ap instanceof ApNil or allowsFieldFlow = true
flowThroughIntoCall(call, arg, p, allowsFieldFlow, config) and
if allowsFieldFlow = false then ap instanceof ApNil else any()
)
}

View File

@@ -289,6 +289,7 @@ private predicate outBarrier(NodeEx node, Configuration config) {
)
}
pragma[nomagic]
private predicate fullBarrier(NodeEx node, Configuration config) {
exists(Node n | node.asNode() = n |
config.isBarrier(n)
@@ -307,11 +308,23 @@ private predicate fullBarrier(NodeEx node, Configuration config) {
}
pragma[nomagic]
private predicate sourceNode(NodeEx node, Configuration config) { config.isSource(node.asNode()) }
private predicate sourceNode(NodeEx node, Configuration config) {
config.isSource(node.asNode()) and
not fullBarrier(node, config)
}
pragma[nomagic]
private predicate sinkNode(NodeEx node, Configuration config) { config.isSink(node.asNode()) }
/** Provides the relevant barriers for a step from `node1` to `node2`. */
pragma[inline]
private predicate stepFilter(NodeEx node1, NodeEx node2, Configuration config) {
not outBarrier(node1, config) and
not inBarrier(node2, config) and
not fullBarrier(node1, config) and
not fullBarrier(node2, config)
}
/**
* Holds if data can flow in one local step from `node1` to `node2`.
*/
@@ -320,16 +333,14 @@ private predicate localFlowStep(NodeEx node1, NodeEx node2, Configuration config
node1.asNode() = n1 and
node2.asNode() = n2 and
simpleLocalFlowStepExt(n1, n2) and
not outBarrier(node1, config) and
not inBarrier(node2, config) and
not fullBarrier(node1, config) and
not fullBarrier(node2, config)
stepFilter(node1, node2, config)
)
or
exists(Node n |
config.allowImplicitRead(n, _) and
node1.asNode() = n and
node2.isImplicitReadNode(n, false)
node2.isImplicitReadNode(n, false) and
not fullBarrier(node1, config)
)
}
@@ -342,16 +353,14 @@ private predicate additionalLocalFlowStep(NodeEx node1, NodeEx node2, Configurat
node2.asNode() = n2 and
config.isAdditionalFlowStep(n1, n2) and
getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and
not outBarrier(node1, config) and
not inBarrier(node2, config) and
not fullBarrier(node1, config) and
not fullBarrier(node2, config)
stepFilter(node1, node2, config)
)
or
exists(Node n |
config.allowImplicitRead(n, _) and
node1.isImplicitReadNode(n, true) and
node2.asNode() = n
node2.asNode() = n and
not fullBarrier(node2, config)
)
}
@@ -363,10 +372,7 @@ private predicate jumpStep(NodeEx node1, NodeEx node2, Configuration config) {
node1.asNode() = n1 and
node2.asNode() = n2 and
jumpStepCached(n1, n2) and
not outBarrier(node1, config) and
not inBarrier(node2, config) and
not fullBarrier(node1, config) and
not fullBarrier(node2, config) and
stepFilter(node1, node2, config) and
not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext
)
}
@@ -380,16 +386,14 @@ private predicate additionalJumpStep(NodeEx node1, NodeEx node2, Configuration c
node2.asNode() = n2 and
config.isAdditionalFlowStep(n1, n2) and
getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and
not outBarrier(node1, config) and
not inBarrier(node2, config) and
not fullBarrier(node1, config) and
not fullBarrier(node2, config) and
stepFilter(node1, node2, config) and
not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext
)
}
private predicate read(NodeEx node1, Content c, NodeEx node2, Configuration config) {
read(node1.asNode(), c, node2.asNode())
read(node1.asNode(), c, node2.asNode()) and
stepFilter(node1, node2, config)
or
exists(Node n |
node2.isImplicitReadNode(n, true) and
@@ -402,7 +406,8 @@ private predicate store(
NodeEx node1, TypedContent tc, NodeEx node2, DataFlowType contentType, Configuration config
) {
store(node1.asNode(), tc, node2.asNode(), contentType) and
read(_, tc.getContent(), _, config)
read(_, tc.getContent(), _, config) and
stepFilter(node1, node2, config)
}
pragma[nomagic]
@@ -451,63 +456,59 @@ private module Stage1 {
* argument in a call.
*/
predicate fwdFlow(NodeEx node, Cc cc, Configuration config) {
not fullBarrier(node, config) and
(
sourceNode(node, config) and
if hasSourceCallCtx(config) then cc = true else cc = false
sourceNode(node, config) and
if hasSourceCallCtx(config) then cc = true else cc = false
or
exists(NodeEx mid |
fwdFlow(mid, cc, config) and
localFlowStep(mid, node, config)
)
or
exists(NodeEx mid |
fwdFlow(mid, cc, config) and
additionalLocalFlowStep(mid, node, config)
)
or
exists(NodeEx mid |
fwdFlow(mid, _, config) and
jumpStep(mid, node, config) and
cc = false
)
or
exists(NodeEx mid |
fwdFlow(mid, _, config) and
additionalJumpStep(mid, node, config) and
cc = false
)
or
// store
exists(NodeEx mid |
useFieldFlow(config) and
fwdFlow(mid, cc, config) and
store(mid, _, node, _, config)
)
or
// read
exists(Content c |
fwdFlowRead(c, node, cc, config) and
fwdFlowConsCand(c, config)
)
or
// flow into a callable
exists(NodeEx arg |
fwdFlow(arg, _, config) and
viableParamArgEx(_, node, arg) and
cc = true and
not fullBarrier(node, config)
)
or
// flow out of a callable
exists(DataFlowCall call |
fwdFlowOut(call, node, false, config) and
cc = false
or
exists(NodeEx mid |
fwdFlow(mid, cc, config) and
localFlowStep(mid, node, config)
)
or
exists(NodeEx mid |
fwdFlow(mid, cc, config) and
additionalLocalFlowStep(mid, node, config)
)
or
exists(NodeEx mid |
fwdFlow(mid, _, config) and
jumpStep(mid, node, config) and
cc = false
)
or
exists(NodeEx mid |
fwdFlow(mid, _, config) and
additionalJumpStep(mid, node, config) and
cc = false
)
or
// store
exists(NodeEx mid |
useFieldFlow(config) and
fwdFlow(mid, cc, config) and
store(mid, _, node, _, config) and
not outBarrier(mid, config)
)
or
// read
exists(Content c |
fwdFlowRead(c, node, cc, config) and
fwdFlowConsCand(c, config) and
not inBarrier(node, config)
)
or
// flow into a callable
exists(NodeEx arg |
fwdFlow(arg, _, config) and
viableParamArgEx(_, node, arg) and
cc = true
)
or
// flow out of a callable
exists(DataFlowCall call |
fwdFlowOut(call, node, false, config) and
cc = false
or
fwdFlowOutFromArg(call, node, config) and
fwdFlowIsEntered(call, cc, config)
)
fwdFlowOutFromArg(call, node, config) and
fwdFlowIsEntered(call, cc, config)
)
}
@@ -547,7 +548,8 @@ private module Stage1 {
private predicate fwdFlowOut(DataFlowCall call, NodeEx out, Cc cc, Configuration config) {
exists(ReturnPosition pos |
fwdFlowReturnPosition(pos, cc, config) and
viableReturnPosOutEx(call, pos, out)
viableReturnPosOutEx(call, pos, out) and
not fullBarrier(out, config)
)
}
@@ -773,6 +775,7 @@ private module Stage1 {
* Holds if flow may enter through `p` and reach a return node making `p` a
* candidate for the origin of a summary.
*/
pragma[nomagic]
predicate parameterMayFlowThrough(ParamNodeEx p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnKindExt kind |
throughFlowNodeCand(p, config) and
@@ -1019,12 +1022,14 @@ private module Stage2 {
pragma[nomagic]
private predicate flowThroughOutOfCall(
DataFlowCall call, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow, Configuration config
DataFlowCall call, CcCall ccc, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow,
Configuration config
) {
flowOutOfCall(call, ret, out, allowsFieldFlow, pragma[only_bind_into](config)) and
PrevStage::callMayFlowThroughRev(call, pragma[only_bind_into](config)) and
PrevStage::parameterMayFlowThrough(_, ret.getEnclosingCallable(), _,
pragma[only_bind_into](config))
pragma[only_bind_into](config)) and
ccc.matchesCall(call)
}
/**
@@ -1142,9 +1147,8 @@ private module Stage2 {
exists(ArgNodeEx arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc)
|
ap instanceof ApNil or allowsFieldFlow = true
innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc) and
if allowsFieldFlow = false then ap instanceof ApNil else any()
)
}
@@ -1159,9 +1163,8 @@ private module Stage2 {
fwdFlow(ret, innercc, argAp, ap, config) and
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
inner = ret.getEnclosingCallable() and
ccOut = getCallContextReturn(inner, call, innercc)
|
ap instanceof ApNil or allowsFieldFlow = true
ccOut = getCallContextReturn(inner, call, innercc) and
if allowsFieldFlow = false then ap instanceof ApNil else any()
)
}
@@ -1171,10 +1174,8 @@ private module Stage2 {
) {
exists(RetNodeEx ret, boolean allowsFieldFlow, CcCall ccc |
fwdFlow(ret, ccc, apSome(argAp), ap, config) and
flowThroughOutOfCall(call, ret, out, allowsFieldFlow, config) and
ccc.matchesCall(call)
|
ap instanceof ApNil or allowsFieldFlow = true
flowThroughOutOfCall(call, ccc, ret, out, allowsFieldFlow, config) and
if allowsFieldFlow = false then ap instanceof ApNil else any()
)
}
@@ -1230,6 +1231,11 @@ private module Stage2 {
callMayFlowThroughFwd(call, pragma[only_bind_into](config))
}
pragma[nomagic]
private predicate returnNodeMayFlowThrough(RetNodeEx ret, Ap ap, Configuration config) {
fwdFlow(ret, any(CcCall ccc), apSome(_), ap, config)
}
/**
* Holds if `node` with access path `ap` is part of a path from a source to a
* sink in the configuration `config`.
@@ -1306,7 +1312,7 @@ private module Stage2 {
// flow out of a callable
revFlowOut(_, node, _, _, ap, config) and
toReturn = true and
if fwdFlow(node, any(CcCall ccc), apSome(_), ap, config)
if returnNodeMayFlowThrough(node, ap, config)
then returnAp = apSome(ap)
else returnAp = apNone()
}
@@ -1341,9 +1347,8 @@ private module Stage2 {
) {
exists(NodeEx out, boolean allowsFieldFlow |
revFlow(out, toReturn, returnAp, ap, config) and
flowOutOfCall(call, ret, out, allowsFieldFlow, config)
|
ap instanceof ApNil or allowsFieldFlow = true
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
if allowsFieldFlow = false then ap instanceof ApNil else any()
)
}
@@ -1353,9 +1358,8 @@ private module Stage2 {
) {
exists(ParamNodeEx p, boolean allowsFieldFlow |
revFlow(p, false, returnAp, ap, config) and
flowIntoCall(_, arg, p, allowsFieldFlow, config)
|
ap instanceof ApNil or allowsFieldFlow = true
flowIntoCall(_, arg, p, allowsFieldFlow, config) and
if allowsFieldFlow = false then ap instanceof ApNil else any()
)
}
@@ -1365,9 +1369,8 @@ private module Stage2 {
) {
exists(ParamNodeEx p, boolean allowsFieldFlow |
revFlow(p, true, apSome(returnAp), ap, config) and
flowThroughIntoCall(call, arg, p, allowsFieldFlow, config)
|
ap instanceof ApNil or allowsFieldFlow = true
flowThroughIntoCall(call, arg, p, allowsFieldFlow, config) and
if allowsFieldFlow = false then ap instanceof ApNil else any()
)
}
@@ -1707,12 +1710,14 @@ private module Stage3 {
pragma[nomagic]
private predicate flowThroughOutOfCall(
DataFlowCall call, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow, Configuration config
DataFlowCall call, CcCall ccc, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow,
Configuration config
) {
flowOutOfCall(call, ret, out, allowsFieldFlow, pragma[only_bind_into](config)) and
PrevStage::callMayFlowThroughRev(call, pragma[only_bind_into](config)) and
PrevStage::parameterMayFlowThrough(_, ret.getEnclosingCallable(), _,
pragma[only_bind_into](config))
pragma[only_bind_into](config)) and
ccc.matchesCall(call)
}
/**
@@ -1837,9 +1842,8 @@ private module Stage3 {
exists(ArgNodeEx arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc)
|
ap instanceof ApNil or allowsFieldFlow = true
innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc) and
if allowsFieldFlow = false then ap instanceof ApNil else any()
)
}
@@ -1854,9 +1858,8 @@ private module Stage3 {
fwdFlow(ret, innercc, argAp, ap, config) and
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
inner = ret.getEnclosingCallable() and
ccOut = getCallContextReturn(inner, call, innercc)
|
ap instanceof ApNil or allowsFieldFlow = true
ccOut = getCallContextReturn(inner, call, innercc) and
if allowsFieldFlow = false then ap instanceof ApNil else any()
)
}
@@ -1866,10 +1869,8 @@ private module Stage3 {
) {
exists(RetNodeEx ret, boolean allowsFieldFlow, CcCall ccc |
fwdFlow(ret, ccc, apSome(argAp), ap, config) and
flowThroughOutOfCall(call, ret, out, allowsFieldFlow, config) and
ccc.matchesCall(call)
|
ap instanceof ApNil or allowsFieldFlow = true
flowThroughOutOfCall(call, ccc, ret, out, allowsFieldFlow, config) and
if allowsFieldFlow = false then ap instanceof ApNil else any()
)
}
@@ -1925,6 +1926,11 @@ private module Stage3 {
callMayFlowThroughFwd(call, pragma[only_bind_into](config))
}
pragma[nomagic]
private predicate returnNodeMayFlowThrough(RetNodeEx ret, Ap ap, Configuration config) {
fwdFlow(ret, any(CcCall ccc), apSome(_), ap, config)
}
/**
* Holds if `node` with access path `ap` is part of a path from a source to a
* sink in the configuration `config`.
@@ -2001,7 +2007,7 @@ private module Stage3 {
// flow out of a callable
revFlowOut(_, node, _, _, ap, config) and
toReturn = true and
if fwdFlow(node, any(CcCall ccc), apSome(_), ap, config)
if returnNodeMayFlowThrough(node, ap, config)
then returnAp = apSome(ap)
else returnAp = apNone()
}
@@ -2036,9 +2042,8 @@ private module Stage3 {
) {
exists(NodeEx out, boolean allowsFieldFlow |
revFlow(out, toReturn, returnAp, ap, config) and
flowOutOfCall(call, ret, out, allowsFieldFlow, config)
|
ap instanceof ApNil or allowsFieldFlow = true
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
if allowsFieldFlow = false then ap instanceof ApNil else any()
)
}
@@ -2048,9 +2053,8 @@ private module Stage3 {
) {
exists(ParamNodeEx p, boolean allowsFieldFlow |
revFlow(p, false, returnAp, ap, config) and
flowIntoCall(_, arg, p, allowsFieldFlow, config)
|
ap instanceof ApNil or allowsFieldFlow = true
flowIntoCall(_, arg, p, allowsFieldFlow, config) and
if allowsFieldFlow = false then ap instanceof ApNil else any()
)
}
@@ -2060,9 +2064,8 @@ private module Stage3 {
) {
exists(ParamNodeEx p, boolean allowsFieldFlow |
revFlow(p, true, apSome(returnAp), ap, config) and
flowThroughIntoCall(call, arg, p, allowsFieldFlow, config)
|
ap instanceof ApNil or allowsFieldFlow = true
flowThroughIntoCall(call, arg, p, allowsFieldFlow, config) and
if allowsFieldFlow = false then ap instanceof ApNil else any()
)
}
@@ -2473,12 +2476,14 @@ private module Stage4 {
pragma[nomagic]
private predicate flowThroughOutOfCall(
DataFlowCall call, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow, Configuration config
DataFlowCall call, CcCall ccc, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow,
Configuration config
) {
flowOutOfCall(call, ret, out, allowsFieldFlow, pragma[only_bind_into](config)) and
PrevStage::callMayFlowThroughRev(call, pragma[only_bind_into](config)) and
PrevStage::parameterMayFlowThrough(_, ret.getEnclosingCallable(), _,
pragma[only_bind_into](config))
pragma[only_bind_into](config)) and
ccc.matchesCall(call)
}
/**
@@ -2603,9 +2608,8 @@ private module Stage4 {
exists(ArgNodeEx arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc)
|
ap instanceof ApNil or allowsFieldFlow = true
innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc) and
if allowsFieldFlow = false then ap instanceof ApNil else any()
)
}
@@ -2620,9 +2624,8 @@ private module Stage4 {
fwdFlow(ret, innercc, argAp, ap, config) and
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
inner = ret.getEnclosingCallable() and
ccOut = getCallContextReturn(inner, call, innercc)
|
ap instanceof ApNil or allowsFieldFlow = true
ccOut = getCallContextReturn(inner, call, innercc) and
if allowsFieldFlow = false then ap instanceof ApNil else any()
)
}
@@ -2632,10 +2635,8 @@ private module Stage4 {
) {
exists(RetNodeEx ret, boolean allowsFieldFlow, CcCall ccc |
fwdFlow(ret, ccc, apSome(argAp), ap, config) and
flowThroughOutOfCall(call, ret, out, allowsFieldFlow, config) and
ccc.matchesCall(call)
|
ap instanceof ApNil or allowsFieldFlow = true
flowThroughOutOfCall(call, ccc, ret, out, allowsFieldFlow, config) and
if allowsFieldFlow = false then ap instanceof ApNil else any()
)
}
@@ -2691,6 +2692,11 @@ private module Stage4 {
callMayFlowThroughFwd(call, pragma[only_bind_into](config))
}
pragma[nomagic]
private predicate returnNodeMayFlowThrough(RetNodeEx ret, Ap ap, Configuration config) {
fwdFlow(ret, any(CcCall ccc), apSome(_), ap, config)
}
/**
* Holds if `node` with access path `ap` is part of a path from a source to a
* sink in the configuration `config`.
@@ -2767,7 +2773,7 @@ private module Stage4 {
// flow out of a callable
revFlowOut(_, node, _, _, ap, config) and
toReturn = true and
if fwdFlow(node, any(CcCall ccc), apSome(_), ap, config)
if returnNodeMayFlowThrough(node, ap, config)
then returnAp = apSome(ap)
else returnAp = apNone()
}
@@ -2802,9 +2808,8 @@ private module Stage4 {
) {
exists(NodeEx out, boolean allowsFieldFlow |
revFlow(out, toReturn, returnAp, ap, config) and
flowOutOfCall(call, ret, out, allowsFieldFlow, config)
|
ap instanceof ApNil or allowsFieldFlow = true
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
if allowsFieldFlow = false then ap instanceof ApNil else any()
)
}
@@ -2814,9 +2819,8 @@ private module Stage4 {
) {
exists(ParamNodeEx p, boolean allowsFieldFlow |
revFlow(p, false, returnAp, ap, config) and
flowIntoCall(_, arg, p, allowsFieldFlow, config)
|
ap instanceof ApNil or allowsFieldFlow = true
flowIntoCall(_, arg, p, allowsFieldFlow, config) and
if allowsFieldFlow = false then ap instanceof ApNil else any()
)
}
@@ -2826,9 +2830,8 @@ private module Stage4 {
) {
exists(ParamNodeEx p, boolean allowsFieldFlow |
revFlow(p, true, apSome(returnAp), ap, config) and
flowThroughIntoCall(call, arg, p, allowsFieldFlow, config)
|
ap instanceof ApNil or allowsFieldFlow = true
flowThroughIntoCall(call, arg, p, allowsFieldFlow, config) and
if allowsFieldFlow = false then ap instanceof ApNil else any()
)
}

View File

@@ -289,6 +289,7 @@ private predicate outBarrier(NodeEx node, Configuration config) {
)
}
pragma[nomagic]
private predicate fullBarrier(NodeEx node, Configuration config) {
exists(Node n | node.asNode() = n |
config.isBarrier(n)
@@ -307,11 +308,23 @@ private predicate fullBarrier(NodeEx node, Configuration config) {
}
pragma[nomagic]
private predicate sourceNode(NodeEx node, Configuration config) { config.isSource(node.asNode()) }
private predicate sourceNode(NodeEx node, Configuration config) {
config.isSource(node.asNode()) and
not fullBarrier(node, config)
}
pragma[nomagic]
private predicate sinkNode(NodeEx node, Configuration config) { config.isSink(node.asNode()) }
/** Provides the relevant barriers for a step from `node1` to `node2`. */
pragma[inline]
private predicate stepFilter(NodeEx node1, NodeEx node2, Configuration config) {
not outBarrier(node1, config) and
not inBarrier(node2, config) and
not fullBarrier(node1, config) and
not fullBarrier(node2, config)
}
/**
* Holds if data can flow in one local step from `node1` to `node2`.
*/
@@ -320,16 +333,14 @@ private predicate localFlowStep(NodeEx node1, NodeEx node2, Configuration config
node1.asNode() = n1 and
node2.asNode() = n2 and
simpleLocalFlowStepExt(n1, n2) and
not outBarrier(node1, config) and
not inBarrier(node2, config) and
not fullBarrier(node1, config) and
not fullBarrier(node2, config)
stepFilter(node1, node2, config)
)
or
exists(Node n |
config.allowImplicitRead(n, _) and
node1.asNode() = n and
node2.isImplicitReadNode(n, false)
node2.isImplicitReadNode(n, false) and
not fullBarrier(node1, config)
)
}
@@ -342,16 +353,14 @@ private predicate additionalLocalFlowStep(NodeEx node1, NodeEx node2, Configurat
node2.asNode() = n2 and
config.isAdditionalFlowStep(n1, n2) and
getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and
not outBarrier(node1, config) and
not inBarrier(node2, config) and
not fullBarrier(node1, config) and
not fullBarrier(node2, config)
stepFilter(node1, node2, config)
)
or
exists(Node n |
config.allowImplicitRead(n, _) and
node1.isImplicitReadNode(n, true) and
node2.asNode() = n
node2.asNode() = n and
not fullBarrier(node2, config)
)
}
@@ -363,10 +372,7 @@ private predicate jumpStep(NodeEx node1, NodeEx node2, Configuration config) {
node1.asNode() = n1 and
node2.asNode() = n2 and
jumpStepCached(n1, n2) and
not outBarrier(node1, config) and
not inBarrier(node2, config) and
not fullBarrier(node1, config) and
not fullBarrier(node2, config) and
stepFilter(node1, node2, config) and
not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext
)
}
@@ -380,16 +386,14 @@ private predicate additionalJumpStep(NodeEx node1, NodeEx node2, Configuration c
node2.asNode() = n2 and
config.isAdditionalFlowStep(n1, n2) and
getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and
not outBarrier(node1, config) and
not inBarrier(node2, config) and
not fullBarrier(node1, config) and
not fullBarrier(node2, config) and
stepFilter(node1, node2, config) and
not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext
)
}
private predicate read(NodeEx node1, Content c, NodeEx node2, Configuration config) {
read(node1.asNode(), c, node2.asNode())
read(node1.asNode(), c, node2.asNode()) and
stepFilter(node1, node2, config)
or
exists(Node n |
node2.isImplicitReadNode(n, true) and
@@ -402,7 +406,8 @@ private predicate store(
NodeEx node1, TypedContent tc, NodeEx node2, DataFlowType contentType, Configuration config
) {
store(node1.asNode(), tc, node2.asNode(), contentType) and
read(_, tc.getContent(), _, config)
read(_, tc.getContent(), _, config) and
stepFilter(node1, node2, config)
}
pragma[nomagic]
@@ -451,63 +456,59 @@ private module Stage1 {
* argument in a call.
*/
predicate fwdFlow(NodeEx node, Cc cc, Configuration config) {
not fullBarrier(node, config) and
(
sourceNode(node, config) and
if hasSourceCallCtx(config) then cc = true else cc = false
sourceNode(node, config) and
if hasSourceCallCtx(config) then cc = true else cc = false
or
exists(NodeEx mid |
fwdFlow(mid, cc, config) and
localFlowStep(mid, node, config)
)
or
exists(NodeEx mid |
fwdFlow(mid, cc, config) and
additionalLocalFlowStep(mid, node, config)
)
or
exists(NodeEx mid |
fwdFlow(mid, _, config) and
jumpStep(mid, node, config) and
cc = false
)
or
exists(NodeEx mid |
fwdFlow(mid, _, config) and
additionalJumpStep(mid, node, config) and
cc = false
)
or
// store
exists(NodeEx mid |
useFieldFlow(config) and
fwdFlow(mid, cc, config) and
store(mid, _, node, _, config)
)
or
// read
exists(Content c |
fwdFlowRead(c, node, cc, config) and
fwdFlowConsCand(c, config)
)
or
// flow into a callable
exists(NodeEx arg |
fwdFlow(arg, _, config) and
viableParamArgEx(_, node, arg) and
cc = true and
not fullBarrier(node, config)
)
or
// flow out of a callable
exists(DataFlowCall call |
fwdFlowOut(call, node, false, config) and
cc = false
or
exists(NodeEx mid |
fwdFlow(mid, cc, config) and
localFlowStep(mid, node, config)
)
or
exists(NodeEx mid |
fwdFlow(mid, cc, config) and
additionalLocalFlowStep(mid, node, config)
)
or
exists(NodeEx mid |
fwdFlow(mid, _, config) and
jumpStep(mid, node, config) and
cc = false
)
or
exists(NodeEx mid |
fwdFlow(mid, _, config) and
additionalJumpStep(mid, node, config) and
cc = false
)
or
// store
exists(NodeEx mid |
useFieldFlow(config) and
fwdFlow(mid, cc, config) and
store(mid, _, node, _, config) and
not outBarrier(mid, config)
)
or
// read
exists(Content c |
fwdFlowRead(c, node, cc, config) and
fwdFlowConsCand(c, config) and
not inBarrier(node, config)
)
or
// flow into a callable
exists(NodeEx arg |
fwdFlow(arg, _, config) and
viableParamArgEx(_, node, arg) and
cc = true
)
or
// flow out of a callable
exists(DataFlowCall call |
fwdFlowOut(call, node, false, config) and
cc = false
or
fwdFlowOutFromArg(call, node, config) and
fwdFlowIsEntered(call, cc, config)
)
fwdFlowOutFromArg(call, node, config) and
fwdFlowIsEntered(call, cc, config)
)
}
@@ -547,7 +548,8 @@ private module Stage1 {
private predicate fwdFlowOut(DataFlowCall call, NodeEx out, Cc cc, Configuration config) {
exists(ReturnPosition pos |
fwdFlowReturnPosition(pos, cc, config) and
viableReturnPosOutEx(call, pos, out)
viableReturnPosOutEx(call, pos, out) and
not fullBarrier(out, config)
)
}
@@ -773,6 +775,7 @@ private module Stage1 {
* Holds if flow may enter through `p` and reach a return node making `p` a
* candidate for the origin of a summary.
*/
pragma[nomagic]
predicate parameterMayFlowThrough(ParamNodeEx p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnKindExt kind |
throughFlowNodeCand(p, config) and
@@ -1019,12 +1022,14 @@ private module Stage2 {
pragma[nomagic]
private predicate flowThroughOutOfCall(
DataFlowCall call, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow, Configuration config
DataFlowCall call, CcCall ccc, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow,
Configuration config
) {
flowOutOfCall(call, ret, out, allowsFieldFlow, pragma[only_bind_into](config)) and
PrevStage::callMayFlowThroughRev(call, pragma[only_bind_into](config)) and
PrevStage::parameterMayFlowThrough(_, ret.getEnclosingCallable(), _,
pragma[only_bind_into](config))
pragma[only_bind_into](config)) and
ccc.matchesCall(call)
}
/**
@@ -1142,9 +1147,8 @@ private module Stage2 {
exists(ArgNodeEx arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc)
|
ap instanceof ApNil or allowsFieldFlow = true
innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc) and
if allowsFieldFlow = false then ap instanceof ApNil else any()
)
}
@@ -1159,9 +1163,8 @@ private module Stage2 {
fwdFlow(ret, innercc, argAp, ap, config) and
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
inner = ret.getEnclosingCallable() and
ccOut = getCallContextReturn(inner, call, innercc)
|
ap instanceof ApNil or allowsFieldFlow = true
ccOut = getCallContextReturn(inner, call, innercc) and
if allowsFieldFlow = false then ap instanceof ApNil else any()
)
}
@@ -1171,10 +1174,8 @@ private module Stage2 {
) {
exists(RetNodeEx ret, boolean allowsFieldFlow, CcCall ccc |
fwdFlow(ret, ccc, apSome(argAp), ap, config) and
flowThroughOutOfCall(call, ret, out, allowsFieldFlow, config) and
ccc.matchesCall(call)
|
ap instanceof ApNil or allowsFieldFlow = true
flowThroughOutOfCall(call, ccc, ret, out, allowsFieldFlow, config) and
if allowsFieldFlow = false then ap instanceof ApNil else any()
)
}
@@ -1230,6 +1231,11 @@ private module Stage2 {
callMayFlowThroughFwd(call, pragma[only_bind_into](config))
}
pragma[nomagic]
private predicate returnNodeMayFlowThrough(RetNodeEx ret, Ap ap, Configuration config) {
fwdFlow(ret, any(CcCall ccc), apSome(_), ap, config)
}
/**
* Holds if `node` with access path `ap` is part of a path from a source to a
* sink in the configuration `config`.
@@ -1306,7 +1312,7 @@ private module Stage2 {
// flow out of a callable
revFlowOut(_, node, _, _, ap, config) and
toReturn = true and
if fwdFlow(node, any(CcCall ccc), apSome(_), ap, config)
if returnNodeMayFlowThrough(node, ap, config)
then returnAp = apSome(ap)
else returnAp = apNone()
}
@@ -1341,9 +1347,8 @@ private module Stage2 {
) {
exists(NodeEx out, boolean allowsFieldFlow |
revFlow(out, toReturn, returnAp, ap, config) and
flowOutOfCall(call, ret, out, allowsFieldFlow, config)
|
ap instanceof ApNil or allowsFieldFlow = true
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
if allowsFieldFlow = false then ap instanceof ApNil else any()
)
}
@@ -1353,9 +1358,8 @@ private module Stage2 {
) {
exists(ParamNodeEx p, boolean allowsFieldFlow |
revFlow(p, false, returnAp, ap, config) and
flowIntoCall(_, arg, p, allowsFieldFlow, config)
|
ap instanceof ApNil or allowsFieldFlow = true
flowIntoCall(_, arg, p, allowsFieldFlow, config) and
if allowsFieldFlow = false then ap instanceof ApNil else any()
)
}
@@ -1365,9 +1369,8 @@ private module Stage2 {
) {
exists(ParamNodeEx p, boolean allowsFieldFlow |
revFlow(p, true, apSome(returnAp), ap, config) and
flowThroughIntoCall(call, arg, p, allowsFieldFlow, config)
|
ap instanceof ApNil or allowsFieldFlow = true
flowThroughIntoCall(call, arg, p, allowsFieldFlow, config) and
if allowsFieldFlow = false then ap instanceof ApNil else any()
)
}
@@ -1707,12 +1710,14 @@ private module Stage3 {
pragma[nomagic]
private predicate flowThroughOutOfCall(
DataFlowCall call, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow, Configuration config
DataFlowCall call, CcCall ccc, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow,
Configuration config
) {
flowOutOfCall(call, ret, out, allowsFieldFlow, pragma[only_bind_into](config)) and
PrevStage::callMayFlowThroughRev(call, pragma[only_bind_into](config)) and
PrevStage::parameterMayFlowThrough(_, ret.getEnclosingCallable(), _,
pragma[only_bind_into](config))
pragma[only_bind_into](config)) and
ccc.matchesCall(call)
}
/**
@@ -1837,9 +1842,8 @@ private module Stage3 {
exists(ArgNodeEx arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc)
|
ap instanceof ApNil or allowsFieldFlow = true
innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc) and
if allowsFieldFlow = false then ap instanceof ApNil else any()
)
}
@@ -1854,9 +1858,8 @@ private module Stage3 {
fwdFlow(ret, innercc, argAp, ap, config) and
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
inner = ret.getEnclosingCallable() and
ccOut = getCallContextReturn(inner, call, innercc)
|
ap instanceof ApNil or allowsFieldFlow = true
ccOut = getCallContextReturn(inner, call, innercc) and
if allowsFieldFlow = false then ap instanceof ApNil else any()
)
}
@@ -1866,10 +1869,8 @@ private module Stage3 {
) {
exists(RetNodeEx ret, boolean allowsFieldFlow, CcCall ccc |
fwdFlow(ret, ccc, apSome(argAp), ap, config) and
flowThroughOutOfCall(call, ret, out, allowsFieldFlow, config) and
ccc.matchesCall(call)
|
ap instanceof ApNil or allowsFieldFlow = true
flowThroughOutOfCall(call, ccc, ret, out, allowsFieldFlow, config) and
if allowsFieldFlow = false then ap instanceof ApNil else any()
)
}
@@ -1925,6 +1926,11 @@ private module Stage3 {
callMayFlowThroughFwd(call, pragma[only_bind_into](config))
}
pragma[nomagic]
private predicate returnNodeMayFlowThrough(RetNodeEx ret, Ap ap, Configuration config) {
fwdFlow(ret, any(CcCall ccc), apSome(_), ap, config)
}
/**
* Holds if `node` with access path `ap` is part of a path from a source to a
* sink in the configuration `config`.
@@ -2001,7 +2007,7 @@ private module Stage3 {
// flow out of a callable
revFlowOut(_, node, _, _, ap, config) and
toReturn = true and
if fwdFlow(node, any(CcCall ccc), apSome(_), ap, config)
if returnNodeMayFlowThrough(node, ap, config)
then returnAp = apSome(ap)
else returnAp = apNone()
}
@@ -2036,9 +2042,8 @@ private module Stage3 {
) {
exists(NodeEx out, boolean allowsFieldFlow |
revFlow(out, toReturn, returnAp, ap, config) and
flowOutOfCall(call, ret, out, allowsFieldFlow, config)
|
ap instanceof ApNil or allowsFieldFlow = true
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
if allowsFieldFlow = false then ap instanceof ApNil else any()
)
}
@@ -2048,9 +2053,8 @@ private module Stage3 {
) {
exists(ParamNodeEx p, boolean allowsFieldFlow |
revFlow(p, false, returnAp, ap, config) and
flowIntoCall(_, arg, p, allowsFieldFlow, config)
|
ap instanceof ApNil or allowsFieldFlow = true
flowIntoCall(_, arg, p, allowsFieldFlow, config) and
if allowsFieldFlow = false then ap instanceof ApNil else any()
)
}
@@ -2060,9 +2064,8 @@ private module Stage3 {
) {
exists(ParamNodeEx p, boolean allowsFieldFlow |
revFlow(p, true, apSome(returnAp), ap, config) and
flowThroughIntoCall(call, arg, p, allowsFieldFlow, config)
|
ap instanceof ApNil or allowsFieldFlow = true
flowThroughIntoCall(call, arg, p, allowsFieldFlow, config) and
if allowsFieldFlow = false then ap instanceof ApNil else any()
)
}
@@ -2473,12 +2476,14 @@ private module Stage4 {
pragma[nomagic]
private predicate flowThroughOutOfCall(
DataFlowCall call, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow, Configuration config
DataFlowCall call, CcCall ccc, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow,
Configuration config
) {
flowOutOfCall(call, ret, out, allowsFieldFlow, pragma[only_bind_into](config)) and
PrevStage::callMayFlowThroughRev(call, pragma[only_bind_into](config)) and
PrevStage::parameterMayFlowThrough(_, ret.getEnclosingCallable(), _,
pragma[only_bind_into](config))
pragma[only_bind_into](config)) and
ccc.matchesCall(call)
}
/**
@@ -2603,9 +2608,8 @@ private module Stage4 {
exists(ArgNodeEx arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc)
|
ap instanceof ApNil or allowsFieldFlow = true
innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc) and
if allowsFieldFlow = false then ap instanceof ApNil else any()
)
}
@@ -2620,9 +2624,8 @@ private module Stage4 {
fwdFlow(ret, innercc, argAp, ap, config) and
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
inner = ret.getEnclosingCallable() and
ccOut = getCallContextReturn(inner, call, innercc)
|
ap instanceof ApNil or allowsFieldFlow = true
ccOut = getCallContextReturn(inner, call, innercc) and
if allowsFieldFlow = false then ap instanceof ApNil else any()
)
}
@@ -2632,10 +2635,8 @@ private module Stage4 {
) {
exists(RetNodeEx ret, boolean allowsFieldFlow, CcCall ccc |
fwdFlow(ret, ccc, apSome(argAp), ap, config) and
flowThroughOutOfCall(call, ret, out, allowsFieldFlow, config) and
ccc.matchesCall(call)
|
ap instanceof ApNil or allowsFieldFlow = true
flowThroughOutOfCall(call, ccc, ret, out, allowsFieldFlow, config) and
if allowsFieldFlow = false then ap instanceof ApNil else any()
)
}
@@ -2691,6 +2692,11 @@ private module Stage4 {
callMayFlowThroughFwd(call, pragma[only_bind_into](config))
}
pragma[nomagic]
private predicate returnNodeMayFlowThrough(RetNodeEx ret, Ap ap, Configuration config) {
fwdFlow(ret, any(CcCall ccc), apSome(_), ap, config)
}
/**
* Holds if `node` with access path `ap` is part of a path from a source to a
* sink in the configuration `config`.
@@ -2767,7 +2773,7 @@ private module Stage4 {
// flow out of a callable
revFlowOut(_, node, _, _, ap, config) and
toReturn = true and
if fwdFlow(node, any(CcCall ccc), apSome(_), ap, config)
if returnNodeMayFlowThrough(node, ap, config)
then returnAp = apSome(ap)
else returnAp = apNone()
}
@@ -2802,9 +2808,8 @@ private module Stage4 {
) {
exists(NodeEx out, boolean allowsFieldFlow |
revFlow(out, toReturn, returnAp, ap, config) and
flowOutOfCall(call, ret, out, allowsFieldFlow, config)
|
ap instanceof ApNil or allowsFieldFlow = true
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
if allowsFieldFlow = false then ap instanceof ApNil else any()
)
}
@@ -2814,9 +2819,8 @@ private module Stage4 {
) {
exists(ParamNodeEx p, boolean allowsFieldFlow |
revFlow(p, false, returnAp, ap, config) and
flowIntoCall(_, arg, p, allowsFieldFlow, config)
|
ap instanceof ApNil or allowsFieldFlow = true
flowIntoCall(_, arg, p, allowsFieldFlow, config) and
if allowsFieldFlow = false then ap instanceof ApNil else any()
)
}
@@ -2826,9 +2830,8 @@ private module Stage4 {
) {
exists(ParamNodeEx p, boolean allowsFieldFlow |
revFlow(p, true, apSome(returnAp), ap, config) and
flowThroughIntoCall(call, arg, p, allowsFieldFlow, config)
|
ap instanceof ApNil or allowsFieldFlow = true
flowThroughIntoCall(call, arg, p, allowsFieldFlow, config) and
if allowsFieldFlow = false then ap instanceof ApNil else any()
)
}

View File

@@ -289,6 +289,7 @@ private predicate outBarrier(NodeEx node, Configuration config) {
)
}
pragma[nomagic]
private predicate fullBarrier(NodeEx node, Configuration config) {
exists(Node n | node.asNode() = n |
config.isBarrier(n)
@@ -307,11 +308,23 @@ private predicate fullBarrier(NodeEx node, Configuration config) {
}
pragma[nomagic]
private predicate sourceNode(NodeEx node, Configuration config) { config.isSource(node.asNode()) }
private predicate sourceNode(NodeEx node, Configuration config) {
config.isSource(node.asNode()) and
not fullBarrier(node, config)
}
pragma[nomagic]
private predicate sinkNode(NodeEx node, Configuration config) { config.isSink(node.asNode()) }
/** Provides the relevant barriers for a step from `node1` to `node2`. */
pragma[inline]
private predicate stepFilter(NodeEx node1, NodeEx node2, Configuration config) {
not outBarrier(node1, config) and
not inBarrier(node2, config) and
not fullBarrier(node1, config) and
not fullBarrier(node2, config)
}
/**
* Holds if data can flow in one local step from `node1` to `node2`.
*/
@@ -320,16 +333,14 @@ private predicate localFlowStep(NodeEx node1, NodeEx node2, Configuration config
node1.asNode() = n1 and
node2.asNode() = n2 and
simpleLocalFlowStepExt(n1, n2) and
not outBarrier(node1, config) and
not inBarrier(node2, config) and
not fullBarrier(node1, config) and
not fullBarrier(node2, config)
stepFilter(node1, node2, config)
)
or
exists(Node n |
config.allowImplicitRead(n, _) and
node1.asNode() = n and
node2.isImplicitReadNode(n, false)
node2.isImplicitReadNode(n, false) and
not fullBarrier(node1, config)
)
}
@@ -342,16 +353,14 @@ private predicate additionalLocalFlowStep(NodeEx node1, NodeEx node2, Configurat
node2.asNode() = n2 and
config.isAdditionalFlowStep(n1, n2) and
getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and
not outBarrier(node1, config) and
not inBarrier(node2, config) and
not fullBarrier(node1, config) and
not fullBarrier(node2, config)
stepFilter(node1, node2, config)
)
or
exists(Node n |
config.allowImplicitRead(n, _) and
node1.isImplicitReadNode(n, true) and
node2.asNode() = n
node2.asNode() = n and
not fullBarrier(node2, config)
)
}
@@ -363,10 +372,7 @@ private predicate jumpStep(NodeEx node1, NodeEx node2, Configuration config) {
node1.asNode() = n1 and
node2.asNode() = n2 and
jumpStepCached(n1, n2) and
not outBarrier(node1, config) and
not inBarrier(node2, config) and
not fullBarrier(node1, config) and
not fullBarrier(node2, config) and
stepFilter(node1, node2, config) and
not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext
)
}
@@ -380,16 +386,14 @@ private predicate additionalJumpStep(NodeEx node1, NodeEx node2, Configuration c
node2.asNode() = n2 and
config.isAdditionalFlowStep(n1, n2) and
getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and
not outBarrier(node1, config) and
not inBarrier(node2, config) and
not fullBarrier(node1, config) and
not fullBarrier(node2, config) and
stepFilter(node1, node2, config) and
not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext
)
}
private predicate read(NodeEx node1, Content c, NodeEx node2, Configuration config) {
read(node1.asNode(), c, node2.asNode())
read(node1.asNode(), c, node2.asNode()) and
stepFilter(node1, node2, config)
or
exists(Node n |
node2.isImplicitReadNode(n, true) and
@@ -402,7 +406,8 @@ private predicate store(
NodeEx node1, TypedContent tc, NodeEx node2, DataFlowType contentType, Configuration config
) {
store(node1.asNode(), tc, node2.asNode(), contentType) and
read(_, tc.getContent(), _, config)
read(_, tc.getContent(), _, config) and
stepFilter(node1, node2, config)
}
pragma[nomagic]
@@ -451,63 +456,59 @@ private module Stage1 {
* argument in a call.
*/
predicate fwdFlow(NodeEx node, Cc cc, Configuration config) {
not fullBarrier(node, config) and
(
sourceNode(node, config) and
if hasSourceCallCtx(config) then cc = true else cc = false
sourceNode(node, config) and
if hasSourceCallCtx(config) then cc = true else cc = false
or
exists(NodeEx mid |
fwdFlow(mid, cc, config) and
localFlowStep(mid, node, config)
)
or
exists(NodeEx mid |
fwdFlow(mid, cc, config) and
additionalLocalFlowStep(mid, node, config)
)
or
exists(NodeEx mid |
fwdFlow(mid, _, config) and
jumpStep(mid, node, config) and
cc = false
)
or
exists(NodeEx mid |
fwdFlow(mid, _, config) and
additionalJumpStep(mid, node, config) and
cc = false
)
or
// store
exists(NodeEx mid |
useFieldFlow(config) and
fwdFlow(mid, cc, config) and
store(mid, _, node, _, config)
)
or
// read
exists(Content c |
fwdFlowRead(c, node, cc, config) and
fwdFlowConsCand(c, config)
)
or
// flow into a callable
exists(NodeEx arg |
fwdFlow(arg, _, config) and
viableParamArgEx(_, node, arg) and
cc = true and
not fullBarrier(node, config)
)
or
// flow out of a callable
exists(DataFlowCall call |
fwdFlowOut(call, node, false, config) and
cc = false
or
exists(NodeEx mid |
fwdFlow(mid, cc, config) and
localFlowStep(mid, node, config)
)
or
exists(NodeEx mid |
fwdFlow(mid, cc, config) and
additionalLocalFlowStep(mid, node, config)
)
or
exists(NodeEx mid |
fwdFlow(mid, _, config) and
jumpStep(mid, node, config) and
cc = false
)
or
exists(NodeEx mid |
fwdFlow(mid, _, config) and
additionalJumpStep(mid, node, config) and
cc = false
)
or
// store
exists(NodeEx mid |
useFieldFlow(config) and
fwdFlow(mid, cc, config) and
store(mid, _, node, _, config) and
not outBarrier(mid, config)
)
or
// read
exists(Content c |
fwdFlowRead(c, node, cc, config) and
fwdFlowConsCand(c, config) and
not inBarrier(node, config)
)
or
// flow into a callable
exists(NodeEx arg |
fwdFlow(arg, _, config) and
viableParamArgEx(_, node, arg) and
cc = true
)
or
// flow out of a callable
exists(DataFlowCall call |
fwdFlowOut(call, node, false, config) and
cc = false
or
fwdFlowOutFromArg(call, node, config) and
fwdFlowIsEntered(call, cc, config)
)
fwdFlowOutFromArg(call, node, config) and
fwdFlowIsEntered(call, cc, config)
)
}
@@ -547,7 +548,8 @@ private module Stage1 {
private predicate fwdFlowOut(DataFlowCall call, NodeEx out, Cc cc, Configuration config) {
exists(ReturnPosition pos |
fwdFlowReturnPosition(pos, cc, config) and
viableReturnPosOutEx(call, pos, out)
viableReturnPosOutEx(call, pos, out) and
not fullBarrier(out, config)
)
}
@@ -773,6 +775,7 @@ private module Stage1 {
* Holds if flow may enter through `p` and reach a return node making `p` a
* candidate for the origin of a summary.
*/
pragma[nomagic]
predicate parameterMayFlowThrough(ParamNodeEx p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnKindExt kind |
throughFlowNodeCand(p, config) and
@@ -1019,12 +1022,14 @@ private module Stage2 {
pragma[nomagic]
private predicate flowThroughOutOfCall(
DataFlowCall call, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow, Configuration config
DataFlowCall call, CcCall ccc, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow,
Configuration config
) {
flowOutOfCall(call, ret, out, allowsFieldFlow, pragma[only_bind_into](config)) and
PrevStage::callMayFlowThroughRev(call, pragma[only_bind_into](config)) and
PrevStage::parameterMayFlowThrough(_, ret.getEnclosingCallable(), _,
pragma[only_bind_into](config))
pragma[only_bind_into](config)) and
ccc.matchesCall(call)
}
/**
@@ -1142,9 +1147,8 @@ private module Stage2 {
exists(ArgNodeEx arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc)
|
ap instanceof ApNil or allowsFieldFlow = true
innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc) and
if allowsFieldFlow = false then ap instanceof ApNil else any()
)
}
@@ -1159,9 +1163,8 @@ private module Stage2 {
fwdFlow(ret, innercc, argAp, ap, config) and
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
inner = ret.getEnclosingCallable() and
ccOut = getCallContextReturn(inner, call, innercc)
|
ap instanceof ApNil or allowsFieldFlow = true
ccOut = getCallContextReturn(inner, call, innercc) and
if allowsFieldFlow = false then ap instanceof ApNil else any()
)
}
@@ -1171,10 +1174,8 @@ private module Stage2 {
) {
exists(RetNodeEx ret, boolean allowsFieldFlow, CcCall ccc |
fwdFlow(ret, ccc, apSome(argAp), ap, config) and
flowThroughOutOfCall(call, ret, out, allowsFieldFlow, config) and
ccc.matchesCall(call)
|
ap instanceof ApNil or allowsFieldFlow = true
flowThroughOutOfCall(call, ccc, ret, out, allowsFieldFlow, config) and
if allowsFieldFlow = false then ap instanceof ApNil else any()
)
}
@@ -1230,6 +1231,11 @@ private module Stage2 {
callMayFlowThroughFwd(call, pragma[only_bind_into](config))
}
pragma[nomagic]
private predicate returnNodeMayFlowThrough(RetNodeEx ret, Ap ap, Configuration config) {
fwdFlow(ret, any(CcCall ccc), apSome(_), ap, config)
}
/**
* Holds if `node` with access path `ap` is part of a path from a source to a
* sink in the configuration `config`.
@@ -1306,7 +1312,7 @@ private module Stage2 {
// flow out of a callable
revFlowOut(_, node, _, _, ap, config) and
toReturn = true and
if fwdFlow(node, any(CcCall ccc), apSome(_), ap, config)
if returnNodeMayFlowThrough(node, ap, config)
then returnAp = apSome(ap)
else returnAp = apNone()
}
@@ -1341,9 +1347,8 @@ private module Stage2 {
) {
exists(NodeEx out, boolean allowsFieldFlow |
revFlow(out, toReturn, returnAp, ap, config) and
flowOutOfCall(call, ret, out, allowsFieldFlow, config)
|
ap instanceof ApNil or allowsFieldFlow = true
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
if allowsFieldFlow = false then ap instanceof ApNil else any()
)
}
@@ -1353,9 +1358,8 @@ private module Stage2 {
) {
exists(ParamNodeEx p, boolean allowsFieldFlow |
revFlow(p, false, returnAp, ap, config) and
flowIntoCall(_, arg, p, allowsFieldFlow, config)
|
ap instanceof ApNil or allowsFieldFlow = true
flowIntoCall(_, arg, p, allowsFieldFlow, config) and
if allowsFieldFlow = false then ap instanceof ApNil else any()
)
}
@@ -1365,9 +1369,8 @@ private module Stage2 {
) {
exists(ParamNodeEx p, boolean allowsFieldFlow |
revFlow(p, true, apSome(returnAp), ap, config) and
flowThroughIntoCall(call, arg, p, allowsFieldFlow, config)
|
ap instanceof ApNil or allowsFieldFlow = true
flowThroughIntoCall(call, arg, p, allowsFieldFlow, config) and
if allowsFieldFlow = false then ap instanceof ApNil else any()
)
}
@@ -1707,12 +1710,14 @@ private module Stage3 {
pragma[nomagic]
private predicate flowThroughOutOfCall(
DataFlowCall call, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow, Configuration config
DataFlowCall call, CcCall ccc, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow,
Configuration config
) {
flowOutOfCall(call, ret, out, allowsFieldFlow, pragma[only_bind_into](config)) and
PrevStage::callMayFlowThroughRev(call, pragma[only_bind_into](config)) and
PrevStage::parameterMayFlowThrough(_, ret.getEnclosingCallable(), _,
pragma[only_bind_into](config))
pragma[only_bind_into](config)) and
ccc.matchesCall(call)
}
/**
@@ -1837,9 +1842,8 @@ private module Stage3 {
exists(ArgNodeEx arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc)
|
ap instanceof ApNil or allowsFieldFlow = true
innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc) and
if allowsFieldFlow = false then ap instanceof ApNil else any()
)
}
@@ -1854,9 +1858,8 @@ private module Stage3 {
fwdFlow(ret, innercc, argAp, ap, config) and
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
inner = ret.getEnclosingCallable() and
ccOut = getCallContextReturn(inner, call, innercc)
|
ap instanceof ApNil or allowsFieldFlow = true
ccOut = getCallContextReturn(inner, call, innercc) and
if allowsFieldFlow = false then ap instanceof ApNil else any()
)
}
@@ -1866,10 +1869,8 @@ private module Stage3 {
) {
exists(RetNodeEx ret, boolean allowsFieldFlow, CcCall ccc |
fwdFlow(ret, ccc, apSome(argAp), ap, config) and
flowThroughOutOfCall(call, ret, out, allowsFieldFlow, config) and
ccc.matchesCall(call)
|
ap instanceof ApNil or allowsFieldFlow = true
flowThroughOutOfCall(call, ccc, ret, out, allowsFieldFlow, config) and
if allowsFieldFlow = false then ap instanceof ApNil else any()
)
}
@@ -1925,6 +1926,11 @@ private module Stage3 {
callMayFlowThroughFwd(call, pragma[only_bind_into](config))
}
pragma[nomagic]
private predicate returnNodeMayFlowThrough(RetNodeEx ret, Ap ap, Configuration config) {
fwdFlow(ret, any(CcCall ccc), apSome(_), ap, config)
}
/**
* Holds if `node` with access path `ap` is part of a path from a source to a
* sink in the configuration `config`.
@@ -2001,7 +2007,7 @@ private module Stage3 {
// flow out of a callable
revFlowOut(_, node, _, _, ap, config) and
toReturn = true and
if fwdFlow(node, any(CcCall ccc), apSome(_), ap, config)
if returnNodeMayFlowThrough(node, ap, config)
then returnAp = apSome(ap)
else returnAp = apNone()
}
@@ -2036,9 +2042,8 @@ private module Stage3 {
) {
exists(NodeEx out, boolean allowsFieldFlow |
revFlow(out, toReturn, returnAp, ap, config) and
flowOutOfCall(call, ret, out, allowsFieldFlow, config)
|
ap instanceof ApNil or allowsFieldFlow = true
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
if allowsFieldFlow = false then ap instanceof ApNil else any()
)
}
@@ -2048,9 +2053,8 @@ private module Stage3 {
) {
exists(ParamNodeEx p, boolean allowsFieldFlow |
revFlow(p, false, returnAp, ap, config) and
flowIntoCall(_, arg, p, allowsFieldFlow, config)
|
ap instanceof ApNil or allowsFieldFlow = true
flowIntoCall(_, arg, p, allowsFieldFlow, config) and
if allowsFieldFlow = false then ap instanceof ApNil else any()
)
}
@@ -2060,9 +2064,8 @@ private module Stage3 {
) {
exists(ParamNodeEx p, boolean allowsFieldFlow |
revFlow(p, true, apSome(returnAp), ap, config) and
flowThroughIntoCall(call, arg, p, allowsFieldFlow, config)
|
ap instanceof ApNil or allowsFieldFlow = true
flowThroughIntoCall(call, arg, p, allowsFieldFlow, config) and
if allowsFieldFlow = false then ap instanceof ApNil else any()
)
}
@@ -2473,12 +2476,14 @@ private module Stage4 {
pragma[nomagic]
private predicate flowThroughOutOfCall(
DataFlowCall call, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow, Configuration config
DataFlowCall call, CcCall ccc, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow,
Configuration config
) {
flowOutOfCall(call, ret, out, allowsFieldFlow, pragma[only_bind_into](config)) and
PrevStage::callMayFlowThroughRev(call, pragma[only_bind_into](config)) and
PrevStage::parameterMayFlowThrough(_, ret.getEnclosingCallable(), _,
pragma[only_bind_into](config))
pragma[only_bind_into](config)) and
ccc.matchesCall(call)
}
/**
@@ -2603,9 +2608,8 @@ private module Stage4 {
exists(ArgNodeEx arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc)
|
ap instanceof ApNil or allowsFieldFlow = true
innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc) and
if allowsFieldFlow = false then ap instanceof ApNil else any()
)
}
@@ -2620,9 +2624,8 @@ private module Stage4 {
fwdFlow(ret, innercc, argAp, ap, config) and
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
inner = ret.getEnclosingCallable() and
ccOut = getCallContextReturn(inner, call, innercc)
|
ap instanceof ApNil or allowsFieldFlow = true
ccOut = getCallContextReturn(inner, call, innercc) and
if allowsFieldFlow = false then ap instanceof ApNil else any()
)
}
@@ -2632,10 +2635,8 @@ private module Stage4 {
) {
exists(RetNodeEx ret, boolean allowsFieldFlow, CcCall ccc |
fwdFlow(ret, ccc, apSome(argAp), ap, config) and
flowThroughOutOfCall(call, ret, out, allowsFieldFlow, config) and
ccc.matchesCall(call)
|
ap instanceof ApNil or allowsFieldFlow = true
flowThroughOutOfCall(call, ccc, ret, out, allowsFieldFlow, config) and
if allowsFieldFlow = false then ap instanceof ApNil else any()
)
}
@@ -2691,6 +2692,11 @@ private module Stage4 {
callMayFlowThroughFwd(call, pragma[only_bind_into](config))
}
pragma[nomagic]
private predicate returnNodeMayFlowThrough(RetNodeEx ret, Ap ap, Configuration config) {
fwdFlow(ret, any(CcCall ccc), apSome(_), ap, config)
}
/**
* Holds if `node` with access path `ap` is part of a path from a source to a
* sink in the configuration `config`.
@@ -2767,7 +2773,7 @@ private module Stage4 {
// flow out of a callable
revFlowOut(_, node, _, _, ap, config) and
toReturn = true and
if fwdFlow(node, any(CcCall ccc), apSome(_), ap, config)
if returnNodeMayFlowThrough(node, ap, config)
then returnAp = apSome(ap)
else returnAp = apNone()
}
@@ -2802,9 +2808,8 @@ private module Stage4 {
) {
exists(NodeEx out, boolean allowsFieldFlow |
revFlow(out, toReturn, returnAp, ap, config) and
flowOutOfCall(call, ret, out, allowsFieldFlow, config)
|
ap instanceof ApNil or allowsFieldFlow = true
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
if allowsFieldFlow = false then ap instanceof ApNil else any()
)
}
@@ -2814,9 +2819,8 @@ private module Stage4 {
) {
exists(ParamNodeEx p, boolean allowsFieldFlow |
revFlow(p, false, returnAp, ap, config) and
flowIntoCall(_, arg, p, allowsFieldFlow, config)
|
ap instanceof ApNil or allowsFieldFlow = true
flowIntoCall(_, arg, p, allowsFieldFlow, config) and
if allowsFieldFlow = false then ap instanceof ApNil else any()
)
}
@@ -2826,9 +2830,8 @@ private module Stage4 {
) {
exists(ParamNodeEx p, boolean allowsFieldFlow |
revFlow(p, true, apSome(returnAp), ap, config) and
flowThroughIntoCall(call, arg, p, allowsFieldFlow, config)
|
ap instanceof ApNil or allowsFieldFlow = true
flowThroughIntoCall(call, arg, p, allowsFieldFlow, config) and
if allowsFieldFlow = false then ap instanceof ApNil else any()
)
}

View File

@@ -289,6 +289,7 @@ private predicate outBarrier(NodeEx node, Configuration config) {
)
}
pragma[nomagic]
private predicate fullBarrier(NodeEx node, Configuration config) {
exists(Node n | node.asNode() = n |
config.isBarrier(n)
@@ -307,11 +308,23 @@ private predicate fullBarrier(NodeEx node, Configuration config) {
}
pragma[nomagic]
private predicate sourceNode(NodeEx node, Configuration config) { config.isSource(node.asNode()) }
private predicate sourceNode(NodeEx node, Configuration config) {
config.isSource(node.asNode()) and
not fullBarrier(node, config)
}
pragma[nomagic]
private predicate sinkNode(NodeEx node, Configuration config) { config.isSink(node.asNode()) }
/** Provides the relevant barriers for a step from `node1` to `node2`. */
pragma[inline]
private predicate stepFilter(NodeEx node1, NodeEx node2, Configuration config) {
not outBarrier(node1, config) and
not inBarrier(node2, config) and
not fullBarrier(node1, config) and
not fullBarrier(node2, config)
}
/**
* Holds if data can flow in one local step from `node1` to `node2`.
*/
@@ -320,16 +333,14 @@ private predicate localFlowStep(NodeEx node1, NodeEx node2, Configuration config
node1.asNode() = n1 and
node2.asNode() = n2 and
simpleLocalFlowStepExt(n1, n2) and
not outBarrier(node1, config) and
not inBarrier(node2, config) and
not fullBarrier(node1, config) and
not fullBarrier(node2, config)
stepFilter(node1, node2, config)
)
or
exists(Node n |
config.allowImplicitRead(n, _) and
node1.asNode() = n and
node2.isImplicitReadNode(n, false)
node2.isImplicitReadNode(n, false) and
not fullBarrier(node1, config)
)
}
@@ -342,16 +353,14 @@ private predicate additionalLocalFlowStep(NodeEx node1, NodeEx node2, Configurat
node2.asNode() = n2 and
config.isAdditionalFlowStep(n1, n2) and
getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and
not outBarrier(node1, config) and
not inBarrier(node2, config) and
not fullBarrier(node1, config) and
not fullBarrier(node2, config)
stepFilter(node1, node2, config)
)
or
exists(Node n |
config.allowImplicitRead(n, _) and
node1.isImplicitReadNode(n, true) and
node2.asNode() = n
node2.asNode() = n and
not fullBarrier(node2, config)
)
}
@@ -363,10 +372,7 @@ private predicate jumpStep(NodeEx node1, NodeEx node2, Configuration config) {
node1.asNode() = n1 and
node2.asNode() = n2 and
jumpStepCached(n1, n2) and
not outBarrier(node1, config) and
not inBarrier(node2, config) and
not fullBarrier(node1, config) and
not fullBarrier(node2, config) and
stepFilter(node1, node2, config) and
not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext
)
}
@@ -380,16 +386,14 @@ private predicate additionalJumpStep(NodeEx node1, NodeEx node2, Configuration c
node2.asNode() = n2 and
config.isAdditionalFlowStep(n1, n2) and
getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and
not outBarrier(node1, config) and
not inBarrier(node2, config) and
not fullBarrier(node1, config) and
not fullBarrier(node2, config) and
stepFilter(node1, node2, config) and
not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext
)
}
private predicate read(NodeEx node1, Content c, NodeEx node2, Configuration config) {
read(node1.asNode(), c, node2.asNode())
read(node1.asNode(), c, node2.asNode()) and
stepFilter(node1, node2, config)
or
exists(Node n |
node2.isImplicitReadNode(n, true) and
@@ -402,7 +406,8 @@ private predicate store(
NodeEx node1, TypedContent tc, NodeEx node2, DataFlowType contentType, Configuration config
) {
store(node1.asNode(), tc, node2.asNode(), contentType) and
read(_, tc.getContent(), _, config)
read(_, tc.getContent(), _, config) and
stepFilter(node1, node2, config)
}
pragma[nomagic]
@@ -451,63 +456,59 @@ private module Stage1 {
* argument in a call.
*/
predicate fwdFlow(NodeEx node, Cc cc, Configuration config) {
not fullBarrier(node, config) and
(
sourceNode(node, config) and
if hasSourceCallCtx(config) then cc = true else cc = false
sourceNode(node, config) and
if hasSourceCallCtx(config) then cc = true else cc = false
or
exists(NodeEx mid |
fwdFlow(mid, cc, config) and
localFlowStep(mid, node, config)
)
or
exists(NodeEx mid |
fwdFlow(mid, cc, config) and
additionalLocalFlowStep(mid, node, config)
)
or
exists(NodeEx mid |
fwdFlow(mid, _, config) and
jumpStep(mid, node, config) and
cc = false
)
or
exists(NodeEx mid |
fwdFlow(mid, _, config) and
additionalJumpStep(mid, node, config) and
cc = false
)
or
// store
exists(NodeEx mid |
useFieldFlow(config) and
fwdFlow(mid, cc, config) and
store(mid, _, node, _, config)
)
or
// read
exists(Content c |
fwdFlowRead(c, node, cc, config) and
fwdFlowConsCand(c, config)
)
or
// flow into a callable
exists(NodeEx arg |
fwdFlow(arg, _, config) and
viableParamArgEx(_, node, arg) and
cc = true and
not fullBarrier(node, config)
)
or
// flow out of a callable
exists(DataFlowCall call |
fwdFlowOut(call, node, false, config) and
cc = false
or
exists(NodeEx mid |
fwdFlow(mid, cc, config) and
localFlowStep(mid, node, config)
)
or
exists(NodeEx mid |
fwdFlow(mid, cc, config) and
additionalLocalFlowStep(mid, node, config)
)
or
exists(NodeEx mid |
fwdFlow(mid, _, config) and
jumpStep(mid, node, config) and
cc = false
)
or
exists(NodeEx mid |
fwdFlow(mid, _, config) and
additionalJumpStep(mid, node, config) and
cc = false
)
or
// store
exists(NodeEx mid |
useFieldFlow(config) and
fwdFlow(mid, cc, config) and
store(mid, _, node, _, config) and
not outBarrier(mid, config)
)
or
// read
exists(Content c |
fwdFlowRead(c, node, cc, config) and
fwdFlowConsCand(c, config) and
not inBarrier(node, config)
)
or
// flow into a callable
exists(NodeEx arg |
fwdFlow(arg, _, config) and
viableParamArgEx(_, node, arg) and
cc = true
)
or
// flow out of a callable
exists(DataFlowCall call |
fwdFlowOut(call, node, false, config) and
cc = false
or
fwdFlowOutFromArg(call, node, config) and
fwdFlowIsEntered(call, cc, config)
)
fwdFlowOutFromArg(call, node, config) and
fwdFlowIsEntered(call, cc, config)
)
}
@@ -547,7 +548,8 @@ private module Stage1 {
private predicate fwdFlowOut(DataFlowCall call, NodeEx out, Cc cc, Configuration config) {
exists(ReturnPosition pos |
fwdFlowReturnPosition(pos, cc, config) and
viableReturnPosOutEx(call, pos, out)
viableReturnPosOutEx(call, pos, out) and
not fullBarrier(out, config)
)
}
@@ -773,6 +775,7 @@ private module Stage1 {
* Holds if flow may enter through `p` and reach a return node making `p` a
* candidate for the origin of a summary.
*/
pragma[nomagic]
predicate parameterMayFlowThrough(ParamNodeEx p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnKindExt kind |
throughFlowNodeCand(p, config) and
@@ -1019,12 +1022,14 @@ private module Stage2 {
pragma[nomagic]
private predicate flowThroughOutOfCall(
DataFlowCall call, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow, Configuration config
DataFlowCall call, CcCall ccc, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow,
Configuration config
) {
flowOutOfCall(call, ret, out, allowsFieldFlow, pragma[only_bind_into](config)) and
PrevStage::callMayFlowThroughRev(call, pragma[only_bind_into](config)) and
PrevStage::parameterMayFlowThrough(_, ret.getEnclosingCallable(), _,
pragma[only_bind_into](config))
pragma[only_bind_into](config)) and
ccc.matchesCall(call)
}
/**
@@ -1142,9 +1147,8 @@ private module Stage2 {
exists(ArgNodeEx arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc)
|
ap instanceof ApNil or allowsFieldFlow = true
innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc) and
if allowsFieldFlow = false then ap instanceof ApNil else any()
)
}
@@ -1159,9 +1163,8 @@ private module Stage2 {
fwdFlow(ret, innercc, argAp, ap, config) and
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
inner = ret.getEnclosingCallable() and
ccOut = getCallContextReturn(inner, call, innercc)
|
ap instanceof ApNil or allowsFieldFlow = true
ccOut = getCallContextReturn(inner, call, innercc) and
if allowsFieldFlow = false then ap instanceof ApNil else any()
)
}
@@ -1171,10 +1174,8 @@ private module Stage2 {
) {
exists(RetNodeEx ret, boolean allowsFieldFlow, CcCall ccc |
fwdFlow(ret, ccc, apSome(argAp), ap, config) and
flowThroughOutOfCall(call, ret, out, allowsFieldFlow, config) and
ccc.matchesCall(call)
|
ap instanceof ApNil or allowsFieldFlow = true
flowThroughOutOfCall(call, ccc, ret, out, allowsFieldFlow, config) and
if allowsFieldFlow = false then ap instanceof ApNil else any()
)
}
@@ -1230,6 +1231,11 @@ private module Stage2 {
callMayFlowThroughFwd(call, pragma[only_bind_into](config))
}
pragma[nomagic]
private predicate returnNodeMayFlowThrough(RetNodeEx ret, Ap ap, Configuration config) {
fwdFlow(ret, any(CcCall ccc), apSome(_), ap, config)
}
/**
* Holds if `node` with access path `ap` is part of a path from a source to a
* sink in the configuration `config`.
@@ -1306,7 +1312,7 @@ private module Stage2 {
// flow out of a callable
revFlowOut(_, node, _, _, ap, config) and
toReturn = true and
if fwdFlow(node, any(CcCall ccc), apSome(_), ap, config)
if returnNodeMayFlowThrough(node, ap, config)
then returnAp = apSome(ap)
else returnAp = apNone()
}
@@ -1341,9 +1347,8 @@ private module Stage2 {
) {
exists(NodeEx out, boolean allowsFieldFlow |
revFlow(out, toReturn, returnAp, ap, config) and
flowOutOfCall(call, ret, out, allowsFieldFlow, config)
|
ap instanceof ApNil or allowsFieldFlow = true
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
if allowsFieldFlow = false then ap instanceof ApNil else any()
)
}
@@ -1353,9 +1358,8 @@ private module Stage2 {
) {
exists(ParamNodeEx p, boolean allowsFieldFlow |
revFlow(p, false, returnAp, ap, config) and
flowIntoCall(_, arg, p, allowsFieldFlow, config)
|
ap instanceof ApNil or allowsFieldFlow = true
flowIntoCall(_, arg, p, allowsFieldFlow, config) and
if allowsFieldFlow = false then ap instanceof ApNil else any()
)
}
@@ -1365,9 +1369,8 @@ private module Stage2 {
) {
exists(ParamNodeEx p, boolean allowsFieldFlow |
revFlow(p, true, apSome(returnAp), ap, config) and
flowThroughIntoCall(call, arg, p, allowsFieldFlow, config)
|
ap instanceof ApNil or allowsFieldFlow = true
flowThroughIntoCall(call, arg, p, allowsFieldFlow, config) and
if allowsFieldFlow = false then ap instanceof ApNil else any()
)
}
@@ -1707,12 +1710,14 @@ private module Stage3 {
pragma[nomagic]
private predicate flowThroughOutOfCall(
DataFlowCall call, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow, Configuration config
DataFlowCall call, CcCall ccc, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow,
Configuration config
) {
flowOutOfCall(call, ret, out, allowsFieldFlow, pragma[only_bind_into](config)) and
PrevStage::callMayFlowThroughRev(call, pragma[only_bind_into](config)) and
PrevStage::parameterMayFlowThrough(_, ret.getEnclosingCallable(), _,
pragma[only_bind_into](config))
pragma[only_bind_into](config)) and
ccc.matchesCall(call)
}
/**
@@ -1837,9 +1842,8 @@ private module Stage3 {
exists(ArgNodeEx arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc)
|
ap instanceof ApNil or allowsFieldFlow = true
innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc) and
if allowsFieldFlow = false then ap instanceof ApNil else any()
)
}
@@ -1854,9 +1858,8 @@ private module Stage3 {
fwdFlow(ret, innercc, argAp, ap, config) and
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
inner = ret.getEnclosingCallable() and
ccOut = getCallContextReturn(inner, call, innercc)
|
ap instanceof ApNil or allowsFieldFlow = true
ccOut = getCallContextReturn(inner, call, innercc) and
if allowsFieldFlow = false then ap instanceof ApNil else any()
)
}
@@ -1866,10 +1869,8 @@ private module Stage3 {
) {
exists(RetNodeEx ret, boolean allowsFieldFlow, CcCall ccc |
fwdFlow(ret, ccc, apSome(argAp), ap, config) and
flowThroughOutOfCall(call, ret, out, allowsFieldFlow, config) and
ccc.matchesCall(call)
|
ap instanceof ApNil or allowsFieldFlow = true
flowThroughOutOfCall(call, ccc, ret, out, allowsFieldFlow, config) and
if allowsFieldFlow = false then ap instanceof ApNil else any()
)
}
@@ -1925,6 +1926,11 @@ private module Stage3 {
callMayFlowThroughFwd(call, pragma[only_bind_into](config))
}
pragma[nomagic]
private predicate returnNodeMayFlowThrough(RetNodeEx ret, Ap ap, Configuration config) {
fwdFlow(ret, any(CcCall ccc), apSome(_), ap, config)
}
/**
* Holds if `node` with access path `ap` is part of a path from a source to a
* sink in the configuration `config`.
@@ -2001,7 +2007,7 @@ private module Stage3 {
// flow out of a callable
revFlowOut(_, node, _, _, ap, config) and
toReturn = true and
if fwdFlow(node, any(CcCall ccc), apSome(_), ap, config)
if returnNodeMayFlowThrough(node, ap, config)
then returnAp = apSome(ap)
else returnAp = apNone()
}
@@ -2036,9 +2042,8 @@ private module Stage3 {
) {
exists(NodeEx out, boolean allowsFieldFlow |
revFlow(out, toReturn, returnAp, ap, config) and
flowOutOfCall(call, ret, out, allowsFieldFlow, config)
|
ap instanceof ApNil or allowsFieldFlow = true
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
if allowsFieldFlow = false then ap instanceof ApNil else any()
)
}
@@ -2048,9 +2053,8 @@ private module Stage3 {
) {
exists(ParamNodeEx p, boolean allowsFieldFlow |
revFlow(p, false, returnAp, ap, config) and
flowIntoCall(_, arg, p, allowsFieldFlow, config)
|
ap instanceof ApNil or allowsFieldFlow = true
flowIntoCall(_, arg, p, allowsFieldFlow, config) and
if allowsFieldFlow = false then ap instanceof ApNil else any()
)
}
@@ -2060,9 +2064,8 @@ private module Stage3 {
) {
exists(ParamNodeEx p, boolean allowsFieldFlow |
revFlow(p, true, apSome(returnAp), ap, config) and
flowThroughIntoCall(call, arg, p, allowsFieldFlow, config)
|
ap instanceof ApNil or allowsFieldFlow = true
flowThroughIntoCall(call, arg, p, allowsFieldFlow, config) and
if allowsFieldFlow = false then ap instanceof ApNil else any()
)
}
@@ -2473,12 +2476,14 @@ private module Stage4 {
pragma[nomagic]
private predicate flowThroughOutOfCall(
DataFlowCall call, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow, Configuration config
DataFlowCall call, CcCall ccc, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow,
Configuration config
) {
flowOutOfCall(call, ret, out, allowsFieldFlow, pragma[only_bind_into](config)) and
PrevStage::callMayFlowThroughRev(call, pragma[only_bind_into](config)) and
PrevStage::parameterMayFlowThrough(_, ret.getEnclosingCallable(), _,
pragma[only_bind_into](config))
pragma[only_bind_into](config)) and
ccc.matchesCall(call)
}
/**
@@ -2603,9 +2608,8 @@ private module Stage4 {
exists(ArgNodeEx arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc)
|
ap instanceof ApNil or allowsFieldFlow = true
innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc) and
if allowsFieldFlow = false then ap instanceof ApNil else any()
)
}
@@ -2620,9 +2624,8 @@ private module Stage4 {
fwdFlow(ret, innercc, argAp, ap, config) and
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
inner = ret.getEnclosingCallable() and
ccOut = getCallContextReturn(inner, call, innercc)
|
ap instanceof ApNil or allowsFieldFlow = true
ccOut = getCallContextReturn(inner, call, innercc) and
if allowsFieldFlow = false then ap instanceof ApNil else any()
)
}
@@ -2632,10 +2635,8 @@ private module Stage4 {
) {
exists(RetNodeEx ret, boolean allowsFieldFlow, CcCall ccc |
fwdFlow(ret, ccc, apSome(argAp), ap, config) and
flowThroughOutOfCall(call, ret, out, allowsFieldFlow, config) and
ccc.matchesCall(call)
|
ap instanceof ApNil or allowsFieldFlow = true
flowThroughOutOfCall(call, ccc, ret, out, allowsFieldFlow, config) and
if allowsFieldFlow = false then ap instanceof ApNil else any()
)
}
@@ -2691,6 +2692,11 @@ private module Stage4 {
callMayFlowThroughFwd(call, pragma[only_bind_into](config))
}
pragma[nomagic]
private predicate returnNodeMayFlowThrough(RetNodeEx ret, Ap ap, Configuration config) {
fwdFlow(ret, any(CcCall ccc), apSome(_), ap, config)
}
/**
* Holds if `node` with access path `ap` is part of a path from a source to a
* sink in the configuration `config`.
@@ -2767,7 +2773,7 @@ private module Stage4 {
// flow out of a callable
revFlowOut(_, node, _, _, ap, config) and
toReturn = true and
if fwdFlow(node, any(CcCall ccc), apSome(_), ap, config)
if returnNodeMayFlowThrough(node, ap, config)
then returnAp = apSome(ap)
else returnAp = apNone()
}
@@ -2802,9 +2808,8 @@ private module Stage4 {
) {
exists(NodeEx out, boolean allowsFieldFlow |
revFlow(out, toReturn, returnAp, ap, config) and
flowOutOfCall(call, ret, out, allowsFieldFlow, config)
|
ap instanceof ApNil or allowsFieldFlow = true
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
if allowsFieldFlow = false then ap instanceof ApNil else any()
)
}
@@ -2814,9 +2819,8 @@ private module Stage4 {
) {
exists(ParamNodeEx p, boolean allowsFieldFlow |
revFlow(p, false, returnAp, ap, config) and
flowIntoCall(_, arg, p, allowsFieldFlow, config)
|
ap instanceof ApNil or allowsFieldFlow = true
flowIntoCall(_, arg, p, allowsFieldFlow, config) and
if allowsFieldFlow = false then ap instanceof ApNil else any()
)
}
@@ -2826,9 +2830,8 @@ private module Stage4 {
) {
exists(ParamNodeEx p, boolean allowsFieldFlow |
revFlow(p, true, apSome(returnAp), ap, config) and
flowThroughIntoCall(call, arg, p, allowsFieldFlow, config)
|
ap instanceof ApNil or allowsFieldFlow = true
flowThroughIntoCall(call, arg, p, allowsFieldFlow, config) and
if allowsFieldFlow = false then ap instanceof ApNil else any()
)
}