Data flow: Sync files

This commit is contained in:
Tom Hvitved
2022-11-24 15:07:45 +01:00
parent c65780ee99
commit cde05e1190
43 changed files with 5894 additions and 4814 deletions

View File

@@ -613,11 +613,28 @@ private predicate hasSinkCallCtx(Configuration config) {
* explicitly allowed
*/
bindingset[p, kind]
private predicate parameterFlowThroughAllowed(ParamNode p, ReturnKindExt kind) {
private predicate parameterFlowThroughAllowed(ParamNodeEx p, ReturnKindExt kind) {
exists(ParameterPosition pos | p.isParameterOf(_, pos) |
not kind.(ParamUpdateReturnKind).getPosition() = pos
or
allowParameterReturnInSelfCached(p)
allowParameterReturnInSelfCached(p.asNode())
)
}
/**
* Holds if flow from a parameter at position `pos` inside `c` to a return node of
* kind `kind` is allowed.
*
* We don't expect a parameter to return stored in itself, unless
* explicitly allowed
*/
bindingset[c, pos, kind]
private predicate parameterFlowThroughAllowed(
DataFlowCallable c, ParameterPosition pos, ReturnKindExt kind
) {
exists(ParamNodeEx p |
p.isParameterOf(c, pos) and
parameterFlowThroughAllowed(p, kind)
)
}
@@ -1000,14 +1017,14 @@ private module Stage1 implements StageSig {
returnFlowCallableNodeCand(c, kind, config) and
p.getEnclosingCallable() = c and
exists(ap) and
parameterFlowThroughAllowed(p.asNode(), kind)
parameterFlowThroughAllowed(p, kind)
)
}
pragma[nomagic]
predicate returnMayFlowThrough(RetNodeEx ret, ReturnPosition pos, Configuration config) {
predicate returnMayFlowThrough(RetNodeEx ret, ReturnKindExt kind, Configuration config) {
throughFlowNodeCand(ret, config) and
pos = ret.getReturnPosition()
kind = ret.getKind()
}
pragma[nomagic]
@@ -1066,13 +1083,16 @@ private predicate viableReturnPosOutNodeCand1(
*/
pragma[nomagic]
private predicate flowOutOfCallNodeCand1(
DataFlowCall call, RetNodeEx ret, ReturnPosition pos, NodeEx out, Configuration config
DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, Configuration config
) {
viableReturnPosOutNodeCand1(call, pos, out, config) and
pos = ret.getReturnPosition() and
Stage1::revFlow(ret, config) and
not outBarrier(ret, config) and
not inBarrier(out, config)
exists(ReturnPosition pos |
viableReturnPosOutNodeCand1(call, pos, out, config) and
pos = ret.getReturnPosition() and
kind = pos.getKind() and
Stage1::revFlow(ret, config) and
not outBarrier(ret, config) and
not inBarrier(out, config)
)
}
pragma[nomagic]
@@ -1102,6 +1122,7 @@ private predicate flowIntoCallNodeCand1(
* edge in the graph of paths between sources and sinks that ignores call
* contexts.
*/
pragma[nomagic]
private int branch(NodeEx n1, Configuration conf) {
result =
strictcount(NodeEx n |
@@ -1114,6 +1135,7 @@ private int branch(NodeEx n1, Configuration conf) {
* edge in the graph of paths between sources and sinks that ignores call
* contexts.
*/
pragma[nomagic]
private int join(NodeEx n2, Configuration conf) {
result =
strictcount(NodeEx n |
@@ -1130,10 +1152,10 @@ private int join(NodeEx n2, Configuration conf) {
*/
pragma[nomagic]
private predicate flowOutOfCallNodeCand1(
DataFlowCall call, RetNodeEx ret, ReturnPosition pos, NodeEx out, boolean allowsFieldFlow,
DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, boolean allowsFieldFlow,
Configuration config
) {
flowOutOfCallNodeCand1(call, ret, pos, out, pragma[only_bind_into](config)) and
flowOutOfCallNodeCand1(call, ret, kind, out, pragma[only_bind_into](config)) and
exists(int b, int j |
b = branch(ret, pragma[only_bind_into](config)) and
j = join(out, pragma[only_bind_into](config)) and
@@ -1152,10 +1174,10 @@ pragma[nomagic]
private predicate flowIntoCallNodeCand1(
DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Configuration config
) {
flowIntoCallNodeCand1(call, arg, p, config) and
flowIntoCallNodeCand1(call, arg, p, pragma[only_bind_into](config)) and
exists(int b, int j |
b = branch(arg, config) and
j = join(p, config) and
b = branch(arg, pragma[only_bind_into](config)) and
j = join(p, pragma[only_bind_into](config)) and
if b.minimum(j) <= config.fieldFlowBranchLimit()
then allowsFieldFlow = true
else allowsFieldFlow = false
@@ -1174,7 +1196,7 @@ private signature module StageSig {
predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap, Configuration config);
predicate returnMayFlowThrough(RetNodeEx ret, ReturnPosition pos, Configuration config);
predicate returnMayFlowThrough(RetNodeEx ret, ReturnKindExt kind, Configuration config);
predicate storeStepCand(
NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, DataFlowType contentType,
@@ -1240,7 +1262,7 @@ private module MkStage<StageSig PrevStage> {
);
predicate flowOutOfCall(
DataFlowCall call, RetNodeEx ret, ReturnPosition pos, NodeEx out, boolean allowsFieldFlow,
DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, boolean allowsFieldFlow,
Configuration config
);
@@ -1266,16 +1288,14 @@ private module MkStage<StageSig PrevStage> {
pragma[nomagic]
private predicate flowThroughOutOfCall(
DataFlowCall call, CcCall ccc, RetNodeEx ret, ReturnKindExt kind, NodeEx out,
boolean allowsFieldFlow, Configuration config
DataFlowCall call, DataFlowCallable c, CcCall ccc, RetNodeEx ret, ReturnKindExt kind,
NodeEx out, boolean allowsFieldFlow, Configuration config
) {
exists(ReturnPosition pos |
flowOutOfCall(call, ret, pos, out, allowsFieldFlow, pragma[only_bind_into](config)) and
kind = pos.getKind() and
PrevStage::callMayFlowThroughRev(call, pragma[only_bind_into](config)) and
PrevStage::returnMayFlowThrough(ret, pos, pragma[only_bind_into](config)) and
matchesCall(ccc, call)
)
flowOutOfCall(call, ret, kind, out, allowsFieldFlow, pragma[only_bind_into](config)) and
PrevStage::callMayFlowThroughRev(call, pragma[only_bind_into](config)) and
PrevStage::returnMayFlowThrough(ret, kind, pragma[only_bind_into](config)) and
matchesCall(ccc, call) and
c = ret.getEnclosingCallable()
}
/**
@@ -1284,12 +1304,12 @@ private module MkStage<StageSig PrevStage> {
*
* The call context `cc` records whether the node is reached through an
* argument in a call, and if so, `summaryCtx` and `argAp` record the
* corresponding parameter and access path of that argument, respectively.
* corresponding parameter position and access path of that argument, respectively.
*/
pragma[nomagic]
additional predicate fwdFlow(
NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap,
Configuration config
NodeEx node, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp,
Ap ap, Configuration config
) {
fwdFlow0(node, state, cc, summaryCtx, argAp, ap, config) and
PrevStage::revFlow(node, state, unbindApa(getApprox(ap)), config) and
@@ -1298,13 +1318,13 @@ private module MkStage<StageSig PrevStage> {
pragma[nomagic]
private predicate fwdFlow0(
NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap,
Configuration config
NodeEx node, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp,
Ap ap, Configuration config
) {
sourceNode(node, state, config) and
(if hasSourceCallCtx(config) then cc = ccSomeCall() else cc = ccNone()) and
argAp = apNone() and
summaryCtx = TParamNodeNone() and
summaryCtx = TParameterPositionNone() and
ap = getApNil(node)
or
exists(NodeEx mid, FlowState state0, Ap ap0, LocalCc localCc |
@@ -1322,7 +1342,7 @@ private module MkStage<StageSig PrevStage> {
fwdFlow(mid, pragma[only_bind_into](state), _, _, _, ap, pragma[only_bind_into](config)) and
jumpStep(mid, node, config) and
cc = ccNone() and
summaryCtx = TParamNodeNone() and
summaryCtx = TParameterPositionNone() and
argAp = apNone()
)
or
@@ -1330,7 +1350,7 @@ private module MkStage<StageSig PrevStage> {
fwdFlow(mid, state, _, _, _, nil, pragma[only_bind_into](config)) and
additionalJumpStep(mid, node, config) and
cc = ccNone() and
summaryCtx = TParamNodeNone() and
summaryCtx = TParameterPositionNone() and
argAp = apNone() and
ap = getApNil(node)
)
@@ -1339,7 +1359,7 @@ private module MkStage<StageSig PrevStage> {
fwdFlow(mid, state0, _, _, _, nil, pragma[only_bind_into](config)) and
additionalJumpStateStep(mid, state0, node, state, config) and
cc = ccNone() and
summaryCtx = TParamNodeNone() and
summaryCtx = TParameterPositionNone() and
argAp = apNone() and
ap = getApNil(node)
)
@@ -1362,17 +1382,27 @@ private module MkStage<StageSig PrevStage> {
apa = getApprox(ap) and
if PrevStage::parameterMayFlowThrough(node, apa, config)
then (
summaryCtx = TParamNodeSome(node.asNode()) and argAp = apSome(ap)
summaryCtx = TParameterPositionSome(node.(ParamNodeEx).getPosition()) and
argAp = apSome(ap)
) else (
summaryCtx = TParamNodeNone() and argAp = apNone()
summaryCtx = TParameterPositionNone() and argAp = apNone()
)
)
or
// flow out of a callable
fwdFlowOutNotFromArg(node, state, cc, summaryCtx, argAp, ap, config)
exists(
DataFlowCall call, RetNodeEx ret, boolean allowsFieldFlow, CcNoCall innercc,
DataFlowCallable inner
|
fwdFlow(ret, state, innercc, summaryCtx, argAp, ap, config) and
flowOutOfCall(call, ret, _, node, allowsFieldFlow, config) and
inner = ret.getEnclosingCallable() and
cc = getCallContextReturn(inner, call, innercc) and
if allowsFieldFlow = false then ap instanceof ApNil else any()
)
or
// flow through a callable
exists(DataFlowCall call, ParamNode summaryCtx0, Ap argAp0 |
exists(DataFlowCall call, ParameterPosition summaryCtx0, Ap argAp0 |
fwdFlowOutFromArg(call, node, state, summaryCtx0, argAp0, ap, config) and
fwdFlowIsEntered(call, cc, summaryCtx, argAp, summaryCtx0, argAp0, config)
)
@@ -1381,7 +1411,7 @@ private module MkStage<StageSig PrevStage> {
pragma[nomagic]
private predicate fwdFlowStore(
NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, FlowState state, Cc cc,
ParamNodeOption summaryCtx, ApOption argAp, Configuration config
ParameterPositionOption summaryCtx, ApOption argAp, Configuration config
) {
exists(DataFlowType contentType |
fwdFlow(node1, state, cc, summaryCtx, argAp, ap1, config) and
@@ -1406,7 +1436,7 @@ private module MkStage<StageSig PrevStage> {
pragma[nomagic]
private predicate fwdFlowRead(
Ap ap, Content c, NodeEx node1, NodeEx node2, FlowState state, Cc cc,
ParamNodeOption summaryCtx, ApOption argAp, Configuration config
ParameterPositionOption summaryCtx, ApOption argAp, Configuration config
) {
fwdFlow(node1, state, cc, summaryCtx, argAp, ap, config) and
PrevStage::readStepCand(node1, c, node2, config) and
@@ -1416,7 +1446,7 @@ private module MkStage<StageSig PrevStage> {
pragma[nomagic]
private predicate fwdFlowIn(
DataFlowCall call, ParamNodeEx p, FlowState state, Cc outercc, Cc innercc,
ParamNodeOption summaryCtx, ApOption argAp, Ap ap, Configuration config
ParameterPositionOption summaryCtx, ApOption argAp, Ap ap, Configuration config
) {
exists(ArgNodeEx arg, boolean allowsFieldFlow |
fwdFlow(arg, state, outercc, summaryCtx, argAp, ap, config) and
@@ -1427,32 +1457,19 @@ private module MkStage<StageSig PrevStage> {
}
pragma[nomagic]
private predicate fwdFlowOutNotFromArg(
NodeEx out, FlowState state, Cc ccOut, ParamNodeOption summaryCtx, ApOption argAp, Ap ap,
private predicate fwdFlowOutFromArg(
DataFlowCall call, NodeEx out, FlowState state, ParameterPosition summaryCtx, Ap argAp, Ap ap,
Configuration config
) {
exists(
DataFlowCall call, RetNodeEx ret, boolean allowsFieldFlow, CcNoCall innercc,
DataFlowCallable inner
DataFlowCallable c, RetNodeEx ret, ReturnKindExt kind, boolean allowsFieldFlow, CcCall ccc
|
fwdFlow(ret, state, innercc, summaryCtx, argAp, ap, config) and
flowOutOfCall(call, ret, _, out, allowsFieldFlow, config) and
inner = ret.getEnclosingCallable() and
ccOut = getCallContextReturn(inner, call, innercc) and
if allowsFieldFlow = false then ap instanceof ApNil else any()
)
}
pragma[nomagic]
private predicate fwdFlowOutFromArg(
DataFlowCall call, NodeEx out, FlowState state, ParamNode summaryCtx, Ap argAp, Ap ap,
Configuration config
) {
exists(RetNodeEx ret, ReturnKindExt kind, boolean allowsFieldFlow, CcCall ccc |
fwdFlow(ret, state, ccc, TParamNodeSome(summaryCtx), apSome(argAp), ap, config) and
flowThroughOutOfCall(call, ccc, ret, kind, out, allowsFieldFlow, config) and
fwdFlow(pragma[only_bind_into](ret), state, pragma[only_bind_into](ccc),
TParameterPositionSome(pragma[only_bind_into](summaryCtx)), apSome(argAp), ap, config) and
flowThroughOutOfCall(call, pragma[only_bind_into](c), ccc, ret, kind, out, allowsFieldFlow,
config) and
(if allowsFieldFlow = false then ap instanceof ApNil else any()) and
parameterFlowThroughAllowed(summaryCtx, kind)
parameterFlowThroughAllowed(c, pragma[only_bind_into](summaryCtx), kind)
)
}
@@ -1462,13 +1479,13 @@ private module MkStage<StageSig PrevStage> {
*/
pragma[nomagic]
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, ParamNode p, Ap ap,
Configuration config
DataFlowCall call, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp,
ParameterPosition pos, Ap ap, Configuration config
) {
exists(ParamNodeEx param |
fwdFlowIn(call, param, _, cc, _, summaryCtx, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(param, unbindApa(getApprox(ap)), config) and
p = param.asNode()
pos = param.getPosition()
)
}
@@ -1489,23 +1506,41 @@ private module MkStage<StageSig PrevStage> {
}
pragma[nomagic]
private predicate returnFlowsThrough(
RetNodeEx ret, ReturnPosition pos, FlowState state, CcCall ccc, ParamNode p, Ap argAp, Ap ap,
Configuration config
private predicate returnFlowsThrough0(
RetNodeEx ret, ReturnKindExt kind, FlowState state, CcCall ccc, DataFlowCallable c,
ParameterPosition ppos, Ap argAp, Ap ap, Configuration config
) {
fwdFlow(ret, state, ccc, TParamNodeSome(p), apSome(argAp), ap, config) and
pos = ret.getReturnPosition() and
parameterFlowThroughAllowed(p, pos.getKind())
exists(boolean allowsFieldFlow |
fwdFlow(ret, state, ccc, TParameterPositionSome(ppos), apSome(argAp), ap, config) and
flowThroughOutOfCall(_, c, _, pragma[only_bind_into](ret), kind, _, allowsFieldFlow,
pragma[only_bind_into](config)) and
if allowsFieldFlow = false then ap instanceof ApNil else any()
)
}
pragma[nomagic]
private predicate returnFlowsThrough(
RetNodeEx ret, ReturnKindExt kind, FlowState state, CcCall ccc, ParamNodeEx p, Ap argAp,
Ap ap, Configuration config
) {
exists(DataFlowCallable c, ParameterPosition ppos |
returnFlowsThrough0(ret, kind, state, ccc, c, ppos, argAp, ap, config) and
p.isParameterOf(c, ppos) and
parameterFlowThroughAllowed(p, kind)
)
}
pragma[nomagic]
private predicate flowThroughIntoCall(
DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Configuration config
) {
flowIntoCall(call, pragma[only_bind_into](arg), pragma[only_bind_into](p), allowsFieldFlow,
pragma[only_bind_into](config)) and
fwdFlow(arg, _, _, _, _, _, pragma[only_bind_into](config)) and
returnFlowsThrough(_, _, _, _, p.asNode(), _, _, pragma[only_bind_into](config))
exists(Ap argAp |
flowIntoCall(call, pragma[only_bind_into](arg), pragma[only_bind_into](p), allowsFieldFlow,
pragma[only_bind_into](config)) and
fwdFlow(arg, _, _, _, _, pragma[only_bind_into](argAp), pragma[only_bind_into](config)) and
returnFlowsThrough(_, _, _, _, p, pragma[only_bind_into](argAp), _,
pragma[only_bind_into](config))
)
}
/**
@@ -1591,21 +1626,25 @@ private module MkStage<StageSig PrevStage> {
)
or
// flow into a callable
revFlowInNotToReturn(node, state, returnAp, ap, config) and
returnCtx = TReturnCtxNone()
exists(ParamNodeEx p, boolean allowsFieldFlow |
revFlow(p, state, TReturnCtxNone(), returnAp, ap, config) and
flowIntoCall(_, node, p, allowsFieldFlow, config) and
(if allowsFieldFlow = false then ap instanceof ApNil else any()) and
returnCtx = TReturnCtxNone()
)
or
// flow through a callable
exists(DataFlowCall call, ReturnPosition returnPos0, Ap returnAp0 |
revFlowInToReturn(call, node, state, returnPos0, returnAp0, ap, config) and
revFlowIsReturned(call, returnCtx, returnAp, returnPos0, returnAp0, config)
exists(DataFlowCall call, ReturnKindExt returnKind0, Ap returnAp0 |
revFlowInToReturn(call, node, state, returnKind0, returnAp0, ap, config) and
revFlowIsReturned(call, returnCtx, returnAp, returnKind0, returnAp0, config)
)
or
// flow out of a callable
exists(ReturnPosition pos |
revFlowOut(_, node, pos, state, _, _, ap, config) and
if returnFlowsThrough(node, pos, state, _, _, _, ap, config)
exists(ReturnKindExt kind |
revFlowOut(_, node, kind, state, _, _, ap, config) and
if returnFlowsThrough(node, kind, state, _, _, _, ap, config)
then (
returnCtx = TReturnCtxMaybeFlowThrough(pos) and
returnCtx = TReturnCtxMaybeFlowThrough(kind) and
returnAp = apSome(ap)
) else (
returnCtx = TReturnCtxNoFlowThrough() and returnAp = apNone()
@@ -1638,37 +1677,27 @@ private module MkStage<StageSig PrevStage> {
pragma[nomagic]
private predicate revFlowOut(
DataFlowCall call, RetNodeEx ret, ReturnPosition pos, FlowState state, ReturnCtx returnCtx,
DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, FlowState state, ReturnCtx returnCtx,
ApOption returnAp, Ap ap, Configuration config
) {
exists(NodeEx out, boolean allowsFieldFlow |
revFlow(out, state, returnCtx, returnAp, ap, config) and
flowOutOfCall(call, ret, pos, out, allowsFieldFlow, config) and
if allowsFieldFlow = false then ap instanceof ApNil else any()
)
}
pragma[nomagic]
private predicate revFlowInNotToReturn(
ArgNodeEx arg, FlowState state, ApOption returnAp, Ap ap, Configuration config
) {
exists(ParamNodeEx p, boolean allowsFieldFlow |
revFlow(p, state, TReturnCtxNone(), returnAp, ap, config) and
flowIntoCall(_, arg, p, allowsFieldFlow, config) and
flowOutOfCall(call, ret, kind, out, allowsFieldFlow, config) and
if allowsFieldFlow = false then ap instanceof ApNil else any()
)
}
pragma[nomagic]
private predicate revFlowInToReturn(
DataFlowCall call, ArgNodeEx arg, FlowState state, ReturnPosition returnPos, Ap returnAp,
Ap ap, Configuration config
DataFlowCall call, ArgNodeEx arg, FlowState state, ReturnKindExt kind, Ap returnAp, Ap ap,
Configuration config
) {
exists(ParamNodeEx p, boolean allowsFieldFlow |
revFlow(p, state, TReturnCtxMaybeFlowThrough(returnPos), apSome(returnAp), ap, config) and
revFlow(pragma[only_bind_into](p), state,
TReturnCtxMaybeFlowThrough(pragma[only_bind_into](kind)), apSome(returnAp), ap, config) and
flowThroughIntoCall(call, arg, p, allowsFieldFlow, config) and
(if allowsFieldFlow = false then ap instanceof ApNil else any()) and
parameterFlowThroughAllowed(p.asNode(), returnPos.getKind())
parameterFlowThroughAllowed(p, kind)
)
}
@@ -1679,12 +1708,12 @@ private module MkStage<StageSig PrevStage> {
*/
pragma[nomagic]
private predicate revFlowIsReturned(
DataFlowCall call, ReturnCtx returnCtx, ApOption returnAp, ReturnPosition pos, Ap ap,
DataFlowCall call, ReturnCtx returnCtx, ApOption returnAp, ReturnKindExt kind, Ap ap,
Configuration config
) {
exists(RetNodeEx ret, FlowState state, CcCall ccc |
revFlowOut(call, ret, pos, state, returnCtx, returnAp, ap, config) and
returnFlowsThrough(ret, pos, state, ccc, _, _, ap, config) and
revFlowOut(call, ret, kind, state, returnCtx, returnAp, ap, config) and
returnFlowsThrough(ret, kind, state, ccc, _, _, ap, config) and
matchesCall(ccc, call)
)
}
@@ -1757,37 +1786,37 @@ private module MkStage<StageSig PrevStage> {
pragma[nomagic]
private predicate parameterFlowsThroughRev(
ParamNodeEx p, Ap ap, ReturnPosition returnPos, Configuration config
ParamNodeEx p, Ap ap, ReturnKindExt kind, Configuration config
) {
revFlow(p, _, TReturnCtxMaybeFlowThrough(returnPos), apSome(_), ap, config) and
parameterFlowThroughAllowed(p.asNode(), returnPos.getKind())
revFlow(p, _, TReturnCtxMaybeFlowThrough(kind), apSome(_), ap, config) and
parameterFlowThroughAllowed(p, kind)
}
pragma[nomagic]
predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap, Configuration config) {
exists(RetNodeEx ret, ReturnPosition pos |
returnFlowsThrough(ret, pos, _, _, p.asNode(), ap, _, config) and
parameterFlowsThroughRev(p, ap, pos, config)
exists(RetNodeEx ret, ReturnKindExt kind |
returnFlowsThrough(ret, kind, _, _, p, ap, _, config) and
parameterFlowsThroughRev(p, ap, kind, config)
)
}
pragma[nomagic]
predicate returnMayFlowThrough(RetNodeEx ret, ReturnPosition pos, Configuration config) {
predicate returnMayFlowThrough(RetNodeEx ret, ReturnKindExt kind, Configuration config) {
exists(ParamNodeEx p, Ap ap |
returnFlowsThrough(ret, pos, _, _, p.asNode(), ap, _, config) and
parameterFlowsThroughRev(p, ap, pos, config)
returnFlowsThrough(ret, kind, _, _, p, ap, _, config) and
parameterFlowsThroughRev(p, ap, kind, config)
)
}
pragma[nomagic]
predicate callMayFlowThroughRev(DataFlowCall call, Configuration config) {
exists(
ReturnPosition returnPos0, Ap returnAp0, ArgNodeEx arg, FlowState state,
ReturnKindExt returnKind0, Ap returnAp0, ArgNodeEx arg, FlowState state,
ReturnCtx returnCtx, ApOption returnAp, Ap ap
|
revFlow(arg, state, returnCtx, returnAp, ap, config) and
revFlowInToReturn(call, arg, state, returnPos0, returnAp0, ap, config) and
revFlowIsReturned(call, returnCtx, returnAp, returnPos0, returnAp0, config)
revFlowInToReturn(call, arg, state, returnKind0, returnAp0, ap, config) and
revFlowIsReturned(call, returnCtx, returnAp, returnKind0, returnAp0, config)
)
}
@@ -1800,9 +1829,8 @@ private module MkStage<StageSig PrevStage> {
conscand = count(TypedContent f0, Ap ap | fwdConsCand(f0, ap, config)) and
states = count(FlowState state | fwdFlow(_, state, _, _, _, _, config)) and
tuples =
count(NodeEx n, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap |
fwdFlow(n, state, cc, summaryCtx, argAp, ap, config)
)
count(NodeEx n, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp,
Ap ap | fwdFlow(n, state, cc, summaryCtx, argAp, ap, config))
or
fwd = false and
nodes = count(NodeEx node | revFlow(node, _, _, _, _, config)) and
@@ -1992,10 +2020,10 @@ private module Stage2 implements StageSig {
pragma[nomagic]
private predicate flowOutOfCallNodeCand2(
DataFlowCall call, RetNodeEx node1, ReturnPosition pos, NodeEx node2, boolean allowsFieldFlow,
DataFlowCall call, RetNodeEx node1, ReturnKindExt kind, NodeEx node2, boolean allowsFieldFlow,
Configuration config
) {
flowOutOfCallNodeCand1(call, node1, pos, node2, allowsFieldFlow, config) and
flowOutOfCallNodeCand1(call, node1, kind, node2, allowsFieldFlow, config) and
Stage2::revFlow(node2, pragma[only_bind_into](config)) and
Stage2::revFlowAlias(node1, pragma[only_bind_into](config))
}
@@ -2511,11 +2539,11 @@ private module Stage4Param implements MkStage<Stage3>::StageParam {
pragma[nomagic]
predicate flowOutOfCall(
DataFlowCall call, RetNodeEx node1, ReturnPosition pos, NodeEx node2, boolean allowsFieldFlow,
DataFlowCall call, RetNodeEx node1, ReturnKindExt kind, NodeEx node2, boolean allowsFieldFlow,
Configuration config
) {
exists(FlowState state |
flowOutOfCallNodeCand2(call, node1, pos, node2, allowsFieldFlow, config) and
flowOutOfCallNodeCand2(call, node1, kind, node2, allowsFieldFlow, config) and
PrevStage::revFlow(node2, pragma[only_bind_into](state), _, pragma[only_bind_into](config)) and
PrevStage::revFlowAlias(node1, pragma[only_bind_into](state), _,
pragma[only_bind_into](config))
@@ -2552,12 +2580,13 @@ private Configuration unbindConf(Configuration conf) {
pragma[nomagic]
private predicate nodeMayUseSummary0(
NodeEx n, ParamNodeEx p, FlowState state, AccessPathApprox apa, Configuration config
NodeEx n, DataFlowCallable c, ParameterPosition pos, FlowState state, AccessPathApprox apa,
Configuration config
) {
exists(AccessPathApprox apa0 |
Stage4::parameterMayFlowThrough(p, _, _) and
c = n.getEnclosingCallable() and
Stage4::revFlow(n, state, TReturnCtxMaybeFlowThrough(_), _, apa0, config) and
Stage4::fwdFlow(n, state, any(CallContextCall ccc), TParamNodeSome(p.asNode()),
Stage4::fwdFlow(n, state, any(CallContextCall ccc), TParameterPositionSome(pos),
TAccessPathApproxSome(apa), apa0, config)
)
}
@@ -2566,9 +2595,10 @@ pragma[nomagic]
private predicate nodeMayUseSummary(
NodeEx n, FlowState state, AccessPathApprox apa, Configuration config
) {
exists(ParamNodeEx p |
exists(DataFlowCallable c, ParameterPosition pos, ParamNodeEx p |
Stage4::parameterMayFlowThrough(p, apa, config) and
nodeMayUseSummary0(n, p, state, apa, config)
nodeMayUseSummary0(n, c, pos, state, apa, config) and
p.isParameterOf(c, pos)
)
}
@@ -3501,7 +3531,7 @@ private predicate paramFlowsThrough(
pathNode(mid, ret, state, cc, sc, ap, config, _) and
kind = ret.getKind() and
apa = ap.getApprox() and
parameterFlowThroughAllowed(sc.getParamNode().asNode(), kind)
parameterFlowThroughAllowed(sc.getParamNode(), kind)
)
}

View File

@@ -613,11 +613,28 @@ private predicate hasSinkCallCtx(Configuration config) {
* explicitly allowed
*/
bindingset[p, kind]
private predicate parameterFlowThroughAllowed(ParamNode p, ReturnKindExt kind) {
private predicate parameterFlowThroughAllowed(ParamNodeEx p, ReturnKindExt kind) {
exists(ParameterPosition pos | p.isParameterOf(_, pos) |
not kind.(ParamUpdateReturnKind).getPosition() = pos
or
allowParameterReturnInSelfCached(p)
allowParameterReturnInSelfCached(p.asNode())
)
}
/**
* Holds if flow from a parameter at position `pos` inside `c` to a return node of
* kind `kind` is allowed.
*
* We don't expect a parameter to return stored in itself, unless
* explicitly allowed
*/
bindingset[c, pos, kind]
private predicate parameterFlowThroughAllowed(
DataFlowCallable c, ParameterPosition pos, ReturnKindExt kind
) {
exists(ParamNodeEx p |
p.isParameterOf(c, pos) and
parameterFlowThroughAllowed(p, kind)
)
}
@@ -1000,14 +1017,14 @@ private module Stage1 implements StageSig {
returnFlowCallableNodeCand(c, kind, config) and
p.getEnclosingCallable() = c and
exists(ap) and
parameterFlowThroughAllowed(p.asNode(), kind)
parameterFlowThroughAllowed(p, kind)
)
}
pragma[nomagic]
predicate returnMayFlowThrough(RetNodeEx ret, ReturnPosition pos, Configuration config) {
predicate returnMayFlowThrough(RetNodeEx ret, ReturnKindExt kind, Configuration config) {
throughFlowNodeCand(ret, config) and
pos = ret.getReturnPosition()
kind = ret.getKind()
}
pragma[nomagic]
@@ -1066,13 +1083,16 @@ private predicate viableReturnPosOutNodeCand1(
*/
pragma[nomagic]
private predicate flowOutOfCallNodeCand1(
DataFlowCall call, RetNodeEx ret, ReturnPosition pos, NodeEx out, Configuration config
DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, Configuration config
) {
viableReturnPosOutNodeCand1(call, pos, out, config) and
pos = ret.getReturnPosition() and
Stage1::revFlow(ret, config) and
not outBarrier(ret, config) and
not inBarrier(out, config)
exists(ReturnPosition pos |
viableReturnPosOutNodeCand1(call, pos, out, config) and
pos = ret.getReturnPosition() and
kind = pos.getKind() and
Stage1::revFlow(ret, config) and
not outBarrier(ret, config) and
not inBarrier(out, config)
)
}
pragma[nomagic]
@@ -1102,6 +1122,7 @@ private predicate flowIntoCallNodeCand1(
* edge in the graph of paths between sources and sinks that ignores call
* contexts.
*/
pragma[nomagic]
private int branch(NodeEx n1, Configuration conf) {
result =
strictcount(NodeEx n |
@@ -1114,6 +1135,7 @@ private int branch(NodeEx n1, Configuration conf) {
* edge in the graph of paths between sources and sinks that ignores call
* contexts.
*/
pragma[nomagic]
private int join(NodeEx n2, Configuration conf) {
result =
strictcount(NodeEx n |
@@ -1130,10 +1152,10 @@ private int join(NodeEx n2, Configuration conf) {
*/
pragma[nomagic]
private predicate flowOutOfCallNodeCand1(
DataFlowCall call, RetNodeEx ret, ReturnPosition pos, NodeEx out, boolean allowsFieldFlow,
DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, boolean allowsFieldFlow,
Configuration config
) {
flowOutOfCallNodeCand1(call, ret, pos, out, pragma[only_bind_into](config)) and
flowOutOfCallNodeCand1(call, ret, kind, out, pragma[only_bind_into](config)) and
exists(int b, int j |
b = branch(ret, pragma[only_bind_into](config)) and
j = join(out, pragma[only_bind_into](config)) and
@@ -1152,10 +1174,10 @@ pragma[nomagic]
private predicate flowIntoCallNodeCand1(
DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Configuration config
) {
flowIntoCallNodeCand1(call, arg, p, config) and
flowIntoCallNodeCand1(call, arg, p, pragma[only_bind_into](config)) and
exists(int b, int j |
b = branch(arg, config) and
j = join(p, config) and
b = branch(arg, pragma[only_bind_into](config)) and
j = join(p, pragma[only_bind_into](config)) and
if b.minimum(j) <= config.fieldFlowBranchLimit()
then allowsFieldFlow = true
else allowsFieldFlow = false
@@ -1174,7 +1196,7 @@ private signature module StageSig {
predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap, Configuration config);
predicate returnMayFlowThrough(RetNodeEx ret, ReturnPosition pos, Configuration config);
predicate returnMayFlowThrough(RetNodeEx ret, ReturnKindExt kind, Configuration config);
predicate storeStepCand(
NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, DataFlowType contentType,
@@ -1240,7 +1262,7 @@ private module MkStage<StageSig PrevStage> {
);
predicate flowOutOfCall(
DataFlowCall call, RetNodeEx ret, ReturnPosition pos, NodeEx out, boolean allowsFieldFlow,
DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, boolean allowsFieldFlow,
Configuration config
);
@@ -1266,16 +1288,14 @@ private module MkStage<StageSig PrevStage> {
pragma[nomagic]
private predicate flowThroughOutOfCall(
DataFlowCall call, CcCall ccc, RetNodeEx ret, ReturnKindExt kind, NodeEx out,
boolean allowsFieldFlow, Configuration config
DataFlowCall call, DataFlowCallable c, CcCall ccc, RetNodeEx ret, ReturnKindExt kind,
NodeEx out, boolean allowsFieldFlow, Configuration config
) {
exists(ReturnPosition pos |
flowOutOfCall(call, ret, pos, out, allowsFieldFlow, pragma[only_bind_into](config)) and
kind = pos.getKind() and
PrevStage::callMayFlowThroughRev(call, pragma[only_bind_into](config)) and
PrevStage::returnMayFlowThrough(ret, pos, pragma[only_bind_into](config)) and
matchesCall(ccc, call)
)
flowOutOfCall(call, ret, kind, out, allowsFieldFlow, pragma[only_bind_into](config)) and
PrevStage::callMayFlowThroughRev(call, pragma[only_bind_into](config)) and
PrevStage::returnMayFlowThrough(ret, kind, pragma[only_bind_into](config)) and
matchesCall(ccc, call) and
c = ret.getEnclosingCallable()
}
/**
@@ -1284,12 +1304,12 @@ private module MkStage<StageSig PrevStage> {
*
* The call context `cc` records whether the node is reached through an
* argument in a call, and if so, `summaryCtx` and `argAp` record the
* corresponding parameter and access path of that argument, respectively.
* corresponding parameter position and access path of that argument, respectively.
*/
pragma[nomagic]
additional predicate fwdFlow(
NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap,
Configuration config
NodeEx node, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp,
Ap ap, Configuration config
) {
fwdFlow0(node, state, cc, summaryCtx, argAp, ap, config) and
PrevStage::revFlow(node, state, unbindApa(getApprox(ap)), config) and
@@ -1298,13 +1318,13 @@ private module MkStage<StageSig PrevStage> {
pragma[nomagic]
private predicate fwdFlow0(
NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap,
Configuration config
NodeEx node, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp,
Ap ap, Configuration config
) {
sourceNode(node, state, config) and
(if hasSourceCallCtx(config) then cc = ccSomeCall() else cc = ccNone()) and
argAp = apNone() and
summaryCtx = TParamNodeNone() and
summaryCtx = TParameterPositionNone() and
ap = getApNil(node)
or
exists(NodeEx mid, FlowState state0, Ap ap0, LocalCc localCc |
@@ -1322,7 +1342,7 @@ private module MkStage<StageSig PrevStage> {
fwdFlow(mid, pragma[only_bind_into](state), _, _, _, ap, pragma[only_bind_into](config)) and
jumpStep(mid, node, config) and
cc = ccNone() and
summaryCtx = TParamNodeNone() and
summaryCtx = TParameterPositionNone() and
argAp = apNone()
)
or
@@ -1330,7 +1350,7 @@ private module MkStage<StageSig PrevStage> {
fwdFlow(mid, state, _, _, _, nil, pragma[only_bind_into](config)) and
additionalJumpStep(mid, node, config) and
cc = ccNone() and
summaryCtx = TParamNodeNone() and
summaryCtx = TParameterPositionNone() and
argAp = apNone() and
ap = getApNil(node)
)
@@ -1339,7 +1359,7 @@ private module MkStage<StageSig PrevStage> {
fwdFlow(mid, state0, _, _, _, nil, pragma[only_bind_into](config)) and
additionalJumpStateStep(mid, state0, node, state, config) and
cc = ccNone() and
summaryCtx = TParamNodeNone() and
summaryCtx = TParameterPositionNone() and
argAp = apNone() and
ap = getApNil(node)
)
@@ -1362,17 +1382,27 @@ private module MkStage<StageSig PrevStage> {
apa = getApprox(ap) and
if PrevStage::parameterMayFlowThrough(node, apa, config)
then (
summaryCtx = TParamNodeSome(node.asNode()) and argAp = apSome(ap)
summaryCtx = TParameterPositionSome(node.(ParamNodeEx).getPosition()) and
argAp = apSome(ap)
) else (
summaryCtx = TParamNodeNone() and argAp = apNone()
summaryCtx = TParameterPositionNone() and argAp = apNone()
)
)
or
// flow out of a callable
fwdFlowOutNotFromArg(node, state, cc, summaryCtx, argAp, ap, config)
exists(
DataFlowCall call, RetNodeEx ret, boolean allowsFieldFlow, CcNoCall innercc,
DataFlowCallable inner
|
fwdFlow(ret, state, innercc, summaryCtx, argAp, ap, config) and
flowOutOfCall(call, ret, _, node, allowsFieldFlow, config) and
inner = ret.getEnclosingCallable() and
cc = getCallContextReturn(inner, call, innercc) and
if allowsFieldFlow = false then ap instanceof ApNil else any()
)
or
// flow through a callable
exists(DataFlowCall call, ParamNode summaryCtx0, Ap argAp0 |
exists(DataFlowCall call, ParameterPosition summaryCtx0, Ap argAp0 |
fwdFlowOutFromArg(call, node, state, summaryCtx0, argAp0, ap, config) and
fwdFlowIsEntered(call, cc, summaryCtx, argAp, summaryCtx0, argAp0, config)
)
@@ -1381,7 +1411,7 @@ private module MkStage<StageSig PrevStage> {
pragma[nomagic]
private predicate fwdFlowStore(
NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, FlowState state, Cc cc,
ParamNodeOption summaryCtx, ApOption argAp, Configuration config
ParameterPositionOption summaryCtx, ApOption argAp, Configuration config
) {
exists(DataFlowType contentType |
fwdFlow(node1, state, cc, summaryCtx, argAp, ap1, config) and
@@ -1406,7 +1436,7 @@ private module MkStage<StageSig PrevStage> {
pragma[nomagic]
private predicate fwdFlowRead(
Ap ap, Content c, NodeEx node1, NodeEx node2, FlowState state, Cc cc,
ParamNodeOption summaryCtx, ApOption argAp, Configuration config
ParameterPositionOption summaryCtx, ApOption argAp, Configuration config
) {
fwdFlow(node1, state, cc, summaryCtx, argAp, ap, config) and
PrevStage::readStepCand(node1, c, node2, config) and
@@ -1416,7 +1446,7 @@ private module MkStage<StageSig PrevStage> {
pragma[nomagic]
private predicate fwdFlowIn(
DataFlowCall call, ParamNodeEx p, FlowState state, Cc outercc, Cc innercc,
ParamNodeOption summaryCtx, ApOption argAp, Ap ap, Configuration config
ParameterPositionOption summaryCtx, ApOption argAp, Ap ap, Configuration config
) {
exists(ArgNodeEx arg, boolean allowsFieldFlow |
fwdFlow(arg, state, outercc, summaryCtx, argAp, ap, config) and
@@ -1427,32 +1457,19 @@ private module MkStage<StageSig PrevStage> {
}
pragma[nomagic]
private predicate fwdFlowOutNotFromArg(
NodeEx out, FlowState state, Cc ccOut, ParamNodeOption summaryCtx, ApOption argAp, Ap ap,
private predicate fwdFlowOutFromArg(
DataFlowCall call, NodeEx out, FlowState state, ParameterPosition summaryCtx, Ap argAp, Ap ap,
Configuration config
) {
exists(
DataFlowCall call, RetNodeEx ret, boolean allowsFieldFlow, CcNoCall innercc,
DataFlowCallable inner
DataFlowCallable c, RetNodeEx ret, ReturnKindExt kind, boolean allowsFieldFlow, CcCall ccc
|
fwdFlow(ret, state, innercc, summaryCtx, argAp, ap, config) and
flowOutOfCall(call, ret, _, out, allowsFieldFlow, config) and
inner = ret.getEnclosingCallable() and
ccOut = getCallContextReturn(inner, call, innercc) and
if allowsFieldFlow = false then ap instanceof ApNil else any()
)
}
pragma[nomagic]
private predicate fwdFlowOutFromArg(
DataFlowCall call, NodeEx out, FlowState state, ParamNode summaryCtx, Ap argAp, Ap ap,
Configuration config
) {
exists(RetNodeEx ret, ReturnKindExt kind, boolean allowsFieldFlow, CcCall ccc |
fwdFlow(ret, state, ccc, TParamNodeSome(summaryCtx), apSome(argAp), ap, config) and
flowThroughOutOfCall(call, ccc, ret, kind, out, allowsFieldFlow, config) and
fwdFlow(pragma[only_bind_into](ret), state, pragma[only_bind_into](ccc),
TParameterPositionSome(pragma[only_bind_into](summaryCtx)), apSome(argAp), ap, config) and
flowThroughOutOfCall(call, pragma[only_bind_into](c), ccc, ret, kind, out, allowsFieldFlow,
config) and
(if allowsFieldFlow = false then ap instanceof ApNil else any()) and
parameterFlowThroughAllowed(summaryCtx, kind)
parameterFlowThroughAllowed(c, pragma[only_bind_into](summaryCtx), kind)
)
}
@@ -1462,13 +1479,13 @@ private module MkStage<StageSig PrevStage> {
*/
pragma[nomagic]
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, ParamNode p, Ap ap,
Configuration config
DataFlowCall call, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp,
ParameterPosition pos, Ap ap, Configuration config
) {
exists(ParamNodeEx param |
fwdFlowIn(call, param, _, cc, _, summaryCtx, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(param, unbindApa(getApprox(ap)), config) and
p = param.asNode()
pos = param.getPosition()
)
}
@@ -1489,23 +1506,41 @@ private module MkStage<StageSig PrevStage> {
}
pragma[nomagic]
private predicate returnFlowsThrough(
RetNodeEx ret, ReturnPosition pos, FlowState state, CcCall ccc, ParamNode p, Ap argAp, Ap ap,
Configuration config
private predicate returnFlowsThrough0(
RetNodeEx ret, ReturnKindExt kind, FlowState state, CcCall ccc, DataFlowCallable c,
ParameterPosition ppos, Ap argAp, Ap ap, Configuration config
) {
fwdFlow(ret, state, ccc, TParamNodeSome(p), apSome(argAp), ap, config) and
pos = ret.getReturnPosition() and
parameterFlowThroughAllowed(p, pos.getKind())
exists(boolean allowsFieldFlow |
fwdFlow(ret, state, ccc, TParameterPositionSome(ppos), apSome(argAp), ap, config) and
flowThroughOutOfCall(_, c, _, pragma[only_bind_into](ret), kind, _, allowsFieldFlow,
pragma[only_bind_into](config)) and
if allowsFieldFlow = false then ap instanceof ApNil else any()
)
}
pragma[nomagic]
private predicate returnFlowsThrough(
RetNodeEx ret, ReturnKindExt kind, FlowState state, CcCall ccc, ParamNodeEx p, Ap argAp,
Ap ap, Configuration config
) {
exists(DataFlowCallable c, ParameterPosition ppos |
returnFlowsThrough0(ret, kind, state, ccc, c, ppos, argAp, ap, config) and
p.isParameterOf(c, ppos) and
parameterFlowThroughAllowed(p, kind)
)
}
pragma[nomagic]
private predicate flowThroughIntoCall(
DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Configuration config
) {
flowIntoCall(call, pragma[only_bind_into](arg), pragma[only_bind_into](p), allowsFieldFlow,
pragma[only_bind_into](config)) and
fwdFlow(arg, _, _, _, _, _, pragma[only_bind_into](config)) and
returnFlowsThrough(_, _, _, _, p.asNode(), _, _, pragma[only_bind_into](config))
exists(Ap argAp |
flowIntoCall(call, pragma[only_bind_into](arg), pragma[only_bind_into](p), allowsFieldFlow,
pragma[only_bind_into](config)) and
fwdFlow(arg, _, _, _, _, pragma[only_bind_into](argAp), pragma[only_bind_into](config)) and
returnFlowsThrough(_, _, _, _, p, pragma[only_bind_into](argAp), _,
pragma[only_bind_into](config))
)
}
/**
@@ -1591,21 +1626,25 @@ private module MkStage<StageSig PrevStage> {
)
or
// flow into a callable
revFlowInNotToReturn(node, state, returnAp, ap, config) and
returnCtx = TReturnCtxNone()
exists(ParamNodeEx p, boolean allowsFieldFlow |
revFlow(p, state, TReturnCtxNone(), returnAp, ap, config) and
flowIntoCall(_, node, p, allowsFieldFlow, config) and
(if allowsFieldFlow = false then ap instanceof ApNil else any()) and
returnCtx = TReturnCtxNone()
)
or
// flow through a callable
exists(DataFlowCall call, ReturnPosition returnPos0, Ap returnAp0 |
revFlowInToReturn(call, node, state, returnPos0, returnAp0, ap, config) and
revFlowIsReturned(call, returnCtx, returnAp, returnPos0, returnAp0, config)
exists(DataFlowCall call, ReturnKindExt returnKind0, Ap returnAp0 |
revFlowInToReturn(call, node, state, returnKind0, returnAp0, ap, config) and
revFlowIsReturned(call, returnCtx, returnAp, returnKind0, returnAp0, config)
)
or
// flow out of a callable
exists(ReturnPosition pos |
revFlowOut(_, node, pos, state, _, _, ap, config) and
if returnFlowsThrough(node, pos, state, _, _, _, ap, config)
exists(ReturnKindExt kind |
revFlowOut(_, node, kind, state, _, _, ap, config) and
if returnFlowsThrough(node, kind, state, _, _, _, ap, config)
then (
returnCtx = TReturnCtxMaybeFlowThrough(pos) and
returnCtx = TReturnCtxMaybeFlowThrough(kind) and
returnAp = apSome(ap)
) else (
returnCtx = TReturnCtxNoFlowThrough() and returnAp = apNone()
@@ -1638,37 +1677,27 @@ private module MkStage<StageSig PrevStage> {
pragma[nomagic]
private predicate revFlowOut(
DataFlowCall call, RetNodeEx ret, ReturnPosition pos, FlowState state, ReturnCtx returnCtx,
DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, FlowState state, ReturnCtx returnCtx,
ApOption returnAp, Ap ap, Configuration config
) {
exists(NodeEx out, boolean allowsFieldFlow |
revFlow(out, state, returnCtx, returnAp, ap, config) and
flowOutOfCall(call, ret, pos, out, allowsFieldFlow, config) and
if allowsFieldFlow = false then ap instanceof ApNil else any()
)
}
pragma[nomagic]
private predicate revFlowInNotToReturn(
ArgNodeEx arg, FlowState state, ApOption returnAp, Ap ap, Configuration config
) {
exists(ParamNodeEx p, boolean allowsFieldFlow |
revFlow(p, state, TReturnCtxNone(), returnAp, ap, config) and
flowIntoCall(_, arg, p, allowsFieldFlow, config) and
flowOutOfCall(call, ret, kind, out, allowsFieldFlow, config) and
if allowsFieldFlow = false then ap instanceof ApNil else any()
)
}
pragma[nomagic]
private predicate revFlowInToReturn(
DataFlowCall call, ArgNodeEx arg, FlowState state, ReturnPosition returnPos, Ap returnAp,
Ap ap, Configuration config
DataFlowCall call, ArgNodeEx arg, FlowState state, ReturnKindExt kind, Ap returnAp, Ap ap,
Configuration config
) {
exists(ParamNodeEx p, boolean allowsFieldFlow |
revFlow(p, state, TReturnCtxMaybeFlowThrough(returnPos), apSome(returnAp), ap, config) and
revFlow(pragma[only_bind_into](p), state,
TReturnCtxMaybeFlowThrough(pragma[only_bind_into](kind)), apSome(returnAp), ap, config) and
flowThroughIntoCall(call, arg, p, allowsFieldFlow, config) and
(if allowsFieldFlow = false then ap instanceof ApNil else any()) and
parameterFlowThroughAllowed(p.asNode(), returnPos.getKind())
parameterFlowThroughAllowed(p, kind)
)
}
@@ -1679,12 +1708,12 @@ private module MkStage<StageSig PrevStage> {
*/
pragma[nomagic]
private predicate revFlowIsReturned(
DataFlowCall call, ReturnCtx returnCtx, ApOption returnAp, ReturnPosition pos, Ap ap,
DataFlowCall call, ReturnCtx returnCtx, ApOption returnAp, ReturnKindExt kind, Ap ap,
Configuration config
) {
exists(RetNodeEx ret, FlowState state, CcCall ccc |
revFlowOut(call, ret, pos, state, returnCtx, returnAp, ap, config) and
returnFlowsThrough(ret, pos, state, ccc, _, _, ap, config) and
revFlowOut(call, ret, kind, state, returnCtx, returnAp, ap, config) and
returnFlowsThrough(ret, kind, state, ccc, _, _, ap, config) and
matchesCall(ccc, call)
)
}
@@ -1757,37 +1786,37 @@ private module MkStage<StageSig PrevStage> {
pragma[nomagic]
private predicate parameterFlowsThroughRev(
ParamNodeEx p, Ap ap, ReturnPosition returnPos, Configuration config
ParamNodeEx p, Ap ap, ReturnKindExt kind, Configuration config
) {
revFlow(p, _, TReturnCtxMaybeFlowThrough(returnPos), apSome(_), ap, config) and
parameterFlowThroughAllowed(p.asNode(), returnPos.getKind())
revFlow(p, _, TReturnCtxMaybeFlowThrough(kind), apSome(_), ap, config) and
parameterFlowThroughAllowed(p, kind)
}
pragma[nomagic]
predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap, Configuration config) {
exists(RetNodeEx ret, ReturnPosition pos |
returnFlowsThrough(ret, pos, _, _, p.asNode(), ap, _, config) and
parameterFlowsThroughRev(p, ap, pos, config)
exists(RetNodeEx ret, ReturnKindExt kind |
returnFlowsThrough(ret, kind, _, _, p, ap, _, config) and
parameterFlowsThroughRev(p, ap, kind, config)
)
}
pragma[nomagic]
predicate returnMayFlowThrough(RetNodeEx ret, ReturnPosition pos, Configuration config) {
predicate returnMayFlowThrough(RetNodeEx ret, ReturnKindExt kind, Configuration config) {
exists(ParamNodeEx p, Ap ap |
returnFlowsThrough(ret, pos, _, _, p.asNode(), ap, _, config) and
parameterFlowsThroughRev(p, ap, pos, config)
returnFlowsThrough(ret, kind, _, _, p, ap, _, config) and
parameterFlowsThroughRev(p, ap, kind, config)
)
}
pragma[nomagic]
predicate callMayFlowThroughRev(DataFlowCall call, Configuration config) {
exists(
ReturnPosition returnPos0, Ap returnAp0, ArgNodeEx arg, FlowState state,
ReturnKindExt returnKind0, Ap returnAp0, ArgNodeEx arg, FlowState state,
ReturnCtx returnCtx, ApOption returnAp, Ap ap
|
revFlow(arg, state, returnCtx, returnAp, ap, config) and
revFlowInToReturn(call, arg, state, returnPos0, returnAp0, ap, config) and
revFlowIsReturned(call, returnCtx, returnAp, returnPos0, returnAp0, config)
revFlowInToReturn(call, arg, state, returnKind0, returnAp0, ap, config) and
revFlowIsReturned(call, returnCtx, returnAp, returnKind0, returnAp0, config)
)
}
@@ -1800,9 +1829,8 @@ private module MkStage<StageSig PrevStage> {
conscand = count(TypedContent f0, Ap ap | fwdConsCand(f0, ap, config)) and
states = count(FlowState state | fwdFlow(_, state, _, _, _, _, config)) and
tuples =
count(NodeEx n, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap |
fwdFlow(n, state, cc, summaryCtx, argAp, ap, config)
)
count(NodeEx n, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp,
Ap ap | fwdFlow(n, state, cc, summaryCtx, argAp, ap, config))
or
fwd = false and
nodes = count(NodeEx node | revFlow(node, _, _, _, _, config)) and
@@ -1992,10 +2020,10 @@ private module Stage2 implements StageSig {
pragma[nomagic]
private predicate flowOutOfCallNodeCand2(
DataFlowCall call, RetNodeEx node1, ReturnPosition pos, NodeEx node2, boolean allowsFieldFlow,
DataFlowCall call, RetNodeEx node1, ReturnKindExt kind, NodeEx node2, boolean allowsFieldFlow,
Configuration config
) {
flowOutOfCallNodeCand1(call, node1, pos, node2, allowsFieldFlow, config) and
flowOutOfCallNodeCand1(call, node1, kind, node2, allowsFieldFlow, config) and
Stage2::revFlow(node2, pragma[only_bind_into](config)) and
Stage2::revFlowAlias(node1, pragma[only_bind_into](config))
}
@@ -2511,11 +2539,11 @@ private module Stage4Param implements MkStage<Stage3>::StageParam {
pragma[nomagic]
predicate flowOutOfCall(
DataFlowCall call, RetNodeEx node1, ReturnPosition pos, NodeEx node2, boolean allowsFieldFlow,
DataFlowCall call, RetNodeEx node1, ReturnKindExt kind, NodeEx node2, boolean allowsFieldFlow,
Configuration config
) {
exists(FlowState state |
flowOutOfCallNodeCand2(call, node1, pos, node2, allowsFieldFlow, config) and
flowOutOfCallNodeCand2(call, node1, kind, node2, allowsFieldFlow, config) and
PrevStage::revFlow(node2, pragma[only_bind_into](state), _, pragma[only_bind_into](config)) and
PrevStage::revFlowAlias(node1, pragma[only_bind_into](state), _,
pragma[only_bind_into](config))
@@ -2552,12 +2580,13 @@ private Configuration unbindConf(Configuration conf) {
pragma[nomagic]
private predicate nodeMayUseSummary0(
NodeEx n, ParamNodeEx p, FlowState state, AccessPathApprox apa, Configuration config
NodeEx n, DataFlowCallable c, ParameterPosition pos, FlowState state, AccessPathApprox apa,
Configuration config
) {
exists(AccessPathApprox apa0 |
Stage4::parameterMayFlowThrough(p, _, _) and
c = n.getEnclosingCallable() and
Stage4::revFlow(n, state, TReturnCtxMaybeFlowThrough(_), _, apa0, config) and
Stage4::fwdFlow(n, state, any(CallContextCall ccc), TParamNodeSome(p.asNode()),
Stage4::fwdFlow(n, state, any(CallContextCall ccc), TParameterPositionSome(pos),
TAccessPathApproxSome(apa), apa0, config)
)
}
@@ -2566,9 +2595,10 @@ pragma[nomagic]
private predicate nodeMayUseSummary(
NodeEx n, FlowState state, AccessPathApprox apa, Configuration config
) {
exists(ParamNodeEx p |
exists(DataFlowCallable c, ParameterPosition pos, ParamNodeEx p |
Stage4::parameterMayFlowThrough(p, apa, config) and
nodeMayUseSummary0(n, p, state, apa, config)
nodeMayUseSummary0(n, c, pos, state, apa, config) and
p.isParameterOf(c, pos)
)
}
@@ -3501,7 +3531,7 @@ private predicate paramFlowsThrough(
pathNode(mid, ret, state, cc, sc, ap, config, _) and
kind = ret.getKind() and
apa = ap.getApprox() and
parameterFlowThroughAllowed(sc.getParamNode().asNode(), kind)
parameterFlowThroughAllowed(sc.getParamNode(), kind)
)
}

View File

@@ -613,11 +613,28 @@ private predicate hasSinkCallCtx(Configuration config) {
* explicitly allowed
*/
bindingset[p, kind]
private predicate parameterFlowThroughAllowed(ParamNode p, ReturnKindExt kind) {
private predicate parameterFlowThroughAllowed(ParamNodeEx p, ReturnKindExt kind) {
exists(ParameterPosition pos | p.isParameterOf(_, pos) |
not kind.(ParamUpdateReturnKind).getPosition() = pos
or
allowParameterReturnInSelfCached(p)
allowParameterReturnInSelfCached(p.asNode())
)
}
/**
* Holds if flow from a parameter at position `pos` inside `c` to a return node of
* kind `kind` is allowed.
*
* We don't expect a parameter to return stored in itself, unless
* explicitly allowed
*/
bindingset[c, pos, kind]
private predicate parameterFlowThroughAllowed(
DataFlowCallable c, ParameterPosition pos, ReturnKindExt kind
) {
exists(ParamNodeEx p |
p.isParameterOf(c, pos) and
parameterFlowThroughAllowed(p, kind)
)
}
@@ -1000,14 +1017,14 @@ private module Stage1 implements StageSig {
returnFlowCallableNodeCand(c, kind, config) and
p.getEnclosingCallable() = c and
exists(ap) and
parameterFlowThroughAllowed(p.asNode(), kind)
parameterFlowThroughAllowed(p, kind)
)
}
pragma[nomagic]
predicate returnMayFlowThrough(RetNodeEx ret, ReturnPosition pos, Configuration config) {
predicate returnMayFlowThrough(RetNodeEx ret, ReturnKindExt kind, Configuration config) {
throughFlowNodeCand(ret, config) and
pos = ret.getReturnPosition()
kind = ret.getKind()
}
pragma[nomagic]
@@ -1066,13 +1083,16 @@ private predicate viableReturnPosOutNodeCand1(
*/
pragma[nomagic]
private predicate flowOutOfCallNodeCand1(
DataFlowCall call, RetNodeEx ret, ReturnPosition pos, NodeEx out, Configuration config
DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, Configuration config
) {
viableReturnPosOutNodeCand1(call, pos, out, config) and
pos = ret.getReturnPosition() and
Stage1::revFlow(ret, config) and
not outBarrier(ret, config) and
not inBarrier(out, config)
exists(ReturnPosition pos |
viableReturnPosOutNodeCand1(call, pos, out, config) and
pos = ret.getReturnPosition() and
kind = pos.getKind() and
Stage1::revFlow(ret, config) and
not outBarrier(ret, config) and
not inBarrier(out, config)
)
}
pragma[nomagic]
@@ -1102,6 +1122,7 @@ private predicate flowIntoCallNodeCand1(
* edge in the graph of paths between sources and sinks that ignores call
* contexts.
*/
pragma[nomagic]
private int branch(NodeEx n1, Configuration conf) {
result =
strictcount(NodeEx n |
@@ -1114,6 +1135,7 @@ private int branch(NodeEx n1, Configuration conf) {
* edge in the graph of paths between sources and sinks that ignores call
* contexts.
*/
pragma[nomagic]
private int join(NodeEx n2, Configuration conf) {
result =
strictcount(NodeEx n |
@@ -1130,10 +1152,10 @@ private int join(NodeEx n2, Configuration conf) {
*/
pragma[nomagic]
private predicate flowOutOfCallNodeCand1(
DataFlowCall call, RetNodeEx ret, ReturnPosition pos, NodeEx out, boolean allowsFieldFlow,
DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, boolean allowsFieldFlow,
Configuration config
) {
flowOutOfCallNodeCand1(call, ret, pos, out, pragma[only_bind_into](config)) and
flowOutOfCallNodeCand1(call, ret, kind, out, pragma[only_bind_into](config)) and
exists(int b, int j |
b = branch(ret, pragma[only_bind_into](config)) and
j = join(out, pragma[only_bind_into](config)) and
@@ -1152,10 +1174,10 @@ pragma[nomagic]
private predicate flowIntoCallNodeCand1(
DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Configuration config
) {
flowIntoCallNodeCand1(call, arg, p, config) and
flowIntoCallNodeCand1(call, arg, p, pragma[only_bind_into](config)) and
exists(int b, int j |
b = branch(arg, config) and
j = join(p, config) and
b = branch(arg, pragma[only_bind_into](config)) and
j = join(p, pragma[only_bind_into](config)) and
if b.minimum(j) <= config.fieldFlowBranchLimit()
then allowsFieldFlow = true
else allowsFieldFlow = false
@@ -1174,7 +1196,7 @@ private signature module StageSig {
predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap, Configuration config);
predicate returnMayFlowThrough(RetNodeEx ret, ReturnPosition pos, Configuration config);
predicate returnMayFlowThrough(RetNodeEx ret, ReturnKindExt kind, Configuration config);
predicate storeStepCand(
NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, DataFlowType contentType,
@@ -1240,7 +1262,7 @@ private module MkStage<StageSig PrevStage> {
);
predicate flowOutOfCall(
DataFlowCall call, RetNodeEx ret, ReturnPosition pos, NodeEx out, boolean allowsFieldFlow,
DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, boolean allowsFieldFlow,
Configuration config
);
@@ -1266,16 +1288,14 @@ private module MkStage<StageSig PrevStage> {
pragma[nomagic]
private predicate flowThroughOutOfCall(
DataFlowCall call, CcCall ccc, RetNodeEx ret, ReturnKindExt kind, NodeEx out,
boolean allowsFieldFlow, Configuration config
DataFlowCall call, DataFlowCallable c, CcCall ccc, RetNodeEx ret, ReturnKindExt kind,
NodeEx out, boolean allowsFieldFlow, Configuration config
) {
exists(ReturnPosition pos |
flowOutOfCall(call, ret, pos, out, allowsFieldFlow, pragma[only_bind_into](config)) and
kind = pos.getKind() and
PrevStage::callMayFlowThroughRev(call, pragma[only_bind_into](config)) and
PrevStage::returnMayFlowThrough(ret, pos, pragma[only_bind_into](config)) and
matchesCall(ccc, call)
)
flowOutOfCall(call, ret, kind, out, allowsFieldFlow, pragma[only_bind_into](config)) and
PrevStage::callMayFlowThroughRev(call, pragma[only_bind_into](config)) and
PrevStage::returnMayFlowThrough(ret, kind, pragma[only_bind_into](config)) and
matchesCall(ccc, call) and
c = ret.getEnclosingCallable()
}
/**
@@ -1284,12 +1304,12 @@ private module MkStage<StageSig PrevStage> {
*
* The call context `cc` records whether the node is reached through an
* argument in a call, and if so, `summaryCtx` and `argAp` record the
* corresponding parameter and access path of that argument, respectively.
* corresponding parameter position and access path of that argument, respectively.
*/
pragma[nomagic]
additional predicate fwdFlow(
NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap,
Configuration config
NodeEx node, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp,
Ap ap, Configuration config
) {
fwdFlow0(node, state, cc, summaryCtx, argAp, ap, config) and
PrevStage::revFlow(node, state, unbindApa(getApprox(ap)), config) and
@@ -1298,13 +1318,13 @@ private module MkStage<StageSig PrevStage> {
pragma[nomagic]
private predicate fwdFlow0(
NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap,
Configuration config
NodeEx node, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp,
Ap ap, Configuration config
) {
sourceNode(node, state, config) and
(if hasSourceCallCtx(config) then cc = ccSomeCall() else cc = ccNone()) and
argAp = apNone() and
summaryCtx = TParamNodeNone() and
summaryCtx = TParameterPositionNone() and
ap = getApNil(node)
or
exists(NodeEx mid, FlowState state0, Ap ap0, LocalCc localCc |
@@ -1322,7 +1342,7 @@ private module MkStage<StageSig PrevStage> {
fwdFlow(mid, pragma[only_bind_into](state), _, _, _, ap, pragma[only_bind_into](config)) and
jumpStep(mid, node, config) and
cc = ccNone() and
summaryCtx = TParamNodeNone() and
summaryCtx = TParameterPositionNone() and
argAp = apNone()
)
or
@@ -1330,7 +1350,7 @@ private module MkStage<StageSig PrevStage> {
fwdFlow(mid, state, _, _, _, nil, pragma[only_bind_into](config)) and
additionalJumpStep(mid, node, config) and
cc = ccNone() and
summaryCtx = TParamNodeNone() and
summaryCtx = TParameterPositionNone() and
argAp = apNone() and
ap = getApNil(node)
)
@@ -1339,7 +1359,7 @@ private module MkStage<StageSig PrevStage> {
fwdFlow(mid, state0, _, _, _, nil, pragma[only_bind_into](config)) and
additionalJumpStateStep(mid, state0, node, state, config) and
cc = ccNone() and
summaryCtx = TParamNodeNone() and
summaryCtx = TParameterPositionNone() and
argAp = apNone() and
ap = getApNil(node)
)
@@ -1362,17 +1382,27 @@ private module MkStage<StageSig PrevStage> {
apa = getApprox(ap) and
if PrevStage::parameterMayFlowThrough(node, apa, config)
then (
summaryCtx = TParamNodeSome(node.asNode()) and argAp = apSome(ap)
summaryCtx = TParameterPositionSome(node.(ParamNodeEx).getPosition()) and
argAp = apSome(ap)
) else (
summaryCtx = TParamNodeNone() and argAp = apNone()
summaryCtx = TParameterPositionNone() and argAp = apNone()
)
)
or
// flow out of a callable
fwdFlowOutNotFromArg(node, state, cc, summaryCtx, argAp, ap, config)
exists(
DataFlowCall call, RetNodeEx ret, boolean allowsFieldFlow, CcNoCall innercc,
DataFlowCallable inner
|
fwdFlow(ret, state, innercc, summaryCtx, argAp, ap, config) and
flowOutOfCall(call, ret, _, node, allowsFieldFlow, config) and
inner = ret.getEnclosingCallable() and
cc = getCallContextReturn(inner, call, innercc) and
if allowsFieldFlow = false then ap instanceof ApNil else any()
)
or
// flow through a callable
exists(DataFlowCall call, ParamNode summaryCtx0, Ap argAp0 |
exists(DataFlowCall call, ParameterPosition summaryCtx0, Ap argAp0 |
fwdFlowOutFromArg(call, node, state, summaryCtx0, argAp0, ap, config) and
fwdFlowIsEntered(call, cc, summaryCtx, argAp, summaryCtx0, argAp0, config)
)
@@ -1381,7 +1411,7 @@ private module MkStage<StageSig PrevStage> {
pragma[nomagic]
private predicate fwdFlowStore(
NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, FlowState state, Cc cc,
ParamNodeOption summaryCtx, ApOption argAp, Configuration config
ParameterPositionOption summaryCtx, ApOption argAp, Configuration config
) {
exists(DataFlowType contentType |
fwdFlow(node1, state, cc, summaryCtx, argAp, ap1, config) and
@@ -1406,7 +1436,7 @@ private module MkStage<StageSig PrevStage> {
pragma[nomagic]
private predicate fwdFlowRead(
Ap ap, Content c, NodeEx node1, NodeEx node2, FlowState state, Cc cc,
ParamNodeOption summaryCtx, ApOption argAp, Configuration config
ParameterPositionOption summaryCtx, ApOption argAp, Configuration config
) {
fwdFlow(node1, state, cc, summaryCtx, argAp, ap, config) and
PrevStage::readStepCand(node1, c, node2, config) and
@@ -1416,7 +1446,7 @@ private module MkStage<StageSig PrevStage> {
pragma[nomagic]
private predicate fwdFlowIn(
DataFlowCall call, ParamNodeEx p, FlowState state, Cc outercc, Cc innercc,
ParamNodeOption summaryCtx, ApOption argAp, Ap ap, Configuration config
ParameterPositionOption summaryCtx, ApOption argAp, Ap ap, Configuration config
) {
exists(ArgNodeEx arg, boolean allowsFieldFlow |
fwdFlow(arg, state, outercc, summaryCtx, argAp, ap, config) and
@@ -1427,32 +1457,19 @@ private module MkStage<StageSig PrevStage> {
}
pragma[nomagic]
private predicate fwdFlowOutNotFromArg(
NodeEx out, FlowState state, Cc ccOut, ParamNodeOption summaryCtx, ApOption argAp, Ap ap,
private predicate fwdFlowOutFromArg(
DataFlowCall call, NodeEx out, FlowState state, ParameterPosition summaryCtx, Ap argAp, Ap ap,
Configuration config
) {
exists(
DataFlowCall call, RetNodeEx ret, boolean allowsFieldFlow, CcNoCall innercc,
DataFlowCallable inner
DataFlowCallable c, RetNodeEx ret, ReturnKindExt kind, boolean allowsFieldFlow, CcCall ccc
|
fwdFlow(ret, state, innercc, summaryCtx, argAp, ap, config) and
flowOutOfCall(call, ret, _, out, allowsFieldFlow, config) and
inner = ret.getEnclosingCallable() and
ccOut = getCallContextReturn(inner, call, innercc) and
if allowsFieldFlow = false then ap instanceof ApNil else any()
)
}
pragma[nomagic]
private predicate fwdFlowOutFromArg(
DataFlowCall call, NodeEx out, FlowState state, ParamNode summaryCtx, Ap argAp, Ap ap,
Configuration config
) {
exists(RetNodeEx ret, ReturnKindExt kind, boolean allowsFieldFlow, CcCall ccc |
fwdFlow(ret, state, ccc, TParamNodeSome(summaryCtx), apSome(argAp), ap, config) and
flowThroughOutOfCall(call, ccc, ret, kind, out, allowsFieldFlow, config) and
fwdFlow(pragma[only_bind_into](ret), state, pragma[only_bind_into](ccc),
TParameterPositionSome(pragma[only_bind_into](summaryCtx)), apSome(argAp), ap, config) and
flowThroughOutOfCall(call, pragma[only_bind_into](c), ccc, ret, kind, out, allowsFieldFlow,
config) and
(if allowsFieldFlow = false then ap instanceof ApNil else any()) and
parameterFlowThroughAllowed(summaryCtx, kind)
parameterFlowThroughAllowed(c, pragma[only_bind_into](summaryCtx), kind)
)
}
@@ -1462,13 +1479,13 @@ private module MkStage<StageSig PrevStage> {
*/
pragma[nomagic]
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, ParamNode p, Ap ap,
Configuration config
DataFlowCall call, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp,
ParameterPosition pos, Ap ap, Configuration config
) {
exists(ParamNodeEx param |
fwdFlowIn(call, param, _, cc, _, summaryCtx, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(param, unbindApa(getApprox(ap)), config) and
p = param.asNode()
pos = param.getPosition()
)
}
@@ -1489,23 +1506,41 @@ private module MkStage<StageSig PrevStage> {
}
pragma[nomagic]
private predicate returnFlowsThrough(
RetNodeEx ret, ReturnPosition pos, FlowState state, CcCall ccc, ParamNode p, Ap argAp, Ap ap,
Configuration config
private predicate returnFlowsThrough0(
RetNodeEx ret, ReturnKindExt kind, FlowState state, CcCall ccc, DataFlowCallable c,
ParameterPosition ppos, Ap argAp, Ap ap, Configuration config
) {
fwdFlow(ret, state, ccc, TParamNodeSome(p), apSome(argAp), ap, config) and
pos = ret.getReturnPosition() and
parameterFlowThroughAllowed(p, pos.getKind())
exists(boolean allowsFieldFlow |
fwdFlow(ret, state, ccc, TParameterPositionSome(ppos), apSome(argAp), ap, config) and
flowThroughOutOfCall(_, c, _, pragma[only_bind_into](ret), kind, _, allowsFieldFlow,
pragma[only_bind_into](config)) and
if allowsFieldFlow = false then ap instanceof ApNil else any()
)
}
pragma[nomagic]
private predicate returnFlowsThrough(
RetNodeEx ret, ReturnKindExt kind, FlowState state, CcCall ccc, ParamNodeEx p, Ap argAp,
Ap ap, Configuration config
) {
exists(DataFlowCallable c, ParameterPosition ppos |
returnFlowsThrough0(ret, kind, state, ccc, c, ppos, argAp, ap, config) and
p.isParameterOf(c, ppos) and
parameterFlowThroughAllowed(p, kind)
)
}
pragma[nomagic]
private predicate flowThroughIntoCall(
DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Configuration config
) {
flowIntoCall(call, pragma[only_bind_into](arg), pragma[only_bind_into](p), allowsFieldFlow,
pragma[only_bind_into](config)) and
fwdFlow(arg, _, _, _, _, _, pragma[only_bind_into](config)) and
returnFlowsThrough(_, _, _, _, p.asNode(), _, _, pragma[only_bind_into](config))
exists(Ap argAp |
flowIntoCall(call, pragma[only_bind_into](arg), pragma[only_bind_into](p), allowsFieldFlow,
pragma[only_bind_into](config)) and
fwdFlow(arg, _, _, _, _, pragma[only_bind_into](argAp), pragma[only_bind_into](config)) and
returnFlowsThrough(_, _, _, _, p, pragma[only_bind_into](argAp), _,
pragma[only_bind_into](config))
)
}
/**
@@ -1591,21 +1626,25 @@ private module MkStage<StageSig PrevStage> {
)
or
// flow into a callable
revFlowInNotToReturn(node, state, returnAp, ap, config) and
returnCtx = TReturnCtxNone()
exists(ParamNodeEx p, boolean allowsFieldFlow |
revFlow(p, state, TReturnCtxNone(), returnAp, ap, config) and
flowIntoCall(_, node, p, allowsFieldFlow, config) and
(if allowsFieldFlow = false then ap instanceof ApNil else any()) and
returnCtx = TReturnCtxNone()
)
or
// flow through a callable
exists(DataFlowCall call, ReturnPosition returnPos0, Ap returnAp0 |
revFlowInToReturn(call, node, state, returnPos0, returnAp0, ap, config) and
revFlowIsReturned(call, returnCtx, returnAp, returnPos0, returnAp0, config)
exists(DataFlowCall call, ReturnKindExt returnKind0, Ap returnAp0 |
revFlowInToReturn(call, node, state, returnKind0, returnAp0, ap, config) and
revFlowIsReturned(call, returnCtx, returnAp, returnKind0, returnAp0, config)
)
or
// flow out of a callable
exists(ReturnPosition pos |
revFlowOut(_, node, pos, state, _, _, ap, config) and
if returnFlowsThrough(node, pos, state, _, _, _, ap, config)
exists(ReturnKindExt kind |
revFlowOut(_, node, kind, state, _, _, ap, config) and
if returnFlowsThrough(node, kind, state, _, _, _, ap, config)
then (
returnCtx = TReturnCtxMaybeFlowThrough(pos) and
returnCtx = TReturnCtxMaybeFlowThrough(kind) and
returnAp = apSome(ap)
) else (
returnCtx = TReturnCtxNoFlowThrough() and returnAp = apNone()
@@ -1638,37 +1677,27 @@ private module MkStage<StageSig PrevStage> {
pragma[nomagic]
private predicate revFlowOut(
DataFlowCall call, RetNodeEx ret, ReturnPosition pos, FlowState state, ReturnCtx returnCtx,
DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, FlowState state, ReturnCtx returnCtx,
ApOption returnAp, Ap ap, Configuration config
) {
exists(NodeEx out, boolean allowsFieldFlow |
revFlow(out, state, returnCtx, returnAp, ap, config) and
flowOutOfCall(call, ret, pos, out, allowsFieldFlow, config) and
if allowsFieldFlow = false then ap instanceof ApNil else any()
)
}
pragma[nomagic]
private predicate revFlowInNotToReturn(
ArgNodeEx arg, FlowState state, ApOption returnAp, Ap ap, Configuration config
) {
exists(ParamNodeEx p, boolean allowsFieldFlow |
revFlow(p, state, TReturnCtxNone(), returnAp, ap, config) and
flowIntoCall(_, arg, p, allowsFieldFlow, config) and
flowOutOfCall(call, ret, kind, out, allowsFieldFlow, config) and
if allowsFieldFlow = false then ap instanceof ApNil else any()
)
}
pragma[nomagic]
private predicate revFlowInToReturn(
DataFlowCall call, ArgNodeEx arg, FlowState state, ReturnPosition returnPos, Ap returnAp,
Ap ap, Configuration config
DataFlowCall call, ArgNodeEx arg, FlowState state, ReturnKindExt kind, Ap returnAp, Ap ap,
Configuration config
) {
exists(ParamNodeEx p, boolean allowsFieldFlow |
revFlow(p, state, TReturnCtxMaybeFlowThrough(returnPos), apSome(returnAp), ap, config) and
revFlow(pragma[only_bind_into](p), state,
TReturnCtxMaybeFlowThrough(pragma[only_bind_into](kind)), apSome(returnAp), ap, config) and
flowThroughIntoCall(call, arg, p, allowsFieldFlow, config) and
(if allowsFieldFlow = false then ap instanceof ApNil else any()) and
parameterFlowThroughAllowed(p.asNode(), returnPos.getKind())
parameterFlowThroughAllowed(p, kind)
)
}
@@ -1679,12 +1708,12 @@ private module MkStage<StageSig PrevStage> {
*/
pragma[nomagic]
private predicate revFlowIsReturned(
DataFlowCall call, ReturnCtx returnCtx, ApOption returnAp, ReturnPosition pos, Ap ap,
DataFlowCall call, ReturnCtx returnCtx, ApOption returnAp, ReturnKindExt kind, Ap ap,
Configuration config
) {
exists(RetNodeEx ret, FlowState state, CcCall ccc |
revFlowOut(call, ret, pos, state, returnCtx, returnAp, ap, config) and
returnFlowsThrough(ret, pos, state, ccc, _, _, ap, config) and
revFlowOut(call, ret, kind, state, returnCtx, returnAp, ap, config) and
returnFlowsThrough(ret, kind, state, ccc, _, _, ap, config) and
matchesCall(ccc, call)
)
}
@@ -1757,37 +1786,37 @@ private module MkStage<StageSig PrevStage> {
pragma[nomagic]
private predicate parameterFlowsThroughRev(
ParamNodeEx p, Ap ap, ReturnPosition returnPos, Configuration config
ParamNodeEx p, Ap ap, ReturnKindExt kind, Configuration config
) {
revFlow(p, _, TReturnCtxMaybeFlowThrough(returnPos), apSome(_), ap, config) and
parameterFlowThroughAllowed(p.asNode(), returnPos.getKind())
revFlow(p, _, TReturnCtxMaybeFlowThrough(kind), apSome(_), ap, config) and
parameterFlowThroughAllowed(p, kind)
}
pragma[nomagic]
predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap, Configuration config) {
exists(RetNodeEx ret, ReturnPosition pos |
returnFlowsThrough(ret, pos, _, _, p.asNode(), ap, _, config) and
parameterFlowsThroughRev(p, ap, pos, config)
exists(RetNodeEx ret, ReturnKindExt kind |
returnFlowsThrough(ret, kind, _, _, p, ap, _, config) and
parameterFlowsThroughRev(p, ap, kind, config)
)
}
pragma[nomagic]
predicate returnMayFlowThrough(RetNodeEx ret, ReturnPosition pos, Configuration config) {
predicate returnMayFlowThrough(RetNodeEx ret, ReturnKindExt kind, Configuration config) {
exists(ParamNodeEx p, Ap ap |
returnFlowsThrough(ret, pos, _, _, p.asNode(), ap, _, config) and
parameterFlowsThroughRev(p, ap, pos, config)
returnFlowsThrough(ret, kind, _, _, p, ap, _, config) and
parameterFlowsThroughRev(p, ap, kind, config)
)
}
pragma[nomagic]
predicate callMayFlowThroughRev(DataFlowCall call, Configuration config) {
exists(
ReturnPosition returnPos0, Ap returnAp0, ArgNodeEx arg, FlowState state,
ReturnKindExt returnKind0, Ap returnAp0, ArgNodeEx arg, FlowState state,
ReturnCtx returnCtx, ApOption returnAp, Ap ap
|
revFlow(arg, state, returnCtx, returnAp, ap, config) and
revFlowInToReturn(call, arg, state, returnPos0, returnAp0, ap, config) and
revFlowIsReturned(call, returnCtx, returnAp, returnPos0, returnAp0, config)
revFlowInToReturn(call, arg, state, returnKind0, returnAp0, ap, config) and
revFlowIsReturned(call, returnCtx, returnAp, returnKind0, returnAp0, config)
)
}
@@ -1800,9 +1829,8 @@ private module MkStage<StageSig PrevStage> {
conscand = count(TypedContent f0, Ap ap | fwdConsCand(f0, ap, config)) and
states = count(FlowState state | fwdFlow(_, state, _, _, _, _, config)) and
tuples =
count(NodeEx n, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap |
fwdFlow(n, state, cc, summaryCtx, argAp, ap, config)
)
count(NodeEx n, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp,
Ap ap | fwdFlow(n, state, cc, summaryCtx, argAp, ap, config))
or
fwd = false and
nodes = count(NodeEx node | revFlow(node, _, _, _, _, config)) and
@@ -1992,10 +2020,10 @@ private module Stage2 implements StageSig {
pragma[nomagic]
private predicate flowOutOfCallNodeCand2(
DataFlowCall call, RetNodeEx node1, ReturnPosition pos, NodeEx node2, boolean allowsFieldFlow,
DataFlowCall call, RetNodeEx node1, ReturnKindExt kind, NodeEx node2, boolean allowsFieldFlow,
Configuration config
) {
flowOutOfCallNodeCand1(call, node1, pos, node2, allowsFieldFlow, config) and
flowOutOfCallNodeCand1(call, node1, kind, node2, allowsFieldFlow, config) and
Stage2::revFlow(node2, pragma[only_bind_into](config)) and
Stage2::revFlowAlias(node1, pragma[only_bind_into](config))
}
@@ -2511,11 +2539,11 @@ private module Stage4Param implements MkStage<Stage3>::StageParam {
pragma[nomagic]
predicate flowOutOfCall(
DataFlowCall call, RetNodeEx node1, ReturnPosition pos, NodeEx node2, boolean allowsFieldFlow,
DataFlowCall call, RetNodeEx node1, ReturnKindExt kind, NodeEx node2, boolean allowsFieldFlow,
Configuration config
) {
exists(FlowState state |
flowOutOfCallNodeCand2(call, node1, pos, node2, allowsFieldFlow, config) and
flowOutOfCallNodeCand2(call, node1, kind, node2, allowsFieldFlow, config) and
PrevStage::revFlow(node2, pragma[only_bind_into](state), _, pragma[only_bind_into](config)) and
PrevStage::revFlowAlias(node1, pragma[only_bind_into](state), _,
pragma[only_bind_into](config))
@@ -2552,12 +2580,13 @@ private Configuration unbindConf(Configuration conf) {
pragma[nomagic]
private predicate nodeMayUseSummary0(
NodeEx n, ParamNodeEx p, FlowState state, AccessPathApprox apa, Configuration config
NodeEx n, DataFlowCallable c, ParameterPosition pos, FlowState state, AccessPathApprox apa,
Configuration config
) {
exists(AccessPathApprox apa0 |
Stage4::parameterMayFlowThrough(p, _, _) and
c = n.getEnclosingCallable() and
Stage4::revFlow(n, state, TReturnCtxMaybeFlowThrough(_), _, apa0, config) and
Stage4::fwdFlow(n, state, any(CallContextCall ccc), TParamNodeSome(p.asNode()),
Stage4::fwdFlow(n, state, any(CallContextCall ccc), TParameterPositionSome(pos),
TAccessPathApproxSome(apa), apa0, config)
)
}
@@ -2566,9 +2595,10 @@ pragma[nomagic]
private predicate nodeMayUseSummary(
NodeEx n, FlowState state, AccessPathApprox apa, Configuration config
) {
exists(ParamNodeEx p |
exists(DataFlowCallable c, ParameterPosition pos, ParamNodeEx p |
Stage4::parameterMayFlowThrough(p, apa, config) and
nodeMayUseSummary0(n, p, state, apa, config)
nodeMayUseSummary0(n, c, pos, state, apa, config) and
p.isParameterOf(c, pos)
)
}
@@ -3501,7 +3531,7 @@ private predicate paramFlowsThrough(
pathNode(mid, ret, state, cc, sc, ap, config, _) and
kind = ret.getKind() and
apa = ap.getApprox() and
parameterFlowThroughAllowed(sc.getParamNode().asNode(), kind)
parameterFlowThroughAllowed(sc.getParamNode(), kind)
)
}

View File

@@ -613,11 +613,28 @@ private predicate hasSinkCallCtx(Configuration config) {
* explicitly allowed
*/
bindingset[p, kind]
private predicate parameterFlowThroughAllowed(ParamNode p, ReturnKindExt kind) {
private predicate parameterFlowThroughAllowed(ParamNodeEx p, ReturnKindExt kind) {
exists(ParameterPosition pos | p.isParameterOf(_, pos) |
not kind.(ParamUpdateReturnKind).getPosition() = pos
or
allowParameterReturnInSelfCached(p)
allowParameterReturnInSelfCached(p.asNode())
)
}
/**
* Holds if flow from a parameter at position `pos` inside `c` to a return node of
* kind `kind` is allowed.
*
* We don't expect a parameter to return stored in itself, unless
* explicitly allowed
*/
bindingset[c, pos, kind]
private predicate parameterFlowThroughAllowed(
DataFlowCallable c, ParameterPosition pos, ReturnKindExt kind
) {
exists(ParamNodeEx p |
p.isParameterOf(c, pos) and
parameterFlowThroughAllowed(p, kind)
)
}
@@ -1000,14 +1017,14 @@ private module Stage1 implements StageSig {
returnFlowCallableNodeCand(c, kind, config) and
p.getEnclosingCallable() = c and
exists(ap) and
parameterFlowThroughAllowed(p.asNode(), kind)
parameterFlowThroughAllowed(p, kind)
)
}
pragma[nomagic]
predicate returnMayFlowThrough(RetNodeEx ret, ReturnPosition pos, Configuration config) {
predicate returnMayFlowThrough(RetNodeEx ret, ReturnKindExt kind, Configuration config) {
throughFlowNodeCand(ret, config) and
pos = ret.getReturnPosition()
kind = ret.getKind()
}
pragma[nomagic]
@@ -1066,13 +1083,16 @@ private predicate viableReturnPosOutNodeCand1(
*/
pragma[nomagic]
private predicate flowOutOfCallNodeCand1(
DataFlowCall call, RetNodeEx ret, ReturnPosition pos, NodeEx out, Configuration config
DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, Configuration config
) {
viableReturnPosOutNodeCand1(call, pos, out, config) and
pos = ret.getReturnPosition() and
Stage1::revFlow(ret, config) and
not outBarrier(ret, config) and
not inBarrier(out, config)
exists(ReturnPosition pos |
viableReturnPosOutNodeCand1(call, pos, out, config) and
pos = ret.getReturnPosition() and
kind = pos.getKind() and
Stage1::revFlow(ret, config) and
not outBarrier(ret, config) and
not inBarrier(out, config)
)
}
pragma[nomagic]
@@ -1102,6 +1122,7 @@ private predicate flowIntoCallNodeCand1(
* edge in the graph of paths between sources and sinks that ignores call
* contexts.
*/
pragma[nomagic]
private int branch(NodeEx n1, Configuration conf) {
result =
strictcount(NodeEx n |
@@ -1114,6 +1135,7 @@ private int branch(NodeEx n1, Configuration conf) {
* edge in the graph of paths between sources and sinks that ignores call
* contexts.
*/
pragma[nomagic]
private int join(NodeEx n2, Configuration conf) {
result =
strictcount(NodeEx n |
@@ -1130,10 +1152,10 @@ private int join(NodeEx n2, Configuration conf) {
*/
pragma[nomagic]
private predicate flowOutOfCallNodeCand1(
DataFlowCall call, RetNodeEx ret, ReturnPosition pos, NodeEx out, boolean allowsFieldFlow,
DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, boolean allowsFieldFlow,
Configuration config
) {
flowOutOfCallNodeCand1(call, ret, pos, out, pragma[only_bind_into](config)) and
flowOutOfCallNodeCand1(call, ret, kind, out, pragma[only_bind_into](config)) and
exists(int b, int j |
b = branch(ret, pragma[only_bind_into](config)) and
j = join(out, pragma[only_bind_into](config)) and
@@ -1152,10 +1174,10 @@ pragma[nomagic]
private predicate flowIntoCallNodeCand1(
DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Configuration config
) {
flowIntoCallNodeCand1(call, arg, p, config) and
flowIntoCallNodeCand1(call, arg, p, pragma[only_bind_into](config)) and
exists(int b, int j |
b = branch(arg, config) and
j = join(p, config) and
b = branch(arg, pragma[only_bind_into](config)) and
j = join(p, pragma[only_bind_into](config)) and
if b.minimum(j) <= config.fieldFlowBranchLimit()
then allowsFieldFlow = true
else allowsFieldFlow = false
@@ -1174,7 +1196,7 @@ private signature module StageSig {
predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap, Configuration config);
predicate returnMayFlowThrough(RetNodeEx ret, ReturnPosition pos, Configuration config);
predicate returnMayFlowThrough(RetNodeEx ret, ReturnKindExt kind, Configuration config);
predicate storeStepCand(
NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, DataFlowType contentType,
@@ -1240,7 +1262,7 @@ private module MkStage<StageSig PrevStage> {
);
predicate flowOutOfCall(
DataFlowCall call, RetNodeEx ret, ReturnPosition pos, NodeEx out, boolean allowsFieldFlow,
DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, boolean allowsFieldFlow,
Configuration config
);
@@ -1266,16 +1288,14 @@ private module MkStage<StageSig PrevStage> {
pragma[nomagic]
private predicate flowThroughOutOfCall(
DataFlowCall call, CcCall ccc, RetNodeEx ret, ReturnKindExt kind, NodeEx out,
boolean allowsFieldFlow, Configuration config
DataFlowCall call, DataFlowCallable c, CcCall ccc, RetNodeEx ret, ReturnKindExt kind,
NodeEx out, boolean allowsFieldFlow, Configuration config
) {
exists(ReturnPosition pos |
flowOutOfCall(call, ret, pos, out, allowsFieldFlow, pragma[only_bind_into](config)) and
kind = pos.getKind() and
PrevStage::callMayFlowThroughRev(call, pragma[only_bind_into](config)) and
PrevStage::returnMayFlowThrough(ret, pos, pragma[only_bind_into](config)) and
matchesCall(ccc, call)
)
flowOutOfCall(call, ret, kind, out, allowsFieldFlow, pragma[only_bind_into](config)) and
PrevStage::callMayFlowThroughRev(call, pragma[only_bind_into](config)) and
PrevStage::returnMayFlowThrough(ret, kind, pragma[only_bind_into](config)) and
matchesCall(ccc, call) and
c = ret.getEnclosingCallable()
}
/**
@@ -1284,12 +1304,12 @@ private module MkStage<StageSig PrevStage> {
*
* The call context `cc` records whether the node is reached through an
* argument in a call, and if so, `summaryCtx` and `argAp` record the
* corresponding parameter and access path of that argument, respectively.
* corresponding parameter position and access path of that argument, respectively.
*/
pragma[nomagic]
additional predicate fwdFlow(
NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap,
Configuration config
NodeEx node, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp,
Ap ap, Configuration config
) {
fwdFlow0(node, state, cc, summaryCtx, argAp, ap, config) and
PrevStage::revFlow(node, state, unbindApa(getApprox(ap)), config) and
@@ -1298,13 +1318,13 @@ private module MkStage<StageSig PrevStage> {
pragma[nomagic]
private predicate fwdFlow0(
NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap,
Configuration config
NodeEx node, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp,
Ap ap, Configuration config
) {
sourceNode(node, state, config) and
(if hasSourceCallCtx(config) then cc = ccSomeCall() else cc = ccNone()) and
argAp = apNone() and
summaryCtx = TParamNodeNone() and
summaryCtx = TParameterPositionNone() and
ap = getApNil(node)
or
exists(NodeEx mid, FlowState state0, Ap ap0, LocalCc localCc |
@@ -1322,7 +1342,7 @@ private module MkStage<StageSig PrevStage> {
fwdFlow(mid, pragma[only_bind_into](state), _, _, _, ap, pragma[only_bind_into](config)) and
jumpStep(mid, node, config) and
cc = ccNone() and
summaryCtx = TParamNodeNone() and
summaryCtx = TParameterPositionNone() and
argAp = apNone()
)
or
@@ -1330,7 +1350,7 @@ private module MkStage<StageSig PrevStage> {
fwdFlow(mid, state, _, _, _, nil, pragma[only_bind_into](config)) and
additionalJumpStep(mid, node, config) and
cc = ccNone() and
summaryCtx = TParamNodeNone() and
summaryCtx = TParameterPositionNone() and
argAp = apNone() and
ap = getApNil(node)
)
@@ -1339,7 +1359,7 @@ private module MkStage<StageSig PrevStage> {
fwdFlow(mid, state0, _, _, _, nil, pragma[only_bind_into](config)) and
additionalJumpStateStep(mid, state0, node, state, config) and
cc = ccNone() and
summaryCtx = TParamNodeNone() and
summaryCtx = TParameterPositionNone() and
argAp = apNone() and
ap = getApNil(node)
)
@@ -1362,17 +1382,27 @@ private module MkStage<StageSig PrevStage> {
apa = getApprox(ap) and
if PrevStage::parameterMayFlowThrough(node, apa, config)
then (
summaryCtx = TParamNodeSome(node.asNode()) and argAp = apSome(ap)
summaryCtx = TParameterPositionSome(node.(ParamNodeEx).getPosition()) and
argAp = apSome(ap)
) else (
summaryCtx = TParamNodeNone() and argAp = apNone()
summaryCtx = TParameterPositionNone() and argAp = apNone()
)
)
or
// flow out of a callable
fwdFlowOutNotFromArg(node, state, cc, summaryCtx, argAp, ap, config)
exists(
DataFlowCall call, RetNodeEx ret, boolean allowsFieldFlow, CcNoCall innercc,
DataFlowCallable inner
|
fwdFlow(ret, state, innercc, summaryCtx, argAp, ap, config) and
flowOutOfCall(call, ret, _, node, allowsFieldFlow, config) and
inner = ret.getEnclosingCallable() and
cc = getCallContextReturn(inner, call, innercc) and
if allowsFieldFlow = false then ap instanceof ApNil else any()
)
or
// flow through a callable
exists(DataFlowCall call, ParamNode summaryCtx0, Ap argAp0 |
exists(DataFlowCall call, ParameterPosition summaryCtx0, Ap argAp0 |
fwdFlowOutFromArg(call, node, state, summaryCtx0, argAp0, ap, config) and
fwdFlowIsEntered(call, cc, summaryCtx, argAp, summaryCtx0, argAp0, config)
)
@@ -1381,7 +1411,7 @@ private module MkStage<StageSig PrevStage> {
pragma[nomagic]
private predicate fwdFlowStore(
NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, FlowState state, Cc cc,
ParamNodeOption summaryCtx, ApOption argAp, Configuration config
ParameterPositionOption summaryCtx, ApOption argAp, Configuration config
) {
exists(DataFlowType contentType |
fwdFlow(node1, state, cc, summaryCtx, argAp, ap1, config) and
@@ -1406,7 +1436,7 @@ private module MkStage<StageSig PrevStage> {
pragma[nomagic]
private predicate fwdFlowRead(
Ap ap, Content c, NodeEx node1, NodeEx node2, FlowState state, Cc cc,
ParamNodeOption summaryCtx, ApOption argAp, Configuration config
ParameterPositionOption summaryCtx, ApOption argAp, Configuration config
) {
fwdFlow(node1, state, cc, summaryCtx, argAp, ap, config) and
PrevStage::readStepCand(node1, c, node2, config) and
@@ -1416,7 +1446,7 @@ private module MkStage<StageSig PrevStage> {
pragma[nomagic]
private predicate fwdFlowIn(
DataFlowCall call, ParamNodeEx p, FlowState state, Cc outercc, Cc innercc,
ParamNodeOption summaryCtx, ApOption argAp, Ap ap, Configuration config
ParameterPositionOption summaryCtx, ApOption argAp, Ap ap, Configuration config
) {
exists(ArgNodeEx arg, boolean allowsFieldFlow |
fwdFlow(arg, state, outercc, summaryCtx, argAp, ap, config) and
@@ -1427,32 +1457,19 @@ private module MkStage<StageSig PrevStage> {
}
pragma[nomagic]
private predicate fwdFlowOutNotFromArg(
NodeEx out, FlowState state, Cc ccOut, ParamNodeOption summaryCtx, ApOption argAp, Ap ap,
private predicate fwdFlowOutFromArg(
DataFlowCall call, NodeEx out, FlowState state, ParameterPosition summaryCtx, Ap argAp, Ap ap,
Configuration config
) {
exists(
DataFlowCall call, RetNodeEx ret, boolean allowsFieldFlow, CcNoCall innercc,
DataFlowCallable inner
DataFlowCallable c, RetNodeEx ret, ReturnKindExt kind, boolean allowsFieldFlow, CcCall ccc
|
fwdFlow(ret, state, innercc, summaryCtx, argAp, ap, config) and
flowOutOfCall(call, ret, _, out, allowsFieldFlow, config) and
inner = ret.getEnclosingCallable() and
ccOut = getCallContextReturn(inner, call, innercc) and
if allowsFieldFlow = false then ap instanceof ApNil else any()
)
}
pragma[nomagic]
private predicate fwdFlowOutFromArg(
DataFlowCall call, NodeEx out, FlowState state, ParamNode summaryCtx, Ap argAp, Ap ap,
Configuration config
) {
exists(RetNodeEx ret, ReturnKindExt kind, boolean allowsFieldFlow, CcCall ccc |
fwdFlow(ret, state, ccc, TParamNodeSome(summaryCtx), apSome(argAp), ap, config) and
flowThroughOutOfCall(call, ccc, ret, kind, out, allowsFieldFlow, config) and
fwdFlow(pragma[only_bind_into](ret), state, pragma[only_bind_into](ccc),
TParameterPositionSome(pragma[only_bind_into](summaryCtx)), apSome(argAp), ap, config) and
flowThroughOutOfCall(call, pragma[only_bind_into](c), ccc, ret, kind, out, allowsFieldFlow,
config) and
(if allowsFieldFlow = false then ap instanceof ApNil else any()) and
parameterFlowThroughAllowed(summaryCtx, kind)
parameterFlowThroughAllowed(c, pragma[only_bind_into](summaryCtx), kind)
)
}
@@ -1462,13 +1479,13 @@ private module MkStage<StageSig PrevStage> {
*/
pragma[nomagic]
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, ParamNode p, Ap ap,
Configuration config
DataFlowCall call, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp,
ParameterPosition pos, Ap ap, Configuration config
) {
exists(ParamNodeEx param |
fwdFlowIn(call, param, _, cc, _, summaryCtx, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(param, unbindApa(getApprox(ap)), config) and
p = param.asNode()
pos = param.getPosition()
)
}
@@ -1489,23 +1506,41 @@ private module MkStage<StageSig PrevStage> {
}
pragma[nomagic]
private predicate returnFlowsThrough(
RetNodeEx ret, ReturnPosition pos, FlowState state, CcCall ccc, ParamNode p, Ap argAp, Ap ap,
Configuration config
private predicate returnFlowsThrough0(
RetNodeEx ret, ReturnKindExt kind, FlowState state, CcCall ccc, DataFlowCallable c,
ParameterPosition ppos, Ap argAp, Ap ap, Configuration config
) {
fwdFlow(ret, state, ccc, TParamNodeSome(p), apSome(argAp), ap, config) and
pos = ret.getReturnPosition() and
parameterFlowThroughAllowed(p, pos.getKind())
exists(boolean allowsFieldFlow |
fwdFlow(ret, state, ccc, TParameterPositionSome(ppos), apSome(argAp), ap, config) and
flowThroughOutOfCall(_, c, _, pragma[only_bind_into](ret), kind, _, allowsFieldFlow,
pragma[only_bind_into](config)) and
if allowsFieldFlow = false then ap instanceof ApNil else any()
)
}
pragma[nomagic]
private predicate returnFlowsThrough(
RetNodeEx ret, ReturnKindExt kind, FlowState state, CcCall ccc, ParamNodeEx p, Ap argAp,
Ap ap, Configuration config
) {
exists(DataFlowCallable c, ParameterPosition ppos |
returnFlowsThrough0(ret, kind, state, ccc, c, ppos, argAp, ap, config) and
p.isParameterOf(c, ppos) and
parameterFlowThroughAllowed(p, kind)
)
}
pragma[nomagic]
private predicate flowThroughIntoCall(
DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Configuration config
) {
flowIntoCall(call, pragma[only_bind_into](arg), pragma[only_bind_into](p), allowsFieldFlow,
pragma[only_bind_into](config)) and
fwdFlow(arg, _, _, _, _, _, pragma[only_bind_into](config)) and
returnFlowsThrough(_, _, _, _, p.asNode(), _, _, pragma[only_bind_into](config))
exists(Ap argAp |
flowIntoCall(call, pragma[only_bind_into](arg), pragma[only_bind_into](p), allowsFieldFlow,
pragma[only_bind_into](config)) and
fwdFlow(arg, _, _, _, _, pragma[only_bind_into](argAp), pragma[only_bind_into](config)) and
returnFlowsThrough(_, _, _, _, p, pragma[only_bind_into](argAp), _,
pragma[only_bind_into](config))
)
}
/**
@@ -1591,21 +1626,25 @@ private module MkStage<StageSig PrevStage> {
)
or
// flow into a callable
revFlowInNotToReturn(node, state, returnAp, ap, config) and
returnCtx = TReturnCtxNone()
exists(ParamNodeEx p, boolean allowsFieldFlow |
revFlow(p, state, TReturnCtxNone(), returnAp, ap, config) and
flowIntoCall(_, node, p, allowsFieldFlow, config) and
(if allowsFieldFlow = false then ap instanceof ApNil else any()) and
returnCtx = TReturnCtxNone()
)
or
// flow through a callable
exists(DataFlowCall call, ReturnPosition returnPos0, Ap returnAp0 |
revFlowInToReturn(call, node, state, returnPos0, returnAp0, ap, config) and
revFlowIsReturned(call, returnCtx, returnAp, returnPos0, returnAp0, config)
exists(DataFlowCall call, ReturnKindExt returnKind0, Ap returnAp0 |
revFlowInToReturn(call, node, state, returnKind0, returnAp0, ap, config) and
revFlowIsReturned(call, returnCtx, returnAp, returnKind0, returnAp0, config)
)
or
// flow out of a callable
exists(ReturnPosition pos |
revFlowOut(_, node, pos, state, _, _, ap, config) and
if returnFlowsThrough(node, pos, state, _, _, _, ap, config)
exists(ReturnKindExt kind |
revFlowOut(_, node, kind, state, _, _, ap, config) and
if returnFlowsThrough(node, kind, state, _, _, _, ap, config)
then (
returnCtx = TReturnCtxMaybeFlowThrough(pos) and
returnCtx = TReturnCtxMaybeFlowThrough(kind) and
returnAp = apSome(ap)
) else (
returnCtx = TReturnCtxNoFlowThrough() and returnAp = apNone()
@@ -1638,37 +1677,27 @@ private module MkStage<StageSig PrevStage> {
pragma[nomagic]
private predicate revFlowOut(
DataFlowCall call, RetNodeEx ret, ReturnPosition pos, FlowState state, ReturnCtx returnCtx,
DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, FlowState state, ReturnCtx returnCtx,
ApOption returnAp, Ap ap, Configuration config
) {
exists(NodeEx out, boolean allowsFieldFlow |
revFlow(out, state, returnCtx, returnAp, ap, config) and
flowOutOfCall(call, ret, pos, out, allowsFieldFlow, config) and
if allowsFieldFlow = false then ap instanceof ApNil else any()
)
}
pragma[nomagic]
private predicate revFlowInNotToReturn(
ArgNodeEx arg, FlowState state, ApOption returnAp, Ap ap, Configuration config
) {
exists(ParamNodeEx p, boolean allowsFieldFlow |
revFlow(p, state, TReturnCtxNone(), returnAp, ap, config) and
flowIntoCall(_, arg, p, allowsFieldFlow, config) and
flowOutOfCall(call, ret, kind, out, allowsFieldFlow, config) and
if allowsFieldFlow = false then ap instanceof ApNil else any()
)
}
pragma[nomagic]
private predicate revFlowInToReturn(
DataFlowCall call, ArgNodeEx arg, FlowState state, ReturnPosition returnPos, Ap returnAp,
Ap ap, Configuration config
DataFlowCall call, ArgNodeEx arg, FlowState state, ReturnKindExt kind, Ap returnAp, Ap ap,
Configuration config
) {
exists(ParamNodeEx p, boolean allowsFieldFlow |
revFlow(p, state, TReturnCtxMaybeFlowThrough(returnPos), apSome(returnAp), ap, config) and
revFlow(pragma[only_bind_into](p), state,
TReturnCtxMaybeFlowThrough(pragma[only_bind_into](kind)), apSome(returnAp), ap, config) and
flowThroughIntoCall(call, arg, p, allowsFieldFlow, config) and
(if allowsFieldFlow = false then ap instanceof ApNil else any()) and
parameterFlowThroughAllowed(p.asNode(), returnPos.getKind())
parameterFlowThroughAllowed(p, kind)
)
}
@@ -1679,12 +1708,12 @@ private module MkStage<StageSig PrevStage> {
*/
pragma[nomagic]
private predicate revFlowIsReturned(
DataFlowCall call, ReturnCtx returnCtx, ApOption returnAp, ReturnPosition pos, Ap ap,
DataFlowCall call, ReturnCtx returnCtx, ApOption returnAp, ReturnKindExt kind, Ap ap,
Configuration config
) {
exists(RetNodeEx ret, FlowState state, CcCall ccc |
revFlowOut(call, ret, pos, state, returnCtx, returnAp, ap, config) and
returnFlowsThrough(ret, pos, state, ccc, _, _, ap, config) and
revFlowOut(call, ret, kind, state, returnCtx, returnAp, ap, config) and
returnFlowsThrough(ret, kind, state, ccc, _, _, ap, config) and
matchesCall(ccc, call)
)
}
@@ -1757,37 +1786,37 @@ private module MkStage<StageSig PrevStage> {
pragma[nomagic]
private predicate parameterFlowsThroughRev(
ParamNodeEx p, Ap ap, ReturnPosition returnPos, Configuration config
ParamNodeEx p, Ap ap, ReturnKindExt kind, Configuration config
) {
revFlow(p, _, TReturnCtxMaybeFlowThrough(returnPos), apSome(_), ap, config) and
parameterFlowThroughAllowed(p.asNode(), returnPos.getKind())
revFlow(p, _, TReturnCtxMaybeFlowThrough(kind), apSome(_), ap, config) and
parameterFlowThroughAllowed(p, kind)
}
pragma[nomagic]
predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap, Configuration config) {
exists(RetNodeEx ret, ReturnPosition pos |
returnFlowsThrough(ret, pos, _, _, p.asNode(), ap, _, config) and
parameterFlowsThroughRev(p, ap, pos, config)
exists(RetNodeEx ret, ReturnKindExt kind |
returnFlowsThrough(ret, kind, _, _, p, ap, _, config) and
parameterFlowsThroughRev(p, ap, kind, config)
)
}
pragma[nomagic]
predicate returnMayFlowThrough(RetNodeEx ret, ReturnPosition pos, Configuration config) {
predicate returnMayFlowThrough(RetNodeEx ret, ReturnKindExt kind, Configuration config) {
exists(ParamNodeEx p, Ap ap |
returnFlowsThrough(ret, pos, _, _, p.asNode(), ap, _, config) and
parameterFlowsThroughRev(p, ap, pos, config)
returnFlowsThrough(ret, kind, _, _, p, ap, _, config) and
parameterFlowsThroughRev(p, ap, kind, config)
)
}
pragma[nomagic]
predicate callMayFlowThroughRev(DataFlowCall call, Configuration config) {
exists(
ReturnPosition returnPos0, Ap returnAp0, ArgNodeEx arg, FlowState state,
ReturnKindExt returnKind0, Ap returnAp0, ArgNodeEx arg, FlowState state,
ReturnCtx returnCtx, ApOption returnAp, Ap ap
|
revFlow(arg, state, returnCtx, returnAp, ap, config) and
revFlowInToReturn(call, arg, state, returnPos0, returnAp0, ap, config) and
revFlowIsReturned(call, returnCtx, returnAp, returnPos0, returnAp0, config)
revFlowInToReturn(call, arg, state, returnKind0, returnAp0, ap, config) and
revFlowIsReturned(call, returnCtx, returnAp, returnKind0, returnAp0, config)
)
}
@@ -1800,9 +1829,8 @@ private module MkStage<StageSig PrevStage> {
conscand = count(TypedContent f0, Ap ap | fwdConsCand(f0, ap, config)) and
states = count(FlowState state | fwdFlow(_, state, _, _, _, _, config)) and
tuples =
count(NodeEx n, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap |
fwdFlow(n, state, cc, summaryCtx, argAp, ap, config)
)
count(NodeEx n, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp,
Ap ap | fwdFlow(n, state, cc, summaryCtx, argAp, ap, config))
or
fwd = false and
nodes = count(NodeEx node | revFlow(node, _, _, _, _, config)) and
@@ -1992,10 +2020,10 @@ private module Stage2 implements StageSig {
pragma[nomagic]
private predicate flowOutOfCallNodeCand2(
DataFlowCall call, RetNodeEx node1, ReturnPosition pos, NodeEx node2, boolean allowsFieldFlow,
DataFlowCall call, RetNodeEx node1, ReturnKindExt kind, NodeEx node2, boolean allowsFieldFlow,
Configuration config
) {
flowOutOfCallNodeCand1(call, node1, pos, node2, allowsFieldFlow, config) and
flowOutOfCallNodeCand1(call, node1, kind, node2, allowsFieldFlow, config) and
Stage2::revFlow(node2, pragma[only_bind_into](config)) and
Stage2::revFlowAlias(node1, pragma[only_bind_into](config))
}
@@ -2511,11 +2539,11 @@ private module Stage4Param implements MkStage<Stage3>::StageParam {
pragma[nomagic]
predicate flowOutOfCall(
DataFlowCall call, RetNodeEx node1, ReturnPosition pos, NodeEx node2, boolean allowsFieldFlow,
DataFlowCall call, RetNodeEx node1, ReturnKindExt kind, NodeEx node2, boolean allowsFieldFlow,
Configuration config
) {
exists(FlowState state |
flowOutOfCallNodeCand2(call, node1, pos, node2, allowsFieldFlow, config) and
flowOutOfCallNodeCand2(call, node1, kind, node2, allowsFieldFlow, config) and
PrevStage::revFlow(node2, pragma[only_bind_into](state), _, pragma[only_bind_into](config)) and
PrevStage::revFlowAlias(node1, pragma[only_bind_into](state), _,
pragma[only_bind_into](config))
@@ -2552,12 +2580,13 @@ private Configuration unbindConf(Configuration conf) {
pragma[nomagic]
private predicate nodeMayUseSummary0(
NodeEx n, ParamNodeEx p, FlowState state, AccessPathApprox apa, Configuration config
NodeEx n, DataFlowCallable c, ParameterPosition pos, FlowState state, AccessPathApprox apa,
Configuration config
) {
exists(AccessPathApprox apa0 |
Stage4::parameterMayFlowThrough(p, _, _) and
c = n.getEnclosingCallable() and
Stage4::revFlow(n, state, TReturnCtxMaybeFlowThrough(_), _, apa0, config) and
Stage4::fwdFlow(n, state, any(CallContextCall ccc), TParamNodeSome(p.asNode()),
Stage4::fwdFlow(n, state, any(CallContextCall ccc), TParameterPositionSome(pos),
TAccessPathApproxSome(apa), apa0, config)
)
}
@@ -2566,9 +2595,10 @@ pragma[nomagic]
private predicate nodeMayUseSummary(
NodeEx n, FlowState state, AccessPathApprox apa, Configuration config
) {
exists(ParamNodeEx p |
exists(DataFlowCallable c, ParameterPosition pos, ParamNodeEx p |
Stage4::parameterMayFlowThrough(p, apa, config) and
nodeMayUseSummary0(n, p, state, apa, config)
nodeMayUseSummary0(n, c, pos, state, apa, config) and
p.isParameterOf(c, pos)
)
}
@@ -3501,7 +3531,7 @@ private predicate paramFlowsThrough(
pathNode(mid, ret, state, cc, sc, ap, config, _) and
kind = ret.getKind() and
apa = ap.getApprox() and
parameterFlowThroughAllowed(sc.getParamNode().asNode(), kind)
parameterFlowThroughAllowed(sc.getParamNode(), kind)
)
}

View File

@@ -916,15 +916,15 @@ private module Cached {
TDataFlowCallSome(DataFlowCall call)
cached
newtype TParamNodeOption =
TParamNodeNone() or
TParamNodeSome(ParamNode p)
newtype TParameterPositionOption =
TParameterPositionNone() or
TParameterPositionSome(ParameterPosition pos)
cached
newtype TReturnCtx =
TReturnCtxNone() or
TReturnCtxNoFlowThrough() or
TReturnCtxMaybeFlowThrough(ReturnPosition pos)
TReturnCtxMaybeFlowThrough(ReturnKindExt kind)
cached
newtype TTypedContent = MkTypedContent(Content c, DataFlowType t) { store(_, c, _, _, t) }
@@ -1315,15 +1315,15 @@ class DataFlowCallOption extends TDataFlowCallOption {
}
}
/** An optional `ParamNode`. */
class ParamNodeOption extends TParamNodeOption {
/** An optional `ParameterPosition`. */
class ParameterPositionOption extends TParameterPositionOption {
string toString() {
this = TParamNodeNone() and
this = TParameterPositionNone() and
result = "(none)"
or
exists(ParamNode p |
this = TParamNodeSome(p) and
result = p.toString()
exists(ParameterPosition pos |
this = TParameterPositionSome(pos) and
result = pos.toString()
)
}
}
@@ -1335,7 +1335,7 @@ class ParamNodeOption extends TParamNodeOption {
*
* - `TReturnCtxNone()`: no return flow.
* - `TReturnCtxNoFlowThrough()`: return flow, but flow through is not possible.
* - `TReturnCtxMaybeFlowThrough(ReturnPosition pos)`: return flow, of kind `pos`, and
* - `TReturnCtxMaybeFlowThrough(ReturnKindExt kind)`: return flow, of kind `kind`, and
* flow through may be possible.
*/
class ReturnCtx extends TReturnCtx {
@@ -1346,9 +1346,9 @@ class ReturnCtx extends TReturnCtx {
this = TReturnCtxNoFlowThrough() and
result = "(no flow through)"
or
exists(ReturnPosition pos |
this = TReturnCtxMaybeFlowThrough(pos) and
result = pos.toString()
exists(ReturnKindExt kind |
this = TReturnCtxMaybeFlowThrough(kind) and
result = kind.toString()
)
}
}

View File

@@ -613,11 +613,28 @@ private predicate hasSinkCallCtx(Configuration config) {
* explicitly allowed
*/
bindingset[p, kind]
private predicate parameterFlowThroughAllowed(ParamNode p, ReturnKindExt kind) {
private predicate parameterFlowThroughAllowed(ParamNodeEx p, ReturnKindExt kind) {
exists(ParameterPosition pos | p.isParameterOf(_, pos) |
not kind.(ParamUpdateReturnKind).getPosition() = pos
or
allowParameterReturnInSelfCached(p)
allowParameterReturnInSelfCached(p.asNode())
)
}
/**
* Holds if flow from a parameter at position `pos` inside `c` to a return node of
* kind `kind` is allowed.
*
* We don't expect a parameter to return stored in itself, unless
* explicitly allowed
*/
bindingset[c, pos, kind]
private predicate parameterFlowThroughAllowed(
DataFlowCallable c, ParameterPosition pos, ReturnKindExt kind
) {
exists(ParamNodeEx p |
p.isParameterOf(c, pos) and
parameterFlowThroughAllowed(p, kind)
)
}
@@ -1000,14 +1017,14 @@ private module Stage1 implements StageSig {
returnFlowCallableNodeCand(c, kind, config) and
p.getEnclosingCallable() = c and
exists(ap) and
parameterFlowThroughAllowed(p.asNode(), kind)
parameterFlowThroughAllowed(p, kind)
)
}
pragma[nomagic]
predicate returnMayFlowThrough(RetNodeEx ret, ReturnPosition pos, Configuration config) {
predicate returnMayFlowThrough(RetNodeEx ret, ReturnKindExt kind, Configuration config) {
throughFlowNodeCand(ret, config) and
pos = ret.getReturnPosition()
kind = ret.getKind()
}
pragma[nomagic]
@@ -1066,13 +1083,16 @@ private predicate viableReturnPosOutNodeCand1(
*/
pragma[nomagic]
private predicate flowOutOfCallNodeCand1(
DataFlowCall call, RetNodeEx ret, ReturnPosition pos, NodeEx out, Configuration config
DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, Configuration config
) {
viableReturnPosOutNodeCand1(call, pos, out, config) and
pos = ret.getReturnPosition() and
Stage1::revFlow(ret, config) and
not outBarrier(ret, config) and
not inBarrier(out, config)
exists(ReturnPosition pos |
viableReturnPosOutNodeCand1(call, pos, out, config) and
pos = ret.getReturnPosition() and
kind = pos.getKind() and
Stage1::revFlow(ret, config) and
not outBarrier(ret, config) and
not inBarrier(out, config)
)
}
pragma[nomagic]
@@ -1102,6 +1122,7 @@ private predicate flowIntoCallNodeCand1(
* edge in the graph of paths between sources and sinks that ignores call
* contexts.
*/
pragma[nomagic]
private int branch(NodeEx n1, Configuration conf) {
result =
strictcount(NodeEx n |
@@ -1114,6 +1135,7 @@ private int branch(NodeEx n1, Configuration conf) {
* edge in the graph of paths between sources and sinks that ignores call
* contexts.
*/
pragma[nomagic]
private int join(NodeEx n2, Configuration conf) {
result =
strictcount(NodeEx n |
@@ -1130,10 +1152,10 @@ private int join(NodeEx n2, Configuration conf) {
*/
pragma[nomagic]
private predicate flowOutOfCallNodeCand1(
DataFlowCall call, RetNodeEx ret, ReturnPosition pos, NodeEx out, boolean allowsFieldFlow,
DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, boolean allowsFieldFlow,
Configuration config
) {
flowOutOfCallNodeCand1(call, ret, pos, out, pragma[only_bind_into](config)) and
flowOutOfCallNodeCand1(call, ret, kind, out, pragma[only_bind_into](config)) and
exists(int b, int j |
b = branch(ret, pragma[only_bind_into](config)) and
j = join(out, pragma[only_bind_into](config)) and
@@ -1152,10 +1174,10 @@ pragma[nomagic]
private predicate flowIntoCallNodeCand1(
DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Configuration config
) {
flowIntoCallNodeCand1(call, arg, p, config) and
flowIntoCallNodeCand1(call, arg, p, pragma[only_bind_into](config)) and
exists(int b, int j |
b = branch(arg, config) and
j = join(p, config) and
b = branch(arg, pragma[only_bind_into](config)) and
j = join(p, pragma[only_bind_into](config)) and
if b.minimum(j) <= config.fieldFlowBranchLimit()
then allowsFieldFlow = true
else allowsFieldFlow = false
@@ -1174,7 +1196,7 @@ private signature module StageSig {
predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap, Configuration config);
predicate returnMayFlowThrough(RetNodeEx ret, ReturnPosition pos, Configuration config);
predicate returnMayFlowThrough(RetNodeEx ret, ReturnKindExt kind, Configuration config);
predicate storeStepCand(
NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, DataFlowType contentType,
@@ -1240,7 +1262,7 @@ private module MkStage<StageSig PrevStage> {
);
predicate flowOutOfCall(
DataFlowCall call, RetNodeEx ret, ReturnPosition pos, NodeEx out, boolean allowsFieldFlow,
DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, boolean allowsFieldFlow,
Configuration config
);
@@ -1266,16 +1288,14 @@ private module MkStage<StageSig PrevStage> {
pragma[nomagic]
private predicate flowThroughOutOfCall(
DataFlowCall call, CcCall ccc, RetNodeEx ret, ReturnKindExt kind, NodeEx out,
boolean allowsFieldFlow, Configuration config
DataFlowCall call, DataFlowCallable c, CcCall ccc, RetNodeEx ret, ReturnKindExt kind,
NodeEx out, boolean allowsFieldFlow, Configuration config
) {
exists(ReturnPosition pos |
flowOutOfCall(call, ret, pos, out, allowsFieldFlow, pragma[only_bind_into](config)) and
kind = pos.getKind() and
PrevStage::callMayFlowThroughRev(call, pragma[only_bind_into](config)) and
PrevStage::returnMayFlowThrough(ret, pos, pragma[only_bind_into](config)) and
matchesCall(ccc, call)
)
flowOutOfCall(call, ret, kind, out, allowsFieldFlow, pragma[only_bind_into](config)) and
PrevStage::callMayFlowThroughRev(call, pragma[only_bind_into](config)) and
PrevStage::returnMayFlowThrough(ret, kind, pragma[only_bind_into](config)) and
matchesCall(ccc, call) and
c = ret.getEnclosingCallable()
}
/**
@@ -1284,12 +1304,12 @@ private module MkStage<StageSig PrevStage> {
*
* The call context `cc` records whether the node is reached through an
* argument in a call, and if so, `summaryCtx` and `argAp` record the
* corresponding parameter and access path of that argument, respectively.
* corresponding parameter position and access path of that argument, respectively.
*/
pragma[nomagic]
additional predicate fwdFlow(
NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap,
Configuration config
NodeEx node, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp,
Ap ap, Configuration config
) {
fwdFlow0(node, state, cc, summaryCtx, argAp, ap, config) and
PrevStage::revFlow(node, state, unbindApa(getApprox(ap)), config) and
@@ -1298,13 +1318,13 @@ private module MkStage<StageSig PrevStage> {
pragma[nomagic]
private predicate fwdFlow0(
NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap,
Configuration config
NodeEx node, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp,
Ap ap, Configuration config
) {
sourceNode(node, state, config) and
(if hasSourceCallCtx(config) then cc = ccSomeCall() else cc = ccNone()) and
argAp = apNone() and
summaryCtx = TParamNodeNone() and
summaryCtx = TParameterPositionNone() and
ap = getApNil(node)
or
exists(NodeEx mid, FlowState state0, Ap ap0, LocalCc localCc |
@@ -1322,7 +1342,7 @@ private module MkStage<StageSig PrevStage> {
fwdFlow(mid, pragma[only_bind_into](state), _, _, _, ap, pragma[only_bind_into](config)) and
jumpStep(mid, node, config) and
cc = ccNone() and
summaryCtx = TParamNodeNone() and
summaryCtx = TParameterPositionNone() and
argAp = apNone()
)
or
@@ -1330,7 +1350,7 @@ private module MkStage<StageSig PrevStage> {
fwdFlow(mid, state, _, _, _, nil, pragma[only_bind_into](config)) and
additionalJumpStep(mid, node, config) and
cc = ccNone() and
summaryCtx = TParamNodeNone() and
summaryCtx = TParameterPositionNone() and
argAp = apNone() and
ap = getApNil(node)
)
@@ -1339,7 +1359,7 @@ private module MkStage<StageSig PrevStage> {
fwdFlow(mid, state0, _, _, _, nil, pragma[only_bind_into](config)) and
additionalJumpStateStep(mid, state0, node, state, config) and
cc = ccNone() and
summaryCtx = TParamNodeNone() and
summaryCtx = TParameterPositionNone() and
argAp = apNone() and
ap = getApNil(node)
)
@@ -1362,17 +1382,27 @@ private module MkStage<StageSig PrevStage> {
apa = getApprox(ap) and
if PrevStage::parameterMayFlowThrough(node, apa, config)
then (
summaryCtx = TParamNodeSome(node.asNode()) and argAp = apSome(ap)
summaryCtx = TParameterPositionSome(node.(ParamNodeEx).getPosition()) and
argAp = apSome(ap)
) else (
summaryCtx = TParamNodeNone() and argAp = apNone()
summaryCtx = TParameterPositionNone() and argAp = apNone()
)
)
or
// flow out of a callable
fwdFlowOutNotFromArg(node, state, cc, summaryCtx, argAp, ap, config)
exists(
DataFlowCall call, RetNodeEx ret, boolean allowsFieldFlow, CcNoCall innercc,
DataFlowCallable inner
|
fwdFlow(ret, state, innercc, summaryCtx, argAp, ap, config) and
flowOutOfCall(call, ret, _, node, allowsFieldFlow, config) and
inner = ret.getEnclosingCallable() and
cc = getCallContextReturn(inner, call, innercc) and
if allowsFieldFlow = false then ap instanceof ApNil else any()
)
or
// flow through a callable
exists(DataFlowCall call, ParamNode summaryCtx0, Ap argAp0 |
exists(DataFlowCall call, ParameterPosition summaryCtx0, Ap argAp0 |
fwdFlowOutFromArg(call, node, state, summaryCtx0, argAp0, ap, config) and
fwdFlowIsEntered(call, cc, summaryCtx, argAp, summaryCtx0, argAp0, config)
)
@@ -1381,7 +1411,7 @@ private module MkStage<StageSig PrevStage> {
pragma[nomagic]
private predicate fwdFlowStore(
NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, FlowState state, Cc cc,
ParamNodeOption summaryCtx, ApOption argAp, Configuration config
ParameterPositionOption summaryCtx, ApOption argAp, Configuration config
) {
exists(DataFlowType contentType |
fwdFlow(node1, state, cc, summaryCtx, argAp, ap1, config) and
@@ -1406,7 +1436,7 @@ private module MkStage<StageSig PrevStage> {
pragma[nomagic]
private predicate fwdFlowRead(
Ap ap, Content c, NodeEx node1, NodeEx node2, FlowState state, Cc cc,
ParamNodeOption summaryCtx, ApOption argAp, Configuration config
ParameterPositionOption summaryCtx, ApOption argAp, Configuration config
) {
fwdFlow(node1, state, cc, summaryCtx, argAp, ap, config) and
PrevStage::readStepCand(node1, c, node2, config) and
@@ -1416,7 +1446,7 @@ private module MkStage<StageSig PrevStage> {
pragma[nomagic]
private predicate fwdFlowIn(
DataFlowCall call, ParamNodeEx p, FlowState state, Cc outercc, Cc innercc,
ParamNodeOption summaryCtx, ApOption argAp, Ap ap, Configuration config
ParameterPositionOption summaryCtx, ApOption argAp, Ap ap, Configuration config
) {
exists(ArgNodeEx arg, boolean allowsFieldFlow |
fwdFlow(arg, state, outercc, summaryCtx, argAp, ap, config) and
@@ -1427,32 +1457,19 @@ private module MkStage<StageSig PrevStage> {
}
pragma[nomagic]
private predicate fwdFlowOutNotFromArg(
NodeEx out, FlowState state, Cc ccOut, ParamNodeOption summaryCtx, ApOption argAp, Ap ap,
private predicate fwdFlowOutFromArg(
DataFlowCall call, NodeEx out, FlowState state, ParameterPosition summaryCtx, Ap argAp, Ap ap,
Configuration config
) {
exists(
DataFlowCall call, RetNodeEx ret, boolean allowsFieldFlow, CcNoCall innercc,
DataFlowCallable inner
DataFlowCallable c, RetNodeEx ret, ReturnKindExt kind, boolean allowsFieldFlow, CcCall ccc
|
fwdFlow(ret, state, innercc, summaryCtx, argAp, ap, config) and
flowOutOfCall(call, ret, _, out, allowsFieldFlow, config) and
inner = ret.getEnclosingCallable() and
ccOut = getCallContextReturn(inner, call, innercc) and
if allowsFieldFlow = false then ap instanceof ApNil else any()
)
}
pragma[nomagic]
private predicate fwdFlowOutFromArg(
DataFlowCall call, NodeEx out, FlowState state, ParamNode summaryCtx, Ap argAp, Ap ap,
Configuration config
) {
exists(RetNodeEx ret, ReturnKindExt kind, boolean allowsFieldFlow, CcCall ccc |
fwdFlow(ret, state, ccc, TParamNodeSome(summaryCtx), apSome(argAp), ap, config) and
flowThroughOutOfCall(call, ccc, ret, kind, out, allowsFieldFlow, config) and
fwdFlow(pragma[only_bind_into](ret), state, pragma[only_bind_into](ccc),
TParameterPositionSome(pragma[only_bind_into](summaryCtx)), apSome(argAp), ap, config) and
flowThroughOutOfCall(call, pragma[only_bind_into](c), ccc, ret, kind, out, allowsFieldFlow,
config) and
(if allowsFieldFlow = false then ap instanceof ApNil else any()) and
parameterFlowThroughAllowed(summaryCtx, kind)
parameterFlowThroughAllowed(c, pragma[only_bind_into](summaryCtx), kind)
)
}
@@ -1462,13 +1479,13 @@ private module MkStage<StageSig PrevStage> {
*/
pragma[nomagic]
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, ParamNode p, Ap ap,
Configuration config
DataFlowCall call, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp,
ParameterPosition pos, Ap ap, Configuration config
) {
exists(ParamNodeEx param |
fwdFlowIn(call, param, _, cc, _, summaryCtx, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(param, unbindApa(getApprox(ap)), config) and
p = param.asNode()
pos = param.getPosition()
)
}
@@ -1489,23 +1506,41 @@ private module MkStage<StageSig PrevStage> {
}
pragma[nomagic]
private predicate returnFlowsThrough(
RetNodeEx ret, ReturnPosition pos, FlowState state, CcCall ccc, ParamNode p, Ap argAp, Ap ap,
Configuration config
private predicate returnFlowsThrough0(
RetNodeEx ret, ReturnKindExt kind, FlowState state, CcCall ccc, DataFlowCallable c,
ParameterPosition ppos, Ap argAp, Ap ap, Configuration config
) {
fwdFlow(ret, state, ccc, TParamNodeSome(p), apSome(argAp), ap, config) and
pos = ret.getReturnPosition() and
parameterFlowThroughAllowed(p, pos.getKind())
exists(boolean allowsFieldFlow |
fwdFlow(ret, state, ccc, TParameterPositionSome(ppos), apSome(argAp), ap, config) and
flowThroughOutOfCall(_, c, _, pragma[only_bind_into](ret), kind, _, allowsFieldFlow,
pragma[only_bind_into](config)) and
if allowsFieldFlow = false then ap instanceof ApNil else any()
)
}
pragma[nomagic]
private predicate returnFlowsThrough(
RetNodeEx ret, ReturnKindExt kind, FlowState state, CcCall ccc, ParamNodeEx p, Ap argAp,
Ap ap, Configuration config
) {
exists(DataFlowCallable c, ParameterPosition ppos |
returnFlowsThrough0(ret, kind, state, ccc, c, ppos, argAp, ap, config) and
p.isParameterOf(c, ppos) and
parameterFlowThroughAllowed(p, kind)
)
}
pragma[nomagic]
private predicate flowThroughIntoCall(
DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Configuration config
) {
flowIntoCall(call, pragma[only_bind_into](arg), pragma[only_bind_into](p), allowsFieldFlow,
pragma[only_bind_into](config)) and
fwdFlow(arg, _, _, _, _, _, pragma[only_bind_into](config)) and
returnFlowsThrough(_, _, _, _, p.asNode(), _, _, pragma[only_bind_into](config))
exists(Ap argAp |
flowIntoCall(call, pragma[only_bind_into](arg), pragma[only_bind_into](p), allowsFieldFlow,
pragma[only_bind_into](config)) and
fwdFlow(arg, _, _, _, _, pragma[only_bind_into](argAp), pragma[only_bind_into](config)) and
returnFlowsThrough(_, _, _, _, p, pragma[only_bind_into](argAp), _,
pragma[only_bind_into](config))
)
}
/**
@@ -1591,21 +1626,25 @@ private module MkStage<StageSig PrevStage> {
)
or
// flow into a callable
revFlowInNotToReturn(node, state, returnAp, ap, config) and
returnCtx = TReturnCtxNone()
exists(ParamNodeEx p, boolean allowsFieldFlow |
revFlow(p, state, TReturnCtxNone(), returnAp, ap, config) and
flowIntoCall(_, node, p, allowsFieldFlow, config) and
(if allowsFieldFlow = false then ap instanceof ApNil else any()) and
returnCtx = TReturnCtxNone()
)
or
// flow through a callable
exists(DataFlowCall call, ReturnPosition returnPos0, Ap returnAp0 |
revFlowInToReturn(call, node, state, returnPos0, returnAp0, ap, config) and
revFlowIsReturned(call, returnCtx, returnAp, returnPos0, returnAp0, config)
exists(DataFlowCall call, ReturnKindExt returnKind0, Ap returnAp0 |
revFlowInToReturn(call, node, state, returnKind0, returnAp0, ap, config) and
revFlowIsReturned(call, returnCtx, returnAp, returnKind0, returnAp0, config)
)
or
// flow out of a callable
exists(ReturnPosition pos |
revFlowOut(_, node, pos, state, _, _, ap, config) and
if returnFlowsThrough(node, pos, state, _, _, _, ap, config)
exists(ReturnKindExt kind |
revFlowOut(_, node, kind, state, _, _, ap, config) and
if returnFlowsThrough(node, kind, state, _, _, _, ap, config)
then (
returnCtx = TReturnCtxMaybeFlowThrough(pos) and
returnCtx = TReturnCtxMaybeFlowThrough(kind) and
returnAp = apSome(ap)
) else (
returnCtx = TReturnCtxNoFlowThrough() and returnAp = apNone()
@@ -1638,37 +1677,27 @@ private module MkStage<StageSig PrevStage> {
pragma[nomagic]
private predicate revFlowOut(
DataFlowCall call, RetNodeEx ret, ReturnPosition pos, FlowState state, ReturnCtx returnCtx,
DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, FlowState state, ReturnCtx returnCtx,
ApOption returnAp, Ap ap, Configuration config
) {
exists(NodeEx out, boolean allowsFieldFlow |
revFlow(out, state, returnCtx, returnAp, ap, config) and
flowOutOfCall(call, ret, pos, out, allowsFieldFlow, config) and
if allowsFieldFlow = false then ap instanceof ApNil else any()
)
}
pragma[nomagic]
private predicate revFlowInNotToReturn(
ArgNodeEx arg, FlowState state, ApOption returnAp, Ap ap, Configuration config
) {
exists(ParamNodeEx p, boolean allowsFieldFlow |
revFlow(p, state, TReturnCtxNone(), returnAp, ap, config) and
flowIntoCall(_, arg, p, allowsFieldFlow, config) and
flowOutOfCall(call, ret, kind, out, allowsFieldFlow, config) and
if allowsFieldFlow = false then ap instanceof ApNil else any()
)
}
pragma[nomagic]
private predicate revFlowInToReturn(
DataFlowCall call, ArgNodeEx arg, FlowState state, ReturnPosition returnPos, Ap returnAp,
Ap ap, Configuration config
DataFlowCall call, ArgNodeEx arg, FlowState state, ReturnKindExt kind, Ap returnAp, Ap ap,
Configuration config
) {
exists(ParamNodeEx p, boolean allowsFieldFlow |
revFlow(p, state, TReturnCtxMaybeFlowThrough(returnPos), apSome(returnAp), ap, config) and
revFlow(pragma[only_bind_into](p), state,
TReturnCtxMaybeFlowThrough(pragma[only_bind_into](kind)), apSome(returnAp), ap, config) and
flowThroughIntoCall(call, arg, p, allowsFieldFlow, config) and
(if allowsFieldFlow = false then ap instanceof ApNil else any()) and
parameterFlowThroughAllowed(p.asNode(), returnPos.getKind())
parameterFlowThroughAllowed(p, kind)
)
}
@@ -1679,12 +1708,12 @@ private module MkStage<StageSig PrevStage> {
*/
pragma[nomagic]
private predicate revFlowIsReturned(
DataFlowCall call, ReturnCtx returnCtx, ApOption returnAp, ReturnPosition pos, Ap ap,
DataFlowCall call, ReturnCtx returnCtx, ApOption returnAp, ReturnKindExt kind, Ap ap,
Configuration config
) {
exists(RetNodeEx ret, FlowState state, CcCall ccc |
revFlowOut(call, ret, pos, state, returnCtx, returnAp, ap, config) and
returnFlowsThrough(ret, pos, state, ccc, _, _, ap, config) and
revFlowOut(call, ret, kind, state, returnCtx, returnAp, ap, config) and
returnFlowsThrough(ret, kind, state, ccc, _, _, ap, config) and
matchesCall(ccc, call)
)
}
@@ -1757,37 +1786,37 @@ private module MkStage<StageSig PrevStage> {
pragma[nomagic]
private predicate parameterFlowsThroughRev(
ParamNodeEx p, Ap ap, ReturnPosition returnPos, Configuration config
ParamNodeEx p, Ap ap, ReturnKindExt kind, Configuration config
) {
revFlow(p, _, TReturnCtxMaybeFlowThrough(returnPos), apSome(_), ap, config) and
parameterFlowThroughAllowed(p.asNode(), returnPos.getKind())
revFlow(p, _, TReturnCtxMaybeFlowThrough(kind), apSome(_), ap, config) and
parameterFlowThroughAllowed(p, kind)
}
pragma[nomagic]
predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap, Configuration config) {
exists(RetNodeEx ret, ReturnPosition pos |
returnFlowsThrough(ret, pos, _, _, p.asNode(), ap, _, config) and
parameterFlowsThroughRev(p, ap, pos, config)
exists(RetNodeEx ret, ReturnKindExt kind |
returnFlowsThrough(ret, kind, _, _, p, ap, _, config) and
parameterFlowsThroughRev(p, ap, kind, config)
)
}
pragma[nomagic]
predicate returnMayFlowThrough(RetNodeEx ret, ReturnPosition pos, Configuration config) {
predicate returnMayFlowThrough(RetNodeEx ret, ReturnKindExt kind, Configuration config) {
exists(ParamNodeEx p, Ap ap |
returnFlowsThrough(ret, pos, _, _, p.asNode(), ap, _, config) and
parameterFlowsThroughRev(p, ap, pos, config)
returnFlowsThrough(ret, kind, _, _, p, ap, _, config) and
parameterFlowsThroughRev(p, ap, kind, config)
)
}
pragma[nomagic]
predicate callMayFlowThroughRev(DataFlowCall call, Configuration config) {
exists(
ReturnPosition returnPos0, Ap returnAp0, ArgNodeEx arg, FlowState state,
ReturnKindExt returnKind0, Ap returnAp0, ArgNodeEx arg, FlowState state,
ReturnCtx returnCtx, ApOption returnAp, Ap ap
|
revFlow(arg, state, returnCtx, returnAp, ap, config) and
revFlowInToReturn(call, arg, state, returnPos0, returnAp0, ap, config) and
revFlowIsReturned(call, returnCtx, returnAp, returnPos0, returnAp0, config)
revFlowInToReturn(call, arg, state, returnKind0, returnAp0, ap, config) and
revFlowIsReturned(call, returnCtx, returnAp, returnKind0, returnAp0, config)
)
}
@@ -1800,9 +1829,8 @@ private module MkStage<StageSig PrevStage> {
conscand = count(TypedContent f0, Ap ap | fwdConsCand(f0, ap, config)) and
states = count(FlowState state | fwdFlow(_, state, _, _, _, _, config)) and
tuples =
count(NodeEx n, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap |
fwdFlow(n, state, cc, summaryCtx, argAp, ap, config)
)
count(NodeEx n, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp,
Ap ap | fwdFlow(n, state, cc, summaryCtx, argAp, ap, config))
or
fwd = false and
nodes = count(NodeEx node | revFlow(node, _, _, _, _, config)) and
@@ -1992,10 +2020,10 @@ private module Stage2 implements StageSig {
pragma[nomagic]
private predicate flowOutOfCallNodeCand2(
DataFlowCall call, RetNodeEx node1, ReturnPosition pos, NodeEx node2, boolean allowsFieldFlow,
DataFlowCall call, RetNodeEx node1, ReturnKindExt kind, NodeEx node2, boolean allowsFieldFlow,
Configuration config
) {
flowOutOfCallNodeCand1(call, node1, pos, node2, allowsFieldFlow, config) and
flowOutOfCallNodeCand1(call, node1, kind, node2, allowsFieldFlow, config) and
Stage2::revFlow(node2, pragma[only_bind_into](config)) and
Stage2::revFlowAlias(node1, pragma[only_bind_into](config))
}
@@ -2511,11 +2539,11 @@ private module Stage4Param implements MkStage<Stage3>::StageParam {
pragma[nomagic]
predicate flowOutOfCall(
DataFlowCall call, RetNodeEx node1, ReturnPosition pos, NodeEx node2, boolean allowsFieldFlow,
DataFlowCall call, RetNodeEx node1, ReturnKindExt kind, NodeEx node2, boolean allowsFieldFlow,
Configuration config
) {
exists(FlowState state |
flowOutOfCallNodeCand2(call, node1, pos, node2, allowsFieldFlow, config) and
flowOutOfCallNodeCand2(call, node1, kind, node2, allowsFieldFlow, config) and
PrevStage::revFlow(node2, pragma[only_bind_into](state), _, pragma[only_bind_into](config)) and
PrevStage::revFlowAlias(node1, pragma[only_bind_into](state), _,
pragma[only_bind_into](config))
@@ -2552,12 +2580,13 @@ private Configuration unbindConf(Configuration conf) {
pragma[nomagic]
private predicate nodeMayUseSummary0(
NodeEx n, ParamNodeEx p, FlowState state, AccessPathApprox apa, Configuration config
NodeEx n, DataFlowCallable c, ParameterPosition pos, FlowState state, AccessPathApprox apa,
Configuration config
) {
exists(AccessPathApprox apa0 |
Stage4::parameterMayFlowThrough(p, _, _) and
c = n.getEnclosingCallable() and
Stage4::revFlow(n, state, TReturnCtxMaybeFlowThrough(_), _, apa0, config) and
Stage4::fwdFlow(n, state, any(CallContextCall ccc), TParamNodeSome(p.asNode()),
Stage4::fwdFlow(n, state, any(CallContextCall ccc), TParameterPositionSome(pos),
TAccessPathApproxSome(apa), apa0, config)
)
}
@@ -2566,9 +2595,10 @@ pragma[nomagic]
private predicate nodeMayUseSummary(
NodeEx n, FlowState state, AccessPathApprox apa, Configuration config
) {
exists(ParamNodeEx p |
exists(DataFlowCallable c, ParameterPosition pos, ParamNodeEx p |
Stage4::parameterMayFlowThrough(p, apa, config) and
nodeMayUseSummary0(n, p, state, apa, config)
nodeMayUseSummary0(n, c, pos, state, apa, config) and
p.isParameterOf(c, pos)
)
}
@@ -3501,7 +3531,7 @@ private predicate paramFlowsThrough(
pathNode(mid, ret, state, cc, sc, ap, config, _) and
kind = ret.getKind() and
apa = ap.getApprox() and
parameterFlowThroughAllowed(sc.getParamNode().asNode(), kind)
parameterFlowThroughAllowed(sc.getParamNode(), kind)
)
}