From 773b1c6a8d240aed8d9ae1d37d09b66cb3e1ed18 Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Wed, 24 Jan 2024 14:59:34 +0100 Subject: [PATCH 01/19] Add more pruning stages --- .../codeql/dataflow/internal/DataFlowImpl.qll | 288 +++++++++++++++++- 1 file changed, 280 insertions(+), 8 deletions(-) diff --git a/shared/dataflow/codeql/dataflow/internal/DataFlowImpl.qll b/shared/dataflow/codeql/dataflow/internal/DataFlowImpl.qll index 3773a2225dd2..9d25f336715b 100644 --- a/shared/dataflow/codeql/dataflow/internal/DataFlowImpl.qll +++ b/shared/dataflow/codeql/dataflow/internal/DataFlowImpl.qll @@ -1270,7 +1270,7 @@ module MakeImpl { /* Begin: Stage logic. */ private module TypOption = Option; - private class TypOption = TypOption::Option; + additional class TypOption = TypOption::Option; pragma[nomagic] private Typ getNodeTyp(NodeEx node) { @@ -2747,10 +2747,74 @@ module MakeImpl { pragma[nomagic] private predicate castingNodeEx(NodeEx node) { node.asNode() instanceof CastingNode } - private module Stage3Param implements MkStage::StageParam { + // private module Stage2_5Param implements MkStage::StageParam { + // private module PrevStage = Stage2; + // class Typ = DataFlowType; + // class Ap = PrevStage::Ap; + // class ApNil = PrevStage::ApNil; + // PrevStage::Ap getApprox(Ap ap) { result = ap } + // Typ getTyp(DataFlowType t) { result = t } + // bindingset[c, t, tail] + // Ap apCons(Content c, Typ t, Ap tail) { + // result = true and exists(c) and exists(t) and exists(tail) + // } + // class ApHeadContent = PrevStage::ApHeadContent; + // predicate getHeadContent = PrevStage::getHeadContent/1; + // // pragma[inline] + // // ApHeadContent getHeadContent(Ap ap) { exists(result) and ap = true } + // predicate projectToHeadContent = PrevStage::projectToHeadContent/1; + // // ApHeadContent projectToHeadContent(Content c) { any() } + // class ApOption = PrevStage::ApOption; + // // class ApOption = BooleanOption; + // predicate apNone = PrevStage::apNone/0; + // // ApOption apNone() { result = TBooleanNone() } + // predicate apSome = PrevStage::apSome/1; + // // ApOption apSome(Ap ap) { result = TBooleanSome(ap) } + // import Level1CallContext + // import NoLocalCallContext + // predicate localStep( + // NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, + // Typ t, LocalCc lcc + // ) { + // localFlowBigStep(node1, state1, node2, state2, preservesValue, t, _) and + // exists(lcc) + // } + // pragma[nomagic] + // private predicate expectsContentCand(NodeEx node) { + // exists(Content c | + // PrevStage::revFlow(node) and + // PrevStage::readStepCand(_, c, _) and + // expectsContentEx(node, c) + // ) + // } + // bindingset[node, state, t0, ap] + // predicate filter(NodeEx node, FlowState state, Typ t0, Ap ap, Typ t) { + // exists(state) and + // // We can get away with not using type strengthening here, since we aren't + // // going to use the tracked types in the construction of Stage 4 access + // // paths. For Stage 4 and onwards, the tracked types must be consistent as + // // the cons candidates including types are used to construct subsequent + // // access path approximations. + // t0 = t and + // (if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), t0) else any()) and + // ( + // notExpectsContent(node) + // or + // expectsContentCand(node) + // ) + // } + // bindingset[typ, contentType] + // predicate typecheckStore(Typ typ, DataFlowType contentType) { + // // We need to typecheck stores here, since reverse flow through a getter + // // might have a different type here compared to inside the getter. + // compatibleTypes(typ, contentType) + // } + // predicate enableTypeFlow() { none() } + // } + private module Stage2_5Param implements MkStage::StageParam { private module PrevStage = Stage2; - class Typ = DataFlowType; + class Typ = PrevStage::Typ; class Ap = ApproxAccessPathFront; @@ -2758,6 +2822,80 @@ module MakeImpl { PrevStage::Ap getApprox(Ap ap) { result = ap.toBoolNonEmpty() } + predicate getTyp = PrevStage::getTyp/1; + + bindingset[c, t, tail] + Ap apCons(Content c, Typ t, Ap tail) { result.getAHead() = c and exists(t) and exists(tail) } + + class ApHeadContent = ContentApprox; + + pragma[noinline] + ApHeadContent getHeadContent(Ap ap) { result = ap.getHead() } + + predicate projectToHeadContent = getContentApproxCached/1; + + class ApOption = ApproxAccessPathFrontOption; + + ApOption apNone() { result = TApproxAccessPathFrontNone() } + + ApOption apSome(Ap ap) { result = TApproxAccessPathFrontSome(ap) } + + // ApOption apSome(Ap ap) { result = TBooleanSome(ap) } + import Level1CallContext + import NoLocalCallContext + + predicate localStep( + NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, + Typ t, LocalCc lcc + ) { + localFlowBigStep(node1, state1, node2, state2, preservesValue, _, _) and + exists(t) and + exists(lcc) + } + + pragma[nomagic] + private predicate expectsContentCand(NodeEx node, Ap ap) { + exists(Content c | + PrevStage::revFlow(node) and + PrevStage::readStepCand(_, c, _) and + expectsContentEx(node, c) and + c = ap.getAHead() + ) + } + + bindingset[node, state, t0, ap] + predicate filter(NodeEx node, FlowState state, Typ t0, Ap ap, Typ t) { + exists(state) and + t0 = t and + exists(ap) and + not stateBarrier(node, state) and + ( + notExpectsContent(node) + or + expectsContentCand(node, ap) + ) + } + + bindingset[typ, contentType] + predicate typecheckStore(Typ typ, DataFlowType contentType) { any() } + + predicate enableTypeFlow() { none() } + } + + private module Stage2_5 = MkStage::Stage; + + private module Stage3Param implements MkStage::StageParam { + private module PrevStage = Stage2_5; + + class Typ = DataFlowType; + + class Ap = ApproxAccessPathFront; + + class ApNil = ApproxAccessPathFrontNil; + + // PrevStage::Ap getApprox(Ap ap) { result = ap.toBoolNonEmpty() } + PrevStage::Ap getApprox(Ap ap) { result = ap } + Typ getTyp(DataFlowType t) { result = t } bindingset[c, t, tail] @@ -2779,11 +2917,14 @@ module MakeImpl { import Level1CallContext import NoLocalCallContext + pragma[nomagic] predicate localStep( NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, Typ t, LocalCc lcc ) { localFlowBigStep(node1, state1, node2, state2, preservesValue, t, _) and + PrevStage::revFlow(node1, pragma[only_bind_into](state1), _) and + PrevStage::revFlow(node2, pragma[only_bind_into](state2), _) and exists(lcc) } @@ -2822,7 +2963,42 @@ module MakeImpl { } } - private module Stage3 = MkStage::Stage; + private module Stage3 = MkStage::Stage; + + pragma[nomagic] + private predicate busy(NodeEx node, int c) { + c = + strictcount(FlowState state, Stage3::Cc cc, ParamNodeOption summaryCtx, + Stage3::TypOption argT, Stage3::ApOption argAp, Stage3::Typ t, Stage3::Ap ap | + Stage3::fwdFlow(node, state, cc, summaryCtx, argT, argAp, t, ap, _) + ) + } + + private predicate busy( + NodeEx node, int c, FlowState state, Stage3::Cc cc, ParamNodeOption summaryCtx, + Stage3::TypOption argT, Stage3::ApOption argAp, Stage3::Typ t, Stage3::Ap ap + ) { + busy(node, c) and + c = max(int i | busy(_, i)) and + Stage3::fwdFlow(node, state, cc, summaryCtx, argT, argAp, t, ap, _) + } + + pragma[nomagic] + private predicate busyRev(NodeEx node, int c) { + c = + strictcount(FlowState state, ReturnCtx returnCtx, Stage3::ApOption returnAp, Stage3::Ap ap | + Stage3::revFlow(node, state, returnCtx, returnAp, ap) + ) + } + + private predicate busyRev( + NodeEx node, int c, FlowState state, ReturnCtx returnCtx, Stage3::ApOption returnAp, + Stage3::Ap ap + ) { + busyRev(node, c) and + c = max(int i | busyRev(_, i)) and + Stage3::revFlow(node, state, returnCtx, returnAp, ap) + } bindingset[node, t0] private predicate strengthenType(NodeEx node, DataFlowType t0, DataFlowType t) { @@ -2834,10 +3010,10 @@ module MakeImpl { else t = t0 } - private module Stage4Param implements MkStage::StageParam { + private module Stage3_5Param implements MkStage::StageParam { private module PrevStage = Stage3; - class Typ = DataFlowType; + class Typ = Unit; class Ap = AccessPathFront; @@ -2845,6 +3021,99 @@ module MakeImpl { PrevStage::Ap getApprox(Ap ap) { result = ap.toApprox() } + Typ getTyp(DataFlowType t) { any() } + + bindingset[c, t, tail] + Ap apCons(Content c, Typ t, Ap tail) { result.getHead() = c and exists(t) and exists(tail) } + + class ApHeadContent = Content; + + pragma[noinline] + ApHeadContent getHeadContent(Ap ap) { result = ap.getHead() } + + ApHeadContent projectToHeadContent(Content c) { result = c } + + class ApOption = AccessPathFrontOption; + + ApOption apNone() { result = TAccessPathFrontNone() } + + ApOption apSome(Ap ap) { result = TAccessPathFrontSome(ap) } + + import Level1CallContext + import NoLocalCallContext + + pragma[nomagic] + predicate localStep( + NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, + Typ t, LocalCc lcc + ) { + localFlowBigStep(node1, state1, node2, state2, preservesValue, _, _) and + PrevStage::revFlow(node1, pragma[only_bind_into](state1), _) and + PrevStage::revFlow(node2, pragma[only_bind_into](state2), _) and + exists(t) and + exists(lcc) + } + + pragma[nomagic] + private predicate clearSet(NodeEx node, ContentSet c) { + PrevStage::revFlow(node) and + clearsContentCached(node.asNode(), c) + } + + pragma[nomagic] + private predicate clearContent(NodeEx node, Content c) { + exists(ContentSet cs | + PrevStage::readStepCand(_, pragma[only_bind_into](c), _) and + c = cs.getAReadContent() and + clearSet(node, cs) + ) + } + + pragma[nomagic] + private predicate clear(NodeEx node, Ap ap) { clearContent(node, ap.getHead()) } + + pragma[nomagic] + private predicate expectsContentCand(NodeEx node, Ap ap) { + exists(Content c | + PrevStage::revFlow(node) and + PrevStage::readStepCand(_, c, _) and + expectsContentEx(node, c) and + c = ap.getHead() + ) + } + + bindingset[node, state, t0, ap] + predicate filter(NodeEx node, FlowState state, Typ t0, Ap ap, Typ t) { + exists(state) and + not clear(node, ap) and + t0 = t and + ( + notExpectsContent(node) + or + expectsContentCand(node, ap) + ) + } + + bindingset[typ, contentType] + predicate typecheckStore(Typ typ, DataFlowType contentType) { any() } + + predicate enableTypeFlow() { none() } + } + + private module Stage3_5 = MkStage::Stage; + + private module Stage4Param implements MkStage::StageParam { + private module PrevStage = Stage3_5; + + class Typ = DataFlowType; + + class Ap = AccessPathFront; + + class ApNil = AccessPathFrontNil; + + // PrevStage::Ap getApprox(Ap ap) { result = ap.toApprox() } + PrevStage::Ap getApprox(Ap ap) { result = ap } + Typ getTyp(DataFlowType t) { result = t } bindingset[c, t, tail] @@ -2863,7 +3132,8 @@ module MakeImpl { ApOption apSome(Ap ap) { result = TAccessPathFrontSome(ap) } - import BooleanCallContext + import Level1CallContext + import NoLocalCallContext pragma[nomagic] predicate localStep( @@ -2922,9 +3192,11 @@ module MakeImpl { // might have a different type here compared to inside the getter. compatibleTypes(typ, contentType) } + + predicate enableTypeFlow() { none() } } - private module Stage4 = MkStage::Stage; + private module Stage4 = MkStage::Stage; /** * Holds if `argApf` is recorded as the summary context for flow reaching `node` From 92b37ceadfcb80fb9763d1aaef420c4a68ace542 Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Wed, 24 Jan 2024 21:25:55 +0100 Subject: [PATCH 02/19] temp --- .../dataflow/internal/DataFlowPrivate.qll | 1 + .../code/java/security/TaintedPathQuery.qll | 4 +- .../codeql/dataflow/internal/DataFlowImpl.qll | 117 +++++++++++------- 3 files changed, 73 insertions(+), 49 deletions(-) diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowPrivate.qll b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowPrivate.qll index b14bbb0ab9be..a751fe8d1d99 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowPrivate.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowPrivate.qll @@ -352,6 +352,7 @@ class DataFlowType extends SrcRefType { pragma[nomagic] predicate typeStrongerThan(DataFlowType t1, DataFlowType t2) { t1.getASourceSupertype+() = t2 } +// predicate typeStrongerThan(DataFlowType t1, DataFlowType t2) { none() } pragma[noinline] DataFlowType getNodeType(Node n) { result = getErasedRepr(n.getTypeBound()) diff --git a/java/ql/lib/semmle/code/java/security/TaintedPathQuery.qll b/java/ql/lib/semmle/code/java/security/TaintedPathQuery.qll index 63bd4949699a..46c1366ae0a6 100644 --- a/java/ql/lib/semmle/code/java/security/TaintedPathQuery.qll +++ b/java/ql/lib/semmle/code/java/security/TaintedPathQuery.qll @@ -94,6 +94,4 @@ module TaintedPathLocalConfig implements DataFlow::ConfigSig { any(TaintedPathAdditionalTaintStep s).step(n1, n2) } } - -/** Tracks flow from local user input to the creation of a path. */ -module TaintedPathLocalFlow = TaintTracking::Global; +// module TaintedPathLocalFlow = TaintTracking::Global; diff --git a/shared/dataflow/codeql/dataflow/internal/DataFlowImpl.qll b/shared/dataflow/codeql/dataflow/internal/DataFlowImpl.qll index 9d25f336715b..9df5cd711378 100644 --- a/shared/dataflow/codeql/dataflow/internal/DataFlowImpl.qll +++ b/shared/dataflow/codeql/dataflow/internal/DataFlowImpl.qll @@ -1270,8 +1270,16 @@ module MakeImpl { /* Begin: Stage logic. */ private module TypOption = Option; + private class ArgTyp = Unit; + + private ArgTyp toArgTyp(Typ t) { any() } + additional class TypOption = TypOption::Option; + private module ArgTypOption = Option; + + additional class ArgTypOption = ArgTypOption::Option; + pragma[nomagic] private Typ getNodeTyp(NodeEx node) { PrevStage::revFlow(node) and result = getTyp(node.getDataFlowType()) @@ -1299,14 +1307,14 @@ module MakeImpl { */ pragma[nomagic] additional predicate fwdFlow( - NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, TypOption argT, + NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ArgTypOption argT, ApOption argAp, Typ t, Ap ap, ApApprox apa ) { fwdFlow1(node, state, cc, summaryCtx, argT, argAp, _, t, ap, apa) } private predicate fwdFlow1( - NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, TypOption argT, + NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ArgTypOption argT, ApOption argAp, Typ t0, Typ t, Ap ap, ApApprox apa ) { fwdFlow0(node, state, cc, summaryCtx, argT, argAp, t0, ap, apa) and @@ -1321,12 +1329,12 @@ module MakeImpl { pragma[nomagic] private predicate fwdFlow0( - NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, TypOption argT, + NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ArgTypOption argT, ApOption argAp, Typ t, Ap ap, ApApprox apa ) { sourceNode(node, state) and (if hasSourceCallCtx() then cc = ccSomeCall() else cc = ccNone()) and - argT instanceof TypOption::None and + argT instanceof ArgTypOption::None and argAp = apNone() and summaryCtx = TParamNodeNone() and t = getNodeTyp(node) and @@ -1347,19 +1355,19 @@ module MakeImpl { fwdFlowJump(node, state, t, ap, apa) and cc = ccNone() and summaryCtx = TParamNodeNone() and - argT instanceof TypOption::None and + argT instanceof ArgTypOption::None and argAp = apNone() or // store exists(Content c, Typ t0, Ap ap0 | - fwdFlowStore(_, t0, ap0, c, t, node, state, cc, summaryCtx, argT, argAp) and + fwdFlowStore(t0, ap0, c, t, node, state, cc, summaryCtx, argT, argAp) and ap = apCons(c, t0, ap0) and apa = getApprox(ap) ) or // read exists(Typ t0, Ap ap0, Content c | - fwdFlowRead(t0, ap0, c, _, node, state, cc, summaryCtx, argT, argAp) and + fwdFlowRead(t0, ap0, c, node, state, cc, summaryCtx, argT, argAp) and fwdFlowConsCand(t0, ap0, c, t, ap) and apa = getApprox(ap) ) @@ -1369,10 +1377,12 @@ module MakeImpl { if PrevStage::parameterMayFlowThrough(node, apa) then ( summaryCtx = TParamNodeSome(node.asNode()) and - argT = TypOption::some(t) and + argT = ArgTypOption::some(toArgTyp(t)) and argAp = apSome(ap) ) else ( - summaryCtx = TParamNodeNone() and argT instanceof TypOption::None and argAp = apNone() + summaryCtx = TParamNodeNone() and + argT instanceof ArgTypOption::None and + argAp = apNone() ) or // flow out of a callable @@ -1411,10 +1421,10 @@ module MakeImpl { ) } - pragma[nomagic] + pragma[inline] private predicate fwdFlowStore( NodeEx node1, Typ t1, Ap ap1, Content c, Typ t2, NodeEx node2, FlowState state, Cc cc, - ParamNodeOption summaryCtx, TypOption argT, ApOption argAp + ParamNodeOption summaryCtx, ArgTypOption argT, ApOption argAp ) { exists(DataFlowType contentType, DataFlowType containerType, ApApprox apa1 | fwdFlow(node1, state, cc, summaryCtx, argT, argAp, t1, ap1, apa1) and @@ -1424,6 +1434,14 @@ module MakeImpl { ) } + pragma[nomagic] + private predicate fwdFlowStore( + Typ t1, Ap ap1, Content c, Typ t2, NodeEx node2, FlowState state, Cc cc, + ParamNodeOption summaryCtx, ArgTypOption argT, ApOption argAp + ) { + fwdFlowStore(_, t1, ap1, c, t2, node2, state, cc, summaryCtx, argT, argAp) + } + /** * Holds if forward flow with access path `tail` and type `t1` reaches a * store of `c` on a container of type `t2` resulting in access path @@ -1431,7 +1449,7 @@ module MakeImpl { */ pragma[nomagic] private predicate fwdFlowConsCand(Typ t2, Ap cons, Content c, Typ t1, Ap tail) { - fwdFlowStore(_, t1, tail, c, t2, _, _, _, _, _, _) and + fwdFlowStore(t1, tail, c, t2, _, _, _, _, _, _) and cons = apCons(c, t1, tail) or exists(Typ t0 | @@ -1452,10 +1470,10 @@ module MakeImpl { readStepCand(node1, apc, c, node2) } - pragma[nomagic] + pragma[inline] private predicate fwdFlowRead( Typ t, Ap ap, Content c, NodeEx node1, NodeEx node2, FlowState state, Cc cc, - ParamNodeOption summaryCtx, TypOption argT, ApOption argAp + ParamNodeOption summaryCtx, ArgTypOption argT, ApOption argAp ) { exists(ApHeadContent apc | fwdFlow(node1, state, cc, summaryCtx, argT, argAp, t, ap, _) and @@ -1464,9 +1482,17 @@ module MakeImpl { ) } + pragma[nomagic] + private predicate fwdFlowRead( + Typ t, Ap ap, Content c, NodeEx node2, FlowState state, Cc cc, ParamNodeOption summaryCtx, + ArgTypOption argT, ApOption argAp + ) { + fwdFlowRead(t, ap, c, _, node2, state, cc, summaryCtx, argT, argAp) + } + pragma[nomagic] private predicate fwdFlowIntoArg( - ArgNodeEx arg, FlowState state, Cc outercc, ParamNodeOption summaryCtx, TypOption argT, + ArgNodeEx arg, FlowState state, Cc outercc, ParamNodeOption summaryCtx, ArgTypOption argT, ApOption argAp, Typ t, Ap ap, boolean emptyAp, ApApprox apa, boolean cc ) { fwdFlow(arg, state, outercc, summaryCtx, argT, argAp, t, ap, apa) and @@ -1556,8 +1582,8 @@ module MakeImpl { pragma[inline] private predicate fwdFlowInCand( DataFlowCall call, ArgNodeEx arg, FlowState state, Cc outercc, DataFlowCallable inner, - ParamNodeEx p, ParamNodeOption summaryCtx, TypOption argT, ApOption argAp, Typ t, Ap ap, - boolean emptyAp, ApApprox apa, boolean cc + ParamNodeEx p, ParamNodeOption summaryCtx, ArgTypOption argT, ApOption argAp, Typ t, + Ap ap, boolean emptyAp, ApApprox apa, boolean cc ) { exists(boolean allowsFieldFlow | fwdFlowIntoArg(arg, state, outercc, summaryCtx, argT, argAp, t, ap, emptyAp, apa, cc) and @@ -1574,8 +1600,8 @@ module MakeImpl { pragma[inline] private predicate fwdFlowInCandTypeFlowDisabled( DataFlowCall call, ArgNodeEx arg, FlowState state, Cc outercc, DataFlowCallable inner, - ParamNodeEx p, ParamNodeOption summaryCtx, TypOption argT, ApOption argAp, Typ t, Ap ap, - ApApprox apa, boolean cc + ParamNodeEx p, ParamNodeOption summaryCtx, ArgTypOption argT, ApOption argAp, Typ t, + Ap ap, ApApprox apa, boolean cc ) { not enableTypeFlow() and fwdFlowInCand(call, arg, state, outercc, inner, p, summaryCtx, argT, argAp, t, ap, _, @@ -1613,7 +1639,7 @@ module MakeImpl { pragma[inline] predicate fwdFlowIn( DataFlowCall call, DataFlowCallable inner, ParamNodeEx p, FlowState state, Cc outercc, - CcCall innercc, ParamNodeOption summaryCtx, TypOption argT, ApOption argAp, Typ t, + CcCall innercc, ParamNodeOption summaryCtx, ArgTypOption argT, ApOption argAp, Typ t, Ap ap, ApApprox apa, boolean cc ) { exists(ArgNodeEx arg | @@ -1680,8 +1706,8 @@ module MakeImpl { pragma[nomagic] private predicate fwdFlowIntoRet( - RetNodeEx ret, FlowState state, CcNoCall cc, ParamNodeOption summaryCtx, TypOption argT, - ApOption argAp, Typ t, Ap ap, ApApprox apa + RetNodeEx ret, FlowState state, CcNoCall cc, ParamNodeOption summaryCtx, + ArgTypOption argT, ApOption argAp, Typ t, Ap ap, ApApprox apa ) { fwdFlow(ret, state, cc, summaryCtx, argT, argAp, t, ap, apa) } @@ -1715,7 +1741,7 @@ module MakeImpl { pragma[inline] private predicate fwdFlowOut( DataFlowCall call, DataFlowCallable inner, NodeEx out, FlowState state, CcNoCall outercc, - ParamNodeOption summaryCtx, TypOption argT, ApOption argAp, Typ t, Ap ap, ApApprox apa + ParamNodeOption summaryCtx, ArgTypOption argT, ApOption argAp, Typ t, Ap ap, ApApprox apa ) { exists(RetNodeEx ret, CcNoCall innercc, boolean allowsFieldFlow | fwdFlowIntoRet(ret, state, innercc, summaryCtx, argT, argAp, t, ap, apa) and @@ -1808,12 +1834,12 @@ module MakeImpl { pragma[nomagic] private predicate fwdFlowRetFromArg( - RetNodeEx ret, FlowState state, CcCall ccc, ParamNodeEx summaryCtx, Typ argT, Ap argAp, + RetNodeEx ret, FlowState state, CcCall ccc, ParamNodeEx summaryCtx, ArgTyp argT, Ap argAp, ApApprox argApa, Typ t, Ap ap, ApApprox apa ) { exists(ReturnKindExt kind | fwdFlow(pragma[only_bind_into](ret), state, ccc, - TParamNodeSome(pragma[only_bind_into](summaryCtx.asNode())), TypOption::some(argT), + TParamNodeSome(pragma[only_bind_into](summaryCtx.asNode())), ArgTypOption::some(argT), pragma[only_bind_into](apSome(argAp)), t, ap, pragma[only_bind_into](apa)) and kind = ret.getKind() and parameterFlowThroughAllowed(summaryCtx, kind) and @@ -1825,8 +1851,8 @@ module MakeImpl { pragma[inline] private predicate fwdFlowThrough0( DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, - TypOption argT, ApOption argAp, Typ t, Ap ap, ApApprox apa, RetNodeEx ret, - ParamNodeEx innerSummaryCtx, Typ innerArgT, Ap innerArgAp, ApApprox innerArgApa + ArgTypOption argT, ApOption argAp, Typ t, Ap ap, ApApprox apa, RetNodeEx ret, + ParamNodeEx innerSummaryCtx, ArgTyp innerArgT, Ap innerArgAp, ApApprox innerArgApa ) { fwdFlowRetFromArg(ret, state, ccc, innerSummaryCtx, innerArgT, innerArgAp, innerArgApa, t, ap, apa) and @@ -1837,7 +1863,7 @@ module MakeImpl { pragma[nomagic] private predicate fwdFlowThrough( DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, - TypOption argT, ApOption argAp, Typ t, Ap ap, ApApprox apa, RetNodeEx ret, + ArgTypOption argT, ApOption argAp, Typ t, Ap ap, ApApprox apa, RetNodeEx ret, ApApprox innerArgApa ) { fwdFlowThrough0(call, cc, state, ccc, summaryCtx, argT, argAp, t, ap, apa, ret, _, _, _, @@ -1856,11 +1882,11 @@ module MakeImpl { */ pragma[nomagic] private predicate fwdFlowIsEntered( - DataFlowCall call, Cc cc, CcCall innerCc, ParamNodeOption summaryCtx, TypOption argT, - ApOption argAp, ParamNodeEx p, Typ t, Ap ap + DataFlowCall call, Cc cc, CcCall innerCc, ParamNodeOption summaryCtx, ArgTypOption argT, + ApOption argAp, ParamNodeEx p, ArgTyp t, Ap ap ) { FwdFlowIn::fwdFlowIn(call, _, p, _, cc, innerCc, summaryCtx, - argT, argAp, t, ap, _, _) + argT, argAp, any(Typ t0 | t = toArgTyp(t0)), ap, _, _) } pragma[nomagic] @@ -1881,7 +1907,7 @@ module MakeImpl { pragma[nomagic] private predicate returnFlowsThrough0( DataFlowCall call, FlowState state, CcCall ccc, Ap ap, ApApprox apa, RetNodeEx ret, - ParamNodeEx innerSummaryCtx, Typ innerArgT, Ap innerArgAp, ApApprox innerArgApa + ParamNodeEx innerSummaryCtx, ArgTyp innerArgT, Ap innerArgAp, ApApprox innerArgApa ) { fwdFlowThrough0(call, _, state, ccc, _, _, _, _, ap, apa, ret, innerSummaryCtx, innerArgT, innerArgAp, innerArgApa) @@ -1889,8 +1915,8 @@ module MakeImpl { pragma[nomagic] private predicate returnFlowsThrough( - RetNodeEx ret, ReturnPosition pos, FlowState state, CcCall ccc, ParamNodeEx p, Typ argT, - Ap argAp, Ap ap + RetNodeEx ret, ReturnPosition pos, FlowState state, CcCall ccc, ParamNodeEx p, + ArgTyp argT, Ap argAp, Ap ap ) { exists(DataFlowCall call, ApApprox apa, boolean allowsFieldFlow, ApApprox innerArgApa | returnFlowsThrough0(call, state, ccc, ap, apa, ret, p, argT, argAp, innerArgApa) and @@ -1905,8 +1931,8 @@ module MakeImpl { DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap argAp, Ap ap ) { exists(ApApprox argApa, Typ argT | - returnFlowsThrough(_, _, _, _, pragma[only_bind_into](p), pragma[only_bind_into](argT), - pragma[only_bind_into](argAp), ap) and + returnFlowsThrough(_, _, _, _, pragma[only_bind_into](p), + pragma[only_bind_into](toArgTyp(argT)), pragma[only_bind_into](argAp), ap) and flowIntoCallApaTaken(call, _, pragma[only_bind_into](arg), p, allowsFieldFlow, argApa) and fwdFlow(arg, _, _, _, _, _, pragma[only_bind_into](argT), pragma[only_bind_into](argAp), argApa) and @@ -2320,7 +2346,7 @@ module MakeImpl { conscand = count(Content f0, Typ t, Ap ap | fwdConsCand(f0, t, ap)) and states = count(FlowState state | fwdFlow(_, state, _, _, _, _, _, _, _)) and tuples = - count(NodeEx n, FlowState state, Cc cc, ParamNodeOption summaryCtx, TypOption argT, + count(NodeEx n, FlowState state, Cc cc, ParamNodeOption summaryCtx, ArgTypOption argT, ApOption argAp, Typ t, Ap ap | fwdFlow(n, state, cc, summaryCtx, argT, argAp, t, ap, _) ) and @@ -2969,14 +2995,14 @@ module MakeImpl { private predicate busy(NodeEx node, int c) { c = strictcount(FlowState state, Stage3::Cc cc, ParamNodeOption summaryCtx, - Stage3::TypOption argT, Stage3::ApOption argAp, Stage3::Typ t, Stage3::Ap ap | + Stage3::ArgTypOption argT, Stage3::ApOption argAp, Stage3::Typ t, Stage3::Ap ap | Stage3::fwdFlow(node, state, cc, summaryCtx, argT, argAp, t, ap, _) ) } private predicate busy( NodeEx node, int c, FlowState state, Stage3::Cc cc, ParamNodeOption summaryCtx, - Stage3::TypOption argT, Stage3::ApOption argAp, Stage3::Typ t, Stage3::Ap ap + Stage3::ArgTypOption argT, Stage3::ApOption argAp, Stage3::Typ t, Stage3::Ap ap ) { busy(node, c) and c = max(int i | busy(_, i)) and @@ -3013,7 +3039,7 @@ module MakeImpl { private module Stage3_5Param implements MkStage::StageParam { private module PrevStage = Stage3; - class Typ = Unit; + class Typ = DataFlowType; class Ap = AccessPathFront; @@ -3021,7 +3047,7 @@ module MakeImpl { PrevStage::Ap getApprox(Ap ap) { result = ap.toApprox() } - Typ getTyp(DataFlowType t) { any() } + Typ getTyp(DataFlowType t) { result = t } bindingset[c, t, tail] Ap apCons(Content c, Typ t, Ap tail) { result.getHead() = c and exists(t) and exists(tail) } @@ -3047,10 +3073,9 @@ module MakeImpl { NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, Typ t, LocalCc lcc ) { - localFlowBigStep(node1, state1, node2, state2, preservesValue, _, _) and + localFlowBigStep(node1, state1, node2, state2, preservesValue, t, _) and PrevStage::revFlow(node1, pragma[only_bind_into](state1), _) and PrevStage::revFlow(node2, pragma[only_bind_into](state2), _) and - exists(t) and exists(lcc) } @@ -3087,6 +3112,7 @@ module MakeImpl { exists(state) and not clear(node, ap) and t0 = t and + (if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), t0) else any()) and ( notExpectsContent(node) or @@ -3096,8 +3122,7 @@ module MakeImpl { bindingset[typ, contentType] predicate typecheckStore(Typ typ, DataFlowType contentType) { any() } - - predicate enableTypeFlow() { none() } + // predicate enableTypeFlow() { none() } } private module Stage3_5 = MkStage::Stage; @@ -3468,7 +3493,7 @@ module MakeImpl { TSummaryCtxSome(ParamNodeEx p, FlowState state, DataFlowType t, AccessPath ap) { exists(AccessPathApprox apa | ap.getApprox() = apa | Stage5::parameterMayFlowThrough(p, apa) and - Stage5::fwdFlow(p, state, _, _, Option::some(t), _, _, apa, _) and + Stage5::fwdFlow(p, state, _, _, Option::some(_), _, t, apa, _) and Stage5::revFlow(p, state, _) ) } From 38dba58c341eae8761f3936fed45c50d50083637 Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Thu, 25 Jan 2024 14:13:54 +0100 Subject: [PATCH 03/19] temp2 --- .../dataflow/internal/DataFlowPrivate.qll | 59 ++++- .../codeql/dataflow/internal/DataFlowImpl.qll | 213 +++++++++++------- 2 files changed, 181 insertions(+), 91 deletions(-) diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowPrivate.qll b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowPrivate.qll index a751fe8d1d99..60be3bac9fe0 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowPrivate.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowPrivate.qll @@ -10,6 +10,7 @@ private import semmle.code.java.dataflow.FlowSummary private import FlowSummaryImpl as FlowSummaryImpl private import DataFlowNodes private import codeql.dataflow.VariableCapture as VariableCapture +private import semmle.code.java.dispatch.VirtualDispatch as VirtualDispatch import DataFlowNodes::Private private newtype TReturnKind = TNormalReturnKind() @@ -204,14 +205,54 @@ predicate jumpStep(Node node1, Node node2) { * Holds if `fa` is an access to an instance field that occurs as the * destination of an assignment of the value `src`. */ -private predicate instanceFieldAssign(Expr src, FieldAccess fa) { - exists(AssignExpr a | - a.getSource() = src and - a.getDest() = fa and - fa.getField() instanceof InstanceField +private predicate instanceFieldAssign(AssignExpr a, Expr src, FieldAccess fa) { + a.getSource() = src and + a.getDest() = fa and + fa.getField() instanceof InstanceField +} + +pragma[nomagic] +private predicate isExactArgument(ArgumentNode arg, BasicBlock bb, Method m, ArgumentPosition apos) { + exists(MethodCall mc, DataFlowCall call | + mc = call.asCall() and + m = VirtualDispatch::exactVirtualMethod(mc) and + arg.argumentOf(call, apos) and + bb = mc.getBasicBlock() + ) +} + +pragma[nomagic] +private predicate setsInstanceField(Field f, Node qualifier, BasicBlock bb) { + exists(AssignExpr a, FieldAccess fa | + instanceFieldAssign(a, _, fa) and + f = fa.getField() and + bb = a.getBasicBlock() and + qualifier = getFieldQualifier(fa) + ) + or + exists(Method m, ArgumentPosition apos | + isExactArgument(qualifier, bb, m, apos) and + isInstanceFieldSetter(m, apos, f) ) } +pragma[nomagic] +private predicate isInstanceFieldSetter(Method m, ArgumentPosition apos, Field f) { + exists(BasicBlock bb, Node qualifier, ParameterNode p, ParameterPosition ppos | + setsInstanceField(f, qualifier, bb) and + m = bb.getEnclosingCallable() and + bb.bbPostDominates(m.getBody().getBasicBlock()) and + localMustFlowStep+(p, qualifier) and + p.isParameterOf(_, ppos) and + parameterMatch(ppos, apos) + ) +} + +private predicate sdf(Field f, Class c) { + f.getName() = "m_clusterRoot" and + c.hasName("Folder") +} + /** * Holds if data can flow from `node1` to `node2` via an assignment to `f`. * Thus, `node2` references an object with a field `f` that contains the @@ -219,7 +260,7 @@ private predicate instanceFieldAssign(Expr src, FieldAccess fa) { */ predicate storeStep(Node node1, ContentSet f, Node node2) { exists(FieldAccess fa | - instanceFieldAssign(node1.asExpr(), fa) and + instanceFieldAssign(_, node1.asExpr(), fa) and node2.(PostUpdateNode).getPreUpdateNode() = getFieldQualifier(fa) and f.(FieldContent).getField() = fa.getField() ) @@ -308,11 +349,7 @@ predicate readStep(Node node1, ContentSet f, Node node2) { * in `x.f = newValue`. */ predicate clearsContent(Node n, ContentSet c) { - exists(FieldAccess fa | - instanceFieldAssign(_, fa) and - n = getFieldQualifier(fa) and - c.(FieldContent).getField() = fa.getField() - ) + setsInstanceField(c.(FieldContent).getField(), n, _) or FlowSummaryImpl::Private::Steps::summaryClearsContent(n.(FlowSummaryNode).getSummaryNode(), c) or diff --git a/shared/dataflow/codeql/dataflow/internal/DataFlowImpl.qll b/shared/dataflow/codeql/dataflow/internal/DataFlowImpl.qll index 9df5cd711378..59dd94ab03e2 100644 --- a/shared/dataflow/codeql/dataflow/internal/DataFlowImpl.qll +++ b/shared/dataflow/codeql/dataflow/internal/DataFlowImpl.qll @@ -955,6 +955,12 @@ module MakeImpl { exists(ap) } + pragma[nomagic] + predicate nodeMayFlowThrough(NodeEx node, Ap ap) { + throughFlowNodeCand(node) and + exists(ap) + } + pragma[nomagic] predicate callMayFlowThroughRev(DataFlowCall call) { exists(ArgNodeEx arg, boolean toReturn | @@ -1158,6 +1164,8 @@ module MakeImpl { predicate returnMayFlowThrough(RetNodeEx ret, Ap argAp, Ap ap, ReturnKindExt kind); + predicate nodeMayFlowThrough(NodeEx node, Ap ap); + predicate storeStepCand( NodeEx node1, Ap ap1, Content c, NodeEx node2, DataFlowType contentType, DataFlowType containerType @@ -1255,8 +1263,8 @@ module MakeImpl { Typ t, LocalCc lcc ); - bindingset[node, state, t0, ap] - predicate filter(NodeEx node, FlowState state, Typ t0, Ap ap, Typ t); + bindingset[node, state, t0, ap, inSummaryCtx] + predicate filter(NodeEx node, FlowState state, Typ t0, Ap ap, Typ t, boolean inSummaryCtx); bindingset[typ, contentType] predicate typecheckStore(Typ typ, DataFlowType contentType); @@ -1317,9 +1325,30 @@ module MakeImpl { NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ArgTypOption argT, ApOption argAp, Typ t0, Typ t, Ap ap, ApApprox apa ) { - fwdFlow0(node, state, cc, summaryCtx, argT, argAp, t0, ap, apa) and - PrevStage::revFlow(node, state, apa) and - filter(node, state, t0, ap, t) + exists( + ParamNodeOption summaryCtx0, ArgTypOption argT0, ApOption argAp0, boolean inSummaryCtx + | + fwdFlow0(node, state, cc, summaryCtx0, argT0, argAp0, t0, ap, apa) and + PrevStage::revFlow(node, state, apa) and + ( + ( + if summaryCtx0 = TParamNodeSome(_) //and + then + // PrevStage::nodeMayFlowThrough(node, apa) + summaryCtx = summaryCtx0 and + argT = argT0 and + argAp = argAp0 and + inSummaryCtx = true + else ( + summaryCtx = TParamNodeNone() and + argT instanceof ArgTypOption::None and + argAp = apNone() and + inSummaryCtx = false + ) + ) and + filter(node, state, t0, ap, t, inSummaryCtx) + ) + ) } pragma[nomagic] @@ -1374,15 +1403,17 @@ module MakeImpl { or // flow into a callable fwdFlowIn(node, apa, state, cc, t, ap) and - if PrevStage::parameterMayFlowThrough(node, apa) - then ( - summaryCtx = TParamNodeSome(node.asNode()) and - argT = ArgTypOption::some(toArgTyp(t)) and - argAp = apSome(ap) - ) else ( - summaryCtx = TParamNodeNone() and - argT instanceof ArgTypOption::None and - argAp = apNone() + ( + if PrevStage::parameterMayFlowThrough(node, apa) + then + summaryCtx = TParamNodeSome(node.asNode()) and + argT = ArgTypOption::some(toArgTyp(t)) and + argAp = apSome(ap) + else ( + summaryCtx = TParamNodeNone() and + argT instanceof ArgTypOption::None and + argAp = apNone() + ) ) or // flow out of a callable @@ -2284,6 +2315,11 @@ module MakeImpl { ) } + pragma[nomagic] + predicate nodeMayFlowThrough(NodeEx node, Ap ap) { + revFlow(node, _, TReturnCtxMaybeFlowThrough(_), _, ap) + } + pragma[nomagic] private predicate revFlowThroughArg( DataFlowCall call, ArgNodeEx arg, FlowState state, ReturnCtx returnCtx, ApOption returnAp, @@ -2336,6 +2372,42 @@ module MakeImpl { ) } + pragma[nomagic] + private predicate tuplesFwd(NodeEx node, int c) { + c = + strictcount(FlowState state, Cc cc, ParamNodeOption summaryCtx, ArgTypOption argT, + ApOption argAp, Typ t, Ap ap | + fwdFlow(node, state, cc, summaryCtx, argT, argAp, t, ap, _) + ) + } + + /** A debug predicate for identifying the most busy node in forwards flow. */ + additional predicate mostBusyNodeFwd( + NodeEx node, int c, FlowState state, Cc cc, ParamNodeOption summaryCtx, ArgTypOption argT, + ApOption argAp, Typ t, Ap ap + ) { + tuplesFwd(node, c) and + c = max(int i | tuplesFwd(_, i)) and + fwdFlow(node, state, cc, summaryCtx, argT, argAp, t, ap, _) + } + + pragma[nomagic] + private predicate tuplesRev(NodeEx node, int c) { + c = + strictcount(FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap | + revFlow(node, state, returnCtx, returnAp, ap) + ) + } + + /** A debug predicate for identifying the most busy node in reverse flow. */ + additional predicate mostBusyNodeRev( + NodeEx node, int c, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap + ) { + tuplesRev(node, c) and + c = max(int i | tuplesRev(_, i)) and + revFlow(node, state, returnCtx, returnAp, ap) + } + additional predicate stats( boolean fwd, int nodes, int fields, int conscand, int states, int tuples, int calledges, int tfnodes, int tftuples @@ -2345,11 +2417,7 @@ module MakeImpl { fields = count(Content f0 | fwdConsCand(f0, _, _)) and conscand = count(Content f0, Typ t, Ap ap | fwdConsCand(f0, t, ap)) and states = count(FlowState state | fwdFlow(_, state, _, _, _, _, _, _, _)) and - tuples = - count(NodeEx n, FlowState state, Cc cc, ParamNodeOption summaryCtx, ArgTypOption argT, - ApOption argAp, Typ t, Ap ap | - fwdFlow(n, state, cc, summaryCtx, argT, argAp, t, ap, _) - ) and + tuples = count(NodeEx n, int c | tuplesFwd(n, c) | c) and calledges = count(DataFlowCall call, DataFlowCallable c | FwdTypeFlowInput::dataFlowTakenCallEdgeIn(call, c, _) or @@ -2362,10 +2430,7 @@ module MakeImpl { fields = count(Content f0 | consCand(f0, _, _)) and conscand = count(Content f0, Typ t, Ap ap | consCand(f0, t, ap)) and states = count(FlowState state | revFlow(_, state, _, _, _)) and - tuples = - count(NodeEx n, FlowState state, ReturnCtx returnCtx, ApOption retAp, Ap ap | - revFlow(n, state, returnCtx, retAp, ap) - ) and + tuples = count(NodeEx n, int c | tuplesRev(n, c) | c) and calledges = count(DataFlowCall call, DataFlowCallable c | RevTypeFlowInput::dataFlowTakenCallEdgeIn(call, c, _) or @@ -2566,8 +2631,8 @@ module MakeImpl { ) } - bindingset[node, state, t0, ap] - predicate filter(NodeEx node, FlowState state, Typ t0, Ap ap, Typ t) { + bindingset[node, state, t0, ap, inSummaryCtx] + predicate filter(NodeEx node, FlowState state, Typ t0, Ap ap, Typ t, boolean inSummaryCtx) { PrevStage::revFlowState(state) and t0 = t and exists(ap) and @@ -2577,7 +2642,8 @@ module MakeImpl { or ap = true and expectsContentCand(node) - ) + ) and + exists(inSummaryCtx) } bindingset[typ, contentType] @@ -2889,8 +2955,8 @@ module MakeImpl { ) } - bindingset[node, state, t0, ap] - predicate filter(NodeEx node, FlowState state, Typ t0, Ap ap, Typ t) { + bindingset[node, state, t0, ap, inSummaryCtx] + predicate filter(NodeEx node, FlowState state, Typ t0, Ap ap, Typ t, boolean inSummaryCtx) { exists(state) and t0 = t and exists(ap) and @@ -2899,7 +2965,8 @@ module MakeImpl { notExpectsContent(node) or expectsContentCand(node, ap) - ) + ) and + exists(inSummaryCtx) } bindingset[typ, contentType] @@ -2964,8 +3031,8 @@ module MakeImpl { ) } - bindingset[node, state, t0, ap] - predicate filter(NodeEx node, FlowState state, Typ t0, Ap ap, Typ t) { + bindingset[node, state, t0, ap, inSummaryCtx] + predicate filter(NodeEx node, FlowState state, Typ t0, Ap ap, Typ t, boolean inSummaryCtx) { exists(state) and // We can get away with not using type strengthening here, since we aren't // going to use the tracked types in the construction of Stage 4 access @@ -2978,7 +3045,8 @@ module MakeImpl { notExpectsContent(node) or expectsContentCand(node, ap) - ) + ) and + exists(inSummaryCtx) } bindingset[typ, contentType] @@ -2991,47 +3059,26 @@ module MakeImpl { private module Stage3 = MkStage::Stage; - pragma[nomagic] - private predicate busy(NodeEx node, int c) { - c = - strictcount(FlowState state, Stage3::Cc cc, ParamNodeOption summaryCtx, - Stage3::ArgTypOption argT, Stage3::ApOption argAp, Stage3::Typ t, Stage3::Ap ap | - Stage3::fwdFlow(node, state, cc, summaryCtx, argT, argAp, t, ap, _) - ) - } + private predicate mostBusyNodeFwd3 = Stage3::mostBusyNodeFwd/9; - private predicate busy( - NodeEx node, int c, FlowState state, Stage3::Cc cc, ParamNodeOption summaryCtx, - Stage3::ArgTypOption argT, Stage3::ApOption argAp, Stage3::Typ t, Stage3::Ap ap - ) { - busy(node, c) and - c = max(int i | busy(_, i)) and - Stage3::fwdFlow(node, state, cc, summaryCtx, argT, argAp, t, ap, _) - } + private predicate mostBusyNodeFwd3_5 = Stage3_5::mostBusyNodeFwd/9; - pragma[nomagic] - private predicate busyRev(NodeEx node, int c) { - c = - strictcount(FlowState state, ReturnCtx returnCtx, Stage3::ApOption returnAp, Stage3::Ap ap | - Stage3::revFlow(node, state, returnCtx, returnAp, ap) - ) - } + private predicate mostBusyNodeFwd4 = Stage4::mostBusyNodeFwd/9; - private predicate busyRev( - NodeEx node, int c, FlowState state, ReturnCtx returnCtx, Stage3::ApOption returnAp, - Stage3::Ap ap - ) { - busyRev(node, c) and - c = max(int i | busyRev(_, i)) and - Stage3::revFlow(node, state, returnCtx, returnAp, ap) - } + private predicate mostBusyNodeFwd5 = Stage5::mostBusyNodeFwd/9; - bindingset[node, t0] - private predicate strengthenType(NodeEx node, DataFlowType t0, DataFlowType t) { + bindingset[node, t0, inSummaryCtx] + private predicate strengthenType( + NodeEx node, DataFlowType t0, DataFlowType t, boolean inSummaryCtx + ) { if castingNodeEx(node) then exists(DataFlowType nt | nt = node.getDataFlowType() | - if typeStrongerThan(nt, t0) then t = nt else (compatibleTypes(nt, t0) and t = t0) + if inSummaryCtx = true and typeStrongerThan(nt, t0) + then t = nt + else ( + compatibleTypes(nt, t0) and t = t0 + ) ) else t = t0 } @@ -3107,8 +3154,8 @@ module MakeImpl { ) } - bindingset[node, state, t0, ap] - predicate filter(NodeEx node, FlowState state, Typ t0, Ap ap, Typ t) { + bindingset[node, state, t0, ap, inSummaryCtx] + predicate filter(NodeEx node, FlowState state, Typ t0, Ap ap, Typ t, boolean inSummaryCtx) { exists(state) and not clear(node, ap) and t0 = t and @@ -3117,7 +3164,8 @@ module MakeImpl { notExpectsContent(node) or expectsContentCand(node, ap) - ) + ) and + exists(inSummaryCtx) } bindingset[typ, contentType] @@ -3157,8 +3205,9 @@ module MakeImpl { ApOption apSome(Ap ap) { result = TAccessPathFrontSome(ap) } - import Level1CallContext - import NoLocalCallContext + // import Level1CallContext + // import NoLocalCallContext + import BooleanCallContext pragma[nomagic] predicate localStep( @@ -3199,11 +3248,11 @@ module MakeImpl { ) } - bindingset[node, state, t0, ap] - predicate filter(NodeEx node, FlowState state, Typ t0, Ap ap, Typ t) { + bindingset[node, state, t0, ap, inSummaryCtx] + predicate filter(NodeEx node, FlowState state, Typ t0, Ap ap, Typ t, boolean inSummaryCtx) { exists(state) and not clear(node, ap) and - strengthenType(node, t0, t) and + strengthenType(node, t0, t, inSummaryCtx) and ( notExpectsContent(node) or @@ -3453,9 +3502,9 @@ module MakeImpl { PrevStage::revFlow(node2, pragma[only_bind_into](state2), _) } - bindingset[node, state, t0, ap] - predicate filter(NodeEx node, FlowState state, Typ t0, Ap ap, Typ t) { - strengthenType(node, t0, t) and + bindingset[node, state, t0, ap, inSummaryCtx] + predicate filter(NodeEx node, FlowState state, Typ t0, Ap ap, Typ t, boolean inSummaryCtx) { + strengthenType(node, t0, t, inSummaryCtx) and exists(state) and exists(ap) } @@ -4205,10 +4254,11 @@ module MakeImpl { PathNodeMid mid, NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, DataFlowType t, AccessPath ap ) { - exists(DataFlowType t0 | + exists(DataFlowType t0, boolean inSummaryCtx | pathStep0(mid, node, state, cc, sc, t0, ap) and Stage5::revFlow(node, state, ap.getApprox()) and - strengthenType(node, t0, t) and + (if sc = TSummaryCtxNone() then inSummaryCtx = false else inSummaryCtx = true) and + strengthenType(node, t0, t, inSummaryCtx) and not inBarrier(node, state) ) } @@ -4950,7 +5000,10 @@ module MakeImpl { notExpectsContent(node) or expectsContentEx(node, ap.getHead()) ) and - strengthenType(node, t0, t) + exists(boolean inSummaryCtx | + (if sc1 = TSummaryCtx1None() then inSummaryCtx = false else inSummaryCtx = true) and + strengthenType(node, t0, t, inSummaryCtx) + ) } pragma[nomagic] From 8aa1960823c69f2282625658203b3fb0ea220796 Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Thu, 25 Jan 2024 20:22:15 +0100 Subject: [PATCH 04/19] temp --- .../dataflow/internal/DataFlowPrivate.qll | 7 ++++- .../dataflow/callback-dispatch/test.expected | 2 +- .../EntryPointTypesTest.expected | 2 +- .../dataflow/taintsources/remote.expected | 2 +- .../codeql/dataflow/internal/DataFlowImpl.qll | 28 +++++++++---------- 5 files changed, 22 insertions(+), 19 deletions(-) diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowPrivate.qll b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowPrivate.qll index 60be3bac9fe0..9d5b92ba3bd7 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowPrivate.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowPrivate.qll @@ -349,7 +349,12 @@ predicate readStep(Node node1, ContentSet f, Node node2) { * in `x.f = newValue`. */ predicate clearsContent(Node n, ContentSet c) { - setsInstanceField(c.(FieldContent).getField(), n, _) + // setsInstanceField(c.(FieldContent).getField(), n, _) + exists(FieldAccess fa | + instanceFieldAssign(_, _, fa) and + n = getFieldQualifier(fa) and + c.(FieldContent).getField() = fa.getField() + ) or FlowSummaryImpl::Private::Steps::summaryClearsContent(n.(FlowSummaryNode).getSummaryNode(), c) or diff --git a/java/ql/test/library-tests/dataflow/callback-dispatch/test.expected b/java/ql/test/library-tests/dataflow/callback-dispatch/test.expected index 48de9172b362..8ec8033d086e 100644 --- a/java/ql/test/library-tests/dataflow/callback-dispatch/test.expected +++ b/java/ql/test/library-tests/dataflow/callback-dispatch/test.expected @@ -1,2 +1,2 @@ -failures testFailures +failures diff --git a/java/ql/test/library-tests/dataflow/entrypoint-types/EntryPointTypesTest.expected b/java/ql/test/library-tests/dataflow/entrypoint-types/EntryPointTypesTest.expected index 48de9172b362..8ec8033d086e 100644 --- a/java/ql/test/library-tests/dataflow/entrypoint-types/EntryPointTypesTest.expected +++ b/java/ql/test/library-tests/dataflow/entrypoint-types/EntryPointTypesTest.expected @@ -1,2 +1,2 @@ -failures testFailures +failures diff --git a/java/ql/test/library-tests/dataflow/taintsources/remote.expected b/java/ql/test/library-tests/dataflow/taintsources/remote.expected index 48de9172b362..8ec8033d086e 100644 --- a/java/ql/test/library-tests/dataflow/taintsources/remote.expected +++ b/java/ql/test/library-tests/dataflow/taintsources/remote.expected @@ -1,2 +1,2 @@ -failures testFailures +failures diff --git a/shared/dataflow/codeql/dataflow/internal/DataFlowImpl.qll b/shared/dataflow/codeql/dataflow/internal/DataFlowImpl.qll index 59dd94ab03e2..f1d81dbe08d5 100644 --- a/shared/dataflow/codeql/dataflow/internal/DataFlowImpl.qll +++ b/shared/dataflow/codeql/dataflow/internal/DataFlowImpl.qll @@ -1332,9 +1332,8 @@ module MakeImpl { PrevStage::revFlow(node, state, apa) and ( ( - if summaryCtx0 = TParamNodeSome(_) //and + if summaryCtx0 = TParamNodeSome(_) and PrevStage::nodeMayFlowThrough(node, apa) then - // PrevStage::nodeMayFlowThrough(node, apa) summaryCtx = summaryCtx0 and argT = argT0 and argAp = argAp0 and @@ -1402,18 +1401,17 @@ module MakeImpl { ) or // flow into a callable - fwdFlowIn(node, apa, state, cc, t, ap) and - ( - if PrevStage::parameterMayFlowThrough(node, apa) - then - summaryCtx = TParamNodeSome(node.asNode()) and - argT = ArgTypOption::some(toArgTyp(t)) and - argAp = apSome(ap) - else ( - summaryCtx = TParamNodeNone() and - argT instanceof ArgTypOption::None and - argAp = apNone() - ) + exists(Typ t0 | fwdFlowIn(node, apa, state, cc, t0, ap) | + PrevStage::parameterMayFlowThrough(node, apa) and + summaryCtx = TParamNodeSome(node.asNode()) and + argT = ArgTypOption::some(toArgTyp(t)) and + argAp = apSome(ap) and + t = t0 // getNodeTyp(node) + or + summaryCtx = TParamNodeNone() and + argT instanceof ArgTypOption::None and + argAp = apNone() and + t = t0 ) or // flow out of a callable @@ -3074,7 +3072,7 @@ module MakeImpl { if castingNodeEx(node) then exists(DataFlowType nt | nt = node.getDataFlowType() | - if inSummaryCtx = true and typeStrongerThan(nt, t0) + if inSummaryCtx = false and typeStrongerThan(nt, t0) then t = nt else ( compatibleTypes(nt, t0) and t = t0 From f205d0a4639041b0dcb6110b2180f5ddf9038258 Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Fri, 26 Jan 2024 14:10:26 +0100 Subject: [PATCH 05/19] temp2 --- .../codeql/dataflow/internal/DataFlowImpl.qll | 319 ++++++++++++------ 1 file changed, 211 insertions(+), 108 deletions(-) diff --git a/shared/dataflow/codeql/dataflow/internal/DataFlowImpl.qll b/shared/dataflow/codeql/dataflow/internal/DataFlowImpl.qll index f1d81dbe08d5..b5633e351f04 100644 --- a/shared/dataflow/codeql/dataflow/internal/DataFlowImpl.qll +++ b/shared/dataflow/codeql/dataflow/internal/DataFlowImpl.qll @@ -956,7 +956,7 @@ module MakeImpl { } pragma[nomagic] - predicate nodeMayFlowThrough(NodeEx node, Ap ap) { + additional predicate nodeMayFlowThrough(NodeEx node, Ap ap) { throughFlowNodeCand(node) and exists(ap) } @@ -1164,8 +1164,7 @@ module MakeImpl { predicate returnMayFlowThrough(RetNodeEx ret, Ap argAp, Ap ap, ReturnKindExt kind); - predicate nodeMayFlowThrough(NodeEx node, Ap ap); - + // predicate nodeMayFlowThrough(NodeEx node, Ap ap); predicate storeStepCand( NodeEx node1, Ap ap1, Content c, NodeEx node2, DataFlowType contentType, DataFlowType containerType @@ -1263,6 +1262,9 @@ module MakeImpl { Typ t, LocalCc lcc ); + bindingset[p, argAp, node, ap] + predicate nodeMayFlowThrough(ParamNode p, ApApprox argAp, NodeEx node, ApApprox ap); + bindingset[node, state, t0, ap, inSummaryCtx] predicate filter(NodeEx node, FlowState state, Typ t0, Ap ap, Typ t, boolean inSummaryCtx); @@ -1293,17 +1295,23 @@ module MakeImpl { PrevStage::revFlow(node) and result = getTyp(node.getDataFlowType()) } + pragma[inline] + private predicate flowThroughOutOfCall( + DataFlowCall call, CcCall ccc, RetNodeEx ret, ReturnKindExt kind, NodeEx out, + boolean allowsFieldFlow, ApApprox argApa, ApApprox apa + ) { + PrevStage::callEdgeReturn(call, _, ret, kind, out, allowsFieldFlow, apa) and + PrevStage::callMayFlowThroughRev(call) and + PrevStage::returnMayFlowThrough(ret, argApa, apa, kind) and + matchesCall(ccc, call) + } + pragma[nomagic] private predicate flowThroughOutOfCall( - DataFlowCall call, CcCall ccc, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow, + DataFlowCall call, CcCall ccc, ReturnKindExt kind, NodeEx out, boolean allowsFieldFlow, ApApprox argApa, ApApprox apa ) { - exists(ReturnKindExt kind | - PrevStage::callEdgeReturn(call, _, ret, kind, out, allowsFieldFlow, apa) and - PrevStage::callMayFlowThroughRev(call) and - PrevStage::returnMayFlowThrough(ret, argApa, apa, kind) and - matchesCall(ccc, call) - ) + flowThroughOutOfCall(call, ccc, _, kind, out, allowsFieldFlow, argApa, apa) } /** @@ -1325,28 +1333,32 @@ module MakeImpl { NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ArgTypOption argT, ApOption argAp, Typ t0, Typ t, Ap ap, ApApprox apa ) { - exists( - ParamNodeOption summaryCtx0, ArgTypOption argT0, ApOption argAp0, boolean inSummaryCtx - | - fwdFlow0(node, state, cc, summaryCtx0, argT0, argAp0, t0, ap, apa) and + exists(ParamNodeOption summaryCtx0, ApOption argAp0, boolean inSummaryCtx | + fwdFlow0(node, state, cc, summaryCtx0, argT, argAp0, t0, ap, apa) and PrevStage::revFlow(node, state, apa) and ( - ( - if summaryCtx0 = TParamNodeSome(_) and PrevStage::nodeMayFlowThrough(node, apa) + exists(ParamNode p, ApApprox argApa | + summaryCtx0 = TParamNodeSome(p) and + argAp0 = apSome(any(Ap argAp1 | argApa = getApprox(argAp1))) + | + if Param::nodeMayFlowThrough(p, argApa, node, apa) then summaryCtx = summaryCtx0 and - argT = argT0 and argAp = argAp0 and inSummaryCtx = true else ( summaryCtx = TParamNodeNone() and - argT instanceof ArgTypOption::None and argAp = apNone() and inSummaryCtx = false ) - ) and - filter(node, state, t0, ap, t, inSummaryCtx) - ) + ) + or + summaryCtx0 = TParamNodeNone() and + summaryCtx = summaryCtx0 and + argAp = argAp0 and + inSummaryCtx = false + ) and + filter(node, state, t0, ap, t, inSummaryCtx) ) } @@ -1402,16 +1414,18 @@ module MakeImpl { or // flow into a callable exists(Typ t0 | fwdFlowIn(node, apa, state, cc, t0, ap) | - PrevStage::parameterMayFlowThrough(node, apa) and - summaryCtx = TParamNodeSome(node.asNode()) and - argT = ArgTypOption::some(toArgTyp(t)) and - argAp = apSome(ap) and - t = t0 // getNodeTyp(node) - or - summaryCtx = TParamNodeNone() and - argT instanceof ArgTypOption::None and - argAp = apNone() and - t = t0 + if PrevStage::parameterMayFlowThrough(node, apa) + then + summaryCtx = TParamNodeSome(node.asNode()) and + argT = ArgTypOption::some(toArgTyp(t)) and + argAp = apSome(ap) and + t = t0 // getNodeTyp(node) + else ( + summaryCtx = TParamNodeNone() and + argT instanceof ArgTypOption::None and + argAp = apNone() and + t = t0 + ) ) or // flow out of a callable @@ -1419,12 +1433,12 @@ module MakeImpl { or // flow through a callable exists( - DataFlowCall call, CcCall ccc, RetNodeEx ret, boolean allowsFieldFlow, + DataFlowCall call, CcCall ccc, ReturnKindExt kind, boolean allowsFieldFlow, ApApprox innerArgApa | - fwdFlowThrough(call, cc, state, ccc, summaryCtx, argT, argAp, t, ap, apa, ret, + fwdFlowThrough(call, cc, state, ccc, summaryCtx, argT, argAp, t, ap, apa, kind, innerArgApa) and - flowThroughOutOfCall(call, ccc, ret, node, allowsFieldFlow, innerArgApa, apa) and + flowThroughOutOfCall(call, ccc, kind, node, allowsFieldFlow, innerArgApa, apa) and if allowsFieldFlow = false then ap instanceof ApNil else any() ) } @@ -1877,6 +1891,22 @@ module MakeImpl { ) } + pragma[nomagic] + private predicate fwdFlowRetFromArg1( + ReturnKindExt kind, FlowState state, CcCall ccc, ParamNodeEx summaryCtx, ArgTyp argT, + Ap argAp, ApApprox argApa, Typ t, Ap ap, ApApprox apa + ) { + exists(RetNodeEx ret | + fwdFlow(pragma[only_bind_into](ret), state, ccc, + TParamNodeSome(pragma[only_bind_into](summaryCtx.asNode())), ArgTypOption::some(argT), + pragma[only_bind_into](apSome(argAp)), t, ap, pragma[only_bind_into](apa)) and + kind = ret.getKind() and + parameterFlowThroughAllowed(summaryCtx, kind) and + argApa = getApprox(argAp) and + PrevStage::returnMayFlowThrough(ret, argApa, apa, kind) + ) + } + pragma[inline] private predicate fwdFlowThrough0( DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, @@ -1889,13 +1919,25 @@ module MakeImpl { innerArgAp) } + pragma[inline] + private predicate fwdFlowThrough1( + DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, + ArgTypOption argT, ApOption argAp, Typ t, Ap ap, ApApprox apa, ReturnKindExt kind, + ParamNodeEx innerSummaryCtx, ArgTyp innerArgT, Ap innerArgAp, ApApprox innerArgApa + ) { + fwdFlowRetFromArg1(kind, state, ccc, innerSummaryCtx, innerArgT, innerArgAp, innerArgApa, + t, ap, apa) and + fwdFlowIsEntered(call, cc, ccc, summaryCtx, argT, argAp, innerSummaryCtx, innerArgT, + innerArgAp) + } + pragma[nomagic] private predicate fwdFlowThrough( DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, - ArgTypOption argT, ApOption argAp, Typ t, Ap ap, ApApprox apa, RetNodeEx ret, + ArgTypOption argT, ApOption argAp, Typ t, Ap ap, ApApprox apa, ReturnKindExt kind, ApApprox innerArgApa ) { - fwdFlowThrough0(call, cc, state, ccc, summaryCtx, argT, argAp, t, ap, apa, ret, _, _, _, + fwdFlowThrough1(call, cc, state, ccc, summaryCtx, argT, argAp, t, ap, apa, kind, _, _, _, innerArgApa) } @@ -1949,7 +1991,7 @@ module MakeImpl { ) { exists(DataFlowCall call, ApApprox apa, boolean allowsFieldFlow, ApApprox innerArgApa | returnFlowsThrough0(call, state, ccc, ap, apa, ret, p, argT, argAp, innerArgApa) and - flowThroughOutOfCall(call, ccc, ret, _, allowsFieldFlow, innerArgApa, apa) and + flowThroughOutOfCall(call, ccc, ret, _, _, allowsFieldFlow, innerArgApa, apa) and pos = ret.getReturnPosition() and if allowsFieldFlow = false then ap instanceof ApNil else any() ) @@ -2298,9 +2340,9 @@ module MakeImpl { pragma[nomagic] predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap) { - exists(ReturnPosition pos | - returnFlowsThrough(_, pos, _, _, p, _, ap, _) and - parameterFlowsThroughRev(p, ap, pos, _) + exists(ReturnPosition pos, Ap returnAp | + returnFlowsThrough(_, pos, _, _, p, _, ap, returnAp) and + parameterFlowsThroughRev(p, ap, pos, returnAp) ) } @@ -2313,9 +2355,22 @@ module MakeImpl { ) } + // pragma[nomagic] + // predicate nodeMayFlowThrough(NodeEx node, Ap ap) { + // revFlow(node, _, TReturnCtxMaybeFlowThrough(_), _, ap) + // } pragma[nomagic] - predicate nodeMayFlowThrough(NodeEx node, Ap ap) { - revFlow(node, _, TReturnCtxMaybeFlowThrough(_), _, ap) + additional predicate nodeMayFlowThrough(ParamNode p, Ap argAp, NodeEx node, Ap ap) { + // revFlow(node, _, TReturnCtxMaybeFlowThrough(_), _, ap) + exists(ReturnPosition pos, Ap returnAp, ParamNodeEx param | + p = param.asNode() and + returnFlowsThrough(_, pos, _, _, param, _, argAp, returnAp) and + parameterFlowsThroughRev(param, argAp, pos, returnAp) and + revFlow(pragma[only_bind_into](node), _, TReturnCtxMaybeFlowThrough(pos), + apSome(returnAp), pragma[only_bind_into](ap)) and + fwdFlow(pragma[only_bind_into](node), _, _, TParamNodeSome(p), _, apSome(argAp), _, + pragma[only_bind_into](ap), _) + ) } pragma[nomagic] @@ -2620,6 +2675,13 @@ module MakeImpl { exists(lcc) } + bindingset[p, argAp, node, ap] + predicate nodeMayFlowThrough(ParamNode p, PrevStage::Ap argAp, NodeEx node, PrevStage::Ap ap) { + PrevStage::nodeMayFlowThrough(node, ap) and + exists(p) and + exists(argAp) + } + pragma[nomagic] private predicate expectsContentCand(NodeEx node) { exists(Content c | @@ -2943,6 +3005,11 @@ module MakeImpl { exists(lcc) } + bindingset[p, argAp, node, ap] + predicate nodeMayFlowThrough(ParamNode p, PrevStage::Ap argAp, NodeEx node, PrevStage::Ap ap) { + PrevStage::nodeMayFlowThrough(p, argAp, node, ap) + } + pragma[nomagic] private predicate expectsContentCand(NodeEx node, Ap ap) { exists(Content c | @@ -3019,6 +3086,11 @@ module MakeImpl { exists(lcc) } + bindingset[p, argAp, node, ap] + predicate nodeMayFlowThrough(ParamNode p, PrevStage::Ap argAp, NodeEx node, PrevStage::Ap ap) { + PrevStage::nodeMayFlowThrough(p, argAp, node, ap) + } + pragma[nomagic] private predicate expectsContentCand(NodeEx node, Ap ap) { exists(Content c | @@ -3057,14 +3129,10 @@ module MakeImpl { private module Stage3 = MkStage::Stage; - private predicate mostBusyNodeFwd3 = Stage3::mostBusyNodeFwd/9; - - private predicate mostBusyNodeFwd3_5 = Stage3_5::mostBusyNodeFwd/9; - - private predicate mostBusyNodeFwd4 = Stage4::mostBusyNodeFwd/9; - - private predicate mostBusyNodeFwd5 = Stage5::mostBusyNodeFwd/9; - + // private predicate mostBusyNodeFwd3 = Stage3::mostBusyNodeFwd/9; + // private predicate mostBusyNodeFwd3_5 = Stage3_5::mostBusyNodeFwd/9; + // private predicate mostBusyNodeFwd4 = Stage4::mostBusyNodeFwd/9; + // private predicate mostBusyNodeFwd5 = Stage5::mostBusyNodeFwd/9; bindingset[node, t0, inSummaryCtx] private predicate strengthenType( NodeEx node, DataFlowType t0, DataFlowType t, boolean inSummaryCtx @@ -3124,6 +3192,11 @@ module MakeImpl { exists(lcc) } + bindingset[p, argAp, node, ap] + predicate nodeMayFlowThrough(ParamNode p, PrevStage::Ap argAp, NodeEx node, PrevStage::Ap ap) { + PrevStage::nodeMayFlowThrough(p, argAp, node, ap) + } + pragma[nomagic] private predicate clearSet(NodeEx node, ContentSet c) { PrevStage::revFlow(node) and @@ -3218,6 +3291,11 @@ module MakeImpl { exists(lcc) } + bindingset[p, argAp, node, ap] + predicate nodeMayFlowThrough(ParamNode p, PrevStage::Ap argAp, NodeEx node, PrevStage::Ap ap) { + PrevStage::nodeMayFlowThrough(p, argAp, node, ap) + } + pragma[nomagic] private predicate clearSet(NodeEx node, ContentSet c) { PrevStage::revFlow(node) and @@ -3500,6 +3578,11 @@ module MakeImpl { PrevStage::revFlow(node2, pragma[only_bind_into](state2), _) } + bindingset[p, argAp, node, ap] + predicate nodeMayFlowThrough(ParamNode p, PrevStage::Ap argAp, NodeEx node, PrevStage::Ap ap) { + PrevStage::nodeMayFlowThrough(p, argAp, node, ap) + } + bindingset[node, state, t0, ap, inSummaryCtx] predicate filter(NodeEx node, FlowState state, Typ t0, Ap ap, Typ t, boolean inSummaryCtx) { strengthenType(node, t0, t, inSummaryCtx) and @@ -4252,12 +4335,29 @@ module MakeImpl { PathNodeMid mid, NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, DataFlowType t, AccessPath ap ) { - exists(DataFlowType t0, boolean inSummaryCtx | - pathStep0(mid, node, state, cc, sc, t0, ap) and - Stage5::revFlow(node, state, ap.getApprox()) and - (if sc = TSummaryCtxNone() then inSummaryCtx = false else inSummaryCtx = true) and + exists(DataFlowType t0, SummaryCtx sc0, Stage5::Ap apa, boolean inSummaryCtx | + pathStep0(mid, node, state, cc, sc0, t0, ap, apa) and + Stage5::revFlow(node, state, apa) and strengthenType(node, t0, t, inSummaryCtx) and not inBarrier(node, state) + | + exists(ParamNodeEx p, ParamNode param, AccessPath argAp, Stage5::Ap argApa | + sc0 = TSummaryCtxSome(p, _, _, argAp) and + param = p.asNode() and + argApa = argAp.getApprox() and + if Stage5::nodeMayFlowThrough(param, argApa, node, apa) + then + sc = sc0 and + inSummaryCtx = true + else ( + sc = TSummaryCtxNone() and + inSummaryCtx = false + ) + ) + or + sc0 = TSummaryCtxNone() and + sc = sc0 and + inSummaryCtx = false ) } @@ -4268,61 +4368,64 @@ module MakeImpl { pragma[nomagic] private predicate pathStep0( PathNodeMid mid, NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, DataFlowType t, - AccessPath ap + AccessPath ap, Stage5::Ap apa ) { - exists(NodeEx midnode, FlowState state0, LocalCallContext localCC | - pathNode(mid, midnode, state0, cc, sc, t, ap, localCC) and - localFlowBigStep(midnode, state0, node, state, true, _, localCC) - ) - or - exists(NodeEx midnode, FlowState state0, LocalCallContext localCC | - pathNode(mid, midnode, state0, cc, sc, _, ap, localCC) and - localFlowBigStep(midnode, state0, node, state, false, t, localCC) and - ap instanceof AccessPathNil - ) - or - jumpStepEx(mid.getNodeExOutgoing(), node) and - state = mid.getState() and - cc instanceof CallContextAny and - sc instanceof SummaryCtxNone and - t = mid.getType() and - ap = mid.getAp() - or - additionalJumpStep(mid.getNodeExOutgoing(), node) and - state = mid.getState() and - cc instanceof CallContextAny and - sc instanceof SummaryCtxNone and - mid.getAp() instanceof AccessPathNil and - t = node.getDataFlowType() and - ap = TAccessPathNil() - or - additionalJumpStateStep(mid.getNodeExOutgoing(), mid.getState(), node, state) and - cc instanceof CallContextAny and - sc instanceof SummaryCtxNone and - mid.getAp() instanceof AccessPathNil and - t = node.getDataFlowType() and - ap = TAccessPathNil() - or - exists(Content c, DataFlowType t0, AccessPath ap0 | - pathStoreStep(mid, node, state, t0, ap0, c, t, cc) and - ap.isCons(c, t0, ap0) and - sc = mid.getSummaryCtx() - ) - or - exists(Content c, AccessPath ap0 | - pathReadStep(mid, node, state, ap0, c, cc) and - ap0.isCons(c, t, ap) and - sc = mid.getSummaryCtx() - ) - or - pathIntoCallable(mid, node, state, _, cc, sc, _) and t = mid.getType() and ap = mid.getAp() - or - pathOutOfCallable(mid, node, state, cc) and - t = mid.getType() and - ap = mid.getAp() and - sc instanceof SummaryCtxNone - or - pathThroughCallable(mid, node, state, cc, t, ap) and sc = mid.getSummaryCtx() + ( + exists(NodeEx midnode, FlowState state0, LocalCallContext localCC | + pathNode(mid, midnode, state0, cc, sc, t, ap, localCC) and + localFlowBigStep(midnode, state0, node, state, true, _, localCC) + ) + or + exists(NodeEx midnode, FlowState state0, LocalCallContext localCC | + pathNode(mid, midnode, state0, cc, sc, _, ap, localCC) and + localFlowBigStep(midnode, state0, node, state, false, t, localCC) and + ap instanceof AccessPathNil + ) + or + jumpStepEx(mid.getNodeExOutgoing(), node) and + state = mid.getState() and + cc instanceof CallContextAny and + sc instanceof SummaryCtxNone and + t = mid.getType() and + ap = mid.getAp() + or + additionalJumpStep(mid.getNodeExOutgoing(), node) and + state = mid.getState() and + cc instanceof CallContextAny and + sc instanceof SummaryCtxNone and + mid.getAp() instanceof AccessPathNil and + t = node.getDataFlowType() and + ap = TAccessPathNil() + or + additionalJumpStateStep(mid.getNodeExOutgoing(), mid.getState(), node, state) and + cc instanceof CallContextAny and + sc instanceof SummaryCtxNone and + mid.getAp() instanceof AccessPathNil and + t = node.getDataFlowType() and + ap = TAccessPathNil() + or + exists(Content c, DataFlowType t0, AccessPath ap0 | + pathStoreStep(mid, node, state, t0, ap0, c, t, cc) and + ap.isCons(c, t0, ap0) and + sc = mid.getSummaryCtx() + ) + or + exists(Content c, AccessPath ap0 | + pathReadStep(mid, node, state, ap0, c, cc) and + ap0.isCons(c, t, ap) and + sc = mid.getSummaryCtx() + ) + or + pathIntoCallable(mid, node, state, _, cc, sc, _) and t = mid.getType() and ap = mid.getAp() + or + pathOutOfCallable(mid, node, state, cc) and + t = mid.getType() and + ap = mid.getAp() and + sc instanceof SummaryCtxNone + or + pathThroughCallable(mid, node, state, cc, t, ap) and sc = mid.getSummaryCtx() + ) and + apa = ap.getApprox() } pragma[nomagic] From 349f2a6d593f3171537cae61906fc0084d70b392 Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Fri, 26 Jan 2024 14:12:02 +0100 Subject: [PATCH 06/19] Dummy change to trigger CI --- cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl1.qll | 2 +- cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl2.qll | 2 +- cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl3.qll | 2 +- cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl4.qll | 2 +- .../lib/semmle/code/cpp/dataflow/internal/DataFlowImplLocal.qll | 2 +- .../lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl1.qll | 2 +- .../lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl2.qll | 2 +- .../lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl3.qll | 2 +- .../lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl4.qll | 2 +- .../lib/semmle/code/csharp/dataflow/internal/DataFlowImpl1.qll | 2 +- .../lib/semmle/code/csharp/dataflow/internal/DataFlowImpl2.qll | 2 +- .../lib/semmle/code/csharp/dataflow/internal/DataFlowImpl3.qll | 2 +- .../lib/semmle/code/csharp/dataflow/internal/DataFlowImpl4.qll | 2 +- .../lib/semmle/code/csharp/dataflow/internal/DataFlowImpl5.qll | 2 +- go/ql/lib/semmle/go/dataflow/internal/DataFlowImpl1.qll | 2 +- go/ql/lib/semmle/go/dataflow/internal/DataFlowImpl2.qll | 2 +- .../ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl1.qll | 2 +- .../ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl2.qll | 2 +- .../ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl3.qll | 2 +- .../ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl4.qll | 2 +- .../ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl5.qll | 2 +- .../ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl6.qll | 2 +- .../lib/semmle/python/dataflow/new/internal/DataFlowImpl1.qll | 2 +- .../lib/semmle/python/dataflow/new/internal/DataFlowImpl2.qll | 2 +- .../lib/semmle/python/dataflow/new/internal/DataFlowImpl3.qll | 2 +- .../lib/semmle/python/dataflow/new/internal/DataFlowImpl4.qll | 2 +- ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImpl1.qll | 2 +- ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImpl2.qll | 2 +- swift/ql/lib/codeql/swift/dataflow/internal/DataFlowImpl1.qll | 2 +- 29 files changed, 29 insertions(+), 29 deletions(-) diff --git a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl1.qll b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl1.qll index 2bbc565daa6b..d0cc969b5af0 100644 --- a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl1.qll +++ b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl1.qll @@ -1,5 +1,5 @@ /** - * DEPRECATED: Use `Global` and `GlobalWithState` instead. + * DEPRECATED: Use `Global` and `GlobalWithState` instead. * * Provides a `Configuration` class backwards-compatible interface to the data * flow library. diff --git a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl2.qll b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl2.qll index 2bbc565daa6b..d0cc969b5af0 100644 --- a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl2.qll +++ b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl2.qll @@ -1,5 +1,5 @@ /** - * DEPRECATED: Use `Global` and `GlobalWithState` instead. + * DEPRECATED: Use `Global` and `GlobalWithState` instead. * * Provides a `Configuration` class backwards-compatible interface to the data * flow library. diff --git a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl3.qll b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl3.qll index 2bbc565daa6b..d0cc969b5af0 100644 --- a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl3.qll +++ b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl3.qll @@ -1,5 +1,5 @@ /** - * DEPRECATED: Use `Global` and `GlobalWithState` instead. + * DEPRECATED: Use `Global` and `GlobalWithState` instead. * * Provides a `Configuration` class backwards-compatible interface to the data * flow library. diff --git a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl4.qll b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl4.qll index 2bbc565daa6b..d0cc969b5af0 100644 --- a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl4.qll +++ b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl4.qll @@ -1,5 +1,5 @@ /** - * DEPRECATED: Use `Global` and `GlobalWithState` instead. + * DEPRECATED: Use `Global` and `GlobalWithState` instead. * * Provides a `Configuration` class backwards-compatible interface to the data * flow library. diff --git a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImplLocal.qll b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImplLocal.qll index 2bbc565daa6b..d0cc969b5af0 100644 --- a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImplLocal.qll +++ b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImplLocal.qll @@ -1,5 +1,5 @@ /** - * DEPRECATED: Use `Global` and `GlobalWithState` instead. + * DEPRECATED: Use `Global` and `GlobalWithState` instead. * * Provides a `Configuration` class backwards-compatible interface to the data * flow library. diff --git a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl1.qll b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl1.qll index 2bbc565daa6b..d0cc969b5af0 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl1.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl1.qll @@ -1,5 +1,5 @@ /** - * DEPRECATED: Use `Global` and `GlobalWithState` instead. + * DEPRECATED: Use `Global` and `GlobalWithState` instead. * * Provides a `Configuration` class backwards-compatible interface to the data * flow library. diff --git a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl2.qll b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl2.qll index 2bbc565daa6b..d0cc969b5af0 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl2.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl2.qll @@ -1,5 +1,5 @@ /** - * DEPRECATED: Use `Global` and `GlobalWithState` instead. + * DEPRECATED: Use `Global` and `GlobalWithState` instead. * * Provides a `Configuration` class backwards-compatible interface to the data * flow library. diff --git a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl3.qll b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl3.qll index 2bbc565daa6b..d0cc969b5af0 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl3.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl3.qll @@ -1,5 +1,5 @@ /** - * DEPRECATED: Use `Global` and `GlobalWithState` instead. + * DEPRECATED: Use `Global` and `GlobalWithState` instead. * * Provides a `Configuration` class backwards-compatible interface to the data * flow library. diff --git a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl4.qll b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl4.qll index 2bbc565daa6b..d0cc969b5af0 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl4.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl4.qll @@ -1,5 +1,5 @@ /** - * DEPRECATED: Use `Global` and `GlobalWithState` instead. + * DEPRECATED: Use `Global` and `GlobalWithState` instead. * * Provides a `Configuration` class backwards-compatible interface to the data * flow library. diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl1.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl1.qll index 2bbc565daa6b..d0cc969b5af0 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl1.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl1.qll @@ -1,5 +1,5 @@ /** - * DEPRECATED: Use `Global` and `GlobalWithState` instead. + * DEPRECATED: Use `Global` and `GlobalWithState` instead. * * Provides a `Configuration` class backwards-compatible interface to the data * flow library. diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl2.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl2.qll index 2bbc565daa6b..d0cc969b5af0 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl2.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl2.qll @@ -1,5 +1,5 @@ /** - * DEPRECATED: Use `Global` and `GlobalWithState` instead. + * DEPRECATED: Use `Global` and `GlobalWithState` instead. * * Provides a `Configuration` class backwards-compatible interface to the data * flow library. diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl3.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl3.qll index 2bbc565daa6b..d0cc969b5af0 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl3.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl3.qll @@ -1,5 +1,5 @@ /** - * DEPRECATED: Use `Global` and `GlobalWithState` instead. + * DEPRECATED: Use `Global` and `GlobalWithState` instead. * * Provides a `Configuration` class backwards-compatible interface to the data * flow library. diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl4.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl4.qll index 2bbc565daa6b..d0cc969b5af0 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl4.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl4.qll @@ -1,5 +1,5 @@ /** - * DEPRECATED: Use `Global` and `GlobalWithState` instead. + * DEPRECATED: Use `Global` and `GlobalWithState` instead. * * Provides a `Configuration` class backwards-compatible interface to the data * flow library. diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl5.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl5.qll index 2bbc565daa6b..d0cc969b5af0 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl5.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl5.qll @@ -1,5 +1,5 @@ /** - * DEPRECATED: Use `Global` and `GlobalWithState` instead. + * DEPRECATED: Use `Global` and `GlobalWithState` instead. * * Provides a `Configuration` class backwards-compatible interface to the data * flow library. diff --git a/go/ql/lib/semmle/go/dataflow/internal/DataFlowImpl1.qll b/go/ql/lib/semmle/go/dataflow/internal/DataFlowImpl1.qll index 2bbc565daa6b..d0cc969b5af0 100644 --- a/go/ql/lib/semmle/go/dataflow/internal/DataFlowImpl1.qll +++ b/go/ql/lib/semmle/go/dataflow/internal/DataFlowImpl1.qll @@ -1,5 +1,5 @@ /** - * DEPRECATED: Use `Global` and `GlobalWithState` instead. + * DEPRECATED: Use `Global` and `GlobalWithState` instead. * * Provides a `Configuration` class backwards-compatible interface to the data * flow library. diff --git a/go/ql/lib/semmle/go/dataflow/internal/DataFlowImpl2.qll b/go/ql/lib/semmle/go/dataflow/internal/DataFlowImpl2.qll index 2bbc565daa6b..d0cc969b5af0 100644 --- a/go/ql/lib/semmle/go/dataflow/internal/DataFlowImpl2.qll +++ b/go/ql/lib/semmle/go/dataflow/internal/DataFlowImpl2.qll @@ -1,5 +1,5 @@ /** - * DEPRECATED: Use `Global` and `GlobalWithState` instead. + * DEPRECATED: Use `Global` and `GlobalWithState` instead. * * Provides a `Configuration` class backwards-compatible interface to the data * flow library. diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl1.qll b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl1.qll index 2bbc565daa6b..d0cc969b5af0 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl1.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl1.qll @@ -1,5 +1,5 @@ /** - * DEPRECATED: Use `Global` and `GlobalWithState` instead. + * DEPRECATED: Use `Global` and `GlobalWithState` instead. * * Provides a `Configuration` class backwards-compatible interface to the data * flow library. diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl2.qll b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl2.qll index 2bbc565daa6b..d0cc969b5af0 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl2.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl2.qll @@ -1,5 +1,5 @@ /** - * DEPRECATED: Use `Global` and `GlobalWithState` instead. + * DEPRECATED: Use `Global` and `GlobalWithState` instead. * * Provides a `Configuration` class backwards-compatible interface to the data * flow library. diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl3.qll b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl3.qll index 2bbc565daa6b..d0cc969b5af0 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl3.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl3.qll @@ -1,5 +1,5 @@ /** - * DEPRECATED: Use `Global` and `GlobalWithState` instead. + * DEPRECATED: Use `Global` and `GlobalWithState` instead. * * Provides a `Configuration` class backwards-compatible interface to the data * flow library. diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl4.qll b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl4.qll index 2bbc565daa6b..d0cc969b5af0 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl4.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl4.qll @@ -1,5 +1,5 @@ /** - * DEPRECATED: Use `Global` and `GlobalWithState` instead. + * DEPRECATED: Use `Global` and `GlobalWithState` instead. * * Provides a `Configuration` class backwards-compatible interface to the data * flow library. diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl5.qll b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl5.qll index 2bbc565daa6b..d0cc969b5af0 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl5.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl5.qll @@ -1,5 +1,5 @@ /** - * DEPRECATED: Use `Global` and `GlobalWithState` instead. + * DEPRECATED: Use `Global` and `GlobalWithState` instead. * * Provides a `Configuration` class backwards-compatible interface to the data * flow library. diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl6.qll b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl6.qll index 2bbc565daa6b..d0cc969b5af0 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl6.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl6.qll @@ -1,5 +1,5 @@ /** - * DEPRECATED: Use `Global` and `GlobalWithState` instead. + * DEPRECATED: Use `Global` and `GlobalWithState` instead. * * Provides a `Configuration` class backwards-compatible interface to the data * flow library. diff --git a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl1.qll b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl1.qll index 2bbc565daa6b..d0cc969b5af0 100644 --- a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl1.qll +++ b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl1.qll @@ -1,5 +1,5 @@ /** - * DEPRECATED: Use `Global` and `GlobalWithState` instead. + * DEPRECATED: Use `Global` and `GlobalWithState` instead. * * Provides a `Configuration` class backwards-compatible interface to the data * flow library. diff --git a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl2.qll b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl2.qll index 2bbc565daa6b..d0cc969b5af0 100644 --- a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl2.qll +++ b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl2.qll @@ -1,5 +1,5 @@ /** - * DEPRECATED: Use `Global` and `GlobalWithState` instead. + * DEPRECATED: Use `Global` and `GlobalWithState` instead. * * Provides a `Configuration` class backwards-compatible interface to the data * flow library. diff --git a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl3.qll b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl3.qll index 2bbc565daa6b..d0cc969b5af0 100644 --- a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl3.qll +++ b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl3.qll @@ -1,5 +1,5 @@ /** - * DEPRECATED: Use `Global` and `GlobalWithState` instead. + * DEPRECATED: Use `Global` and `GlobalWithState` instead. * * Provides a `Configuration` class backwards-compatible interface to the data * flow library. diff --git a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl4.qll b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl4.qll index 2bbc565daa6b..d0cc969b5af0 100644 --- a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl4.qll +++ b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl4.qll @@ -1,5 +1,5 @@ /** - * DEPRECATED: Use `Global` and `GlobalWithState` instead. + * DEPRECATED: Use `Global` and `GlobalWithState` instead. * * Provides a `Configuration` class backwards-compatible interface to the data * flow library. diff --git a/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImpl1.qll b/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImpl1.qll index 2bbc565daa6b..d0cc969b5af0 100644 --- a/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImpl1.qll +++ b/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImpl1.qll @@ -1,5 +1,5 @@ /** - * DEPRECATED: Use `Global` and `GlobalWithState` instead. + * DEPRECATED: Use `Global` and `GlobalWithState` instead. * * Provides a `Configuration` class backwards-compatible interface to the data * flow library. diff --git a/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImpl2.qll b/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImpl2.qll index 2bbc565daa6b..d0cc969b5af0 100644 --- a/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImpl2.qll +++ b/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImpl2.qll @@ -1,5 +1,5 @@ /** - * DEPRECATED: Use `Global` and `GlobalWithState` instead. + * DEPRECATED: Use `Global` and `GlobalWithState` instead. * * Provides a `Configuration` class backwards-compatible interface to the data * flow library. diff --git a/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowImpl1.qll b/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowImpl1.qll index 2bbc565daa6b..d0cc969b5af0 100644 --- a/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowImpl1.qll +++ b/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowImpl1.qll @@ -1,5 +1,5 @@ /** - * DEPRECATED: Use `Global` and `GlobalWithState` instead. + * DEPRECATED: Use `Global` and `GlobalWithState` instead. * * Provides a `Configuration` class backwards-compatible interface to the data * flow library. From 3533b6a94fc876d12d66581f51c1cf47b5cb11ae Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Mon, 29 Jan 2024 10:50:32 +0100 Subject: [PATCH 07/19] temp --- .../collections/CollectionFlow.expected | 12 +- .../codeql/dataflow/internal/DataFlowImpl.qll | 109 +++++++++++++----- 2 files changed, 83 insertions(+), 38 deletions(-) diff --git a/csharp/ql/test/library-tests/dataflow/collections/CollectionFlow.expected b/csharp/ql/test/library-tests/dataflow/collections/CollectionFlow.expected index 2aadd5b0bbf5..62dd80411b07 100644 --- a/csharp/ql/test/library-tests/dataflow/collections/CollectionFlow.expected +++ b/csharp/ql/test/library-tests/dataflow/collections/CollectionFlow.expected @@ -31,8 +31,8 @@ edges | CollectionFlow.cs:26:58:26:61 | dict : Dictionary [element, property Value] : A | CollectionFlow.cs:26:67:26:70 | access to parameter dict : Dictionary [element, property Value] : A | provenance | | | CollectionFlow.cs:26:67:26:70 | access to parameter dict : Dictionary [element, property Value] : A | CollectionFlow.cs:26:67:26:73 | access to indexer : A | provenance | | | CollectionFlow.cs:28:59:28:62 | dict : Dictionary [element, property Value] : A | CollectionFlow.cs:28:68:28:71 | access to parameter dict : Dictionary [element, property Value] : A | provenance | | -| CollectionFlow.cs:28:68:28:71 | access to parameter dict : Dictionary [element, property Value] : A | CollectionFlow.cs:28:68:28:79 | call to method First> : KeyValuePair [property Value] : A | provenance | | -| CollectionFlow.cs:28:68:28:79 | call to method First> : KeyValuePair [property Value] : A | CollectionFlow.cs:28:68:28:85 | access to property Value : A | provenance | | +| CollectionFlow.cs:28:68:28:71 | access to parameter dict : Dictionary [element, property Value] : A | CollectionFlow.cs:28:68:28:79 | call to method First> : Object [property Value] : A | provenance | | +| CollectionFlow.cs:28:68:28:79 | call to method First> : Object [property Value] : A | CollectionFlow.cs:28:68:28:85 | access to property Value : A | provenance | | | CollectionFlow.cs:30:60:30:63 | dict : Dictionary [element, property Value] : A | CollectionFlow.cs:30:69:30:72 | access to parameter dict : Dictionary [element, property Value] : A | provenance | | | CollectionFlow.cs:30:69:30:72 | access to parameter dict : Dictionary [element, property Value] : A | CollectionFlow.cs:30:69:30:79 | access to property Values : ICollection [element] : A | provenance | | | CollectionFlow.cs:30:69:30:79 | access to property Values : ICollection [element] : A | CollectionFlow.cs:30:69:30:87 | call to method First : A | provenance | | @@ -40,8 +40,8 @@ edges | CollectionFlow.cs:32:67:32:70 | access to parameter dict : Dictionary [element, property Key] : A | CollectionFlow.cs:32:67:32:75 | access to property Keys : ICollection [element] : A | provenance | | | CollectionFlow.cs:32:67:32:75 | access to property Keys : ICollection [element] : A | CollectionFlow.cs:32:67:32:83 | call to method First : A | provenance | | | CollectionFlow.cs:34:57:34:60 | dict : Dictionary [element, property Key] : A | CollectionFlow.cs:34:66:34:69 | access to parameter dict : Dictionary [element, property Key] : A | provenance | | -| CollectionFlow.cs:34:66:34:69 | access to parameter dict : Dictionary [element, property Key] : A | CollectionFlow.cs:34:66:34:77 | call to method First> : KeyValuePair [property Key] : A | provenance | | -| CollectionFlow.cs:34:66:34:77 | call to method First> : KeyValuePair [property Key] : A | CollectionFlow.cs:34:66:34:81 | access to property Key : A | provenance | | +| CollectionFlow.cs:34:66:34:69 | access to parameter dict : Dictionary [element, property Key] : A | CollectionFlow.cs:34:66:34:77 | call to method First> : Object [property Key] : A | provenance | | +| CollectionFlow.cs:34:66:34:77 | call to method First> : Object [property Key] : A | CollectionFlow.cs:34:66:34:81 | access to property Key : A | provenance | | | CollectionFlow.cs:36:49:36:52 | args : A[] [element] : A | CollectionFlow.cs:36:63:36:66 | access to parameter args : A[] [element] : A | provenance | | | CollectionFlow.cs:36:49:36:52 | args : null [element] : A | CollectionFlow.cs:36:63:36:66 | access to parameter args : null [element] : A | provenance | | | CollectionFlow.cs:36:63:36:66 | access to parameter args : A[] [element] : A | CollectionFlow.cs:36:63:36:69 | access to array element | provenance | | @@ -318,7 +318,7 @@ nodes | CollectionFlow.cs:26:67:26:73 | access to indexer : A | semmle.label | access to indexer : A | | CollectionFlow.cs:28:59:28:62 | dict : Dictionary [element, property Value] : A | semmle.label | dict : Dictionary [element, property Value] : A | | CollectionFlow.cs:28:68:28:71 | access to parameter dict : Dictionary [element, property Value] : A | semmle.label | access to parameter dict : Dictionary [element, property Value] : A | -| CollectionFlow.cs:28:68:28:79 | call to method First> : KeyValuePair [property Value] : A | semmle.label | call to method First> : KeyValuePair [property Value] : A | +| CollectionFlow.cs:28:68:28:79 | call to method First> : Object [property Value] : A | semmle.label | call to method First> : Object [property Value] : A | | CollectionFlow.cs:28:68:28:85 | access to property Value : A | semmle.label | access to property Value : A | | CollectionFlow.cs:30:60:30:63 | dict : Dictionary [element, property Value] : A | semmle.label | dict : Dictionary [element, property Value] : A | | CollectionFlow.cs:30:69:30:72 | access to parameter dict : Dictionary [element, property Value] : A | semmle.label | access to parameter dict : Dictionary [element, property Value] : A | @@ -330,7 +330,7 @@ nodes | CollectionFlow.cs:32:67:32:83 | call to method First : A | semmle.label | call to method First : A | | CollectionFlow.cs:34:57:34:60 | dict : Dictionary [element, property Key] : A | semmle.label | dict : Dictionary [element, property Key] : A | | CollectionFlow.cs:34:66:34:69 | access to parameter dict : Dictionary [element, property Key] : A | semmle.label | access to parameter dict : Dictionary [element, property Key] : A | -| CollectionFlow.cs:34:66:34:77 | call to method First> : KeyValuePair [property Key] : A | semmle.label | call to method First> : KeyValuePair [property Key] : A | +| CollectionFlow.cs:34:66:34:77 | call to method First> : Object [property Key] : A | semmle.label | call to method First> : Object [property Key] : A | | CollectionFlow.cs:34:66:34:81 | access to property Key : A | semmle.label | access to property Key : A | | CollectionFlow.cs:36:49:36:52 | args : A[] [element] : A | semmle.label | args : A[] [element] : A | | CollectionFlow.cs:36:49:36:52 | args : null [element] : A | semmle.label | args : null [element] : A | diff --git a/shared/dataflow/codeql/dataflow/internal/DataFlowImpl.qll b/shared/dataflow/codeql/dataflow/internal/DataFlowImpl.qll index b5633e351f04..b4d4d5b0ec72 100644 --- a/shared/dataflow/codeql/dataflow/internal/DataFlowImpl.qll +++ b/shared/dataflow/codeql/dataflow/internal/DataFlowImpl.qll @@ -961,6 +961,16 @@ module MakeImpl { exists(ap) } + pragma[nomagic] + additional predicate nodeMayFlowNotThrough(NodeEx node, Ap ap) { + revFlow(node, false) and + exists(ap) + or + revFlow(node, true) and + exists(ap) and + hasSinkCallCtx() + } + pragma[nomagic] predicate callMayFlowThroughRev(DataFlowCall call) { exists(ArgNodeEx arg, boolean toReturn | @@ -1265,6 +1275,9 @@ module MakeImpl { bindingset[p, argAp, node, ap] predicate nodeMayFlowThrough(ParamNode p, ApApprox argAp, NodeEx node, ApApprox ap); + bindingset[node, ap] + predicate nodeMayFlowNotThrough(NodeEx node, ApApprox ap); + bindingset[node, state, t0, ap, inSummaryCtx] predicate filter(NodeEx node, FlowState state, Typ t0, Ap ap, Typ t, boolean inSummaryCtx); @@ -1333,29 +1346,19 @@ module MakeImpl { NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ArgTypOption argT, ApOption argAp, Typ t0, Typ t, Ap ap, ApApprox apa ) { - exists(ParamNodeOption summaryCtx0, ApOption argAp0, boolean inSummaryCtx | - fwdFlow0(node, state, cc, summaryCtx0, argT, argAp0, t0, ap, apa) and + exists(boolean inSummaryCtx | + fwdFlow0(node, state, cc, summaryCtx, argT, argAp, t0, ap, apa) and PrevStage::revFlow(node, state, apa) and ( exists(ParamNode p, ApApprox argApa | - summaryCtx0 = TParamNodeSome(p) and - argAp0 = apSome(any(Ap argAp1 | argApa = getApprox(argAp1))) - | - if Param::nodeMayFlowThrough(p, argApa, node, apa) - then - summaryCtx = summaryCtx0 and - argAp = argAp0 and - inSummaryCtx = true - else ( - summaryCtx = TParamNodeNone() and - argAp = apNone() and - inSummaryCtx = false - ) + summaryCtx = TParamNodeSome(p) and + argAp = apSome(any(Ap argAp1 | argApa = getApprox(argAp1))) and + Param::nodeMayFlowThrough(p, argApa, node, apa) and + inSummaryCtx = true ) or - summaryCtx0 = TParamNodeNone() and - summaryCtx = summaryCtx0 and - argAp = argAp0 and + summaryCtx = TParamNodeNone() and + (cc instanceof CcNoCall or Param::nodeMayFlowNotThrough(node, apa)) and inSummaryCtx = false ) and filter(node, state, t0, ap, t, inSummaryCtx) @@ -1414,22 +1417,24 @@ module MakeImpl { or // flow into a callable exists(Typ t0 | fwdFlowIn(node, apa, state, cc, t0, ap) | - if PrevStage::parameterMayFlowThrough(node, apa) - then - summaryCtx = TParamNodeSome(node.asNode()) and - argT = ArgTypOption::some(toArgTyp(t)) and - argAp = apSome(ap) and - t = t0 // getNodeTyp(node) - else ( - summaryCtx = TParamNodeNone() and - argT instanceof ArgTypOption::None and - argAp = apNone() and - t = t0 - ) + PrevStage::parameterMayFlowThrough(node, apa) and + summaryCtx = TParamNodeSome(node.asNode()) and + argT = ArgTypOption::some(toArgTyp(t)) and + argAp = apSome(ap) and + t = t0 // getNodeTyp(node) + or + Param::nodeMayFlowNotThrough(node, apa) and + summaryCtx = TParamNodeNone() and + argT instanceof ArgTypOption::None and + argAp = apNone() and + t = t0 ) or // flow out of a callable - fwdFlowOut(_, _, node, state, cc, summaryCtx, argT, argAp, t, ap, apa) + fwdFlowOut(_, _, node, state, cc, _, _, _, t, ap, apa) and + argT instanceof ArgTypOption::None and + argAp = apNone() and + summaryCtx = TParamNodeNone() or // flow through a callable exists( @@ -2373,6 +2378,14 @@ module MakeImpl { ) } + pragma[nomagic] + additional predicate nodeMayFlowNotThrough(NodeEx node, Ap ap) { + revFlow(node, _, TReturnCtxNone(), _, ap) + or + revFlow(node, _, TReturnCtxNoFlowThrough(), _, ap) and + hasSinkCallCtx() + } + pragma[nomagic] private predicate revFlowThroughArg( DataFlowCall call, ArgNodeEx arg, FlowState state, ReturnCtx returnCtx, ApOption returnAp, @@ -2682,6 +2695,11 @@ module MakeImpl { exists(argAp) } + bindingset[node, ap] + predicate nodeMayFlowNotThrough(NodeEx node, PrevStage::Ap ap) { + PrevStage::nodeMayFlowNotThrough(node, ap) + } + pragma[nomagic] private predicate expectsContentCand(NodeEx node) { exists(Content c | @@ -3010,6 +3028,11 @@ module MakeImpl { PrevStage::nodeMayFlowThrough(p, argAp, node, ap) } + bindingset[node, ap] + predicate nodeMayFlowNotThrough(NodeEx node, PrevStage::Ap ap) { + PrevStage::nodeMayFlowNotThrough(node, ap) + } + pragma[nomagic] private predicate expectsContentCand(NodeEx node, Ap ap) { exists(Content c | @@ -3091,6 +3114,11 @@ module MakeImpl { PrevStage::nodeMayFlowThrough(p, argAp, node, ap) } + bindingset[node, ap] + predicate nodeMayFlowNotThrough(NodeEx node, PrevStage::Ap ap) { + PrevStage::nodeMayFlowNotThrough(node, ap) + } + pragma[nomagic] private predicate expectsContentCand(NodeEx node, Ap ap) { exists(Content c | @@ -3137,6 +3165,7 @@ module MakeImpl { private predicate strengthenType( NodeEx node, DataFlowType t0, DataFlowType t, boolean inSummaryCtx ) { + exists(inSummaryCtx) and if castingNodeEx(node) then exists(DataFlowType nt | nt = node.getDataFlowType() | @@ -3197,6 +3226,11 @@ module MakeImpl { PrevStage::nodeMayFlowThrough(p, argAp, node, ap) } + bindingset[node, ap] + predicate nodeMayFlowNotThrough(NodeEx node, PrevStage::Ap ap) { + PrevStage::nodeMayFlowNotThrough(node, ap) + } + pragma[nomagic] private predicate clearSet(NodeEx node, ContentSet c) { PrevStage::revFlow(node) and @@ -3296,6 +3330,11 @@ module MakeImpl { PrevStage::nodeMayFlowThrough(p, argAp, node, ap) } + bindingset[node, ap] + predicate nodeMayFlowNotThrough(NodeEx node, PrevStage::Ap ap) { + PrevStage::nodeMayFlowNotThrough(node, ap) + } + pragma[nomagic] private predicate clearSet(NodeEx node, ContentSet c) { PrevStage::revFlow(node) and @@ -3583,6 +3622,11 @@ module MakeImpl { PrevStage::nodeMayFlowThrough(p, argAp, node, ap) } + bindingset[node, ap] + predicate nodeMayFlowNotThrough(NodeEx node, PrevStage::Ap ap) { + PrevStage::nodeMayFlowNotThrough(node, ap) + } + bindingset[node, state, t0, ap, inSummaryCtx] predicate filter(NodeEx node, FlowState state, Typ t0, Ap ap, Typ t, boolean inSummaryCtx) { strengthenType(node, t0, t, inSummaryCtx) and @@ -4563,7 +4607,8 @@ module MakeImpl { ( sc = TSummaryCtxSome(p, state, t, ap) or - not exists(TSummaryCtxSome(p, state, t, ap)) and + // not exists(TSummaryCtxSome(p, state, t, ap)) and + Stage5::nodeMayFlowNotThrough(p, ap.getApprox()) and sc = TSummaryCtxNone() and // When the call contexts of source and sink needs to match then there's // never any reason to enter a callable except to find a summary. See also From d34dfaab2b891bf7a20515e09720056a59d1871c Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Mon, 29 Jan 2024 19:53:13 +0100 Subject: [PATCH 08/19] temp --- .../dataflow/call-sensitivity/flow.expected | 48 ++- .../codeql/dataflow/internal/DataFlowImpl.qll | 324 +++++++++++------- 2 files changed, 238 insertions(+), 134 deletions(-) diff --git a/java/ql/test/library-tests/dataflow/call-sensitivity/flow.expected b/java/ql/test/library-tests/dataflow/call-sensitivity/flow.expected index dc35379e71ee..e01b3dac1cca 100644 --- a/java/ql/test/library-tests/dataflow/call-sensitivity/flow.expected +++ b/java/ql/test/library-tests/dataflow/call-sensitivity/flow.expected @@ -1,4 +1,5 @@ edges +<<<<<<< HEAD | A2.java:15:15:15:28 | new Integer(...) : Number | A2.java:27:27:27:34 | o : Number | provenance | | | A2.java:27:27:27:34 | o : Number | A2.java:29:9:29:9 | o | provenance | | | A.java:6:28:6:35 | o : Number | A.java:8:11:8:11 | o : Number | provenance | | @@ -32,14 +33,49 @@ edges | A.java:106:30:106:37 | o : Number | A.java:108:10:108:10 | o | provenance | | | A.java:113:31:113:38 | o : Number | A.java:115:10:115:10 | o | provenance | | | A.java:120:36:120:43 | o : Number | A.java:128:9:128:10 | o3 | provenance | | +======= +| A2.java:15:15:15:28 | new Integer(...) : Number | A2.java:27:27:27:34 | o : Number | +| A2.java:27:27:27:34 | o : Number | A2.java:29:9:29:9 | o | +| A.java:6:28:6:35 | o : Object | A.java:8:11:8:11 | o : Object | +| A.java:6:28:6:35 | o : Object | A.java:8:11:8:11 | o : Object | +| A.java:14:29:14:36 | o : Number | A.java:16:9:16:9 | o | +| A.java:20:30:20:37 | o : Number | A.java:22:9:22:9 | o | +| A.java:26:31:26:38 | o : Number | A.java:28:9:28:9 | o | +| A.java:32:35:32:42 | o : Number | A.java:40:8:40:9 | o3 | +| A.java:43:36:43:43 | o : Number | A.java:51:8:51:9 | o3 | +| A.java:43:36:43:43 | o : Number | A.java:51:8:51:9 | o3 | +| A.java:43:36:43:43 | o : Number | A.java:51:8:51:9 | o3 | +| A.java:62:18:62:31 | new Integer(...) : Number | A.java:14:29:14:36 | o : Number | +| A.java:63:19:63:32 | new Integer(...) : Number | A.java:20:30:20:37 | o : Number | +| A.java:64:20:64:33 | new Integer(...) : Number | A.java:26:31:26:38 | o : Number | +| A.java:65:24:65:37 | new Integer(...) : Number | A.java:32:35:32:42 | o : Number | +| A.java:66:25:66:38 | new Integer(...) : Number | A.java:43:36:43:43 | o : Number | +| A.java:67:25:67:38 | new Integer(...) : Number | A.java:43:36:43:43 | o : Number | +| A.java:68:25:68:38 | new Integer(...) : Number | A.java:43:36:43:43 | o : Number | +| A.java:69:20:69:33 | new Integer(...) : Number | A.java:6:28:6:35 | o : Object | +| A.java:69:20:69:33 | new Integer(...) : Number | A.java:69:8:69:40 | flowThrough(...) | +| A.java:71:25:71:38 | new Integer(...) : Number | A.java:43:36:43:43 | o : Number | +| A.java:84:18:84:31 | new Integer(...) : Number | A.java:14:29:14:36 | o : Number | +| A.java:85:19:85:32 | new Integer(...) : Number | A.java:20:30:20:37 | o : Number | +| A.java:86:20:86:33 | new Integer(...) : Number | A.java:26:31:26:38 | o : Number | +| A.java:87:24:87:37 | new Integer(...) : Number | A.java:32:35:32:42 | o : Number | +| A.java:88:20:88:33 | new Integer(...) : Number | A.java:6:28:6:35 | o : Object | +| A.java:88:20:88:33 | new Integer(...) : Number | A.java:88:8:88:37 | flowThrough(...) | +| A.java:99:20:99:33 | new Integer(...) : Number | A.java:106:30:106:37 | o : Number | +| A.java:100:21:100:34 | new Integer(...) : Number | A.java:113:31:113:38 | o : Number | +| A.java:101:26:101:39 | new Integer(...) : Number | A.java:120:36:120:43 | o : Number | +| A.java:106:30:106:37 | o : Number | A.java:108:10:108:10 | o | +| A.java:113:31:113:38 | o : Number | A.java:115:10:115:10 | o | +| A.java:120:36:120:43 | o : Number | A.java:128:9:128:10 | o3 | +>>>>>>> 62a7e4947d (temp) nodes | A2.java:15:15:15:28 | new Integer(...) : Number | semmle.label | new Integer(...) : Number | | A2.java:27:27:27:34 | o : Number | semmle.label | o : Number | | A2.java:29:9:29:9 | o | semmle.label | o | -| A.java:6:28:6:35 | o : Number | semmle.label | o : Number | -| A.java:6:28:6:35 | o : Number | semmle.label | o : Number | -| A.java:8:11:8:11 | o : Number | semmle.label | o : Number | -| A.java:8:11:8:11 | o : Number | semmle.label | o : Number | +| A.java:6:28:6:35 | o : Object | semmle.label | o : Object | +| A.java:6:28:6:35 | o : Object | semmle.label | o : Object | +| A.java:8:11:8:11 | o : Object | semmle.label | o : Object | +| A.java:8:11:8:11 | o : Object | semmle.label | o : Object | | A.java:14:29:14:36 | o : Number | semmle.label | o : Number | | A.java:16:9:16:9 | o | semmle.label | o | | A.java:20:30:20:37 | o : Number | semmle.label | o : Number | @@ -78,8 +114,8 @@ nodes | A.java:120:36:120:43 | o : Number | semmle.label | o : Number | | A.java:128:9:128:10 | o3 | semmle.label | o3 | subpaths -| A.java:69:20:69:33 | new Integer(...) : Number | A.java:6:28:6:35 | o : Number | A.java:8:11:8:11 | o : Number | A.java:69:8:69:40 | flowThrough(...) | -| A.java:88:20:88:33 | new Integer(...) : Number | A.java:6:28:6:35 | o : Number | A.java:8:11:8:11 | o : Number | A.java:88:8:88:37 | flowThrough(...) | +| A.java:69:20:69:33 | new Integer(...) : Number | A.java:6:28:6:35 | o : Object | A.java:8:11:8:11 | o : Object | A.java:69:8:69:40 | flowThrough(...) | +| A.java:88:20:88:33 | new Integer(...) : Number | A.java:6:28:6:35 | o : Object | A.java:8:11:8:11 | o : Object | A.java:88:8:88:37 | flowThrough(...) | #select | A2.java:15:15:15:28 | new Integer(...) : Number | A2.java:15:15:15:28 | new Integer(...) : Number | A2.java:29:9:29:9 | o | $@ | A2.java:29:9:29:9 | o | o | | A.java:62:18:62:31 | new Integer(...) : Number | A.java:62:18:62:31 | new Integer(...) : Number | A.java:16:9:16:9 | o | $@ | A.java:16:9:16:9 | o | o | diff --git a/shared/dataflow/codeql/dataflow/internal/DataFlowImpl.qll b/shared/dataflow/codeql/dataflow/internal/DataFlowImpl.qll index b4d4d5b0ec72..f8d6fbc65822 100644 --- a/shared/dataflow/codeql/dataflow/internal/DataFlowImpl.qll +++ b/shared/dataflow/codeql/dataflow/internal/DataFlowImpl.qll @@ -1337,17 +1337,18 @@ module MakeImpl { pragma[nomagic] additional predicate fwdFlow( NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ArgTypOption argT, - ApOption argAp, Typ t, Ap ap, ApApprox apa + ApOption argAp, Typ t, TypOption origT, Ap ap, ApApprox apa ) { - fwdFlow1(node, state, cc, summaryCtx, argT, argAp, _, t, ap, apa) + fwdFlow1(node, state, cc, summaryCtx, argT, argAp, _, t, _, origT, ap, apa) } - private predicate fwdFlow1( + pragma[nomagic] + additional predicate fwdFlow1( NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ArgTypOption argT, - ApOption argAp, Typ t0, Typ t, Ap ap, ApApprox apa + ApOption argAp, Typ t0, Typ t, TypOption origT0, TypOption origT, Ap ap, ApApprox apa ) { exists(boolean inSummaryCtx | - fwdFlow0(node, state, cc, summaryCtx, argT, argAp, t0, ap, apa) and + fwdFlow0(node, state, cc, summaryCtx, argT, argAp, t0, origT0, ap, apa) and PrevStage::revFlow(node, state, apa) and ( exists(ParamNode p, ApApprox argApa | @@ -1361,19 +1362,23 @@ module MakeImpl { (cc instanceof CcNoCall or Param::nodeMayFlowNotThrough(node, apa)) and inSummaryCtx = false ) and - filter(node, state, t0, ap, t, inSummaryCtx) + filter(node, state, t0, ap, t, inSummaryCtx) and + // origT.asSome() = t + if t != t0 and origT0.isNone() and not ap instanceof ApNil + then origT.asSome() = t0 + else origT = origT0 ) } pragma[nomagic] private predicate typeStrengthen(Typ t0, Ap ap, Typ t) { - fwdFlow1(_, _, _, _, _, _, t0, t, ap, _) and t0 != t + fwdFlow1(_, _, _, _, _, _, t0, t, _, _, ap, _) and t0 != t } pragma[nomagic] private predicate fwdFlow0( NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ArgTypOption argT, - ApOption argAp, Typ t, Ap ap, ApApprox apa + ApOption argAp, Typ t, TypOption origT, Ap ap, ApApprox apa ) { sourceNode(node, state) and (if hasSourceCallCtx() then cc = ccSomeCall() else cc = ccNone()) and @@ -1381,21 +1386,26 @@ module MakeImpl { argAp = apNone() and summaryCtx = TParamNodeNone() and t = getNodeTyp(node) and + // origT.asSome() = t and + origT.isNone() and ap instanceof ApNil and apa = getApprox(ap) or - exists(NodeEx mid, FlowState state0, Typ t0, LocalCc localCc | - fwdFlow(mid, state0, cc, summaryCtx, argT, argAp, t0, ap, apa) and + exists(NodeEx mid, FlowState state0, Typ t0, TypOption origT0, LocalCc localCc | + fwdFlow(mid, state0, cc, summaryCtx, argT, argAp, t0, origT0, ap, apa) and localCc = getLocalCc(mid, cc) | localStep(mid, state0, node, state, true, _, localCc) and - t = t0 + t = t0 and + origT = origT0 or localStep(mid, state0, node, state, false, t, localCc) and - ap instanceof ApNil + ap instanceof ApNil and + // origT.asSome() = t + origT.isNone() ) or - fwdFlowJump(node, state, t, ap, apa) and + fwdFlowJump(node, state, t, origT, ap, apa) and cc = ccNone() and summaryCtx = TParamNodeNone() and argT instanceof ArgTypOption::None and @@ -1403,35 +1413,46 @@ module MakeImpl { or // store exists(Content c, Typ t0, Ap ap0 | - fwdFlowStore(t0, ap0, c, t, node, state, cc, summaryCtx, argT, argAp) and + fwdFlowStore(t0, _, ap0, c, t, node, state, cc, summaryCtx, argT, argAp) and ap = apCons(c, t0, ap0) and - apa = getApprox(ap) + apa = getApprox(ap) and + // origT.asSome() = t + origT.isNone() ) or // read exists(Typ t0, Ap ap0, Content c | fwdFlowRead(t0, ap0, c, node, state, cc, summaryCtx, argT, argAp) and - fwdFlowConsCand(t0, ap0, c, t, ap) and + fwdFlowConsCandNoStrenght(t0, ap0, c, t, origT, ap) and apa = getApprox(ap) ) or // flow into a callable - exists(Typ t0 | fwdFlowIn(node, apa, state, cc, t0, ap) | + exists(Typ t0, TypOption origT0, boolean inSummaryCtx | + fwdFlowIn(node, apa, state, cc, t0, origT0, ap, inSummaryCtx) + | PrevStage::parameterMayFlowThrough(node, apa) and summaryCtx = TParamNodeSome(node.asNode()) and argT = ArgTypOption::some(toArgTyp(t)) and argAp = apSome(ap) and - t = t0 // getNodeTyp(node) + // t = getNodeTyp(node) and + // if origT0.isNone() then origT.asSome() = t0 else origT = origT0 + t = t0 and + origT = origT0 or + // t = t0 and + // origT = origT0 Param::nodeMayFlowNotThrough(node, apa) and summaryCtx = TParamNodeNone() and argT instanceof ArgTypOption::None and argAp = apNone() and - t = t0 + t = t0 and + origT = origT0 and + inSummaryCtx = false ) or // flow out of a callable - fwdFlowOut(_, _, node, state, cc, _, _, _, t, ap, apa) and + fwdFlowOut(_, _, node, state, cc, _, _, _, t, origT, ap, apa) and argT instanceof ArgTypOption::None and argAp = apNone() and summaryCtx = TParamNodeNone() @@ -1441,41 +1462,47 @@ module MakeImpl { DataFlowCall call, CcCall ccc, ReturnKindExt kind, boolean allowsFieldFlow, ApApprox innerArgApa | - fwdFlowThrough(call, cc, state, ccc, summaryCtx, argT, argAp, t, ap, apa, kind, + fwdFlowThrough(call, cc, state, ccc, summaryCtx, argT, argAp, t, origT, ap, apa, kind, innerArgApa) and flowThroughOutOfCall(call, ccc, kind, node, allowsFieldFlow, innerArgApa, apa) and if allowsFieldFlow = false then ap instanceof ApNil else any() ) } - private predicate fwdFlowJump(NodeEx node, FlowState state, Typ t, Ap ap, ApApprox apa) { + private predicate fwdFlowJump( + NodeEx node, FlowState state, Typ t, TypOption origT, Ap ap, ApApprox apa + ) { exists(NodeEx mid | - fwdFlow(mid, state, _, _, _, _, t, ap, apa) and + fwdFlow(mid, state, _, _, _, _, t, origT, ap, apa) and jumpStepEx(mid, node) ) or exists(NodeEx mid | - fwdFlow(mid, state, _, _, _, _, _, ap, apa) and + fwdFlow(mid, state, _, _, _, _, _, _, ap, apa) and additionalJumpStep(mid, node) and t = getNodeTyp(node) and + // origT.asSome() = t and + origT.isNone() and ap instanceof ApNil ) or exists(NodeEx mid, FlowState state0 | - fwdFlow(mid, state0, _, _, _, _, _, ap, apa) and + fwdFlow(mid, state0, _, _, _, _, _, _, ap, apa) and additionalJumpStateStep(mid, state0, node, state) and t = getNodeTyp(node) and + // origT.asSome() = t and + origT.isNone() and ap instanceof ApNil ) } pragma[inline] private predicate fwdFlowStore( - NodeEx node1, Typ t1, Ap ap1, Content c, Typ t2, NodeEx node2, FlowState state, Cc cc, - ParamNodeOption summaryCtx, ArgTypOption argT, ApOption argAp + NodeEx node1, Typ t1, TypOption origT1, Ap ap1, Content c, Typ t2, NodeEx node2, + FlowState state, Cc cc, ParamNodeOption summaryCtx, ArgTypOption argT, ApOption argAp ) { exists(DataFlowType contentType, DataFlowType containerType, ApApprox apa1 | - fwdFlow(node1, state, cc, summaryCtx, argT, argAp, t1, ap1, apa1) and + fwdFlow(node1, state, cc, summaryCtx, argT, argAp, t1, origT1, ap1, apa1) and PrevStage::storeStepCand(node1, apa1, c, node2, contentType, containerType) and t2 = getTyp(containerType) and typecheckStore(t1, contentType) @@ -1484,10 +1511,10 @@ module MakeImpl { pragma[nomagic] private predicate fwdFlowStore( - Typ t1, Ap ap1, Content c, Typ t2, NodeEx node2, FlowState state, Cc cc, + Typ t1, TypOption origT1, Ap ap1, Content c, Typ t2, NodeEx node2, FlowState state, Cc cc, ParamNodeOption summaryCtx, ArgTypOption argT, ApOption argAp ) { - fwdFlowStore(_, t1, ap1, c, t2, node2, state, cc, summaryCtx, argT, argAp) + fwdFlowStore(_, t1, origT1, ap1, c, t2, node2, state, cc, summaryCtx, argT, argAp) } /** @@ -1496,13 +1523,33 @@ module MakeImpl { * `cons`. */ pragma[nomagic] - private predicate fwdFlowConsCand(Typ t2, Ap cons, Content c, Typ t1, Ap tail) { - fwdFlowStore(t1, tail, c, t2, _, _, _, _, _, _) and + private predicate fwdFlowConsCandNoStrenght( + Typ t2, Ap cons, Content c, Typ t1, TypOption origT1, Ap tail + ) { + fwdFlowStore(t1, origT1, tail, c, t2, _, _, _, _, _, _) and + cons = apCons(c, t1, tail) + // or + // exists(Typ t0 | + // typeStrengthen(t0, cons, t2) and + // fwdFlowConsCand(t0, cons, c, t1, origT1, tail) + // ) + } + + /** + * Holds if forward flow with access path `tail` and type `t1` reaches a + * store of `c` on a container of type `t2` resulting in access path + * `cons`. + */ + pragma[nomagic] + private predicate fwdFlowConsCand_( + Typ t2, Ap cons, Content c, Typ t1, TypOption origT1, Ap tail + ) { + fwdFlowStore(t1, origT1, tail, c, t2, _, _, _, _, _, _) and cons = apCons(c, t1, tail) or exists(Typ t0 | typeStrengthen(t0, cons, t2) and - fwdFlowConsCand(t0, cons, c, t1, tail) + fwdFlowConsCand_(t0, cons, c, t1, origT1, tail) ) } @@ -1523,10 +1570,15 @@ module MakeImpl { Typ t, Ap ap, Content c, NodeEx node1, NodeEx node2, FlowState state, Cc cc, ParamNodeOption summaryCtx, ArgTypOption argT, ApOption argAp ) { - exists(ApHeadContent apc | - fwdFlow(node1, state, cc, summaryCtx, argT, argAp, t, ap, _) and + exists(Typ t0, TypOption origT, ApHeadContent apc | + fwdFlow(node1, state, cc, summaryCtx, argT, argAp, t0, origT, ap, _) and apc = getHeadContent(ap) and readStepCand0(node1, apc, c, node2) + | + t = origT.asSome() + or + origT.isNone() and + t = t0 ) } @@ -1541,9 +1593,9 @@ module MakeImpl { pragma[nomagic] private predicate fwdFlowIntoArg( ArgNodeEx arg, FlowState state, Cc outercc, ParamNodeOption summaryCtx, ArgTypOption argT, - ApOption argAp, Typ t, Ap ap, boolean emptyAp, ApApprox apa, boolean cc + ApOption argAp, Typ t, TypOption origT, Ap ap, boolean emptyAp, ApApprox apa, boolean cc ) { - fwdFlow(arg, state, outercc, summaryCtx, argT, argAp, t, ap, apa) and + fwdFlow(arg, state, outercc, summaryCtx, argT, argAp, t, origT, ap, apa) and (if outercc instanceof CcCall then cc = true else cc = false) and if ap instanceof ApNil then emptyAp = true else emptyAp = false } @@ -1631,10 +1683,11 @@ module MakeImpl { private predicate fwdFlowInCand( DataFlowCall call, ArgNodeEx arg, FlowState state, Cc outercc, DataFlowCallable inner, ParamNodeEx p, ParamNodeOption summaryCtx, ArgTypOption argT, ApOption argAp, Typ t, - Ap ap, boolean emptyAp, ApApprox apa, boolean cc + TypOption origT, Ap ap, boolean emptyAp, ApApprox apa, boolean cc ) { exists(boolean allowsFieldFlow | - fwdFlowIntoArg(arg, state, outercc, summaryCtx, argT, argAp, t, ap, emptyAp, apa, cc) and + fwdFlowIntoArg(arg, state, outercc, summaryCtx, argT, argAp, t, origT, ap, emptyAp, + apa, cc) and ( inner = viableImplCallContextReducedInlineLate(call, arg, outercc) or @@ -1649,11 +1702,11 @@ module MakeImpl { private predicate fwdFlowInCandTypeFlowDisabled( DataFlowCall call, ArgNodeEx arg, FlowState state, Cc outercc, DataFlowCallable inner, ParamNodeEx p, ParamNodeOption summaryCtx, ArgTypOption argT, ApOption argAp, Typ t, - Ap ap, ApApprox apa, boolean cc + TypOption origT, Ap ap, ApApprox apa, boolean cc ) { not enableTypeFlow() and - fwdFlowInCand(call, arg, state, outercc, inner, p, summaryCtx, argT, argAp, t, ap, _, - apa, cc) + fwdFlowInCand(call, arg, state, outercc, inner, p, summaryCtx, argT, argAp, t, origT, + ap, _, apa, cc) } pragma[nomagic] @@ -1662,7 +1715,7 @@ module MakeImpl { boolean emptyAp, ApApprox apa, boolean cc ) { enableTypeFlow() and - fwdFlowInCand(call, arg, _, outercc, inner, p, _, _, _, _, _, emptyAp, apa, cc) + fwdFlowInCand(call, arg, _, outercc, inner, p, _, _, _, _, _, _, emptyAp, apa, cc) } pragma[nomagic] @@ -1688,17 +1741,18 @@ module MakeImpl { predicate fwdFlowIn( DataFlowCall call, DataFlowCallable inner, ParamNodeEx p, FlowState state, Cc outercc, CcCall innercc, ParamNodeOption summaryCtx, ArgTypOption argT, ApOption argAp, Typ t, - Ap ap, ApApprox apa, boolean cc + TypOption origT, Ap ap, ApApprox apa, boolean cc ) { exists(ArgNodeEx arg | // type flow disabled: linear recursion fwdFlowInCandTypeFlowDisabled(call, arg, state, outercc, inner, p, summaryCtx, argT, - argAp, t, ap, apa, cc) and + argAp, t, origT, ap, apa, cc) and fwdFlowInValidEdgeTypeFlowDisabled(call, inner, innercc, pragma[only_bind_into](cc)) or // type flow enabled: non-linear recursion exists(boolean emptyAp | - fwdFlowIntoArg(arg, state, outercc, summaryCtx, argT, argAp, t, ap, emptyAp, apa, cc) and + fwdFlowIntoArg(arg, state, outercc, summaryCtx, argT, argAp, t, origT, ap, emptyAp, + apa, cc) and fwdFlowInValidEdgeTypeFlowEnabled(call, arg, outercc, inner, p, innercc, emptyAp, apa, cc) ) @@ -1710,10 +1764,14 @@ module MakeImpl { pragma[nomagic] private predicate fwdFlowIn( - ParamNodeEx p, ApApprox apa, FlowState state, CcCall innercc, Typ t, Ap ap + ParamNodeEx p, ApApprox apa, FlowState state, CcCall innercc, Typ t, TypOption origT, + Ap ap, boolean inSummaryCtx ) { - FwdFlowIn::fwdFlowIn(_, _, p, state, _, innercc, _, _, _, t, ap, - apa, _) + exists(ParamNodeOption summaryCtx | + FwdFlowIn::fwdFlowIn(_, _, p, state, _, innercc, summaryCtx, _, + _, t, origT, ap, apa, _) and + if summaryCtx = TParamNodeNone() then inSummaryCtx = false else inSummaryCtx = true + ) } pragma[nomagic] @@ -1755,9 +1813,9 @@ module MakeImpl { pragma[nomagic] private predicate fwdFlowIntoRet( RetNodeEx ret, FlowState state, CcNoCall cc, ParamNodeOption summaryCtx, - ArgTypOption argT, ApOption argAp, Typ t, Ap ap, ApApprox apa + ArgTypOption argT, ApOption argAp, Typ t, TypOption origT, Ap ap, ApApprox apa ) { - fwdFlow(ret, state, cc, summaryCtx, argT, argAp, t, ap, apa) + fwdFlow(ret, state, cc, summaryCtx, argT, argAp, t, origT, ap, apa) } pragma[nomagic] @@ -1765,7 +1823,7 @@ module MakeImpl { DataFlowCall call, RetNodeEx ret, CcNoCall innercc, DataFlowCallable inner, NodeEx out, ApApprox apa, boolean allowsFieldFlow ) { - fwdFlowIntoRet(ret, _, innercc, _, _, _, _, _, apa) and + fwdFlowIntoRet(ret, _, innercc, _, _, _, _, _, _, apa) and inner = ret.getEnclosingCallable() and ( inner = viableImplCallContextReducedReverseInlineLate(call, innercc) and @@ -1789,10 +1847,11 @@ module MakeImpl { pragma[inline] private predicate fwdFlowOut( DataFlowCall call, DataFlowCallable inner, NodeEx out, FlowState state, CcNoCall outercc, - ParamNodeOption summaryCtx, ArgTypOption argT, ApOption argAp, Typ t, Ap ap, ApApprox apa + ParamNodeOption summaryCtx, ArgTypOption argT, ApOption argAp, Typ t, TypOption origT, + Ap ap, ApApprox apa ) { exists(RetNodeEx ret, CcNoCall innercc, boolean allowsFieldFlow | - fwdFlowIntoRet(ret, state, innercc, summaryCtx, argT, argAp, t, ap, apa) and + fwdFlowIntoRet(ret, state, innercc, summaryCtx, argT, argAp, t, origT, ap, apa) and fwdFlowOutValidEdge(call, ret, innercc, inner, out, outercc, apa, allowsFieldFlow) and if allowsFieldFlow = false then ap instanceof ApNil else any() ) @@ -1812,22 +1871,22 @@ module MakeImpl { pragma[nomagic] private predicate dataFlowTakenCallEdgeIn0( DataFlowCall call, DataFlowCallable c, ParamNodeEx p, FlowState state, CcCall innercc, - Typ t, Ap ap, boolean cc + Ap ap, boolean cc ) { - FwdFlowIn::fwdFlowIn(call, c, p, state, _, innercc, _, _, _, t, - ap, _, cc) + FwdFlowIn::fwdFlowIn(call, c, p, state, _, innercc, _, _, _, _, + _, ap, _, cc) } pragma[nomagic] - private predicate fwdFlow1Param(ParamNodeEx p, FlowState state, CcCall cc, Typ t0, Ap ap) { - fwdFlow1(p, state, cc, _, _, _, t0, _, ap, _) + private predicate fwdFlow1Param(ParamNodeEx p, FlowState state, CcCall cc, Ap ap) { + fwdFlow1(p, state, cc, _, _, _, _, _, _, _, ap, _) } pragma[nomagic] predicate dataFlowTakenCallEdgeIn(DataFlowCall call, DataFlowCallable c, boolean cc) { - exists(ParamNodeEx p, FlowState state, CcCall innercc, Typ t, Ap ap | - dataFlowTakenCallEdgeIn0(call, c, p, state, innercc, t, ap, cc) and - fwdFlow1Param(p, state, innercc, t, ap) + exists(ParamNodeEx p, FlowState state, CcCall innercc, Ap ap | + dataFlowTakenCallEdgeIn0(call, c, p, state, innercc, ap, cc) and + fwdFlow1Param(p, state, innercc, ap) ) } @@ -1835,13 +1894,13 @@ module MakeImpl { private predicate dataFlowTakenCallEdgeOut0( DataFlowCall call, DataFlowCallable c, NodeEx node, FlowState state, Cc cc, Typ t, Ap ap ) { - fwdFlowOut(call, c, node, state, cc, _, _, _, t, ap, _) + fwdFlowOut(call, c, node, state, cc, _, _, _, t, _, ap, _) } pragma[nomagic] private predicate fwdFlow1Out(NodeEx node, FlowState state, Cc cc, Typ t0, Ap ap) { exists(ApApprox apa | - fwdFlow1(node, state, cc, _, _, _, t0, _, ap, apa) and + fwdFlow1(node, state, cc, _, _, _, t0, _, _, _, ap, apa) and PrevStage::callEdgeReturn(_, _, _, _, node, _, apa) ) } @@ -1864,7 +1923,7 @@ module MakeImpl { or exists(NodeEx node | cc = false and - fwdFlowJump(node, _, _, _, _) and + fwdFlowJump(node, _, _, _, _, _) and c = node.getEnclosingCallable() ) } @@ -1883,12 +1942,12 @@ module MakeImpl { pragma[nomagic] private predicate fwdFlowRetFromArg( RetNodeEx ret, FlowState state, CcCall ccc, ParamNodeEx summaryCtx, ArgTyp argT, Ap argAp, - ApApprox argApa, Typ t, Ap ap, ApApprox apa + ApApprox argApa, Typ t, TypOption origT, Ap ap, ApApprox apa ) { exists(ReturnKindExt kind | fwdFlow(pragma[only_bind_into](ret), state, ccc, TParamNodeSome(pragma[only_bind_into](summaryCtx.asNode())), ArgTypOption::some(argT), - pragma[only_bind_into](apSome(argAp)), t, ap, pragma[only_bind_into](apa)) and + pragma[only_bind_into](apSome(argAp)), t, origT, ap, pragma[only_bind_into](apa)) and kind = ret.getKind() and parameterFlowThroughAllowed(summaryCtx, kind) and argApa = getApprox(argAp) and @@ -1899,12 +1958,12 @@ module MakeImpl { pragma[nomagic] private predicate fwdFlowRetFromArg1( ReturnKindExt kind, FlowState state, CcCall ccc, ParamNodeEx summaryCtx, ArgTyp argT, - Ap argAp, ApApprox argApa, Typ t, Ap ap, ApApprox apa + Ap argAp, ApApprox argApa, Typ t, TypOption origT, Ap ap, ApApprox apa ) { exists(RetNodeEx ret | fwdFlow(pragma[only_bind_into](ret), state, ccc, TParamNodeSome(pragma[only_bind_into](summaryCtx.asNode())), ArgTypOption::some(argT), - pragma[only_bind_into](apSome(argAp)), t, ap, pragma[only_bind_into](apa)) and + pragma[only_bind_into](apSome(argAp)), t, origT, ap, pragma[only_bind_into](apa)) and kind = ret.getKind() and parameterFlowThroughAllowed(summaryCtx, kind) and argApa = getApprox(argAp) and @@ -1915,11 +1974,12 @@ module MakeImpl { pragma[inline] private predicate fwdFlowThrough0( DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, - ArgTypOption argT, ApOption argAp, Typ t, Ap ap, ApApprox apa, RetNodeEx ret, - ParamNodeEx innerSummaryCtx, ArgTyp innerArgT, Ap innerArgAp, ApApprox innerArgApa + ArgTypOption argT, ApOption argAp, Typ t, TypOption origT, Ap ap, ApApprox apa, + RetNodeEx ret, ParamNodeEx innerSummaryCtx, ArgTyp innerArgT, Ap innerArgAp, + ApApprox innerArgApa ) { fwdFlowRetFromArg(ret, state, ccc, innerSummaryCtx, innerArgT, innerArgAp, innerArgApa, t, - ap, apa) and + origT, ap, apa) and fwdFlowIsEntered(call, cc, ccc, summaryCtx, argT, argAp, innerSummaryCtx, innerArgT, innerArgAp) } @@ -1927,11 +1987,12 @@ module MakeImpl { pragma[inline] private predicate fwdFlowThrough1( DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, - ArgTypOption argT, ApOption argAp, Typ t, Ap ap, ApApprox apa, ReturnKindExt kind, - ParamNodeEx innerSummaryCtx, ArgTyp innerArgT, Ap innerArgAp, ApApprox innerArgApa + ArgTypOption argT, ApOption argAp, Typ t, TypOption origT, Ap ap, ApApprox apa, + ReturnKindExt kind, ParamNodeEx innerSummaryCtx, ArgTyp innerArgT, Ap innerArgAp, + ApApprox innerArgApa ) { fwdFlowRetFromArg1(kind, state, ccc, innerSummaryCtx, innerArgT, innerArgAp, innerArgApa, - t, ap, apa) and + t, origT, ap, apa) and fwdFlowIsEntered(call, cc, ccc, summaryCtx, argT, argAp, innerSummaryCtx, innerArgT, innerArgAp) } @@ -1939,11 +2000,11 @@ module MakeImpl { pragma[nomagic] private predicate fwdFlowThrough( DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, - ArgTypOption argT, ApOption argAp, Typ t, Ap ap, ApApprox apa, ReturnKindExt kind, - ApApprox innerArgApa + ArgTypOption argT, ApOption argAp, Typ t, TypOption origT, Ap ap, ApApprox apa, + ReturnKindExt kind, ApApprox innerArgApa ) { - fwdFlowThrough1(call, cc, state, ccc, summaryCtx, argT, argAp, t, ap, apa, kind, _, _, _, - innerArgApa) + fwdFlowThrough1(call, cc, state, ccc, summaryCtx, argT, argAp, t, origT, ap, apa, kind, _, + _, _, innerArgApa) } private module FwdFlowThroughRestriction implements FwdFlowInInputSig { @@ -1962,12 +2023,14 @@ module MakeImpl { ApOption argAp, ParamNodeEx p, ArgTyp t, Ap ap ) { FwdFlowIn::fwdFlowIn(call, _, p, _, cc, innerCc, summaryCtx, - argT, argAp, any(Typ t0 | t = toArgTyp(t0)), ap, _, _) + argT, argAp, any(Typ t0 | t = toArgTyp(t0)), _, ap, _, _) } pragma[nomagic] - private predicate storeStepFwd(NodeEx node1, Typ t1, Ap ap1, Content c, NodeEx node2, Ap ap2) { - fwdFlowStore(node1, t1, ap1, c, _, node2, _, _, _, _, _) and + private predicate storeStepFwd( + NodeEx node1, Typ t1, TypOption origT1, Ap ap1, Content c, NodeEx node2, Ap ap2 + ) { + fwdFlowStore(node1, t1, origT1, ap1, c, _, node2, _, _, _, _, _) and ap2 = apCons(c, t1, ap1) and readStepFwd(_, ap2, c, _, _) } @@ -1976,7 +2039,7 @@ module MakeImpl { private predicate readStepFwd(NodeEx n1, Ap ap1, Content c, NodeEx n2, Ap ap2) { exists(Typ t1 | fwdFlowRead(t1, ap1, c, n1, n2, _, _, _, _, _) and - fwdFlowConsCand(t1, ap1, c, _, ap2) + fwdFlowConsCandNoStrenght(t1, ap1, c, _, _, ap2) ) } @@ -1985,8 +2048,8 @@ module MakeImpl { DataFlowCall call, FlowState state, CcCall ccc, Ap ap, ApApprox apa, RetNodeEx ret, ParamNodeEx innerSummaryCtx, ArgTyp innerArgT, Ap innerArgAp, ApApprox innerArgApa ) { - fwdFlowThrough0(call, _, state, ccc, _, _, _, _, ap, apa, ret, innerSummaryCtx, innerArgT, - innerArgAp, innerArgApa) + fwdFlowThrough0(call, _, state, ccc, _, _, _, _, _, ap, apa, ret, innerSummaryCtx, + innerArgT, innerArgAp, innerArgApa) } pragma[nomagic] @@ -2010,8 +2073,8 @@ module MakeImpl { returnFlowsThrough(_, _, _, _, pragma[only_bind_into](p), pragma[only_bind_into](toArgTyp(argT)), pragma[only_bind_into](argAp), ap) and flowIntoCallApaTaken(call, _, pragma[only_bind_into](arg), p, allowsFieldFlow, argApa) and - fwdFlow(arg, _, _, _, _, _, pragma[only_bind_into](argT), pragma[only_bind_into](argAp), - argApa) and + fwdFlow(arg, _, _, _, _, _, pragma[only_bind_into](argT), _, + pragma[only_bind_into](argAp), argApa) and if allowsFieldFlow = false then argAp instanceof ApNil else any() ) } @@ -2022,7 +2085,7 @@ module MakeImpl { ) { exists(ApApprox apa, boolean allowsFieldFlow | flowIntoCallApaTaken(call, c, arg, p, allowsFieldFlow, apa) and - fwdFlow(arg, _, _, _, _, _, _, ap, apa) and + fwdFlow(arg, _, _, _, _, _, _, _, ap, apa) and if allowsFieldFlow = false then ap instanceof ApNil else any() ) } @@ -2034,7 +2097,7 @@ module MakeImpl { ) { exists(ApApprox apa, boolean allowsFieldFlow | PrevStage::callEdgeReturn(call, c, ret, _, out, allowsFieldFlow, apa) and - fwdFlow(ret, _, _, _, _, _, _, ap, apa) and + fwdFlow(ret, _, _, _, _, _, _, _, ap, apa) and pos = ret.getReturnPosition() and if allowsFieldFlow = false then ap instanceof ApNil else any() | @@ -2057,14 +2120,14 @@ module MakeImpl { NodeEx node, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap ) { revFlow0(node, state, returnCtx, returnAp, ap) and - fwdFlow(node, state, _, _, _, _, _, ap, _) + fwdFlow(node, state, _, _, _, _, _, _, ap, _) } pragma[nomagic] private predicate revFlow0( NodeEx node, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap ) { - fwdFlow(node, state, _, _, _, _, _, ap, _) and + fwdFlow(node, state, _, _, _, _, _, _, ap, _) and sinkNode(node, state) and ( if hasSinkCallCtx() @@ -2091,7 +2154,7 @@ module MakeImpl { or // store exists(Ap ap0, Content c | - revFlowStore(ap0, c, ap, _, node, state, _, returnCtx, returnAp) and + revFlowStore(ap0, c, ap, _, _, node, state, _, returnCtx, returnAp) and revFlowConsCand(ap0, c, ap) ) or @@ -2146,11 +2209,11 @@ module MakeImpl { pragma[nomagic] private predicate revFlowStore( - Ap ap0, Content c, Ap ap, Typ t, NodeEx node, FlowState state, NodeEx mid, - ReturnCtx returnCtx, ApOption returnAp + Ap ap0, Content c, Ap ap, Typ t, TypOption origT, NodeEx node, FlowState state, + NodeEx mid, ReturnCtx returnCtx, ApOption returnAp ) { revFlow(mid, state, returnCtx, returnAp, ap0) and - storeStepFwd(node, t, ap, c, mid, ap0) + storeStepFwd(node, t, origT, ap, c, mid, ap0) } /** @@ -2192,7 +2255,7 @@ module MakeImpl { predicate dataFlowNonCallEntry(DataFlowCallable c, boolean cc) { exists(NodeEx node, FlowState state, ApNil nil | - fwdFlow(node, state, _, _, _, _, _, nil, _) and + fwdFlow(node, state, _, _, _, _, _, _, nil, _) and sinkNode(node, state) and (if hasSinkCallCtx() then cc = true else cc = false) and c = node.getEnclosingCallable() @@ -2289,7 +2352,7 @@ module MakeImpl { ) { exists(Ap ap2 | PrevStage::storeStepCand(node1, _, c, node2, contentType, containerType) and - revFlowStore(ap2, c, ap1, _, node1, _, node2, _, _) and + revFlowStore(ap2, c, ap1, _, _, node1, _, node2, _, _) and revFlowConsCand(ap2, c, ap1) ) } @@ -2298,7 +2361,7 @@ module MakeImpl { exists(Ap ap1, Ap ap2 | revFlow(node2, _, _, _, pragma[only_bind_into](ap2)) and readStepFwd(node1, ap1, c, node2, ap2) and - revFlowStore(ap1, c, pragma[only_bind_into](ap2), _, _, _, _, _, _) + revFlowStore(ap1, c, pragma[only_bind_into](ap2), _, _, _, _, _, _, _) ) } @@ -2312,11 +2375,13 @@ module MakeImpl { pragma[nomagic] predicate revFlowAp(NodeEx node, Ap ap) { revFlow(node, _, _, _, ap) } - private predicate fwdConsCand(Content c, Typ t, Ap ap) { storeStepFwd(_, t, ap, c, _, _) } + private predicate fwdConsCand(Content c, Typ t, TypOption origT, Ap ap) { + storeStepFwd(_, t, origT, ap, c, _, _) + } - private predicate revConsCand(Content c, Typ t, Ap ap) { + private predicate revConsCand(Content c, Typ t, TypOption origT, Ap ap) { exists(Ap ap2 | - revFlowStore(ap2, c, ap, t, _, _, _, _, _) and + revFlowStore(ap2, c, ap, t, origT, _, _, _, _, _) and revFlowConsCand(ap2, c, ap) ) } @@ -2325,13 +2390,13 @@ module MakeImpl { revFlow(_, _, _, _, ap) and ap instanceof ApNil or exists(Content head, Typ t, Ap tail | - consCand(head, t, tail) and + consCand(head, t, _, tail) and ap = apCons(head, t, tail) ) } - additional predicate consCand(Content c, Typ t, Ap ap) { - revConsCand(c, t, ap) and + additional predicate consCand(Content c, Typ t, TypOption origT, Ap ap) { + revConsCand(c, t, origT, ap) and validAp(ap) } @@ -2373,7 +2438,7 @@ module MakeImpl { parameterFlowsThroughRev(param, argAp, pos, returnAp) and revFlow(pragma[only_bind_into](node), _, TReturnCtxMaybeFlowThrough(pos), apSome(returnAp), pragma[only_bind_into](ap)) and - fwdFlow(pragma[only_bind_into](node), _, _, TParamNodeSome(p), _, apSome(argAp), _, + fwdFlow(pragma[only_bind_into](node), _, _, TParamNodeSome(p), _, apSome(argAp), _, _, pragma[only_bind_into](ap), _) ) } @@ -2442,19 +2507,19 @@ module MakeImpl { private predicate tuplesFwd(NodeEx node, int c) { c = strictcount(FlowState state, Cc cc, ParamNodeOption summaryCtx, ArgTypOption argT, - ApOption argAp, Typ t, Ap ap | - fwdFlow(node, state, cc, summaryCtx, argT, argAp, t, ap, _) + ApOption argAp, Typ t, TypOption origT, Ap ap | + fwdFlow(node, state, cc, summaryCtx, argT, argAp, t, origT, ap, _) ) } /** A debug predicate for identifying the most busy node in forwards flow. */ additional predicate mostBusyNodeFwd( NodeEx node, int c, FlowState state, Cc cc, ParamNodeOption summaryCtx, ArgTypOption argT, - ApOption argAp, Typ t, Ap ap + ApOption argAp, Typ t, TypOption origT, Ap ap ) { tuplesFwd(node, c) and c = max(int i | tuplesFwd(_, i)) and - fwdFlow(node, state, cc, summaryCtx, argT, argAp, t, ap, _) + fwdFlow(node, state, cc, summaryCtx, argT, argAp, t, origT, ap, _) } pragma[nomagic] @@ -2479,10 +2544,11 @@ module MakeImpl { int tfnodes, int tftuples ) { fwd = true and - nodes = count(NodeEx node | fwdFlow(node, _, _, _, _, _, _, _, _)) and - fields = count(Content f0 | fwdConsCand(f0, _, _)) and - conscand = count(Content f0, Typ t, Ap ap | fwdConsCand(f0, t, ap)) and - states = count(FlowState state | fwdFlow(_, state, _, _, _, _, _, _, _)) and + nodes = count(NodeEx node | fwdFlow(node, _, _, _, _, _, _, _, _, _)) and + fields = count(Content f0 | fwdConsCand(f0, _, _, _)) and + conscand = + count(Content f0, Typ t, TypOption origT, Ap ap | fwdConsCand(f0, t, origT, ap)) and + states = count(FlowState state | fwdFlow(_, state, _, _, _, _, _, _, _, _)) and tuples = count(NodeEx n, int c | tuplesFwd(n, c) | c) and calledges = count(DataFlowCall call, DataFlowCallable c | @@ -2493,8 +2559,8 @@ module MakeImpl { or fwd = false and nodes = count(NodeEx node | revFlow(node, _, _, _, _)) and - fields = count(Content f0 | consCand(f0, _, _)) and - conscand = count(Content f0, Typ t, Ap ap | consCand(f0, t, ap)) and + fields = count(Content f0 | consCand(f0, _, _, _)) and + conscand = count(Content f0, Typ t, TypOption origT, Ap ap | consCand(f0, t, origT, ap)) and states = count(FlowState state | revFlow(_, state, _, _, _)) and tuples = count(NodeEx n, int c | tuplesRev(n, c) | c) and calledges = @@ -3172,7 +3238,8 @@ module MakeImpl { if inSummaryCtx = false and typeStrongerThan(nt, t0) then t = nt else ( - compatibleTypes(nt, t0) and t = t0 + compatibleTypes(nt, t0) and + if inSummaryCtx = true and node instanceof ParamNodeEx then t = nt else t = t0 ) ) else t = t0 @@ -3395,7 +3462,7 @@ module MakeImpl { exists(AccessPathFront apf | Stage4::revFlow(node, state, TReturnCtxMaybeFlowThrough(_), _, apf) and Stage4::fwdFlow(node, state, any(Stage4::CcCall ccc), _, _, TAccessPathFrontSome(argApf), _, - apf, _) + _, apf, _) ) } @@ -3405,7 +3472,7 @@ module MakeImpl { */ private predicate expensiveLen2unfolding(Content c) { exists(int tails, int nodes, int apLimit, int tupleLimit | - tails = strictcount(DataFlowType t, AccessPathFront apf | Stage4::consCand(c, t, apf)) and + tails = strictcount(DataFlowType t, AccessPathFront apf | Stage4::consCand(c, t, _, apf)) and nodes = strictcount(NodeEx n, FlowState state | Stage4::revFlow(n, state, any(AccessPathFrontHead apf | apf.getHead() = c)) @@ -3422,11 +3489,11 @@ module MakeImpl { private newtype TAccessPathApprox = TNil() or TConsNil(Content c, DataFlowType t) { - Stage4::consCand(c, t, TFrontNil()) and + Stage4::consCand(c, t, _, TFrontNil()) and not expensiveLen2unfolding(c) } or TConsCons(Content c1, DataFlowType t, Content c2, int len) { - Stage4::consCand(c1, t, TFrontHead(c2)) and + Stage4::consCand(c1, t, _, TFrontHead(c2)) and len in [2 .. accessPathLimit()] and not expensiveLen2unfolding(c1) } or @@ -3547,7 +3614,7 @@ module MakeImpl { override predicate isCons(Content head, DataFlowType typ, AccessPathApprox tail) { head = c and ( - exists(Content c2 | Stage4::consCand(c, typ, TFrontHead(c2)) | + exists(Content c2 | Stage4::consCand(c, typ, _, TFrontHead(c2)) | tail = TConsCons(c2, _, _, len - 1) or len = 2 and @@ -3557,7 +3624,7 @@ module MakeImpl { ) or len = 1 and - Stage4::consCand(c, typ, TFrontNil()) and + Stage4::consCand(c, typ, _, TFrontNil()) and tail = TNil() ) } @@ -3650,7 +3717,7 @@ module MakeImpl { Stage5::parameterMayFlowThrough(p, _) and Stage5::revFlow(n, state, TReturnCtxMaybeFlowThrough(_), _, apa0) and Stage5::fwdFlow(n, state, any(CallContextCall ccc), TParamNodeSome(p.asNode()), _, - TAccessPathApproxSome(apa), _, apa0, _) + TAccessPathApproxSome(apa), _, _, apa0, _) ) } @@ -3667,7 +3734,8 @@ module MakeImpl { TSummaryCtxSome(ParamNodeEx p, FlowState state, DataFlowType t, AccessPath ap) { exists(AccessPathApprox apa | ap.getApprox() = apa | Stage5::parameterMayFlowThrough(p, apa) and - Stage5::fwdFlow(p, state, _, _, Option::some(_), _, t, apa, _) and + Stage5::fwdFlow1(p, state, _, _, Option::some(_), _, t, _, _, _, apa, _) and + Stage5::fwdFlow1(p, state, _, _, Option::some(_), _, t, _, _, _, apa, _) and Stage5::revFlow(p, state, _) ) } @@ -3716,7 +3784,7 @@ module MakeImpl { len = apa.len() and result = strictcount(DataFlowType t, AccessPathFront apf | - Stage5::consCand(c, t, + Stage5::consCand(c, t, _, any(AccessPathApprox ap | ap.getFront() = apf and ap.len() = len - 1)) ) ) @@ -3746,7 +3814,7 @@ module MakeImpl { private predicate hasTail(AccessPathApprox apa, DataFlowType t, AccessPathApprox tail) { exists(Content head | apa.isCons(head, t, tail) and - Stage5::consCand(head, t, tail) + Stage5::consCand(head, t, _, tail) ) } @@ -3966,7 +4034,7 @@ module MakeImpl { override predicate isCons(Content head, DataFlowType typ, AccessPath tail) { head = head1 and typ = t and - Stage5::consCand(head1, t, tail.getApprox()) and + Stage5::consCand(head1, t, _, tail.getApprox()) and tail.getHead() = head2 and tail.length() = len - 1 } @@ -3999,7 +4067,7 @@ module MakeImpl { override predicate isCons(Content head, DataFlowType typ, AccessPath tail) { head = head_ and - Stage5::consCand(head_, typ, tail.getApprox()) and + Stage5::consCand(head_, typ, _, tail.getApprox()) and tail.length() = len - 1 } From 93f62de4ab8987fa39775075f2c6e73360f915e8 Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Thu, 1 Feb 2024 10:29:42 +0100 Subject: [PATCH 09/19] temp --- .../dataflow/taintsources/local.expected | 2 +- .../codeql/dataflow/internal/DataFlowImpl.qll | 65 +++++-------------- 2 files changed, 16 insertions(+), 51 deletions(-) diff --git a/java/ql/test/library-tests/dataflow/taintsources/local.expected b/java/ql/test/library-tests/dataflow/taintsources/local.expected index 48de9172b362..8ec8033d086e 100644 --- a/java/ql/test/library-tests/dataflow/taintsources/local.expected +++ b/java/ql/test/library-tests/dataflow/taintsources/local.expected @@ -1,2 +1,2 @@ -failures testFailures +failures diff --git a/shared/dataflow/codeql/dataflow/internal/DataFlowImpl.qll b/shared/dataflow/codeql/dataflow/internal/DataFlowImpl.qll index f8d6fbc65822..8153597a4035 100644 --- a/shared/dataflow/codeql/dataflow/internal/DataFlowImpl.qll +++ b/shared/dataflow/codeql/dataflow/internal/DataFlowImpl.qll @@ -1428,26 +1428,18 @@ module MakeImpl { ) or // flow into a callable - exists(Typ t0, TypOption origT0, boolean inSummaryCtx | - fwdFlowIn(node, apa, state, cc, t0, origT0, ap, inSummaryCtx) + exists(boolean inSummaryCtx | + fwdFlowIn(node, apa, state, cc, t, origT, ap, inSummaryCtx) | PrevStage::parameterMayFlowThrough(node, apa) and summaryCtx = TParamNodeSome(node.asNode()) and argT = ArgTypOption::some(toArgTyp(t)) and - argAp = apSome(ap) and - // t = getNodeTyp(node) and - // if origT0.isNone() then origT.asSome() = t0 else origT = origT0 - t = t0 and - origT = origT0 + argAp = apSome(ap) or - // t = t0 and - // origT = origT0 Param::nodeMayFlowNotThrough(node, apa) and summaryCtx = TParamNodeNone() and argT instanceof ArgTypOption::None and argAp = apNone() and - t = t0 and - origT = origT0 and inSummaryCtx = false ) or @@ -1459,12 +1451,12 @@ module MakeImpl { or // flow through a callable exists( - DataFlowCall call, CcCall ccc, ReturnKindExt kind, boolean allowsFieldFlow, + DataFlowCall call, CcCall ccc, RetNodeEx ret, boolean allowsFieldFlow, ApApprox innerArgApa | - fwdFlowThrough(call, cc, state, ccc, summaryCtx, argT, argAp, t, origT, ap, apa, kind, + fwdFlowThrough(call, cc, state, ccc, summaryCtx, argT, argAp, t, origT, ap, apa, ret, innerArgApa) and - flowThroughOutOfCall(call, ccc, kind, node, allowsFieldFlow, innerArgApa, apa) and + flowThroughOutOfCall(call, ccc, ret, _, node, allowsFieldFlow, innerArgApa, apa) and if allowsFieldFlow = false then ap instanceof ApNil else any() ) } @@ -1944,30 +1936,14 @@ module MakeImpl { RetNodeEx ret, FlowState state, CcCall ccc, ParamNodeEx summaryCtx, ArgTyp argT, Ap argAp, ApApprox argApa, Typ t, TypOption origT, Ap ap, ApApprox apa ) { - exists(ReturnKindExt kind | + exists(DataFlowCall call, ReturnKindExt kind, boolean allowsFieldFlow | fwdFlow(pragma[only_bind_into](ret), state, ccc, TParamNodeSome(pragma[only_bind_into](summaryCtx.asNode())), ArgTypOption::some(argT), pragma[only_bind_into](apSome(argAp)), t, origT, ap, pragma[only_bind_into](apa)) and - kind = ret.getKind() and parameterFlowThroughAllowed(summaryCtx, kind) and argApa = getApprox(argAp) and - PrevStage::returnMayFlowThrough(ret, argApa, apa, kind) - ) - } - - pragma[nomagic] - private predicate fwdFlowRetFromArg1( - ReturnKindExt kind, FlowState state, CcCall ccc, ParamNodeEx summaryCtx, ArgTyp argT, - Ap argAp, ApApprox argApa, Typ t, TypOption origT, Ap ap, ApApprox apa - ) { - exists(RetNodeEx ret | - fwdFlow(pragma[only_bind_into](ret), state, ccc, - TParamNodeSome(pragma[only_bind_into](summaryCtx.asNode())), ArgTypOption::some(argT), - pragma[only_bind_into](apSome(argAp)), t, origT, ap, pragma[only_bind_into](apa)) and - kind = ret.getKind() and - parameterFlowThroughAllowed(summaryCtx, kind) and - argApa = getApprox(argAp) and - PrevStage::returnMayFlowThrough(ret, argApa, apa, kind) + flowThroughOutOfCall(call, ccc, ret, kind, _, allowsFieldFlow, argApa, apa) and + if allowsFieldFlow = false then ap instanceof ApNil else any() ) } @@ -1984,26 +1960,13 @@ module MakeImpl { innerArgAp) } - pragma[inline] - private predicate fwdFlowThrough1( - DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, - ArgTypOption argT, ApOption argAp, Typ t, TypOption origT, Ap ap, ApApprox apa, - ReturnKindExt kind, ParamNodeEx innerSummaryCtx, ArgTyp innerArgT, Ap innerArgAp, - ApApprox innerArgApa - ) { - fwdFlowRetFromArg1(kind, state, ccc, innerSummaryCtx, innerArgT, innerArgAp, innerArgApa, - t, origT, ap, apa) and - fwdFlowIsEntered(call, cc, ccc, summaryCtx, argT, argAp, innerSummaryCtx, innerArgT, - innerArgAp) - } - pragma[nomagic] private predicate fwdFlowThrough( DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, ArgTypOption argT, ApOption argAp, Typ t, TypOption origT, Ap ap, ApApprox apa, - ReturnKindExt kind, ApApprox innerArgApa + RetNodeEx ret, ApApprox innerArgApa ) { - fwdFlowThrough1(call, cc, state, ccc, summaryCtx, argT, argAp, t, origT, ap, apa, kind, _, + fwdFlowThrough0(call, cc, state, ccc, summaryCtx, argT, argAp, t, origT, ap, apa, ret, _, _, _, innerArgApa) } @@ -2022,8 +1985,10 @@ module MakeImpl { DataFlowCall call, Cc cc, CcCall innerCc, ParamNodeOption summaryCtx, ArgTypOption argT, ApOption argAp, ParamNodeEx p, ArgTyp t, Ap ap ) { - FwdFlowIn::fwdFlowIn(call, _, p, _, cc, innerCc, summaryCtx, - argT, argAp, any(Typ t0 | t = toArgTyp(t0)), _, ap, _, _) + exists(ApApprox apa | + FwdFlowIn::fwdFlowIn(call, _, p, _, cc, innerCc, summaryCtx, + argT, argAp, any(Typ t0 | t = toArgTyp(t0)), _, ap, apa, _) + ) } pragma[nomagic] From 963c4a1028940ded99301c544b03bae8ff627016 Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Fri, 2 Feb 2024 09:57:55 +0100 Subject: [PATCH 10/19] debug --- .../dataflow/internal/DataFlowDispatch.qll | 25 +++++ .../dataflow/internal/DataFlowPrivate.qll | 6 +- .../code/java/security/TaintedPathQuery.qll | 3 +- .../codeql/dataflow/internal/DataFlowImpl.qll | 91 +++++++++++-------- 4 files changed, 81 insertions(+), 44 deletions(-) diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowDispatch.qll b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowDispatch.qll index a7877fdf2f9d..0e496b5c9cc6 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowDispatch.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowDispatch.qll @@ -33,6 +33,11 @@ private module DispatchImpl { result.asSummarizedCallable().getACall() = c.asCall() } + private DataFlowCallable viableCallable(DataFlowCall c, int k) { + result = viableCallable(c) and + k = strictcount(viableCallable(c)) + } + /** * Holds if the set of viable implementations that can be called by `ma` * might be improved by knowing the call context. This is the case if the @@ -122,6 +127,26 @@ private module DispatchImpl { mayBenefitFromCallContext(call.asCall(), _, _) } + private DataFlowCallable testviableImplInCallContext(DataFlowCall call, DataFlowCall ctx) { + result = viableImplInCallContext(call, ctx) and + call.toString() = "getClassName(...)" + } + + pragma[nomagic] + private predicate foo(DataFlowCall call, DataFlowCall ctx1, DataFlowCall ctx2) { + forex(DataFlowCallable c | c = viableImplInCallContext(call, ctx1) | + c = viableImplInCallContext(call, ctx2) + ) + } + + private DataFlowCallable testviableImplInCallContext( + DataFlowCall call, DataFlowCall ctx1, DataFlowCall ctx2 + ) { + result = viableImplInCallContext(call, ctx1) and + foo(call, ctx1, ctx2) and + foo(call, ctx2, ctx1) + } + /** * Gets a viable dispatch target of `call` in the context `ctx`. This is * restricted to those `call`s for which a context might make a difference. diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowPrivate.qll b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowPrivate.qll index 9d5b92ba3bd7..c02986d7d917 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowPrivate.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowPrivate.qll @@ -391,10 +391,10 @@ class DataFlowType extends SrcRefType { DataFlowType() { this = getErasedRepr(_) } } -pragma[nomagic] -predicate typeStrongerThan(DataFlowType t1, DataFlowType t2) { t1.getASourceSupertype+() = t2 } +// pragma[nomagic] +// predicate typeStrongerThan(DataFlowType t1, DataFlowType t2) { t1.getASourceSupertype+() = t2 } +predicate typeStrongerThan(DataFlowType t1, DataFlowType t2) { none() } -// predicate typeStrongerThan(DataFlowType t1, DataFlowType t2) { none() } pragma[noinline] DataFlowType getNodeType(Node n) { result = getErasedRepr(n.getTypeBound()) diff --git a/java/ql/lib/semmle/code/java/security/TaintedPathQuery.qll b/java/ql/lib/semmle/code/java/security/TaintedPathQuery.qll index 46c1366ae0a6..20529e35620c 100644 --- a/java/ql/lib/semmle/code/java/security/TaintedPathQuery.qll +++ b/java/ql/lib/semmle/code/java/security/TaintedPathQuery.qll @@ -66,7 +66,8 @@ module TaintedPathConfig implements DataFlow::ConfigSig { predicate isBarrier(DataFlow::Node sanitizer) { sanitizer instanceof SimpleTypeSanitizer or - sanitizer instanceof PathInjectionSanitizer + sanitizer instanceof PathInjectionSanitizer or + sanitizer.getLocation().getFile().getBaseName() = "BaseObject.java" } predicate isAdditionalFlowStep(DataFlow::Node n1, DataFlow::Node n2) { diff --git a/shared/dataflow/codeql/dataflow/internal/DataFlowImpl.qll b/shared/dataflow/codeql/dataflow/internal/DataFlowImpl.qll index 8153597a4035..c213641fac05 100644 --- a/shared/dataflow/codeql/dataflow/internal/DataFlowImpl.qll +++ b/shared/dataflow/codeql/dataflow/internal/DataFlowImpl.qll @@ -1342,6 +1342,11 @@ module MakeImpl { fwdFlow1(node, state, cc, summaryCtx, argT, argAp, _, t, _, origT, ap, apa) } + pragma[nomagic] + private ApOption blah(ApApprox apa) { + result = apSome(any(Ap argAp1 | apa = getApprox(argAp1))) + } + pragma[nomagic] additional predicate fwdFlow1( NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ArgTypOption argT, @@ -1353,7 +1358,7 @@ module MakeImpl { ( exists(ParamNode p, ApApprox argApa | summaryCtx = TParamNodeSome(p) and - argAp = apSome(any(Ap argAp1 | argApa = getApprox(argAp1))) and + argAp = blah(argApa) and //apSome(any(Ap argAp1 | argApa = getApprox(argAp1))) and Param::nodeMayFlowThrough(p, argApa, node, apa) and inSummaryCtx = true ) @@ -3188,26 +3193,30 @@ module MakeImpl { private module Stage3 = MkStage::Stage; - // private predicate mostBusyNodeFwd3 = Stage3::mostBusyNodeFwd/9; - // private predicate mostBusyNodeFwd3_5 = Stage3_5::mostBusyNodeFwd/9; - // private predicate mostBusyNodeFwd4 = Stage4::mostBusyNodeFwd/9; - // private predicate mostBusyNodeFwd5 = Stage5::mostBusyNodeFwd/9; + // private predicate mostBusyNodeFwd3 = Stage3::mostBusyNodeFwd/10; + // private predicate mostBusyNodeFwd3_5 = Stage3_5::mostBusyNodeFwd/10; + // private predicate mostBusyNodeFwd4 = Stage4::mostBusyNodeFwd/10; + private predicate mostBusyNodeFwd5 = Stage5::mostBusyNodeFwd/10; + bindingset[node, t0, inSummaryCtx] private predicate strengthenType( NodeEx node, DataFlowType t0, DataFlowType t, boolean inSummaryCtx ) { exists(inSummaryCtx) and - if castingNodeEx(node) - then - exists(DataFlowType nt | nt = node.getDataFlowType() | - if inSummaryCtx = false and typeStrongerThan(nt, t0) - then t = nt - else ( - compatibleTypes(nt, t0) and - if inSummaryCtx = true and node instanceof ParamNodeEx then t = nt else t = t0 + if node instanceof RetNodeEx and inSummaryCtx = true + then t = node.getDataFlowType() and compatibleTypes(t, t0) + else + if castingNodeEx(node) + then + exists(DataFlowType nt | nt = node.getDataFlowType() | + if inSummaryCtx = false and typeStrongerThan(nt, t0) + then t = nt + else ( + compatibleTypes(nt, t0) and + if inSummaryCtx = true and node instanceof ParamNodeEx then t = nt else t = t0 + ) ) - ) - else t = t0 + else t = t0 } private module Stage3_5Param implements MkStage::StageParam { @@ -3631,11 +3640,12 @@ module MakeImpl { ApHeadContent projectToHeadContent(Content c) { result = c } - class ApOption = AccessPathApproxOption; + class ApOption = AccessPathFrontOption; - ApOption apNone() { result = TAccessPathApproxNone() } + // class ApOption = AccessPathApproxOption; + ApOption apNone() { result = TAccessPathFrontNone() } - ApOption apSome(Ap ap) { result = TAccessPathApproxSome(ap) } + ApOption apSome(Ap ap) { result = TAccessPathFrontSome(ap.getFront()) } import Level1CallContext import LocalCallContext @@ -3670,6 +3680,8 @@ module MakeImpl { predicate typecheckStore(Typ typ, DataFlowType contentType) { compatibleTypes(typ, contentType) } + + predicate enableTypeFlow() { none() } } private module Stage5 = MkStage::Stage; @@ -3682,7 +3694,7 @@ module MakeImpl { Stage5::parameterMayFlowThrough(p, _) and Stage5::revFlow(n, state, TReturnCtxMaybeFlowThrough(_), _, apa0) and Stage5::fwdFlow(n, state, any(CallContextCall ccc), TParamNodeSome(p.asNode()), _, - TAccessPathApproxSome(apa), _, _, apa0, _) + TAccessPathFrontSome(apa.getFront()), _, _, apa0, _) ) } @@ -4412,28 +4424,22 @@ module MakeImpl { PathNodeMid mid, NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, DataFlowType t, AccessPath ap ) { - exists(DataFlowType t0, SummaryCtx sc0, Stage5::Ap apa, boolean inSummaryCtx | - pathStep0(mid, node, state, cc, sc0, t0, ap, apa) and + exists(DataFlowType t0, Stage5::Ap apa, boolean inSummaryCtx | + pathStep0(mid, node, state, cc, sc, t0, ap, apa) and Stage5::revFlow(node, state, apa) and strengthenType(node, t0, t, inSummaryCtx) and not inBarrier(node, state) | exists(ParamNodeEx p, ParamNode param, AccessPath argAp, Stage5::Ap argApa | - sc0 = TSummaryCtxSome(p, _, _, argAp) and + sc = TSummaryCtxSome(p, _, _, argAp) and param = p.asNode() and argApa = argAp.getApprox() and - if Stage5::nodeMayFlowThrough(param, argApa, node, apa) - then - sc = sc0 and - inSummaryCtx = true - else ( - sc = TSummaryCtxNone() and - inSummaryCtx = false - ) + Stage5::nodeMayFlowThrough(param, argApa, node, apa) and + inSummaryCtx = true ) or - sc0 = TSummaryCtxNone() and - sc = sc0 and + sc = TSummaryCtxNone() and + (cc instanceof CallContextNoCall or Stage5::nodeMayFlowNotThrough(node, apa)) and inSummaryCtx = false ) } @@ -4587,14 +4593,15 @@ module MakeImpl { pragma[noinline] private predicate pathIntoArg( PathNodeMid mid, ParameterPosition ppos, FlowState state, CallContext cc, DataFlowCall call, - DataFlowType t, AccessPath ap, AccessPathApprox apa + DataFlowType t, AccessPath ap, AccessPathApprox apa, boolean inSummaryCtx ) { - exists(ArgNodeEx arg, ArgumentPosition apos | - pathNode(mid, arg, state, cc, _, t, ap, _) and + exists(ArgNodeEx arg, SummaryCtx sc, ArgumentPosition apos | + pathNode(mid, arg, state, cc, sc, t, ap, _) and not outBarrier(arg, state) and arg.asNode().(ArgNode).argumentOf(call, apos) and apa = ap.getApprox() and - parameterMatch(ppos, apos) + parameterMatch(ppos, apos) and + if sc = TSummaryCtxNone() then inSummaryCtx = false else inSummaryCtx = true ) } @@ -4613,11 +4620,11 @@ module MakeImpl { pragma[nomagic] private predicate pathIntoCallable0( PathNodeMid mid, DataFlowCallable callable, ParameterPosition pos, FlowState state, - CallContext outercc, DataFlowCall call, DataFlowType t, AccessPath ap + CallContext outercc, DataFlowCall call, DataFlowType t, AccessPath ap, boolean inSummaryCtx ) { exists(AccessPathApprox apa | pathIntoArg(mid, pragma[only_bind_into](pos), state, outercc, call, t, ap, - pragma[only_bind_into](apa)) and + pragma[only_bind_into](apa), inSummaryCtx) and callable = ResolveCall::resolveCall(call, outercc) and parameterCand(callable, pragma[only_bind_into](pos), pragma[only_bind_into](apa)) ) @@ -4633,13 +4640,17 @@ module MakeImpl { PathNodeMid mid, ParamNodeEx p, FlowState state, CallContext outercc, CallContextCall innercc, SummaryCtx sc, DataFlowCall call ) { - exists(ParameterPosition pos, DataFlowCallable callable, DataFlowType t, AccessPath ap | - pathIntoCallable0(mid, callable, pos, state, outercc, call, t, ap) and + exists( + ParameterPosition pos, DataFlowCallable callable, DataFlowType t, AccessPath ap, + boolean inSummaryCtx + | + pathIntoCallable0(mid, callable, pos, state, outercc, call, t, ap, inSummaryCtx) and p.isParameterOf(callable, pos) and not inBarrier(p, state) and ( sc = TSummaryCtxSome(p, state, t, ap) or + inSummaryCtx = false and // not exists(TSummaryCtxSome(p, state, t, ap)) and Stage5::nodeMayFlowNotThrough(p, ap.getApprox()) and sc = TSummaryCtxNone() and From fff4e2d668f7f3d330797fbfe17e4ddd2e728878 Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Wed, 7 Feb 2024 13:50:25 +0100 Subject: [PATCH 11/19] debug --- .../dataflow/internal/DataFlowPrivate.qll | 6 +++ .../code/java/security/TaintedPathQuery.qll | 3 +- .../codeql/dataflow/internal/DataFlowImpl.qll | 38 ++++++++++++------- 3 files changed, 33 insertions(+), 14 deletions(-) diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowPrivate.qll b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowPrivate.qll index c02986d7d917..04a09bcc5ee4 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowPrivate.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowPrivate.qll @@ -414,6 +414,12 @@ private predicate compatibleTypes0(DataFlowType t1, DataFlowType t2) { erasedHaveIntersection(t1, t2) } +private predicate sdef(DataFlowType t1, DataFlowType t2) { + t1.toString() = "String" and + t2.toString() = "ArrayList" and + compatibleTypes(t1, t2) +} + /** * Holds if `t1` and `t2` are compatible, that is, whether data can flow from * a node of type `t1` to a node of type `t2`. diff --git a/java/ql/lib/semmle/code/java/security/TaintedPathQuery.qll b/java/ql/lib/semmle/code/java/security/TaintedPathQuery.qll index 20529e35620c..1cf6bc54c5de 100644 --- a/java/ql/lib/semmle/code/java/security/TaintedPathQuery.qll +++ b/java/ql/lib/semmle/code/java/security/TaintedPathQuery.qll @@ -67,7 +67,8 @@ module TaintedPathConfig implements DataFlow::ConfigSig { predicate isBarrier(DataFlow::Node sanitizer) { sanitizer instanceof SimpleTypeSanitizer or sanitizer instanceof PathInjectionSanitizer or - sanitizer.getLocation().getFile().getBaseName() = "BaseObject.java" + sanitizer.getLocation().getFile().getBaseName() = + ["BaseObject.java", "SimpleNode.java", "Context.java"] } predicate isAdditionalFlowStep(DataFlow::Node n1, DataFlow::Node n2) { diff --git a/shared/dataflow/codeql/dataflow/internal/DataFlowImpl.qll b/shared/dataflow/codeql/dataflow/internal/DataFlowImpl.qll index c213641fac05..7a46a72c1d28 100644 --- a/shared/dataflow/codeql/dataflow/internal/DataFlowImpl.qll +++ b/shared/dataflow/codeql/dataflow/internal/DataFlowImpl.qll @@ -3203,20 +3203,32 @@ module MakeImpl { NodeEx node, DataFlowType t0, DataFlowType t, boolean inSummaryCtx ) { exists(inSummaryCtx) and - if node instanceof RetNodeEx and inSummaryCtx = true - then t = node.getDataFlowType() and compatibleTypes(t, t0) - else - if castingNodeEx(node) - then - exists(DataFlowType nt | nt = node.getDataFlowType() | - if inSummaryCtx = false and typeStrongerThan(nt, t0) - then t = nt - else ( - compatibleTypes(nt, t0) and - if inSummaryCtx = true and node instanceof ParamNodeEx then t = nt else t = t0 - ) + // if node instanceof RetNodeEx and inSummaryCtx = true + // then t = node.getDataFlowType() and compatibleTypes(t, t0) + // else + // if castingNodeEx(node) + // then + // exists(DataFlowType nt | nt = node.getDataFlowType() | + // if inSummaryCtx = false and typeStrongerThan(nt, t0) + // then t = nt + // else ( + // compatibleTypes(nt, t0) and + // if inSummaryCtx = true and node instanceof ParamNodeEx then t = nt else t = t0 + // ) + // ) + // else t = t0 + if castingNodeEx(node) + then + exists(DataFlowType nt | nt = node.getDataFlowType() | + if inSummaryCtx = false and typeStrongerThan(nt, t0) + then t = nt + else ( + compatibleTypes(nt, t0) and + // t = t0 + if inSummaryCtx = true and node instanceof ParamNodeEx then t = nt else t = t0 ) - else t = t0 + ) + else t = t0 } private module Stage3_5Param implements MkStage::StageParam { From bc4462eb4756cf0778ded4c95c928e527dd66c64 Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Thu, 8 Feb 2024 15:00:41 +0100 Subject: [PATCH 12/19] works --- .../dataflow/internal/DataFlowPrivate.qll | 6 +- .../codeql/dataflow/internal/DataFlowImpl.qll | 97 +++++++++++++------ 2 files changed, 72 insertions(+), 31 deletions(-) diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowPrivate.qll b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowPrivate.qll index 04a09bcc5ee4..a1f5124454db 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowPrivate.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowPrivate.qll @@ -391,10 +391,10 @@ class DataFlowType extends SrcRefType { DataFlowType() { this = getErasedRepr(_) } } -// pragma[nomagic] -// predicate typeStrongerThan(DataFlowType t1, DataFlowType t2) { t1.getASourceSupertype+() = t2 } -predicate typeStrongerThan(DataFlowType t1, DataFlowType t2) { none() } +pragma[nomagic] +predicate typeStrongerThan(DataFlowType t1, DataFlowType t2) { t1.getASourceSupertype+() = t2 } +// predicate typeStrongerThan(DataFlowType t1, DataFlowType t2) { none() } pragma[noinline] DataFlowType getNodeType(Node n) { result = getErasedRepr(n.getTypeBound()) diff --git a/shared/dataflow/codeql/dataflow/internal/DataFlowImpl.qll b/shared/dataflow/codeql/dataflow/internal/DataFlowImpl.qll index 7a46a72c1d28..21a017449662 100644 --- a/shared/dataflow/codeql/dataflow/internal/DataFlowImpl.qll +++ b/shared/dataflow/codeql/dataflow/internal/DataFlowImpl.qll @@ -1278,8 +1278,10 @@ module MakeImpl { bindingset[node, ap] predicate nodeMayFlowNotThrough(NodeEx node, ApApprox ap); - bindingset[node, state, t0, ap, inSummaryCtx] - predicate filter(NodeEx node, FlowState state, Typ t0, Ap ap, Typ t, boolean inSummaryCtx); + bindingset[node, state, origT, t0, ap, inSummaryCtx] + predicate filter( + NodeEx node, FlowState state, Typ origT, Typ t0, Ap ap, Typ t, boolean inSummaryCtx + ); bindingset[typ, contentType] predicate typecheckStore(Typ typ, DataFlowType contentType); @@ -1367,7 +1369,13 @@ module MakeImpl { (cc instanceof CcNoCall or Param::nodeMayFlowNotThrough(node, apa)) and inSummaryCtx = false ) and - filter(node, state, t0, ap, t, inSummaryCtx) and + exists(Typ origT1 | + origT1 = origT0.asSome() + or + origT0.isNone() and origT1 = t0 + | + filter(node, state, origT1, t0, ap, t, inSummaryCtx) + ) and // origT.asSome() = t if t != t0 and origT0.isNone() and not ap instanceof ApNil then origT.asSome() = t0 @@ -2395,6 +2403,21 @@ module MakeImpl { ) } + pragma[nomagic] + private predicate nodeMayFlowThrough0( + ParamNode p, Ap argAp, ApOption argApO, ReturnPosition pos, Ap returnAp, + ApOption returnApO + ) { + // revFlow(node, _, TReturnCtxMaybeFlowThrough(_), _, ap) + exists(ParamNodeEx param | + p = param.asNode() and + returnFlowsThrough(_, pos, _, _, param, _, argAp, returnAp) and + parameterFlowsThroughRev(param, argAp, pos, returnAp) and + argApO = apSome(argAp) and + returnApO = apSome(returnAp) + ) + } + // pragma[nomagic] // predicate nodeMayFlowThrough(NodeEx node, Ap ap) { // revFlow(node, _, TReturnCtxMaybeFlowThrough(_), _, ap) @@ -2402,13 +2425,11 @@ module MakeImpl { pragma[nomagic] additional predicate nodeMayFlowThrough(ParamNode p, Ap argAp, NodeEx node, Ap ap) { // revFlow(node, _, TReturnCtxMaybeFlowThrough(_), _, ap) - exists(ReturnPosition pos, Ap returnAp, ParamNodeEx param | - p = param.asNode() and - returnFlowsThrough(_, pos, _, _, param, _, argAp, returnAp) and - parameterFlowsThroughRev(param, argAp, pos, returnAp) and - revFlow(pragma[only_bind_into](node), _, TReturnCtxMaybeFlowThrough(pos), - apSome(returnAp), pragma[only_bind_into](ap)) and - fwdFlow(pragma[only_bind_into](node), _, _, TParamNodeSome(p), _, apSome(argAp), _, _, + exists(ApOption argApO, ReturnPosition pos, Ap returnAp, ApOption returnApO | + nodeMayFlowThrough0(p, argAp, argApO, pos, returnAp, returnApO) and + revFlow(pragma[only_bind_into](node), _, TReturnCtxMaybeFlowThrough(pos), returnApO, + pragma[only_bind_into](ap)) and + fwdFlow(pragma[only_bind_into](node), _, _, TParamNodeSome(p), _, argApO, _, _, pragma[only_bind_into](ap), _) ) } @@ -2745,9 +2766,12 @@ module MakeImpl { ) } - bindingset[node, state, t0, ap, inSummaryCtx] - predicate filter(NodeEx node, FlowState state, Typ t0, Ap ap, Typ t, boolean inSummaryCtx) { + bindingset[node, state, origT, t0, ap, inSummaryCtx] + predicate filter( + NodeEx node, FlowState state, Typ origT, Typ t0, Ap ap, Typ t, boolean inSummaryCtx + ) { PrevStage::revFlowState(state) and + exists(origT) and t0 = t and exists(ap) and not stateBarrier(node, state) and @@ -3079,9 +3103,12 @@ module MakeImpl { ) } - bindingset[node, state, t0, ap, inSummaryCtx] - predicate filter(NodeEx node, FlowState state, Typ t0, Ap ap, Typ t, boolean inSummaryCtx) { + bindingset[node, state, origT, t0, ap, inSummaryCtx] + predicate filter( + NodeEx node, FlowState state, Typ origT, Typ t0, Ap ap, Typ t, boolean inSummaryCtx + ) { exists(state) and + exists(origT) and t0 = t and exists(ap) and not stateBarrier(node, state) and @@ -3165,9 +3192,12 @@ module MakeImpl { ) } - bindingset[node, state, t0, ap, inSummaryCtx] - predicate filter(NodeEx node, FlowState state, Typ t0, Ap ap, Typ t, boolean inSummaryCtx) { + bindingset[node, state, origT, t0, ap, inSummaryCtx] + predicate filter( + NodeEx node, FlowState state, Typ origT, Typ t0, Ap ap, Typ t, boolean inSummaryCtx + ) { exists(state) and + exists(origT) and // We can get away with not using type strengthening here, since we aren't // going to use the tracked types in the construction of Stage 4 access // paths. For Stage 4 and onwards, the tracked types must be consistent as @@ -3200,7 +3230,7 @@ module MakeImpl { bindingset[node, t0, inSummaryCtx] private predicate strengthenType( - NodeEx node, DataFlowType t0, DataFlowType t, boolean inSummaryCtx + NodeEx node, DataFlowType origT, DataFlowType t0, DataFlowType t, boolean inSummaryCtx ) { exists(inSummaryCtx) and // if node instanceof RetNodeEx and inSummaryCtx = true @@ -3225,7 +3255,11 @@ module MakeImpl { else ( compatibleTypes(nt, t0) and // t = t0 - if inSummaryCtx = true and node instanceof ParamNodeEx then t = nt else t = t0 + if inSummaryCtx = true and node instanceof ParamNodeEx + then + t = nt and + compatibleTypes(origT, t) + else t = t0 ) ) else t = t0 @@ -3312,9 +3346,12 @@ module MakeImpl { ) } - bindingset[node, state, t0, ap, inSummaryCtx] - predicate filter(NodeEx node, FlowState state, Typ t0, Ap ap, Typ t, boolean inSummaryCtx) { + bindingset[node, state, origT, t0, ap, inSummaryCtx] + predicate filter( + NodeEx node, FlowState state, Typ origT, Typ t0, Ap ap, Typ t, boolean inSummaryCtx + ) { exists(state) and + exists(origT) and not clear(node, ap) and t0 = t and (if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), t0) else any()) and @@ -3416,11 +3453,13 @@ module MakeImpl { ) } - bindingset[node, state, t0, ap, inSummaryCtx] - predicate filter(NodeEx node, FlowState state, Typ t0, Ap ap, Typ t, boolean inSummaryCtx) { + bindingset[node, state, origT, t0, ap, inSummaryCtx] + predicate filter( + NodeEx node, FlowState state, Typ origT, Typ t0, Ap ap, Typ t, boolean inSummaryCtx + ) { exists(state) and not clear(node, ap) and - strengthenType(node, t0, t, inSummaryCtx) and + strengthenType(node, origT, t0, t, inSummaryCtx) and ( notExpectsContent(node) or @@ -3681,9 +3720,11 @@ module MakeImpl { PrevStage::nodeMayFlowNotThrough(node, ap) } - bindingset[node, state, t0, ap, inSummaryCtx] - predicate filter(NodeEx node, FlowState state, Typ t0, Ap ap, Typ t, boolean inSummaryCtx) { - strengthenType(node, t0, t, inSummaryCtx) and + bindingset[node, state, origT, t0, ap, inSummaryCtx] + predicate filter( + NodeEx node, FlowState state, Typ origT, Typ t0, Ap ap, Typ t, boolean inSummaryCtx + ) { + strengthenType(node, origT, t0, t, inSummaryCtx) and exists(state) and exists(ap) } @@ -4439,7 +4480,7 @@ module MakeImpl { exists(DataFlowType t0, Stage5::Ap apa, boolean inSummaryCtx | pathStep0(mid, node, state, cc, sc, t0, ap, apa) and Stage5::revFlow(node, state, apa) and - strengthenType(node, t0, t, inSummaryCtx) and + strengthenType(node, t0, t0, t, inSummaryCtx) and not inBarrier(node, state) | exists(ParamNodeEx p, ParamNode param, AccessPath argAp, Stage5::Ap argApa | @@ -5204,7 +5245,7 @@ module MakeImpl { ) and exists(boolean inSummaryCtx | (if sc1 = TSummaryCtx1None() then inSummaryCtx = false else inSummaryCtx = true) and - strengthenType(node, t0, t, inSummaryCtx) + strengthenType(node, t0, t0, t, inSummaryCtx) ) } From aae8079b5583b280d7f5ac705199a5dbe12b3901 Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Fri, 9 Feb 2024 10:08:51 +0100 Subject: [PATCH 13/19] temp --- .../code/java/security/TaintedPathQuery.qll | 6 ++--- .../dataflow/call-sensitivity/flow.expected | 20 +++++++------- .../codeql/dataflow/internal/DataFlowImpl.qll | 27 ++++++++++--------- 3 files changed, 28 insertions(+), 25 deletions(-) diff --git a/java/ql/lib/semmle/code/java/security/TaintedPathQuery.qll b/java/ql/lib/semmle/code/java/security/TaintedPathQuery.qll index 1cf6bc54c5de..2ae8b124a3c1 100644 --- a/java/ql/lib/semmle/code/java/security/TaintedPathQuery.qll +++ b/java/ql/lib/semmle/code/java/security/TaintedPathQuery.qll @@ -66,9 +66,9 @@ module TaintedPathConfig implements DataFlow::ConfigSig { predicate isBarrier(DataFlow::Node sanitizer) { sanitizer instanceof SimpleTypeSanitizer or - sanitizer instanceof PathInjectionSanitizer or - sanitizer.getLocation().getFile().getBaseName() = - ["BaseObject.java", "SimpleNode.java", "Context.java"] + sanitizer instanceof PathInjectionSanitizer //or + // sanitizer.getLocation().getFile().getBaseName() = + // ["BaseObject.java", "SimpleNode.java", "Context.java"] } predicate isAdditionalFlowStep(DataFlow::Node n1, DataFlow::Node n2) { diff --git a/java/ql/test/library-tests/dataflow/call-sensitivity/flow.expected b/java/ql/test/library-tests/dataflow/call-sensitivity/flow.expected index e01b3dac1cca..3bb82f254e12 100644 --- a/java/ql/test/library-tests/dataflow/call-sensitivity/flow.expected +++ b/java/ql/test/library-tests/dataflow/call-sensitivity/flow.expected @@ -36,8 +36,8 @@ edges ======= | A2.java:15:15:15:28 | new Integer(...) : Number | A2.java:27:27:27:34 | o : Number | | A2.java:27:27:27:34 | o : Number | A2.java:29:9:29:9 | o | -| A.java:6:28:6:35 | o : Object | A.java:8:11:8:11 | o : Object | -| A.java:6:28:6:35 | o : Object | A.java:8:11:8:11 | o : Object | +| A.java:6:28:6:35 | o : Number | A.java:8:11:8:11 | o : Number | +| A.java:6:28:6:35 | o : Number | A.java:8:11:8:11 | o : Number | | A.java:14:29:14:36 | o : Number | A.java:16:9:16:9 | o | | A.java:20:30:20:37 | o : Number | A.java:22:9:22:9 | o | | A.java:26:31:26:38 | o : Number | A.java:28:9:28:9 | o | @@ -52,14 +52,14 @@ edges | A.java:66:25:66:38 | new Integer(...) : Number | A.java:43:36:43:43 | o : Number | | A.java:67:25:67:38 | new Integer(...) : Number | A.java:43:36:43:43 | o : Number | | A.java:68:25:68:38 | new Integer(...) : Number | A.java:43:36:43:43 | o : Number | -| A.java:69:20:69:33 | new Integer(...) : Number | A.java:6:28:6:35 | o : Object | +| A.java:69:20:69:33 | new Integer(...) : Number | A.java:6:28:6:35 | o : Number | | A.java:69:20:69:33 | new Integer(...) : Number | A.java:69:8:69:40 | flowThrough(...) | | A.java:71:25:71:38 | new Integer(...) : Number | A.java:43:36:43:43 | o : Number | | A.java:84:18:84:31 | new Integer(...) : Number | A.java:14:29:14:36 | o : Number | | A.java:85:19:85:32 | new Integer(...) : Number | A.java:20:30:20:37 | o : Number | | A.java:86:20:86:33 | new Integer(...) : Number | A.java:26:31:26:38 | o : Number | | A.java:87:24:87:37 | new Integer(...) : Number | A.java:32:35:32:42 | o : Number | -| A.java:88:20:88:33 | new Integer(...) : Number | A.java:6:28:6:35 | o : Object | +| A.java:88:20:88:33 | new Integer(...) : Number | A.java:6:28:6:35 | o : Number | | A.java:88:20:88:33 | new Integer(...) : Number | A.java:88:8:88:37 | flowThrough(...) | | A.java:99:20:99:33 | new Integer(...) : Number | A.java:106:30:106:37 | o : Number | | A.java:100:21:100:34 | new Integer(...) : Number | A.java:113:31:113:38 | o : Number | @@ -72,10 +72,10 @@ nodes | A2.java:15:15:15:28 | new Integer(...) : Number | semmle.label | new Integer(...) : Number | | A2.java:27:27:27:34 | o : Number | semmle.label | o : Number | | A2.java:29:9:29:9 | o | semmle.label | o | -| A.java:6:28:6:35 | o : Object | semmle.label | o : Object | -| A.java:6:28:6:35 | o : Object | semmle.label | o : Object | -| A.java:8:11:8:11 | o : Object | semmle.label | o : Object | -| A.java:8:11:8:11 | o : Object | semmle.label | o : Object | +| A.java:6:28:6:35 | o : Number | semmle.label | o : Number | +| A.java:6:28:6:35 | o : Number | semmle.label | o : Number | +| A.java:8:11:8:11 | o : Number | semmle.label | o : Number | +| A.java:8:11:8:11 | o : Number | semmle.label | o : Number | | A.java:14:29:14:36 | o : Number | semmle.label | o : Number | | A.java:16:9:16:9 | o | semmle.label | o | | A.java:20:30:20:37 | o : Number | semmle.label | o : Number | @@ -114,8 +114,8 @@ nodes | A.java:120:36:120:43 | o : Number | semmle.label | o : Number | | A.java:128:9:128:10 | o3 | semmle.label | o3 | subpaths -| A.java:69:20:69:33 | new Integer(...) : Number | A.java:6:28:6:35 | o : Object | A.java:8:11:8:11 | o : Object | A.java:69:8:69:40 | flowThrough(...) | -| A.java:88:20:88:33 | new Integer(...) : Number | A.java:6:28:6:35 | o : Object | A.java:8:11:8:11 | o : Object | A.java:88:8:88:37 | flowThrough(...) | +| A.java:69:20:69:33 | new Integer(...) : Number | A.java:6:28:6:35 | o : Number | A.java:8:11:8:11 | o : Number | A.java:69:8:69:40 | flowThrough(...) | +| A.java:88:20:88:33 | new Integer(...) : Number | A.java:6:28:6:35 | o : Number | A.java:8:11:8:11 | o : Number | A.java:88:8:88:37 | flowThrough(...) | #select | A2.java:15:15:15:28 | new Integer(...) : Number | A2.java:15:15:15:28 | new Integer(...) : Number | A2.java:29:9:29:9 | o | $@ | A2.java:29:9:29:9 | o | o | | A.java:62:18:62:31 | new Integer(...) : Number | A.java:62:18:62:31 | new Integer(...) : Number | A.java:16:9:16:9 | o | $@ | A.java:16:9:16:9 | o | o | diff --git a/shared/dataflow/codeql/dataflow/internal/DataFlowImpl.qll b/shared/dataflow/codeql/dataflow/internal/DataFlowImpl.qll index 21a017449662..d520f35ebfbd 100644 --- a/shared/dataflow/codeql/dataflow/internal/DataFlowImpl.qll +++ b/shared/dataflow/codeql/dataflow/internal/DataFlowImpl.qll @@ -3228,11 +3228,12 @@ module MakeImpl { // private predicate mostBusyNodeFwd4 = Stage4::mostBusyNodeFwd/10; private predicate mostBusyNodeFwd5 = Stage5::mostBusyNodeFwd/10; - bindingset[node, t0, inSummaryCtx] + bindingset[node, origT, t0, inSummaryCtx] private predicate strengthenType( NodeEx node, DataFlowType origT, DataFlowType t0, DataFlowType t, boolean inSummaryCtx ) { exists(inSummaryCtx) and + exists(origT) and // if node instanceof RetNodeEx and inSummaryCtx = true // then t = node.getDataFlowType() and compatibleTypes(t, t0) // else @@ -3254,12 +3255,7 @@ module MakeImpl { then t = nt else ( compatibleTypes(nt, t0) and - // t = t0 - if inSummaryCtx = true and node instanceof ParamNodeEx - then - t = nt and - compatibleTypes(origT, t) - else t = t0 + t = t0 ) ) else t = t0 @@ -3545,6 +3541,7 @@ module MakeImpl { abstract AccessPathFront getFront(); /** Holds if this is a representation of `head` followed by the `typ,tail` pair. */ + bindingset[head, typ, tail] abstract predicate isCons(Content head, DataFlowType typ, AccessPathApprox tail); } @@ -3557,6 +3554,7 @@ module MakeImpl { override AccessPathFront getFront() { result = TFrontNil() } + bindingset[head, typ, tail] override predicate isCons(Content head, DataFlowType typ, AccessPathApprox tail) { none() } } @@ -3579,6 +3577,7 @@ module MakeImpl { override AccessPathFront getFront() { result = TFrontHead(c) } + bindingset[head, typ, tail] override predicate isCons(Content head, DataFlowType typ, AccessPathApprox tail) { head = c and typ = t and tail = TNil() } @@ -3604,6 +3603,7 @@ module MakeImpl { override AccessPathFront getFront() { result = TFrontHead(c1) } + bindingset[head, typ, tail] override predicate isCons(Content head, DataFlowType typ, AccessPathApprox tail) { head = c1 and typ = t and @@ -3636,6 +3636,7 @@ module MakeImpl { override AccessPathFront getFront() { result = TFrontHead(c) } + bindingset[head, typ, tail] override predicate isCons(Content head, DataFlowType typ, AccessPathApprox tail) { head = c and ( @@ -3691,13 +3692,15 @@ module MakeImpl { ApHeadContent projectToHeadContent(Content c) { result = c } - class ApOption = AccessPathFrontOption; + // class ApOption = AccessPathFrontOption; + class ApOption = AccessPathApproxOption; - // class ApOption = AccessPathApproxOption; - ApOption apNone() { result = TAccessPathFrontNone() } + ApOption apNone() { result = TAccessPathApproxNone() } - ApOption apSome(Ap ap) { result = TAccessPathFrontSome(ap.getFront()) } + ApOption apSome(Ap ap) { result = TAccessPathApproxSome(ap) } + // ApOption apNone() { result = TAccessPathFrontNone() } + // ApOption apSome(Ap ap) { result = TAccessPathFrontSome(ap.getFront()) } import Level1CallContext import LocalCallContext @@ -3747,7 +3750,7 @@ module MakeImpl { Stage5::parameterMayFlowThrough(p, _) and Stage5::revFlow(n, state, TReturnCtxMaybeFlowThrough(_), _, apa0) and Stage5::fwdFlow(n, state, any(CallContextCall ccc), TParamNodeSome(p.asNode()), _, - TAccessPathFrontSome(apa.getFront()), _, _, apa0, _) + TAccessPathApproxSome(apa), _, _, apa0, _) ) } From 705243be30e178db948ae2b5efa179158a68d762 Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Fri, 9 Feb 2024 12:29:13 +0100 Subject: [PATCH 14/19] temp --- shared/dataflow/codeql/dataflow/internal/DataFlowImpl.qll | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/shared/dataflow/codeql/dataflow/internal/DataFlowImpl.qll b/shared/dataflow/codeql/dataflow/internal/DataFlowImpl.qll index d520f35ebfbd..ce181f708004 100644 --- a/shared/dataflow/codeql/dataflow/internal/DataFlowImpl.qll +++ b/shared/dataflow/codeql/dataflow/internal/DataFlowImpl.qll @@ -3255,7 +3255,12 @@ module MakeImpl { then t = nt else ( compatibleTypes(nt, t0) and - t = t0 + // t = t0 + if inSummaryCtx = true and node instanceof ParamNodeEx + then + t = nt and + compatibleTypes(origT, t) + else t = t0 ) ) else t = t0 From 7766b709a913498afcb5a26d4c53672f16b4e994 Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Mon, 12 Feb 2024 13:07:10 +0100 Subject: [PATCH 15/19] temp --- .../codeql/dataflow/internal/DataFlowImpl.qll | 133 +++++++++++------- 1 file changed, 84 insertions(+), 49 deletions(-) diff --git a/shared/dataflow/codeql/dataflow/internal/DataFlowImpl.qll b/shared/dataflow/codeql/dataflow/internal/DataFlowImpl.qll index ce181f708004..240465842fbb 100644 --- a/shared/dataflow/codeql/dataflow/internal/DataFlowImpl.qll +++ b/shared/dataflow/codeql/dataflow/internal/DataFlowImpl.qll @@ -1310,7 +1310,7 @@ module MakeImpl { PrevStage::revFlow(node) and result = getTyp(node.getDataFlowType()) } - pragma[inline] + pragma[nomagic] private predicate flowThroughOutOfCall( DataFlowCall call, CcCall ccc, RetNodeEx ret, ReturnKindExt kind, NodeEx out, boolean allowsFieldFlow, ApApprox argApa, ApApprox apa @@ -1321,14 +1321,13 @@ module MakeImpl { matchesCall(ccc, call) } - pragma[nomagic] - private predicate flowThroughOutOfCall( - DataFlowCall call, CcCall ccc, ReturnKindExt kind, NodeEx out, boolean allowsFieldFlow, - ApApprox argApa, ApApprox apa - ) { - flowThroughOutOfCall(call, ccc, _, kind, out, allowsFieldFlow, argApa, apa) - } - + // pragma[nomagic] + // private predicate flowThroughOutOfCall( + // DataFlowCall call, CcCall ccc, ReturnKindExt kind, NodeEx out, boolean allowsFieldFlow, + // ApApprox argApa, ApApprox apa + // ) { + // flowThroughOutOfCall(call, ccc, _, kind, out, allowsFieldFlow, argApa, apa) + // } /** * Holds if `node` is reachable with access path `ap` from a source. * @@ -1441,10 +1440,10 @@ module MakeImpl { ) or // flow into a callable - exists(boolean inSummaryCtx | - fwdFlowIn(node, apa, state, cc, t, origT, ap, inSummaryCtx) + exists(boolean inSummaryCtx, boolean allowsFlowThrough | + fwdFlowIn(node, apa, state, cc, t, origT, ap, inSummaryCtx, allowsFlowThrough) | - PrevStage::parameterMayFlowThrough(node, apa) and + allowsFlowThrough = true and summaryCtx = TParamNodeSome(node.asNode()) and argT = ArgTypOption::some(toArgTyp(t)) and argAp = apSome(ap) @@ -1468,9 +1467,8 @@ module MakeImpl { ApApprox innerArgApa | fwdFlowThrough(call, cc, state, ccc, summaryCtx, argT, argAp, t, origT, ap, apa, ret, - innerArgApa) and - flowThroughOutOfCall(call, ccc, ret, _, node, allowsFieldFlow, innerArgApa, apa) and - if allowsFieldFlow = false then ap instanceof ApNil else any() + innerArgApa, allowsFieldFlow) and + flowThroughOutOfCall(call, ccc, ret, _, node, allowsFieldFlow, innerArgApa, apa) ) } @@ -1606,10 +1604,14 @@ module MakeImpl { } private signature module FwdFlowInInputSig { - default predicate callRestriction(DataFlowCall call) { any() } - - bindingset[p, apa] - default predicate parameterRestriction(ParamNodeEx p, ApApprox apa) { any() } + // default predicate callRestriction(DataFlowCall call) { any() } + // bindingset[p, apa] + // default predicate parameterRestriction(ParamNodeEx p, ApApprox apa) { any() } + default predicate restriction( + DataFlowCall call, ParamNodeEx p, ApApprox apa, boolean allowsFieldFlow + ) { + PrevStage::callEdgeArgParam(call, _, _, p, allowsFieldFlow, apa) + } } /** @@ -1630,9 +1632,13 @@ module MakeImpl { DataFlowCall call, DataFlowCallable c, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, ApApprox apa ) { - PrevStage::callEdgeArgParam(call, c, arg, p, allowsFieldFlow, apa) and - I::callRestriction(call) and - I::parameterRestriction(p, apa) + exists(boolean allowsFieldFlow1, boolean allowsFieldFlow2 | + PrevStage::callEdgeArgParam(call, c, arg, p, allowsFieldFlow1, apa) and + I::restriction(call, p, apa, allowsFieldFlow2) and + allowsFieldFlow = allowsFieldFlow1.booleanAnd(allowsFieldFlow2) + ) + // I::callRestriction(call) and + // I::parameterRestriction(p, apa) } pragma[nomagic] @@ -1767,15 +1773,40 @@ module MakeImpl { private module FwdFlowInNoRestriction implements FwdFlowInInputSig { } + pragma[nomagic] + private predicate flowThroughOutOfCall( + DataFlowCall call, ParamNodeEx p, ApApprox apa, boolean allowsFieldFlow + ) { + PrevStage::parameterMayFlowThrough(p, apa) and + flowThroughOutOfCall(call, _, _, _, _, allowsFieldFlow, apa, _) and + PrevStage::callEdgeArgParam(call, _, _, p, _, apa) + } + + bindingset[call, p, ap, apa] + pragma[inline_late] + private predicate fwdFlowInFlowThroughAllowed( + DataFlowCall call, ParamNodeEx p, Ap ap, ApApprox apa + ) { + exists(boolean allowsFieldFlow | + flowThroughOutOfCall(call, p, apa, allowsFieldFlow) and + if allowsFieldFlow = false then ap instanceof ApNil else any() + ) + } + pragma[nomagic] private predicate fwdFlowIn( ParamNodeEx p, ApApprox apa, FlowState state, CcCall innercc, Typ t, TypOption origT, - Ap ap, boolean inSummaryCtx + Ap ap, boolean inSummaryCtx, boolean allowsFlowThrough ) { - exists(ParamNodeOption summaryCtx | - FwdFlowIn::fwdFlowIn(_, _, p, state, _, innercc, summaryCtx, _, - _, t, origT, ap, apa, _) and + exists(DataFlowCall call, ParamNodeOption summaryCtx | + FwdFlowIn::fwdFlowIn(call, _, p, state, _, innercc, summaryCtx, + _, _, t, origT, ap, apa, _) and if summaryCtx = TParamNodeNone() then inSummaryCtx = false else inSummaryCtx = true + | + allowsFlowThrough = false + or + allowsFlowThrough = true and + fwdFlowInFlowThroughAllowed(call, p, ap, apa) ) } @@ -1947,16 +1978,18 @@ module MakeImpl { pragma[nomagic] private predicate fwdFlowRetFromArg( RetNodeEx ret, FlowState state, CcCall ccc, ParamNodeEx summaryCtx, ArgTyp argT, Ap argAp, - ApApprox argApa, Typ t, TypOption origT, Ap ap, ApApprox apa + ApApprox argApa, Typ t, TypOption origT, Ap ap, ApApprox apa, boolean allowsFieldFlow ) { - exists(DataFlowCall call, ReturnKindExt kind, boolean allowsFieldFlow | + exists(DataFlowCall call, ReturnKindExt kind | fwdFlow(pragma[only_bind_into](ret), state, ccc, TParamNodeSome(pragma[only_bind_into](summaryCtx.asNode())), ArgTypOption::some(argT), pragma[only_bind_into](apSome(argAp)), t, origT, ap, pragma[only_bind_into](apa)) and parameterFlowThroughAllowed(summaryCtx, kind) and argApa = getApprox(argAp) and flowThroughOutOfCall(call, ccc, ret, kind, _, allowsFieldFlow, argApa, apa) and - if allowsFieldFlow = false then ap instanceof ApNil else any() + if allowsFieldFlow = false + then ap instanceof ApNil and argAp instanceof ApNil + else any() ) } @@ -1965,10 +1998,10 @@ module MakeImpl { DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, ArgTypOption argT, ApOption argAp, Typ t, TypOption origT, Ap ap, ApApprox apa, RetNodeEx ret, ParamNodeEx innerSummaryCtx, ArgTyp innerArgT, Ap innerArgAp, - ApApprox innerArgApa + ApApprox innerArgApa, boolean allowsFieldFlow ) { fwdFlowRetFromArg(ret, state, ccc, innerSummaryCtx, innerArgT, innerArgAp, innerArgApa, t, - origT, ap, apa) and + origT, ap, apa, allowsFieldFlow) and fwdFlowIsEntered(call, cc, ccc, summaryCtx, argT, argAp, innerSummaryCtx, innerArgT, innerArgAp) } @@ -1977,16 +2010,14 @@ module MakeImpl { private predicate fwdFlowThrough( DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, ArgTypOption argT, ApOption argAp, Typ t, TypOption origT, Ap ap, ApApprox apa, - RetNodeEx ret, ApApprox innerArgApa + RetNodeEx ret, ApApprox innerArgApa, boolean allowsFieldFlow ) { fwdFlowThrough0(call, cc, state, ccc, summaryCtx, argT, argAp, t, origT, ap, apa, ret, _, - _, _, innerArgApa) + _, _, innerArgApa, allowsFieldFlow) } private module FwdFlowThroughRestriction implements FwdFlowInInputSig { - predicate callRestriction = PrevStage::callMayFlowThroughRev/1; - - predicate parameterRestriction = PrevStage::parameterMayFlowThrough/2; + predicate restriction = flowThroughOutOfCall/4; } /** @@ -2000,7 +2031,8 @@ module MakeImpl { ) { exists(ApApprox apa | FwdFlowIn::fwdFlowIn(call, _, p, _, cc, innerCc, summaryCtx, - argT, argAp, any(Typ t0 | t = toArgTyp(t0)), _, ap, apa, _) + argT, argAp, any(Typ t0 | t = toArgTyp(t0)), _, ap, apa, _) and + fwdFlowInFlowThroughAllowed(call, p, ap, apa) ) } @@ -2024,10 +2056,11 @@ module MakeImpl { pragma[nomagic] private predicate returnFlowsThrough0( DataFlowCall call, FlowState state, CcCall ccc, Ap ap, ApApprox apa, RetNodeEx ret, - ParamNodeEx innerSummaryCtx, ArgTyp innerArgT, Ap innerArgAp, ApApprox innerArgApa + ParamNodeEx innerSummaryCtx, ArgTyp innerArgT, Ap innerArgAp, ApApprox innerArgApa, + boolean allowsFieldFlow ) { fwdFlowThrough0(call, _, state, ccc, _, _, _, _, _, ap, apa, ret, innerSummaryCtx, - innerArgT, innerArgAp, innerArgApa) + innerArgT, innerArgAp, innerArgApa, allowsFieldFlow) } pragma[nomagic] @@ -2036,10 +2069,10 @@ module MakeImpl { ArgTyp argT, Ap argAp, Ap ap ) { exists(DataFlowCall call, ApApprox apa, boolean allowsFieldFlow, ApApprox innerArgApa | - returnFlowsThrough0(call, state, ccc, ap, apa, ret, p, argT, argAp, innerArgApa) and + returnFlowsThrough0(call, state, ccc, ap, apa, ret, p, argT, argAp, innerArgApa, + allowsFieldFlow) and flowThroughOutOfCall(call, ccc, ret, _, _, allowsFieldFlow, innerArgApa, apa) and - pos = ret.getReturnPosition() and - if allowsFieldFlow = false then ap instanceof ApNil else any() + pos = ret.getReturnPosition() ) } @@ -2053,7 +2086,9 @@ module MakeImpl { flowIntoCallApaTaken(call, _, pragma[only_bind_into](arg), p, allowsFieldFlow, argApa) and fwdFlow(arg, _, _, _, _, _, pragma[only_bind_into](argT), _, pragma[only_bind_into](argAp), argApa) and - if allowsFieldFlow = false then argAp instanceof ApNil else any() + if allowsFieldFlow = false + then argAp instanceof ApNil and ap instanceof ApNil + else any() ) } @@ -3255,12 +3290,12 @@ module MakeImpl { then t = nt else ( compatibleTypes(nt, t0) and - // t = t0 - if inSummaryCtx = true and node instanceof ParamNodeEx - then - t = nt and - compatibleTypes(origT, t) - else t = t0 + t = t0 + // if inSummaryCtx = true and node instanceof ParamNodeEx + // then + // t = nt and + // compatibleTypes(origT, t) + // else t = t0 ) ) else t = t0 From 98503b67824e13c45e9534cf76a771f80793bb72 Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Tue, 13 Feb 2024 09:47:36 +0100 Subject: [PATCH 16/19] debug --- java/ql/lib/semmle/code/java/security/TaintedPathQuery.qll | 6 +++--- shared/dataflow/codeql/dataflow/internal/DataFlowImpl.qll | 3 ++- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/java/ql/lib/semmle/code/java/security/TaintedPathQuery.qll b/java/ql/lib/semmle/code/java/security/TaintedPathQuery.qll index 2ae8b124a3c1..49a727c59553 100644 --- a/java/ql/lib/semmle/code/java/security/TaintedPathQuery.qll +++ b/java/ql/lib/semmle/code/java/security/TaintedPathQuery.qll @@ -66,9 +66,9 @@ module TaintedPathConfig implements DataFlow::ConfigSig { predicate isBarrier(DataFlow::Node sanitizer) { sanitizer instanceof SimpleTypeSanitizer or - sanitizer instanceof PathInjectionSanitizer //or - // sanitizer.getLocation().getFile().getBaseName() = - // ["BaseObject.java", "SimpleNode.java", "Context.java"] + sanitizer instanceof PathInjectionSanitizer or + sanitizer.getLocation().getFile().getBaseName() = + [/*"BaseObject.java", "SimpleNode.java",*/ "Context.java"] } predicate isAdditionalFlowStep(DataFlow::Node n1, DataFlow::Node n2) { diff --git a/shared/dataflow/codeql/dataflow/internal/DataFlowImpl.qll b/shared/dataflow/codeql/dataflow/internal/DataFlowImpl.qll index 240465842fbb..6c21716a5884 100644 --- a/shared/dataflow/codeql/dataflow/internal/DataFlowImpl.qll +++ b/shared/dataflow/codeql/dataflow/internal/DataFlowImpl.qll @@ -3259,7 +3259,8 @@ module MakeImpl { private module Stage3 = MkStage::Stage; // private predicate mostBusyNodeFwd3 = Stage3::mostBusyNodeFwd/10; - // private predicate mostBusyNodeFwd3_5 = Stage3_5::mostBusyNodeFwd/10; + private predicate mostBusyNodeFwd3_5 = Stage3_5::mostBusyNodeFwd/10; + // private predicate mostBusyNodeFwd4 = Stage4::mostBusyNodeFwd/10; private predicate mostBusyNodeFwd5 = Stage5::mostBusyNodeFwd/10; From 4cbea36889cfe07fa6a8ef9aa125127323d4ac61 Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Tue, 13 Feb 2024 14:10:50 +0100 Subject: [PATCH 17/19] branch limit --- .../codeql/dataflow/internal/DataFlowImpl.qll | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/shared/dataflow/codeql/dataflow/internal/DataFlowImpl.qll b/shared/dataflow/codeql/dataflow/internal/DataFlowImpl.qll index 6c21716a5884..c3b59e14198b 100644 --- a/shared/dataflow/codeql/dataflow/internal/DataFlowImpl.qll +++ b/shared/dataflow/codeql/dataflow/internal/DataFlowImpl.qll @@ -1133,7 +1133,7 @@ module MakeImpl { exists(int b, int j | b = branch(ret) and j = join(out) and - if b.minimum(j) <= Config::fieldFlowBranchLimit() + if j <= Config::fieldFlowBranchLimit() then allowsFieldFlow = true else allowsFieldFlow = false ) @@ -1149,13 +1149,14 @@ module MakeImpl { DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow ) { flowIntoCallNodeCand1(call, arg, p) and - exists(int b, int j | - b = branch(arg) and - j = join(p) and - if b.minimum(j) <= Config::fieldFlowBranchLimit() - then allowsFieldFlow = true - else allowsFieldFlow = false - ) + allowsFieldFlow = true + // exists(int b, int j | + // b = branch(arg) and + // j = join(p) and + // if b.minimum(j) <= Config::fieldFlowBranchLimit() + // then allowsFieldFlow = true + // else allowsFieldFlow = false + // ) } private signature module StageSig { From 276a4dca1a1b38a06c26c82c8196b036aaed217a Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Tue, 13 Feb 2024 21:05:27 +0100 Subject: [PATCH 18/19] debug --- .../semmle/code/java/dataflow/internal/DataFlowDispatch.qll | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowDispatch.qll b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowDispatch.qll index 0e496b5c9cc6..1d17b3f9925f 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowDispatch.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowDispatch.qll @@ -33,6 +33,11 @@ private module DispatchImpl { result.asSummarizedCallable().getACall() = c.asCall() } + private DataFlowCallable testviableCallable(DataFlowCall c) { + result = viableCallable(c) and + result.asCallable().hasName("_getMember") + } + private DataFlowCallable viableCallable(DataFlowCall c, int k) { result = viableCallable(c) and k = strictcount(viableCallable(c)) From f8347e9cb04c3fe5de2ea1c6022395aff36902de Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Mon, 19 Feb 2024 11:30:00 +0100 Subject: [PATCH 19/19] temp --- .../dataflow/callback-dispatch/test.expected | 3 + .../codeql/dataflow/internal/DataFlowImpl.qll | 184 ++++++++++++------ .../dataflow/internal/DataFlowImplCommon.qll | 169 ++++++++++------ 3 files changed, 233 insertions(+), 123 deletions(-) diff --git a/java/ql/test/library-tests/dataflow/callback-dispatch/test.expected b/java/ql/test/library-tests/dataflow/callback-dispatch/test.expected index 8ec8033d086e..b0851914d60e 100644 --- a/java/ql/test/library-tests/dataflow/callback-dispatch/test.expected +++ b/java/ql/test/library-tests/dataflow/callback-dispatch/test.expected @@ -1,2 +1,5 @@ testFailures +| A.java:135:34:135:45 | // $ flow=11 | Missing result:flow=11 | +| A.java:143:16:143:27 | // $ flow=13 | Missing result:flow=13 | +| A.java:197:34:197:45 | // $ flow=21 | Missing result:flow=21 | failures diff --git a/shared/dataflow/codeql/dataflow/internal/DataFlowImpl.qll b/shared/dataflow/codeql/dataflow/internal/DataFlowImpl.qll index c3b59e14198b..681c97df5bef 100644 --- a/shared/dataflow/codeql/dataflow/internal/DataFlowImpl.qll +++ b/shared/dataflow/codeql/dataflow/internal/DataFlowImpl.qll @@ -1100,8 +1100,14 @@ module MakeImpl { pragma[nomagic] private int branch(NodeEx n1) { result = - strictcount(NodeEx n | - flowOutOfCallNodeCand1(_, n1, _, n) or flowIntoCallNodeCand1(_, n1, n) + // strictcount(NodeEx n | + // flowOutOfCallNodeCand1(_, n1, _, n) or flowIntoCallNodeCand1(_, n1, n) + strictcount(DataFlowCallable c | + exists(NodeEx n | + flowOutOfCallNodeCand1(_, n1, _, n) or flowIntoCallNodeCand1(_, n1, n) + | + c = n.getEnclosingCallable() + ) ) + sum(ParamNodeEx p1 | | getLanguageSpecificFlowIntoCallNodeCand1(n1, p1)) } @@ -1113,8 +1119,14 @@ module MakeImpl { pragma[nomagic] private int join(NodeEx n2) { result = - strictcount(NodeEx n | - flowOutOfCallNodeCand1(_, n, _, n2) or flowIntoCallNodeCand1(_, n, n2) + // strictcount(NodeEx n | + // flowOutOfCallNodeCand1(_, n, _, n2) or flowIntoCallNodeCand1(_, n, n2) + strictcount(DataFlowCallable c | + exists(NodeEx n | + flowOutOfCallNodeCand1(_, n, _, n2) or flowIntoCallNodeCand1(_, n, n2) + | + c = n.getEnclosingCallable() + ) ) + sum(ArgNodeEx arg2 | | getLanguageSpecificFlowIntoCallNodeCand1(arg2, n2)) } @@ -1149,14 +1161,14 @@ module MakeImpl { DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow ) { flowIntoCallNodeCand1(call, arg, p) and - allowsFieldFlow = true - // exists(int b, int j | - // b = branch(arg) and - // j = join(p) and - // if b.minimum(j) <= Config::fieldFlowBranchLimit() - // then allowsFieldFlow = true - // else allowsFieldFlow = false - // ) + // allowsFieldFlow = true + exists(int b, int j | + b = branch(arg) and + j = join(p) and + if b.minimum(j) <= Config::fieldFlowBranchLimit() + then allowsFieldFlow = true + else allowsFieldFlow = false + ) } private signature module StageSig { @@ -1296,9 +1308,9 @@ module MakeImpl { /* Begin: Stage logic. */ private module TypOption = Option; - private class ArgTyp = Unit; + private class ArgTyp = Typ; - private ArgTyp toArgTyp(Typ t) { any() } + private ArgTyp toArgTyp(Typ t) { result = t } additional class TypOption = TypOption::Option; @@ -1377,9 +1389,10 @@ module MakeImpl { filter(node, state, origT1, t0, ap, t, inSummaryCtx) ) and // origT.asSome() = t - if t != t0 and origT0.isNone() and not ap instanceof ApNil - then origT.asSome() = t0 - else origT = origT0 + origT = origT0 + // if t != t0 and origT0.isNone() and not ap instanceof ApNil + // then origT.asSome() = t0 + // else origT = origT0 ) } @@ -1436,7 +1449,8 @@ module MakeImpl { // read exists(Typ t0, Ap ap0, Content c | fwdFlowRead(t0, ap0, c, node, state, cc, summaryCtx, argT, argAp) and - fwdFlowConsCandNoStrenght(t0, ap0, c, t, origT, ap) and + // fwdFlowConsCandNoStrenght(t0, ap0, c, t, origT, ap) and + fwdFlowConsCand(t0, ap0, c, t, origT, ap) and apa = getApprox(ap) ) or @@ -1464,12 +1478,13 @@ module MakeImpl { or // flow through a callable exists( - DataFlowCall call, CcCall ccc, RetNodeEx ret, boolean allowsFieldFlow, + DataFlowCall call, CcCall ccc, ReturnKindExt kind, boolean allowsFieldFlow, ApApprox innerArgApa | - fwdFlowThrough(call, cc, state, ccc, summaryCtx, argT, argAp, t, origT, ap, apa, ret, - innerArgApa, allowsFieldFlow) and - flowThroughOutOfCall(call, ccc, ret, _, node, allowsFieldFlow, innerArgApa, apa) + fwdFlowThrough(call, cc, state, ccc, summaryCtx, argT, argAp, t, origT, ap, apa, kind, + /* TODO */ + /*innerArgApa,*/ allowsFieldFlow) and + flowThroughOutOfCall(call, ccc, _, kind, node, allowsFieldFlow, innerArgApa, apa) ) } @@ -1545,7 +1560,7 @@ module MakeImpl { * `cons`. */ pragma[nomagic] - private predicate fwdFlowConsCand_( + private predicate fwdFlowConsCand( Typ t2, Ap cons, Content c, Typ t1, TypOption origT1, Ap tail ) { fwdFlowStore(t1, origT1, tail, c, t2, _, _, _, _, _, _) and @@ -1553,7 +1568,7 @@ module MakeImpl { or exists(Typ t0 | typeStrengthen(t0, cons, t2) and - fwdFlowConsCand_(t0, cons, c, t1, origT1, tail) + fwdFlowConsCand(t0, cons, c, t1, origT1, tail) ) } @@ -1800,13 +1815,18 @@ module MakeImpl { Ap ap, boolean inSummaryCtx, boolean allowsFlowThrough ) { exists(DataFlowCall call, ParamNodeOption summaryCtx | - FwdFlowIn::fwdFlowIn(call, _, p, state, _, innercc, summaryCtx, - _, _, t, origT, ap, apa, _) and if summaryCtx = TParamNodeNone() then inSummaryCtx = false else inSummaryCtx = true | + FwdFlowIn::fwdFlowIn(call, _, p, state, _, innercc, summaryCtx, + _, _, t, origT, ap, apa, _) and allowsFlowThrough = false or + // allowsFlowThrough = true and + // fwdFlowInFlowThroughAllowed(call, p, ap, apa) + // or allowsFlowThrough = true and + FwdFlowIn::fwdFlowIn(call, _, p, state, _, innercc, + summaryCtx, _, _, t, origT, ap, apa, _) and fwdFlowInFlowThroughAllowed(call, p, ap, apa) ) } @@ -1978,6 +1998,27 @@ module MakeImpl { pragma[nomagic] private predicate fwdFlowRetFromArg( + ReturnKindExt kind, /*RetNodeEx ret*/ FlowState state, CcCall ccc, ParamNodeEx summaryCtx, + ArgTyp argT, Ap argAp, ApApprox argApa, Typ t, TypOption origT, Ap ap, ApApprox apa, + boolean allowsFieldFlow + ) { + exists(DataFlowCall call, RetNodeEx ret | + fwdFlow(pragma[only_bind_into](ret), state, ccc, + TParamNodeSome(pragma[only_bind_into](summaryCtx.asNode())), ArgTypOption::some(argT), + pragma[only_bind_into](apSome(argAp)), t, origT, ap, pragma[only_bind_into](apa)) and + parameterFlowThroughAllowed(summaryCtx, kind) and + argApa = getApprox(argAp) and + flowThroughOutOfCall(call, ccc, ret, kind, _, allowsFieldFlow, argApa, apa) and + ( + if allowsFieldFlow = false + then ap instanceof ApNil and argAp instanceof ApNil + else any() + ) + ) + } + + pragma[nomagic] + private predicate fwdFlowRetFromArg1( RetNodeEx ret, FlowState state, CcCall ccc, ParamNodeEx summaryCtx, ArgTyp argT, Ap argAp, ApApprox argApa, Typ t, TypOption origT, Ap ap, ApApprox apa, boolean allowsFieldFlow ) { @@ -1988,21 +2029,36 @@ module MakeImpl { parameterFlowThroughAllowed(summaryCtx, kind) and argApa = getApprox(argAp) and flowThroughOutOfCall(call, ccc, ret, kind, _, allowsFieldFlow, argApa, apa) and - if allowsFieldFlow = false - then ap instanceof ApNil and argAp instanceof ApNil - else any() + ( + if allowsFieldFlow = false + then ap instanceof ApNil and argAp instanceof ApNil + else any() + ) ) } pragma[inline] private predicate fwdFlowThrough0( + DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, + ArgTypOption argT, ApOption argAp, Typ t, TypOption origT, Ap ap, ApApprox apa, + ReturnKindExt kind, /*RetNodeEx ret*/ ParamNodeEx innerSummaryCtx, ArgTyp innerArgT, + Ap innerArgAp, ApApprox innerArgApa, boolean allowsFieldFlow + ) { + fwdFlowRetFromArg(kind, state, ccc, innerSummaryCtx, innerArgT, innerArgAp, innerArgApa, + t, origT, ap, apa, allowsFieldFlow) and + fwdFlowIsEntered(call, cc, ccc, summaryCtx, argT, argAp, innerSummaryCtx, innerArgT, + innerArgAp) + } + + pragma[inline] + private predicate fwdFlowThrough1( DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, ArgTypOption argT, ApOption argAp, Typ t, TypOption origT, Ap ap, ApApprox apa, RetNodeEx ret, ParamNodeEx innerSummaryCtx, ArgTyp innerArgT, Ap innerArgAp, ApApprox innerArgApa, boolean allowsFieldFlow ) { - fwdFlowRetFromArg(ret, state, ccc, innerSummaryCtx, innerArgT, innerArgAp, innerArgApa, t, - origT, ap, apa, allowsFieldFlow) and + fwdFlowRetFromArg1(ret, state, ccc, innerSummaryCtx, innerArgT, innerArgAp, innerArgApa, + t, origT, ap, apa, allowsFieldFlow) and fwdFlowIsEntered(call, cc, ccc, summaryCtx, argT, argAp, innerSummaryCtx, innerArgT, innerArgAp) } @@ -2011,10 +2067,10 @@ module MakeImpl { private predicate fwdFlowThrough( DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, ArgTypOption argT, ApOption argAp, Typ t, TypOption origT, Ap ap, ApApprox apa, - RetNodeEx ret, ApApprox innerArgApa, boolean allowsFieldFlow + ReturnKindExt kind, /*RetNodeEx ret ApApprox innerArgApa,*/ boolean allowsFieldFlow ) { - fwdFlowThrough0(call, cc, state, ccc, summaryCtx, argT, argAp, t, origT, ap, apa, ret, _, - _, _, innerArgApa, allowsFieldFlow) + fwdFlowThrough0(call, cc, state, ccc, summaryCtx, argT, argAp, t, origT, ap, apa, kind, _, + _, _, _, /*innerArgApa*/ allowsFieldFlow) } private module FwdFlowThroughRestriction implements FwdFlowInInputSig { @@ -2050,7 +2106,8 @@ module MakeImpl { private predicate readStepFwd(NodeEx n1, Ap ap1, Content c, NodeEx n2, Ap ap2) { exists(Typ t1 | fwdFlowRead(t1, ap1, c, n1, n2, _, _, _, _, _) and - fwdFlowConsCandNoStrenght(t1, ap1, c, _, _, ap2) + // fwdFlowConsCandNoStrenght(t1, ap1, c, _, _, ap2) and + fwdFlowConsCand(t1, ap1, c, _, _, ap2) ) } @@ -2060,7 +2117,7 @@ module MakeImpl { ParamNodeEx innerSummaryCtx, ArgTyp innerArgT, Ap innerArgAp, ApApprox innerArgApa, boolean allowsFieldFlow ) { - fwdFlowThrough0(call, _, state, ccc, _, _, _, _, _, ap, apa, ret, innerSummaryCtx, + fwdFlowThrough1(call, _, state, ccc, _, _, _, _, _, ap, apa, ret, innerSummaryCtx, innerArgT, innerArgAp, innerArgApa, allowsFieldFlow) } @@ -2095,9 +2152,10 @@ module MakeImpl { pragma[nomagic] private predicate flowIntoCallAp( - DataFlowCall call, DataFlowCallable c, ArgNodeEx arg, ParamNodeEx p, Ap ap + DataFlowCall call, DataFlowCallable c, ArgNodeEx arg, ParamNodeEx p, Ap ap, + boolean allowsFieldFlow ) { - exists(ApApprox apa, boolean allowsFieldFlow | + exists(ApApprox apa | flowIntoCallApaTaken(call, c, arg, p, allowsFieldFlow, apa) and fwdFlow(arg, _, _, _, _, _, _, _, ap, apa) and if allowsFieldFlow = false then ap instanceof ApNil else any() @@ -2107,9 +2165,9 @@ module MakeImpl { pragma[nomagic] private predicate flowOutOfCallAp( DataFlowCall call, DataFlowCallable c, RetNodeEx ret, ReturnPosition pos, NodeEx out, - Ap ap + Ap ap, boolean allowsFieldFlow ) { - exists(ApApprox apa, boolean allowsFieldFlow | + exists(ApApprox apa | PrevStage::callEdgeReturn(call, c, ret, _, out, allowsFieldFlow, apa) and fwdFlow(ret, _, _, _, _, _, _, _, ap, apa) and pos = ret.getReturnPosition() and @@ -2247,11 +2305,11 @@ module MakeImpl { predicate enableTypeFlow = Param::enableTypeFlow/0; predicate relevantCallEdgeIn(DataFlowCall call, DataFlowCallable c) { - flowOutOfCallAp(call, c, _, _, _, _) + flowOutOfCallAp(call, c, _, _, _, _, _) } predicate relevantCallEdgeOut(DataFlowCall call, DataFlowCallable c) { - flowIntoCallAp(call, c, _, _, _) + flowIntoCallAp(call, c, _, _, _, _) } pragma[nomagic] @@ -2289,7 +2347,7 @@ module MakeImpl { private predicate flowIntoCallApValid( DataFlowCall call, DataFlowCallable c, ArgNodeEx arg, ParamNodeEx p, Ap ap ) { - flowIntoCallAp(call, c, arg, p, ap) and + flowIntoCallAp(call, c, arg, p, ap, _) and RevTypeFlow::typeFlowValidEdgeOut(call, c) } @@ -2298,7 +2356,7 @@ module MakeImpl { DataFlowCall call, RetNodeEx ret, ReturnPosition pos, NodeEx out, Ap ap, boolean cc ) { exists(DataFlowCallable c | - flowOutOfCallAp(call, c, ret, pos, out, ap) and + flowOutOfCallAp(call, c, ret, pos, out, ap, _) and RevTypeFlow::typeFlowValidEdgeIn(call, c, cc) ) } @@ -2502,14 +2560,14 @@ module MakeImpl { boolean allowsFieldFlow, Ap ap ) { exists(FlowState state | - flowIntoCallAp(call, c, arg, p, ap) and + flowIntoCallAp(call, c, arg, p, ap, allowsFieldFlow) and revFlow(arg, pragma[only_bind_into](state), pragma[only_bind_into](ap)) and - revFlow(p, pragma[only_bind_into](state), pragma[only_bind_into](ap)) and - // allowsFieldFlow has already been checked in flowIntoCallAp, since - // `Ap` is at least as precise as a boolean from Stage 2 and - // forward, so no need to check it again later. - allowsFieldFlow = true + revFlow(p, pragma[only_bind_into](state), pragma[only_bind_into](ap)) //and | + // // allowsFieldFlow has already been checked in flowIntoCallAp, since + // // `Ap` is at least as precise as a boolean from Stage 2 and + // // forward, so no need to check it again later. + // allowsFieldFlow = true // both directions are needed for flow-through RevTypeFlowInput::dataFlowTakenCallEdgeIn(call, c, _) or RevTypeFlowInput::dataFlowTakenCallEdgeOut(call, c) @@ -2521,11 +2579,10 @@ module MakeImpl { boolean allowsFieldFlow, Ap ap ) { exists(FlowState state, ReturnPosition pos | - flowOutOfCallAp(call, c, ret, pos, out, ap) and + flowOutOfCallAp(call, c, ret, pos, out, ap, allowsFieldFlow) and revFlow(ret, pragma[only_bind_into](state), pragma[only_bind_into](ap)) and revFlow(out, pragma[only_bind_into](state), pragma[only_bind_into](ap)) and kind = pos.getKind() and - allowsFieldFlow = true and RevTypeFlowInput::dataFlowTakenCallEdgeIn(call, c, _) ) } @@ -3258,7 +3315,7 @@ module MakeImpl { } private module Stage3 = MkStage::Stage; - + // private predicate mostBusyNodeFwd3 = Stage3::mostBusyNodeFwd/10; private predicate mostBusyNodeFwd3_5 = Stage3_5::mostBusyNodeFwd/10; @@ -3438,10 +3495,10 @@ module MakeImpl { ApOption apSome(Ap ap) { result = TAccessPathFrontSome(ap) } - // import Level1CallContext - // import NoLocalCallContext - import BooleanCallContext + import Level1CallContext + import NoLocalCallContext + // import BooleanCallContext pragma[nomagic] predicate localStep( NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, @@ -3809,8 +3866,8 @@ module MakeImpl { TSummaryCtxSome(ParamNodeEx p, FlowState state, DataFlowType t, AccessPath ap) { exists(AccessPathApprox apa | ap.getApprox() = apa | Stage5::parameterMayFlowThrough(p, apa) and - Stage5::fwdFlow1(p, state, _, _, Option::some(_), _, t, _, _, _, apa, _) and - Stage5::fwdFlow1(p, state, _, _, Option::some(_), _, t, _, _, _, apa, _) and + Stage5::fwdFlow1(p, state, _, _, Option::some(_), _, t, _, _, _, apa, _) and + Stage5::fwdFlow1(p, state, _, _, Option::some(_), _, t, _, _, _, apa, _) and Stage5::revFlow(p, state, _) ) } @@ -4059,10 +4116,19 @@ module MakeImpl { override AccessPathFrontHead getFront() { result = TFrontHead(head_) } + pragma[nomagic] + private predicate isConsCons(Content tailHead, int length) { + tailHead = tail_.getHead() and + length = this.length() + } + override AccessPathApproxCons getApprox() { result = TConsNil(head_, t) and tail_ = TAccessPathNil() or - result = TConsCons(head_, t, tail_.getHead(), this.length()) + exists(Content tailHead, int length | + this.isConsCons(tailHead, length) and + result = TConsCons(head_, t, tailHead, length) + ) or result = TCons1(head_, this.length()) } diff --git a/shared/dataflow/codeql/dataflow/internal/DataFlowImplCommon.qll b/shared/dataflow/codeql/dataflow/internal/DataFlowImplCommon.qll index 21040c2d0d92..d9762f00c6ac 100644 --- a/shared/dataflow/codeql/dataflow/internal/DataFlowImplCommon.qll +++ b/shared/dataflow/codeql/dataflow/internal/DataFlowImplCommon.qll @@ -109,7 +109,7 @@ module MakeImplCommon { predicate levelStepNoCall(Node n1, LocalSourceNode n2) { none() } predicate levelStepCall(Node n1, LocalSourceNode n2) { - argumentValueFlowsThrough(n1, TReadStepTypesNone(), n2) + argumentValueFlowsThrough(n1, _, TReadStepTypesNone(), n2) } // TODO: support setters @@ -118,7 +118,7 @@ module MakeImplCommon { private predicate loadStep0(Node n1, Node n2, Content f) { readSet(n1, f, n2) or - argumentValueFlowsThrough(n1, TReadStepTypesSome(_, f, _), n2) + argumentValueFlowsThrough(n1, _, TReadStepTypesSome(f, _), n2) } predicate loadStep(Node n1, LocalSourceNode n2, Content f) { loadStep0(n1, n2, f) } @@ -660,73 +660,106 @@ module MakeImplCommon { * If a read step was taken, then `read` captures the `Content`, the * container type, and the content type. */ - predicate parameterValueFlow(ParamNode p, Node node, ReadStepTypesOption read) { - parameterValueFlow0(p, node, read) and - if node instanceof CastingNode - then - // normal flow through - read = TReadStepTypesNone() and - compatibleTypes(getNodeDataFlowType(p), getNodeDataFlowType(node)) - or - // getter - compatibleTypes(read.getContentType(), getNodeDataFlowType(node)) - else any() + predicate parameterValueFlow( + ParamNode p, Node node, DataFlowType t, ReadStepTypesOption read + ) { + exists(DataFlowType t0 | + parameterValueFlow0(p, node, t0, read) and + if node instanceof CastingNode + then + exists(DataFlowType nt | nt = getNodeDataFlowType(node) | + if typeStrongerThan(nt, t0) + then t = nt + else ( + compatibleTypes(nt, t0) and + t = t0 + ) + ) + else t = t0 + ) + // // normal flow through + // read = TReadStepTypesNone() and + // compatibleTypes(getNodeDataFlowType(p), getNodeDataFlowType(node)) + // or + // // getter + // compatibleTypes(read.getContentType(), getNodeDataFlowType(node)) + // else any() } pragma[nomagic] - private predicate parameterValueFlow0(ParamNode p, Node node, ReadStepTypesOption read) { + private predicate parameterValueFlow0( + ParamNode p, Node node, DataFlowType t, ReadStepTypesOption read + ) { p = node and Cand::cand(p, _) and - read = TReadStepTypesNone() + read = TReadStepTypesNone() and + t = getNodeDataFlowType(node) or // local flow exists(Node mid | - parameterValueFlow(p, mid, read) and + parameterValueFlow(p, mid, t, read) and simpleLocalFlowStep(mid, node) and validParameterAliasStep(mid, node) ) or // read - exists(Node mid | - parameterValueFlow(p, mid, TReadStepTypesNone()) and - readStepWithTypes(mid, read.getContainerType(), read.getContent(), node, - read.getContentType()) and + exists(Node mid, DataFlowType t0, DataFlowType rt | + parameterValueFlow(p, mid, t0, TReadStepTypesNone()) and + rt = read.getContentType() and + readStepWithTypes(mid, t, read.getContent(), node, rt) and Cand::parameterValueFlowReturnCand(p, _, true) and - compatibleTypes(getNodeDataFlowType(p), read.getContainerType()) + compatibleTypes(t0, rt) ) or - parameterValueFlow0_0(TReadStepTypesNone(), p, node, read) - } - - pragma[nomagic] - private predicate parameterValueFlow0_0( - ReadStepTypesOption mustBeNone, ParamNode p, Node node, ReadStepTypesOption read - ) { // flow through: no prior read - exists(ArgNode arg | - parameterValueFlowArg(p, arg, mustBeNone) and - argumentValueFlowsThrough(arg, read, node) + exists(ArgNode arg, DataFlowType t1, DataFlowType t2 | + parameterValueFlowArg(p, arg, t1, TReadStepTypesNone()) and + argumentValueFlowsThrough(arg, t2, read, node) and + if read = TReadStepTypesNone() + then + if typeStrongerThan(t1, t2) + then t = t1 + else + if typeStrongerThan(t2, t1) + then t = t2 + else ( + compatibleTypes(t1, t2) and t = t1 + ) + else t = t2 ) or // flow through: no read inside method - exists(ArgNode arg | - parameterValueFlowArg(p, arg, read) and - argumentValueFlowsThrough(arg, mustBeNone, node) + exists(ArgNode arg, DataFlowType t1, DataFlowType t2 | + parameterValueFlowArg(p, arg, t1, read) and + argumentValueFlowsThrough(arg, t2, TReadStepTypesNone(), node) and + if typeStrongerThan(t1, t2) + then t = t1 + else + if typeStrongerThan(t2, t1) + then t = t2 + else ( + compatibleTypes(t1, t2) and t = t1 + ) ) } pragma[nomagic] - private predicate parameterValueFlowArg(ParamNode p, ArgNode arg, ReadStepTypesOption read) { - parameterValueFlow(p, arg, read) and + private predicate parameterValueFlowArg( + ParamNode p, ArgNode arg, DataFlowType t, ReadStepTypesOption read + ) { + parameterValueFlow(p, arg, t, read) and Cand::argumentValueFlowsThroughCand(arg, _, _) } pragma[nomagic] private predicate argumentValueFlowsThrough0( - DataFlowCall call, ArgNode arg, ReturnKind kind, ReadStepTypesOption read + DataFlowCall call, ArgNode arg, ReturnKind kind, DataFlowType t, ReadStepTypesOption read ) { - exists(ParamNode param | viableParamArg(call, param, arg) | - parameterValueFlowReturn(param, kind, read) + exists(ParamNode param, DataFlowType pt, DataFlowType at | + viableParamArg(call, param, arg) and + parameterValueFlowReturn(param, kind, pt, read) and + at = getNodeDataFlowType(arg) and + if read = TReadStepTypesNone() and typeStrongerThan(at, pt) then t = at else t = pt ) } @@ -739,18 +772,27 @@ module MakeImplCommon { * container type, and the content type. */ cached - predicate argumentValueFlowsThrough(ArgNode arg, ReadStepTypesOption read, Node out) { - exists(DataFlowCall call, ReturnKind kind | - argumentValueFlowsThrough0(call, arg, kind, read) and - out = getAnOutNode(call, kind) - | - // normal flow through - read = TReadStepTypesNone() and - compatibleTypes(getNodeDataFlowType(arg), getNodeDataFlowType(out)) - or - // getter - compatibleTypes(getNodeDataFlowType(arg), read.getContainerType()) and - compatibleTypes(read.getContentType(), getNodeDataFlowType(out)) + predicate argumentValueFlowsThrough( + ArgNode arg, DataFlowType t, ReadStepTypesOption read, Node out + ) { + exists(DataFlowCall call, ReturnKind kind, DataFlowType at, DataFlowType ot | + argumentValueFlowsThrough0(call, arg, kind, at, read) and + out = getAnOutNode(call, kind) and + ot = getNodeDataFlowType(out) and + if typeStrongerThan(ot, at) + then t = ot + else ( + t = at and + compatibleTypes(at, ot) + ) + // | + // // normal flow through + // read = TReadStepTypesNone() and + // compatibleTypes(getNodeDataFlowType(arg), getNodeDataFlowType(out)) + // or + // // getter + // compatibleTypes(getNodeDataFlowType(arg), read.getContainerType()) and + // compatibleTypes(read.getContentType(), getNodeDataFlowType(out)) ) } @@ -762,7 +804,7 @@ module MakeImplCommon { * This predicate is exposed for testing only. */ predicate getterStep(ArgNode arg, ContentSet c, Node out) { - argumentValueFlowsThrough(arg, TReadStepTypesSome(_, c, _), out) + argumentValueFlowsThrough(arg, _, TReadStepTypesSome(c, _), out) } /** @@ -774,10 +816,10 @@ module MakeImplCommon { * container type, and the content type. */ private predicate parameterValueFlowReturn( - ParamNode p, ReturnKind kind, ReadStepTypesOption read + ParamNode p, ReturnKind kind, DataFlowType t, ReadStepTypesOption read ) { exists(ReturnNode ret | - parameterValueFlow(p, ret, read) and + parameterValueFlow(p, ret, t, read) and kind = ret.getKind() ) } @@ -893,7 +935,7 @@ module MakeImplCommon { * node `n`, in the same callable, using only value-preserving steps. */ private predicate parameterValueFlowsToPreUpdate(ParamNode p, PostUpdateNode n) { - parameterValueFlow(p, n.getPreUpdateNode(), TReadStepTypesNone()) + parameterValueFlow(p, n.getPreUpdateNode(), _, TReadStepTypesNone()) } cached @@ -911,7 +953,7 @@ module MakeImplCommon { n1 = node1.(PostUpdateNode).getPreUpdateNode() and n2 = node2.(PostUpdateNode).getPreUpdateNode() | - argumentValueFlowsThrough(n2, TReadStepTypesSome(containerType, c, contentType), n1) + argumentValueFlowsThrough(n2, containerType, TReadStepTypesSome(c, contentType), n1) or readSet(n2, c, n1) and contentType = getNodeDataFlowType(n1) and @@ -953,10 +995,10 @@ module MakeImplCommon { // from function input to output? fromPre = getAnOutNode(c, _) and toPre.(ArgNode).argumentOf(c, _) and - simpleLocalFlowStep(toPre.(ArgNode), fromPre) + simpleLocalFlowStep(toPre, fromPre) ) or - argumentValueFlowsThrough(toPre, TReadStepTypesNone(), fromPre) + argumentValueFlowsThrough(toPre, _, TReadStepTypesNone(), fromPre) ) } @@ -1482,18 +1524,17 @@ module MakeImplCommon { private newtype TReadStepTypesOption = TReadStepTypesNone() or - TReadStepTypesSome(DataFlowType container, ContentSet c, DataFlowType content) { - readStepWithTypes(_, container, c, _, content) + TReadStepTypesSome(ContentSet c, DataFlowType content) { + readStepWithTypes(_, _, c, _, content) } private class ReadStepTypesOption extends TReadStepTypesOption { predicate isSome() { this instanceof TReadStepTypesSome } - DataFlowType getContainerType() { this = TReadStepTypesSome(result, _, _) } - - ContentSet getContent() { this = TReadStepTypesSome(_, result, _) } + // DataFlowType getContainerType() { this = TReadStepTypesSome(result, _, _) } + ContentSet getContent() { this = TReadStepTypesSome(result, _) } - DataFlowType getContentType() { this = TReadStepTypesSome(_, _, result) } + DataFlowType getContentType() { this = TReadStepTypesSome(_, result) } string toString() { if this.isSome() then result = "Some(..)" else result = "None()" } }