diff --git a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl.qll b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl.qll index ddf98ac0f2f..984c5ae2018 100644 --- a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl.qll +++ b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl.qll @@ -1135,8 +1135,8 @@ module Impl { DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow ); - bindingset[node, state, t, ap] - predicate filter(NodeEx node, FlowState state, Typ t, Ap ap); + bindingset[node, state, t0, ap] + predicate filter(NodeEx node, FlowState state, Typ t0, Ap ap, Typ t); bindingset[typ, contentType] predicate typecheckStore(Typ typ, DataFlowType contentType); @@ -1199,17 +1199,21 @@ module Impl { NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, TypOption argT, ApOption argAp, Typ t, Ap ap, ApApprox apa ) { - fwdFlow0(node, state, cc, summaryCtx, argT, argAp, t, ap, apa) and - PrevStage::revFlow(node, state, apa) and - filter(node, state, t, ap) + fwdFlow1(node, state, cc, summaryCtx, argT, argAp, _, t, ap, apa) } - pragma[inline] - additional predicate fwdFlow( + private predicate fwdFlow1( NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, TypOption argT, - ApOption argAp, Typ t, Ap ap + ApOption argAp, Typ t0, Typ t, Ap ap, ApApprox apa ) { - fwdFlow(node, state, cc, summaryCtx, argT, argAp, t, ap, _) + fwdFlow0(node, state, cc, summaryCtx, argT, argAp, t0, ap, apa) and + PrevStage::revFlow(node, state, apa) and + filter(node, state, t0, ap, t) + } + + pragma[nomagic] + private predicate typeStrengthen(Typ t0, Ap ap, Typ t) { + fwdFlow1(_, _, _, _, _, _, t0, t, ap, _) and t0 != t } pragma[assume_small_delta] @@ -1339,6 +1343,11 @@ module Impl { private predicate fwdFlowConsCand(Typ t2, Ap cons, Content c, Typ t1, Ap tail) { fwdFlowStore(_, t1, tail, c, t2, _, _, _, _, _, _) and cons = apCons(c, t1, tail) + or + exists(Typ t0 | + typeStrengthen(t0, cons, t2) and + fwdFlowConsCand(t0, cons, c, t1, tail) + ) } pragma[nomagic] @@ -1359,7 +1368,7 @@ module Impl { ParamNodeOption summaryCtx, TypOption argT, ApOption argAp ) { exists(ApHeadContent apc | - fwdFlow(node1, state, cc, summaryCtx, argT, argAp, t, ap) and + fwdFlow(node1, state, cc, summaryCtx, argT, argAp, t, ap, _) and apc = getHeadContent(ap) and readStepCand0(node1, apc, c, node2) ) @@ -1520,14 +1529,14 @@ module Impl { 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() @@ -1780,13 +1789,13 @@ module Impl { boolean fwd, int nodes, int fields, int conscand, int states, int tuples ) { fwd = true and - nodes = count(NodeEx node | fwdFlow(node, _, _, _, _, _, _, _)) 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 + states = count(FlowState state | fwdFlow(_, state, _, _, _, _, _, _, _)) and tuples = count(NodeEx n, FlowState state, Cc cc, ParamNodeOption summaryCtx, TypOption argT, - ApOption argAp, Typ t, Ap ap | fwdFlow(n, state, cc, summaryCtx, argT, argAp, t, ap)) + ApOption argAp, Typ t, Ap ap | fwdFlow(n, state, cc, summaryCtx, argT, argAp, t, ap, _)) or fwd = false and nodes = count(NodeEx node | revFlow(node, _, _, _, _)) and @@ -1963,10 +1972,10 @@ module Impl { ) } - bindingset[node, state, t, ap] - predicate filter(NodeEx node, FlowState state, Typ t, Ap ap) { + bindingset[node, state, t0, ap] + predicate filter(NodeEx node, FlowState state, Typ t0, Ap ap, Typ t) { PrevStage::revFlowState(state) and - exists(t) and + t0 = t and exists(ap) and not stateBarrier(node, state) and ( @@ -2197,8 +2206,8 @@ module Impl { import BooleanCallContext predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - DataFlowType t, LocalCc lcc + NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, Typ t, + LocalCc lcc ) { localFlowBigStep(node1, state1, node2, state2, preservesValue, t, _) and exists(lcc) @@ -2218,10 +2227,16 @@ module Impl { ) } - bindingset[node, state, t, ap] - predicate filter(NodeEx node, FlowState state, Typ t, Ap ap) { + bindingset[node, state, t0, ap] + predicate filter(NodeEx node, FlowState state, Typ t0, Ap ap, Typ t) { exists(state) and - (if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), t) else any()) 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 @@ -2241,6 +2256,16 @@ module Impl { import MkStage::Stage } + bindingset[node, t0] + private predicate strengthenType(NodeEx node, DataFlowType t0, DataFlowType t) { + if castingNodeEx(node) + then + exists(DataFlowType nt | nt = node.getDataFlowType() | + if typeStrongerThan(nt, t0) then t = nt else (compatibleTypes(nt, t0) and t = t0) + ) + else t = t0 + } + private module Stage4Param implements MkStage::StageParam { private module PrevStage = Stage3; @@ -2274,8 +2299,8 @@ module Impl { pragma[nomagic] predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - DataFlowType t, LocalCc lcc + 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 @@ -2333,11 +2358,11 @@ module Impl { ) } - bindingset[node, state, t, ap] - predicate filter(NodeEx node, FlowState state, Typ t, Ap ap) { + 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 - (if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), t) else any()) and + strengthenType(node, t0, t) and ( notExpectsContent(node) or @@ -2365,7 +2390,7 @@ module Impl { exists(AccessPathFront apf | Stage4::revFlow(node, state, TReturnCtxMaybeFlowThrough(_), _, apf) and Stage4::fwdFlow(node, state, any(Stage4::CcCall ccc), _, _, TAccessPathFrontSome(argApf), _, - apf) + apf, _) ) } @@ -2579,8 +2604,8 @@ module Impl { import LocalCallContext predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - DataFlowType t, LocalCc lcc + NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, Typ t, + LocalCc lcc ) { localFlowBigStep(node1, state1, node2, state2, preservesValue, t, lcc) and PrevStage::revFlow(node1, pragma[only_bind_into](state1), _) and @@ -2609,9 +2634,9 @@ module Impl { ) } - bindingset[node, state, t, ap] - predicate filter(NodeEx node, FlowState state, Typ t, Ap ap) { - (if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), t) else any()) and + bindingset[node, state, t0, ap] + predicate filter(NodeEx node, FlowState state, Typ t0, Ap ap, Typ t) { + strengthenType(node, t0, t) and exists(state) and exists(ap) } @@ -2632,7 +2657,7 @@ module Impl { 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, _) ) } @@ -2649,7 +2674,7 @@ module Impl { TSummaryCtxSome(ParamNodeEx p, FlowState state, DataFlowType t, AccessPath ap) { exists(AccessPathApprox apa | ap.getApprox() = apa | Stage5::parameterMayFlowThrough(p, apa) and - Stage5::fwdFlow(p, state, _, _, _, _, t, apa) and + Stage5::fwdFlow(p, state, _, _, Option::some(t), _, _, apa, _) and Stage5::revFlow(p, state, _) ) } @@ -2820,9 +2845,7 @@ module Impl { ap = TAccessPathNil() or // ... or a step from an existing PathNode to another node. - pathStep(_, node, state, cc, sc, t, ap) and - Stage5::revFlow(node, state, ap.getApprox()) and - (if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), t) else any()) + pathStep(_, node, state, cc, sc, t, ap) } or TPathNodeSink(NodeEx node, FlowState state) { exists(PathNodeMid sink | @@ -3340,13 +3363,24 @@ module Impl { ap = mid.getAp() } + private predicate pathStep( + PathNodeMid mid, NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, DataFlowType t, + AccessPath ap + ) { + exists(DataFlowType t0 | + pathStep0(mid, node, state, cc, sc, t0, ap) and + Stage5::revFlow(node, state, ap.getApprox()) and + strengthenType(node, t0, t) + ) + } + /** * Holds if data may flow from `mid` to `node`. The last step in or out of * a callable is recorded by `cc`. */ pragma[assume_small_delta] pragma[nomagic] - private predicate pathStep( + private predicate pathStep0( PathNodeMid mid, NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, DataFlowType t, AccessPath ap ) { @@ -3964,7 +3998,7 @@ module Impl { ap = TPartialNil() and exists(explorationLimit()) or - partialPathNodeMk0(node, state, cc, sc1, sc2, sc3, sc4, t, ap) and + partialPathStep(_, node, state, cc, sc1, sc2, sc3, sc4, t, ap) and distSrc(node.getEnclosingCallable()) <= explorationLimit() } or TPartialPathNodeRev( @@ -3990,11 +4024,20 @@ module Impl { } pragma[nomagic] - private predicate partialPathNodeMk0( - NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, - TSummaryCtx3 sc3, TSummaryCtx4 sc4, DataFlowType t, PartialAccessPath ap + private predicate partialPathStep( + PartialPathNodeFwd mid, NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, + TSummaryCtx2 sc2, TSummaryCtx3 sc3, TSummaryCtx4 sc4, DataFlowType t, PartialAccessPath ap ) { - partialPathStep(_, node, state, cc, sc1, sc2, sc3, sc4, t, ap) and + partialPathStep1(mid, node, state, cc, sc1, sc2, sc3, sc4, _, t, ap) + } + + pragma[nomagic] + private predicate partialPathStep1( + PartialPathNodeFwd mid, NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, + TSummaryCtx2 sc2, TSummaryCtx3 sc3, TSummaryCtx4 sc4, DataFlowType t0, DataFlowType t, + PartialAccessPath ap + ) { + partialPathStep0(mid, node, state, cc, sc1, sc2, sc3, sc4, t0, ap) and not fullBarrier(node) and not stateBarrier(node, state) and not clearsContentEx(node, ap.getHead()) and @@ -4002,9 +4045,14 @@ module Impl { notExpectsContent(node) or expectsContentEx(node, ap.getHead()) ) and - if node.asNode() instanceof CastingNode - then compatibleTypes(node.getDataFlowType(), t) - else any() + strengthenType(node, t0, t) + } + + pragma[nomagic] + private predicate partialPathTypeStrengthen( + DataFlowType t0, PartialAccessPath ap, DataFlowType t + ) { + partialPathStep1(_, _, _, _, _, _, _, _, t0, t, ap) and t0 != t } /** @@ -4183,7 +4231,8 @@ module Impl { } } - private predicate partialPathStep( + pragma[nomagic] + private predicate partialPathStep0( PartialPathNodeFwd mid, NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, TSummaryCtx3 sc3, TSummaryCtx4 sc4, DataFlowType t, PartialAccessPath ap ) { @@ -4309,6 +4358,11 @@ module Impl { DataFlowType t1, PartialAccessPath ap1, Content c, DataFlowType t2, PartialAccessPath ap2 ) { partialPathStoreStep(_, t1, ap1, c, _, t2, ap2) + or + exists(DataFlowType t0 | + partialPathTypeStrengthen(t0, ap2, t2) and + apConsFwd(t1, ap1, c, t0, ap2) + ) } pragma[nomagic] diff --git a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowPrivate.qll b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowPrivate.qll index 9b4e0e6a4f9..115989e3dea 100644 --- a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowPrivate.qll +++ b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowPrivate.qll @@ -205,6 +205,8 @@ predicate clearsContent(Node n, Content c) { */ predicate expectsContent(Node n, ContentSet c) { none() } +predicate typeStrongerThan(DataFlowType t1, DataFlowType t2) { none() } + /** Gets the type of `n` used for type pruning. */ Type getNodeType(Node n) { suppressUnusedNode(n) and diff --git a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl.qll b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl.qll index ddf98ac0f2f..984c5ae2018 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl.qll @@ -1135,8 +1135,8 @@ module Impl { DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow ); - bindingset[node, state, t, ap] - predicate filter(NodeEx node, FlowState state, Typ t, Ap ap); + bindingset[node, state, t0, ap] + predicate filter(NodeEx node, FlowState state, Typ t0, Ap ap, Typ t); bindingset[typ, contentType] predicate typecheckStore(Typ typ, DataFlowType contentType); @@ -1199,17 +1199,21 @@ module Impl { NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, TypOption argT, ApOption argAp, Typ t, Ap ap, ApApprox apa ) { - fwdFlow0(node, state, cc, summaryCtx, argT, argAp, t, ap, apa) and - PrevStage::revFlow(node, state, apa) and - filter(node, state, t, ap) + fwdFlow1(node, state, cc, summaryCtx, argT, argAp, _, t, ap, apa) } - pragma[inline] - additional predicate fwdFlow( + private predicate fwdFlow1( NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, TypOption argT, - ApOption argAp, Typ t, Ap ap + ApOption argAp, Typ t0, Typ t, Ap ap, ApApprox apa ) { - fwdFlow(node, state, cc, summaryCtx, argT, argAp, t, ap, _) + fwdFlow0(node, state, cc, summaryCtx, argT, argAp, t0, ap, apa) and + PrevStage::revFlow(node, state, apa) and + filter(node, state, t0, ap, t) + } + + pragma[nomagic] + private predicate typeStrengthen(Typ t0, Ap ap, Typ t) { + fwdFlow1(_, _, _, _, _, _, t0, t, ap, _) and t0 != t } pragma[assume_small_delta] @@ -1339,6 +1343,11 @@ module Impl { private predicate fwdFlowConsCand(Typ t2, Ap cons, Content c, Typ t1, Ap tail) { fwdFlowStore(_, t1, tail, c, t2, _, _, _, _, _, _) and cons = apCons(c, t1, tail) + or + exists(Typ t0 | + typeStrengthen(t0, cons, t2) and + fwdFlowConsCand(t0, cons, c, t1, tail) + ) } pragma[nomagic] @@ -1359,7 +1368,7 @@ module Impl { ParamNodeOption summaryCtx, TypOption argT, ApOption argAp ) { exists(ApHeadContent apc | - fwdFlow(node1, state, cc, summaryCtx, argT, argAp, t, ap) and + fwdFlow(node1, state, cc, summaryCtx, argT, argAp, t, ap, _) and apc = getHeadContent(ap) and readStepCand0(node1, apc, c, node2) ) @@ -1520,14 +1529,14 @@ module Impl { 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() @@ -1780,13 +1789,13 @@ module Impl { boolean fwd, int nodes, int fields, int conscand, int states, int tuples ) { fwd = true and - nodes = count(NodeEx node | fwdFlow(node, _, _, _, _, _, _, _)) 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 + states = count(FlowState state | fwdFlow(_, state, _, _, _, _, _, _, _)) and tuples = count(NodeEx n, FlowState state, Cc cc, ParamNodeOption summaryCtx, TypOption argT, - ApOption argAp, Typ t, Ap ap | fwdFlow(n, state, cc, summaryCtx, argT, argAp, t, ap)) + ApOption argAp, Typ t, Ap ap | fwdFlow(n, state, cc, summaryCtx, argT, argAp, t, ap, _)) or fwd = false and nodes = count(NodeEx node | revFlow(node, _, _, _, _)) and @@ -1963,10 +1972,10 @@ module Impl { ) } - bindingset[node, state, t, ap] - predicate filter(NodeEx node, FlowState state, Typ t, Ap ap) { + bindingset[node, state, t0, ap] + predicate filter(NodeEx node, FlowState state, Typ t0, Ap ap, Typ t) { PrevStage::revFlowState(state) and - exists(t) and + t0 = t and exists(ap) and not stateBarrier(node, state) and ( @@ -2197,8 +2206,8 @@ module Impl { import BooleanCallContext predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - DataFlowType t, LocalCc lcc + NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, Typ t, + LocalCc lcc ) { localFlowBigStep(node1, state1, node2, state2, preservesValue, t, _) and exists(lcc) @@ -2218,10 +2227,16 @@ module Impl { ) } - bindingset[node, state, t, ap] - predicate filter(NodeEx node, FlowState state, Typ t, Ap ap) { + bindingset[node, state, t0, ap] + predicate filter(NodeEx node, FlowState state, Typ t0, Ap ap, Typ t) { exists(state) and - (if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), t) else any()) 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 @@ -2241,6 +2256,16 @@ module Impl { import MkStage::Stage } + bindingset[node, t0] + private predicate strengthenType(NodeEx node, DataFlowType t0, DataFlowType t) { + if castingNodeEx(node) + then + exists(DataFlowType nt | nt = node.getDataFlowType() | + if typeStrongerThan(nt, t0) then t = nt else (compatibleTypes(nt, t0) and t = t0) + ) + else t = t0 + } + private module Stage4Param implements MkStage::StageParam { private module PrevStage = Stage3; @@ -2274,8 +2299,8 @@ module Impl { pragma[nomagic] predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - DataFlowType t, LocalCc lcc + 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 @@ -2333,11 +2358,11 @@ module Impl { ) } - bindingset[node, state, t, ap] - predicate filter(NodeEx node, FlowState state, Typ t, Ap ap) { + 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 - (if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), t) else any()) and + strengthenType(node, t0, t) and ( notExpectsContent(node) or @@ -2365,7 +2390,7 @@ module Impl { exists(AccessPathFront apf | Stage4::revFlow(node, state, TReturnCtxMaybeFlowThrough(_), _, apf) and Stage4::fwdFlow(node, state, any(Stage4::CcCall ccc), _, _, TAccessPathFrontSome(argApf), _, - apf) + apf, _) ) } @@ -2579,8 +2604,8 @@ module Impl { import LocalCallContext predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - DataFlowType t, LocalCc lcc + NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, Typ t, + LocalCc lcc ) { localFlowBigStep(node1, state1, node2, state2, preservesValue, t, lcc) and PrevStage::revFlow(node1, pragma[only_bind_into](state1), _) and @@ -2609,9 +2634,9 @@ module Impl { ) } - bindingset[node, state, t, ap] - predicate filter(NodeEx node, FlowState state, Typ t, Ap ap) { - (if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), t) else any()) and + bindingset[node, state, t0, ap] + predicate filter(NodeEx node, FlowState state, Typ t0, Ap ap, Typ t) { + strengthenType(node, t0, t) and exists(state) and exists(ap) } @@ -2632,7 +2657,7 @@ module Impl { 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, _) ) } @@ -2649,7 +2674,7 @@ module Impl { TSummaryCtxSome(ParamNodeEx p, FlowState state, DataFlowType t, AccessPath ap) { exists(AccessPathApprox apa | ap.getApprox() = apa | Stage5::parameterMayFlowThrough(p, apa) and - Stage5::fwdFlow(p, state, _, _, _, _, t, apa) and + Stage5::fwdFlow(p, state, _, _, Option::some(t), _, _, apa, _) and Stage5::revFlow(p, state, _) ) } @@ -2820,9 +2845,7 @@ module Impl { ap = TAccessPathNil() or // ... or a step from an existing PathNode to another node. - pathStep(_, node, state, cc, sc, t, ap) and - Stage5::revFlow(node, state, ap.getApprox()) and - (if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), t) else any()) + pathStep(_, node, state, cc, sc, t, ap) } or TPathNodeSink(NodeEx node, FlowState state) { exists(PathNodeMid sink | @@ -3340,13 +3363,24 @@ module Impl { ap = mid.getAp() } + private predicate pathStep( + PathNodeMid mid, NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, DataFlowType t, + AccessPath ap + ) { + exists(DataFlowType t0 | + pathStep0(mid, node, state, cc, sc, t0, ap) and + Stage5::revFlow(node, state, ap.getApprox()) and + strengthenType(node, t0, t) + ) + } + /** * Holds if data may flow from `mid` to `node`. The last step in or out of * a callable is recorded by `cc`. */ pragma[assume_small_delta] pragma[nomagic] - private predicate pathStep( + private predicate pathStep0( PathNodeMid mid, NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, DataFlowType t, AccessPath ap ) { @@ -3964,7 +3998,7 @@ module Impl { ap = TPartialNil() and exists(explorationLimit()) or - partialPathNodeMk0(node, state, cc, sc1, sc2, sc3, sc4, t, ap) and + partialPathStep(_, node, state, cc, sc1, sc2, sc3, sc4, t, ap) and distSrc(node.getEnclosingCallable()) <= explorationLimit() } or TPartialPathNodeRev( @@ -3990,11 +4024,20 @@ module Impl { } pragma[nomagic] - private predicate partialPathNodeMk0( - NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, - TSummaryCtx3 sc3, TSummaryCtx4 sc4, DataFlowType t, PartialAccessPath ap + private predicate partialPathStep( + PartialPathNodeFwd mid, NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, + TSummaryCtx2 sc2, TSummaryCtx3 sc3, TSummaryCtx4 sc4, DataFlowType t, PartialAccessPath ap ) { - partialPathStep(_, node, state, cc, sc1, sc2, sc3, sc4, t, ap) and + partialPathStep1(mid, node, state, cc, sc1, sc2, sc3, sc4, _, t, ap) + } + + pragma[nomagic] + private predicate partialPathStep1( + PartialPathNodeFwd mid, NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, + TSummaryCtx2 sc2, TSummaryCtx3 sc3, TSummaryCtx4 sc4, DataFlowType t0, DataFlowType t, + PartialAccessPath ap + ) { + partialPathStep0(mid, node, state, cc, sc1, sc2, sc3, sc4, t0, ap) and not fullBarrier(node) and not stateBarrier(node, state) and not clearsContentEx(node, ap.getHead()) and @@ -4002,9 +4045,14 @@ module Impl { notExpectsContent(node) or expectsContentEx(node, ap.getHead()) ) and - if node.asNode() instanceof CastingNode - then compatibleTypes(node.getDataFlowType(), t) - else any() + strengthenType(node, t0, t) + } + + pragma[nomagic] + private predicate partialPathTypeStrengthen( + DataFlowType t0, PartialAccessPath ap, DataFlowType t + ) { + partialPathStep1(_, _, _, _, _, _, _, _, t0, t, ap) and t0 != t } /** @@ -4183,7 +4231,8 @@ module Impl { } } - private predicate partialPathStep( + pragma[nomagic] + private predicate partialPathStep0( PartialPathNodeFwd mid, NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, TSummaryCtx3 sc3, TSummaryCtx4 sc4, DataFlowType t, PartialAccessPath ap ) { @@ -4309,6 +4358,11 @@ module Impl { DataFlowType t1, PartialAccessPath ap1, Content c, DataFlowType t2, PartialAccessPath ap2 ) { partialPathStoreStep(_, t1, ap1, c, _, t2, ap2) + or + exists(DataFlowType t0 | + partialPathTypeStrengthen(t0, ap2, t2) and + apConsFwd(t1, ap1, c, t0, ap2) + ) } pragma[nomagic] diff --git a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll index cc8d0cdbe94..33ff6f74775 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll @@ -753,6 +753,8 @@ predicate clearsContent(Node n, Content c) { */ predicate expectsContent(Node n, ContentSet c) { none() } +predicate typeStrongerThan(DataFlowType t1, DataFlowType t2) { none() } + /** Gets the type of `n` used for type pruning. */ DataFlowType getNodeType(Node n) { suppressUnusedNode(n) and diff --git a/csharp/ql/lib/change-notes/2023-06-08-type-strengthening.md b/csharp/ql/lib/change-notes/2023-06-08-type-strengthening.md new file mode 100644 index 00000000000..60daaa53058 --- /dev/null +++ b/csharp/ql/lib/change-notes/2023-06-08-type-strengthening.md @@ -0,0 +1,4 @@ +--- +category: majorAnalysis +--- +* The data flow library now performs type strengthening. This increases precision for all data flow queries by excluding paths that can be inferred to be impossible due to incompatible types. diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl.qll index ddf98ac0f2f..984c5ae2018 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl.qll @@ -1135,8 +1135,8 @@ module Impl { DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow ); - bindingset[node, state, t, ap] - predicate filter(NodeEx node, FlowState state, Typ t, Ap ap); + bindingset[node, state, t0, ap] + predicate filter(NodeEx node, FlowState state, Typ t0, Ap ap, Typ t); bindingset[typ, contentType] predicate typecheckStore(Typ typ, DataFlowType contentType); @@ -1199,17 +1199,21 @@ module Impl { NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, TypOption argT, ApOption argAp, Typ t, Ap ap, ApApprox apa ) { - fwdFlow0(node, state, cc, summaryCtx, argT, argAp, t, ap, apa) and - PrevStage::revFlow(node, state, apa) and - filter(node, state, t, ap) + fwdFlow1(node, state, cc, summaryCtx, argT, argAp, _, t, ap, apa) } - pragma[inline] - additional predicate fwdFlow( + private predicate fwdFlow1( NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, TypOption argT, - ApOption argAp, Typ t, Ap ap + ApOption argAp, Typ t0, Typ t, Ap ap, ApApprox apa ) { - fwdFlow(node, state, cc, summaryCtx, argT, argAp, t, ap, _) + fwdFlow0(node, state, cc, summaryCtx, argT, argAp, t0, ap, apa) and + PrevStage::revFlow(node, state, apa) and + filter(node, state, t0, ap, t) + } + + pragma[nomagic] + private predicate typeStrengthen(Typ t0, Ap ap, Typ t) { + fwdFlow1(_, _, _, _, _, _, t0, t, ap, _) and t0 != t } pragma[assume_small_delta] @@ -1339,6 +1343,11 @@ module Impl { private predicate fwdFlowConsCand(Typ t2, Ap cons, Content c, Typ t1, Ap tail) { fwdFlowStore(_, t1, tail, c, t2, _, _, _, _, _, _) and cons = apCons(c, t1, tail) + or + exists(Typ t0 | + typeStrengthen(t0, cons, t2) and + fwdFlowConsCand(t0, cons, c, t1, tail) + ) } pragma[nomagic] @@ -1359,7 +1368,7 @@ module Impl { ParamNodeOption summaryCtx, TypOption argT, ApOption argAp ) { exists(ApHeadContent apc | - fwdFlow(node1, state, cc, summaryCtx, argT, argAp, t, ap) and + fwdFlow(node1, state, cc, summaryCtx, argT, argAp, t, ap, _) and apc = getHeadContent(ap) and readStepCand0(node1, apc, c, node2) ) @@ -1520,14 +1529,14 @@ module Impl { 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() @@ -1780,13 +1789,13 @@ module Impl { boolean fwd, int nodes, int fields, int conscand, int states, int tuples ) { fwd = true and - nodes = count(NodeEx node | fwdFlow(node, _, _, _, _, _, _, _)) 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 + states = count(FlowState state | fwdFlow(_, state, _, _, _, _, _, _, _)) and tuples = count(NodeEx n, FlowState state, Cc cc, ParamNodeOption summaryCtx, TypOption argT, - ApOption argAp, Typ t, Ap ap | fwdFlow(n, state, cc, summaryCtx, argT, argAp, t, ap)) + ApOption argAp, Typ t, Ap ap | fwdFlow(n, state, cc, summaryCtx, argT, argAp, t, ap, _)) or fwd = false and nodes = count(NodeEx node | revFlow(node, _, _, _, _)) and @@ -1963,10 +1972,10 @@ module Impl { ) } - bindingset[node, state, t, ap] - predicate filter(NodeEx node, FlowState state, Typ t, Ap ap) { + bindingset[node, state, t0, ap] + predicate filter(NodeEx node, FlowState state, Typ t0, Ap ap, Typ t) { PrevStage::revFlowState(state) and - exists(t) and + t0 = t and exists(ap) and not stateBarrier(node, state) and ( @@ -2197,8 +2206,8 @@ module Impl { import BooleanCallContext predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - DataFlowType t, LocalCc lcc + NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, Typ t, + LocalCc lcc ) { localFlowBigStep(node1, state1, node2, state2, preservesValue, t, _) and exists(lcc) @@ -2218,10 +2227,16 @@ module Impl { ) } - bindingset[node, state, t, ap] - predicate filter(NodeEx node, FlowState state, Typ t, Ap ap) { + bindingset[node, state, t0, ap] + predicate filter(NodeEx node, FlowState state, Typ t0, Ap ap, Typ t) { exists(state) and - (if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), t) else any()) 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 @@ -2241,6 +2256,16 @@ module Impl { import MkStage::Stage } + bindingset[node, t0] + private predicate strengthenType(NodeEx node, DataFlowType t0, DataFlowType t) { + if castingNodeEx(node) + then + exists(DataFlowType nt | nt = node.getDataFlowType() | + if typeStrongerThan(nt, t0) then t = nt else (compatibleTypes(nt, t0) and t = t0) + ) + else t = t0 + } + private module Stage4Param implements MkStage::StageParam { private module PrevStage = Stage3; @@ -2274,8 +2299,8 @@ module Impl { pragma[nomagic] predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - DataFlowType t, LocalCc lcc + 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 @@ -2333,11 +2358,11 @@ module Impl { ) } - bindingset[node, state, t, ap] - predicate filter(NodeEx node, FlowState state, Typ t, Ap ap) { + 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 - (if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), t) else any()) and + strengthenType(node, t0, t) and ( notExpectsContent(node) or @@ -2365,7 +2390,7 @@ module Impl { exists(AccessPathFront apf | Stage4::revFlow(node, state, TReturnCtxMaybeFlowThrough(_), _, apf) and Stage4::fwdFlow(node, state, any(Stage4::CcCall ccc), _, _, TAccessPathFrontSome(argApf), _, - apf) + apf, _) ) } @@ -2579,8 +2604,8 @@ module Impl { import LocalCallContext predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - DataFlowType t, LocalCc lcc + NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, Typ t, + LocalCc lcc ) { localFlowBigStep(node1, state1, node2, state2, preservesValue, t, lcc) and PrevStage::revFlow(node1, pragma[only_bind_into](state1), _) and @@ -2609,9 +2634,9 @@ module Impl { ) } - bindingset[node, state, t, ap] - predicate filter(NodeEx node, FlowState state, Typ t, Ap ap) { - (if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), t) else any()) and + bindingset[node, state, t0, ap] + predicate filter(NodeEx node, FlowState state, Typ t0, Ap ap, Typ t) { + strengthenType(node, t0, t) and exists(state) and exists(ap) } @@ -2632,7 +2657,7 @@ module Impl { 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, _) ) } @@ -2649,7 +2674,7 @@ module Impl { TSummaryCtxSome(ParamNodeEx p, FlowState state, DataFlowType t, AccessPath ap) { exists(AccessPathApprox apa | ap.getApprox() = apa | Stage5::parameterMayFlowThrough(p, apa) and - Stage5::fwdFlow(p, state, _, _, _, _, t, apa) and + Stage5::fwdFlow(p, state, _, _, Option::some(t), _, _, apa, _) and Stage5::revFlow(p, state, _) ) } @@ -2820,9 +2845,7 @@ module Impl { ap = TAccessPathNil() or // ... or a step from an existing PathNode to another node. - pathStep(_, node, state, cc, sc, t, ap) and - Stage5::revFlow(node, state, ap.getApprox()) and - (if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), t) else any()) + pathStep(_, node, state, cc, sc, t, ap) } or TPathNodeSink(NodeEx node, FlowState state) { exists(PathNodeMid sink | @@ -3340,13 +3363,24 @@ module Impl { ap = mid.getAp() } + private predicate pathStep( + PathNodeMid mid, NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, DataFlowType t, + AccessPath ap + ) { + exists(DataFlowType t0 | + pathStep0(mid, node, state, cc, sc, t0, ap) and + Stage5::revFlow(node, state, ap.getApprox()) and + strengthenType(node, t0, t) + ) + } + /** * Holds if data may flow from `mid` to `node`. The last step in or out of * a callable is recorded by `cc`. */ pragma[assume_small_delta] pragma[nomagic] - private predicate pathStep( + private predicate pathStep0( PathNodeMid mid, NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, DataFlowType t, AccessPath ap ) { @@ -3964,7 +3998,7 @@ module Impl { ap = TPartialNil() and exists(explorationLimit()) or - partialPathNodeMk0(node, state, cc, sc1, sc2, sc3, sc4, t, ap) and + partialPathStep(_, node, state, cc, sc1, sc2, sc3, sc4, t, ap) and distSrc(node.getEnclosingCallable()) <= explorationLimit() } or TPartialPathNodeRev( @@ -3990,11 +4024,20 @@ module Impl { } pragma[nomagic] - private predicate partialPathNodeMk0( - NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, - TSummaryCtx3 sc3, TSummaryCtx4 sc4, DataFlowType t, PartialAccessPath ap + private predicate partialPathStep( + PartialPathNodeFwd mid, NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, + TSummaryCtx2 sc2, TSummaryCtx3 sc3, TSummaryCtx4 sc4, DataFlowType t, PartialAccessPath ap ) { - partialPathStep(_, node, state, cc, sc1, sc2, sc3, sc4, t, ap) and + partialPathStep1(mid, node, state, cc, sc1, sc2, sc3, sc4, _, t, ap) + } + + pragma[nomagic] + private predicate partialPathStep1( + PartialPathNodeFwd mid, NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, + TSummaryCtx2 sc2, TSummaryCtx3 sc3, TSummaryCtx4 sc4, DataFlowType t0, DataFlowType t, + PartialAccessPath ap + ) { + partialPathStep0(mid, node, state, cc, sc1, sc2, sc3, sc4, t0, ap) and not fullBarrier(node) and not stateBarrier(node, state) and not clearsContentEx(node, ap.getHead()) and @@ -4002,9 +4045,14 @@ module Impl { notExpectsContent(node) or expectsContentEx(node, ap.getHead()) ) and - if node.asNode() instanceof CastingNode - then compatibleTypes(node.getDataFlowType(), t) - else any() + strengthenType(node, t0, t) + } + + pragma[nomagic] + private predicate partialPathTypeStrengthen( + DataFlowType t0, PartialAccessPath ap, DataFlowType t + ) { + partialPathStep1(_, _, _, _, _, _, _, _, t0, t, ap) and t0 != t } /** @@ -4183,7 +4231,8 @@ module Impl { } } - private predicate partialPathStep( + pragma[nomagic] + private predicate partialPathStep0( PartialPathNodeFwd mid, NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, TSummaryCtx3 sc3, TSummaryCtx4 sc4, DataFlowType t, PartialAccessPath ap ) { @@ -4309,6 +4358,11 @@ module Impl { DataFlowType t1, PartialAccessPath ap1, Content c, DataFlowType t2, PartialAccessPath ap2 ) { partialPathStoreStep(_, t1, ap1, c, _, t2, ap2) + or + exists(DataFlowType t0 | + partialPathTypeStrengthen(t0, ap2, t2) and + apConsFwd(t1, ap1, c, t0, ap2) + ) } pragma[nomagic] diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowPrivate.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowPrivate.qll index d683e03dc2d..578c8fb8ed5 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowPrivate.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowPrivate.qll @@ -1984,6 +1984,21 @@ private class DataFlowUnknownType extends DataFlowType { DataFlowUnknownType() { this = Gvn::getGlobalValueNumber(any(UnknownType ut)) } } +private predicate uselessTypebound(DataFlowType t) { + t instanceof DataFlowUnknownType or + t instanceof Gvn::TypeParameterGvnType +} + +pragma[nomagic] +predicate typeStrongerThan(DataFlowType t1, DataFlowType t2) { + t1 != t2 and + t1 = getANonTypeParameterSubTypeRestricted(t2) + or + t1 instanceof RelevantDataFlowType and + not uselessTypebound(t1) and + uselessTypebound(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/csharp/ql/test/library-tests/dataflow/collections/CollectionFlow.expected b/csharp/ql/test/library-tests/dataflow/collections/CollectionFlow.expected index d5bbeef765a..1aabed1e806 100644 --- a/csharp/ql/test/library-tests/dataflow/collections/CollectionFlow.expected +++ b/csharp/ql/test/library-tests/dataflow/collections/CollectionFlow.expected @@ -214,8 +214,8 @@ edges | CollectionFlow.cs:385:58:385:61 | dict : Dictionary [element, property Value] : A | CollectionFlow.cs:385:67:385:70 | access to parameter dict : Dictionary [element, property Value] : A | | CollectionFlow.cs:385:67:385:70 | access to parameter dict : Dictionary [element, property Value] : A | CollectionFlow.cs:385:67:385:73 | access to indexer : A | | CollectionFlow.cs:387:59:387:62 | dict : Dictionary [element, property Value] : A | CollectionFlow.cs:387:68:387:71 | access to parameter dict : Dictionary [element, property Value] : A | -| CollectionFlow.cs:387:68:387:71 | access to parameter dict : Dictionary [element, property Value] : A | CollectionFlow.cs:387:68:387:79 | call to method First> : Object [property Value] : A | -| CollectionFlow.cs:387:68:387:79 | call to method First> : Object [property Value] : A | CollectionFlow.cs:387:68:387:85 | access to property Value : A | +| CollectionFlow.cs:387:68:387:71 | access to parameter dict : Dictionary [element, property Value] : A | CollectionFlow.cs:387:68:387:79 | call to method First> : KeyValuePair [property Value] : A | +| CollectionFlow.cs:387:68:387:79 | call to method First> : KeyValuePair [property Value] : A | CollectionFlow.cs:387:68:387:85 | access to property Value : A | | CollectionFlow.cs:389:60:389:63 | dict : Dictionary [element, property Value] : A | CollectionFlow.cs:389:69:389:72 | access to parameter dict : Dictionary [element, property Value] : A | | CollectionFlow.cs:389:69:389:72 | access to parameter dict : Dictionary [element, property Value] : A | CollectionFlow.cs:389:69:389:79 | access to property Values : ICollection [element] : A | | CollectionFlow.cs:389:69:389:79 | access to property Values : ICollection [element] : A | CollectionFlow.cs:389:69:389:87 | call to method First : A | @@ -223,8 +223,8 @@ edges | CollectionFlow.cs:391:67:391:70 | access to parameter dict : Dictionary [element, property Key] : A | CollectionFlow.cs:391:67:391:75 | access to property Keys : ICollection [element] : A | | CollectionFlow.cs:391:67:391:75 | access to property Keys : ICollection [element] : A | CollectionFlow.cs:391:67:391:83 | call to method First : A | | CollectionFlow.cs:393:57:393:60 | dict : Dictionary [element, property Key] : A | CollectionFlow.cs:393:66:393:69 | access to parameter dict : Dictionary [element, property Key] : A | -| CollectionFlow.cs:393:66:393:69 | access to parameter dict : Dictionary [element, property Key] : A | CollectionFlow.cs:393:66:393:77 | call to method First> : Object [property Key] : A | -| CollectionFlow.cs:393:66:393:77 | call to method First> : Object [property Key] : A | CollectionFlow.cs:393:66:393:81 | access to property Key : A | +| CollectionFlow.cs:393:66:393:69 | access to parameter dict : Dictionary [element, property Key] : A | CollectionFlow.cs:393:66:393:77 | call to method First> : KeyValuePair [property Key] : A | +| CollectionFlow.cs:393:66:393:77 | call to method First> : KeyValuePair [property Key] : A | CollectionFlow.cs:393:66:393:81 | access to property Key : A | | CollectionFlow.cs:395:49:395:52 | args : A[] [element] : A | CollectionFlow.cs:395:63:395:66 | access to parameter args : A[] [element] : A | | CollectionFlow.cs:395:49:395:52 | args : null [element] : A | CollectionFlow.cs:395:63:395:66 | access to parameter args : null [element] : A | | CollectionFlow.cs:395:63:395:66 | access to parameter args : A[] [element] : A | CollectionFlow.cs:395:63:395:69 | access to array element | @@ -440,7 +440,7 @@ nodes | CollectionFlow.cs:385:67:385:73 | access to indexer : A | semmle.label | access to indexer : A | | CollectionFlow.cs:387:59:387:62 | dict : Dictionary [element, property Value] : A | semmle.label | dict : Dictionary [element, property Value] : A | | CollectionFlow.cs:387:68:387:71 | access to parameter dict : Dictionary [element, property Value] : A | semmle.label | access to parameter dict : Dictionary [element, property Value] : A | -| CollectionFlow.cs:387:68:387:79 | call to method First> : Object [property Value] : A | semmle.label | call to method First> : Object [property Value] : A | +| CollectionFlow.cs:387:68:387:79 | call to method First> : KeyValuePair [property Value] : A | semmle.label | call to method First> : KeyValuePair [property Value] : A | | CollectionFlow.cs:387:68:387:85 | access to property Value : A | semmle.label | access to property Value : A | | CollectionFlow.cs:389:60:389:63 | dict : Dictionary [element, property Value] : A | semmle.label | dict : Dictionary [element, property Value] : A | | CollectionFlow.cs:389:69:389:72 | access to parameter dict : Dictionary [element, property Value] : A | semmle.label | access to parameter dict : Dictionary [element, property Value] : A | @@ -452,7 +452,7 @@ nodes | CollectionFlow.cs:391:67:391:83 | call to method First : A | semmle.label | call to method First : A | | CollectionFlow.cs:393:57:393:60 | dict : Dictionary [element, property Key] : A | semmle.label | dict : Dictionary [element, property Key] : A | | CollectionFlow.cs:393:66:393:69 | access to parameter dict : Dictionary [element, property Key] : A | semmle.label | access to parameter dict : Dictionary [element, property Key] : A | -| CollectionFlow.cs:393:66:393:77 | call to method First> : Object [property Key] : A | semmle.label | call to method First> : Object [property Key] : A | +| CollectionFlow.cs:393:66:393:77 | call to method First> : KeyValuePair [property Key] : A | semmle.label | call to method First> : KeyValuePair [property Key] : A | | CollectionFlow.cs:393:66:393:81 | access to property Key : A | semmle.label | access to property Key : A | | CollectionFlow.cs:395:49:395:52 | args : A[] [element] : A | semmle.label | args : A[] [element] : A | | CollectionFlow.cs:395:49:395:52 | args : null [element] : A | semmle.label | args : null [element] : A | diff --git a/csharp/ql/test/library-tests/dataflow/external-models/ExternalFlow.cs b/csharp/ql/test/library-tests/dataflow/external-models/ExternalFlow.cs index 05772dfb29a..7a0e896e54d 100644 --- a/csharp/ql/test/library-tests/dataflow/external-models/ExternalFlow.cs +++ b/csharp/ql/test/library-tests/dataflow/external-models/ExternalFlow.cs @@ -149,9 +149,9 @@ namespace My.Qltest static T Apply(Func f, S s) => throw null; - static S[] Map(S[] elements, Func f) => throw null; + static T[] Map(S[] elements, Func f) => throw null; - static void Apply2(Action f, S s1, S s2) => throw null; + static void Apply2(Action f, D d1, D d2) => throw null; static void Parse(string s, out int i) => throw null; @@ -235,4 +235,4 @@ namespace My.Qltest static void Sink(object o) { } } -} \ No newline at end of file +} diff --git a/csharp/ql/test/library-tests/dataflow/external-models/ExternalFlow.expected b/csharp/ql/test/library-tests/dataflow/external-models/ExternalFlow.expected index 09ce9945cdf..c69a86a5cb3 100644 --- a/csharp/ql/test/library-tests/dataflow/external-models/ExternalFlow.expected +++ b/csharp/ql/test/library-tests/dataflow/external-models/ExternalFlow.expected @@ -12,10 +12,10 @@ edges | ExternalFlow.cs:30:13:30:16 | [post] this access : D [field Field] : Object | ExternalFlow.cs:31:18:31:21 | this access : D [field Field] : Object | | ExternalFlow.cs:30:26:30:37 | object creation of type Object : Object | ExternalFlow.cs:30:13:30:16 | [post] this access : D [field Field] : Object | | ExternalFlow.cs:31:18:31:21 | this access : D [field Field] : Object | ExternalFlow.cs:31:18:31:39 | call to method StepFieldGetter | -| ExternalFlow.cs:36:19:36:62 | (...) ... : Object [field Field] : Object | ExternalFlow.cs:36:18:36:69 | access to field Field | +| ExternalFlow.cs:36:19:36:62 | (...) ... : D [field Field] : Object | ExternalFlow.cs:36:18:36:69 | access to field Field | | ExternalFlow.cs:36:22:36:25 | [post] this access : D [field Field] : Object | ExternalFlow.cs:37:18:37:21 | this access : D [field Field] : Object | | ExternalFlow.cs:36:22:36:55 | call to method StepFieldSetter : D [field Field2, field Field] : Object | ExternalFlow.cs:36:22:36:62 | access to field Field2 : Object [field Field] : Object | -| ExternalFlow.cs:36:22:36:62 | access to field Field2 : Object [field Field] : Object | ExternalFlow.cs:36:19:36:62 | (...) ... : Object [field Field] : Object | +| ExternalFlow.cs:36:22:36:62 | access to field Field2 : Object [field Field] : Object | ExternalFlow.cs:36:19:36:62 | (...) ... : D [field Field] : Object | | ExternalFlow.cs:36:43:36:54 | object creation of type Object : Object | ExternalFlow.cs:36:22:36:25 | [post] this access : D [field Field] : Object | | ExternalFlow.cs:36:43:36:54 | object creation of type Object : Object | ExternalFlow.cs:36:22:36:55 | call to method StepFieldSetter : D [field Field2, field Field] : Object | | ExternalFlow.cs:37:18:37:21 | this access : D [field Field] : Object | ExternalFlow.cs:37:18:37:27 | access to field Field | @@ -38,8 +38,7 @@ edges | ExternalFlow.cs:72:23:72:23 | o : Object | ExternalFlow.cs:72:35:72:35 | access to parameter o | | ExternalFlow.cs:77:24:77:58 | call to method Map : T[] [element] : Object | ExternalFlow.cs:78:18:78:21 | access to local variable objs : T[] [element] : Object | | ExternalFlow.cs:77:46:77:57 | object creation of type Object : Object | ExternalFlow.cs:77:24:77:58 | call to method Map : T[] [element] : Object | -| ExternalFlow.cs:78:18:78:21 | access to local variable objs : T[] [element] : Object | ExternalFlow.cs:78:18:78:24 | access to array element : Object | -| ExternalFlow.cs:78:18:78:24 | access to array element : Object | ExternalFlow.cs:78:18:78:24 | (...) ... | +| ExternalFlow.cs:78:18:78:21 | access to local variable objs : T[] [element] : Object | ExternalFlow.cs:78:18:78:24 | access to array element | | ExternalFlow.cs:83:30:83:45 | { ..., ... } : null [element] : Object | ExternalFlow.cs:84:29:84:32 | access to local variable objs : null [element] : Object | | ExternalFlow.cs:83:32:83:43 | object creation of type Object : Object | ExternalFlow.cs:83:30:83:45 | { ..., ... } : null [element] : Object | | ExternalFlow.cs:84:25:84:41 | call to method Map : T[] [element] : Object | ExternalFlow.cs:85:18:85:22 | access to local variable objs2 : T[] [element] : Object | @@ -91,7 +90,7 @@ nodes | ExternalFlow.cs:31:18:31:21 | this access : D [field Field] : Object | semmle.label | this access : D [field Field] : Object | | ExternalFlow.cs:31:18:31:39 | call to method StepFieldGetter | semmle.label | call to method StepFieldGetter | | ExternalFlow.cs:36:18:36:69 | access to field Field | semmle.label | access to field Field | -| ExternalFlow.cs:36:19:36:62 | (...) ... : Object [field Field] : Object | semmle.label | (...) ... : Object [field Field] : Object | +| ExternalFlow.cs:36:19:36:62 | (...) ... : D [field Field] : Object | semmle.label | (...) ... : D [field Field] : Object | | ExternalFlow.cs:36:22:36:25 | [post] this access : D [field Field] : Object | semmle.label | [post] this access : D [field Field] : Object | | ExternalFlow.cs:36:22:36:55 | call to method StepFieldSetter : D [field Field2, field Field] : Object | semmle.label | call to method StepFieldSetter : D [field Field2, field Field] : Object | | ExternalFlow.cs:36:22:36:62 | access to field Field2 : Object [field Field] : Object | semmle.label | access to field Field2 : Object [field Field] : Object | @@ -124,8 +123,7 @@ nodes | ExternalFlow.cs:77:24:77:58 | call to method Map : T[] [element] : Object | semmle.label | call to method Map : T[] [element] : Object | | ExternalFlow.cs:77:46:77:57 | object creation of type Object : Object | semmle.label | object creation of type Object : Object | | ExternalFlow.cs:78:18:78:21 | access to local variable objs : T[] [element] : Object | semmle.label | access to local variable objs : T[] [element] : Object | -| ExternalFlow.cs:78:18:78:24 | (...) ... | semmle.label | (...) ... | -| ExternalFlow.cs:78:18:78:24 | access to array element : Object | semmle.label | access to array element : Object | +| ExternalFlow.cs:78:18:78:24 | access to array element | semmle.label | access to array element | | ExternalFlow.cs:83:30:83:45 | { ..., ... } : null [element] : Object | semmle.label | { ..., ... } : null [element] : Object | | ExternalFlow.cs:83:32:83:43 | object creation of type Object : Object | semmle.label | object creation of type Object : Object | | ExternalFlow.cs:84:25:84:41 | call to method Map : T[] [element] : Object | semmle.label | call to method Map : T[] [element] : Object | @@ -184,7 +182,7 @@ subpaths | ExternalFlow.cs:60:47:60:47 | access to parameter o | ExternalFlow.cs:60:64:60:75 | object creation of type Object : Object | ExternalFlow.cs:60:47:60:47 | access to parameter o | $@ | ExternalFlow.cs:60:64:60:75 | object creation of type Object : Object | object creation of type Object : Object | | ExternalFlow.cs:66:18:66:18 | access to local variable o | ExternalFlow.cs:65:45:65:56 | object creation of type Object : Object | ExternalFlow.cs:66:18:66:18 | access to local variable o | $@ | ExternalFlow.cs:65:45:65:56 | object creation of type Object : Object | object creation of type Object : Object | | ExternalFlow.cs:72:35:72:35 | access to parameter o | ExternalFlow.cs:71:32:71:43 | object creation of type Object : Object | ExternalFlow.cs:72:35:72:35 | access to parameter o | $@ | ExternalFlow.cs:71:32:71:43 | object creation of type Object : Object | object creation of type Object : Object | -| ExternalFlow.cs:78:18:78:24 | (...) ... | ExternalFlow.cs:77:46:77:57 | object creation of type Object : Object | ExternalFlow.cs:78:18:78:24 | (...) ... | $@ | ExternalFlow.cs:77:46:77:57 | object creation of type Object : Object | object creation of type Object : Object | +| ExternalFlow.cs:78:18:78:24 | access to array element | ExternalFlow.cs:77:46:77:57 | object creation of type Object : Object | ExternalFlow.cs:78:18:78:24 | access to array element | $@ | ExternalFlow.cs:77:46:77:57 | object creation of type Object : Object | object creation of type Object : Object | | ExternalFlow.cs:85:18:85:25 | access to array element | ExternalFlow.cs:83:32:83:43 | object creation of type Object : Object | ExternalFlow.cs:85:18:85:25 | access to array element | $@ | ExternalFlow.cs:83:32:83:43 | object creation of type Object : Object | object creation of type Object : Object | | ExternalFlow.cs:92:18:92:18 | (...) ... | ExternalFlow.cs:90:21:90:34 | object creation of type String : String | ExternalFlow.cs:92:18:92:18 | (...) ... | $@ | ExternalFlow.cs:90:21:90:34 | object creation of type String : String | object creation of type String : String | | ExternalFlow.cs:102:22:102:22 | access to parameter d | ExternalFlow.cs:98:24:98:35 | object creation of type Object : Object | ExternalFlow.cs:102:22:102:22 | access to parameter d | $@ | ExternalFlow.cs:98:24:98:35 | object creation of type Object : Object | object creation of type Object : Object | diff --git a/csharp/ql/test/library-tests/dataflow/external-models/ExternalFlow.ext.yml b/csharp/ql/test/library-tests/dataflow/external-models/ExternalFlow.ext.yml index f626949e6f4..a2bf0d8b525 100644 --- a/csharp/ql/test/library-tests/dataflow/external-models/ExternalFlow.ext.yml +++ b/csharp/ql/test/library-tests/dataflow/external-models/ExternalFlow.ext.yml @@ -16,8 +16,8 @@ extensions: - ["My.Qltest", "D", false, "StepElementSetter", "(System.Object)", "", "Argument[0]", "Argument[this].Element", "value", "manual"] - ["My.Qltest", "D", false, "Apply<,>", "(System.Func,S)", "", "Argument[1]", "Argument[0].Parameter[0]", "value", "manual"] - ["My.Qltest", "D", false, "Apply<,>", "(System.Func,S)", "", "Argument[0].ReturnValue", "ReturnValue", "value", "manual"] - - ["My.Qltest", "D", false, "Apply2<>", "(System.Action,S,S)", "", "Argument[1].Field[My.Qltest.D.Field]", "Argument[0].Parameter[0]", "value", "manual"] - - ["My.Qltest", "D", false, "Apply2<>", "(System.Action,S,S)", "", "Argument[2].Field[My.Qltest.D.Field2]", "Argument[0].Parameter[0]", "value", "manual"] + - ["My.Qltest", "D", false, "Apply2", "(System.Action,My.Qltest.D,My.Qltest.D)", "", "Argument[1].Field[My.Qltest.D.Field]", "Argument[0].Parameter[0]", "value", "manual"] + - ["My.Qltest", "D", false, "Apply2", "(System.Action,My.Qltest.D,My.Qltest.D)", "", "Argument[2].Field[My.Qltest.D.Field2]", "Argument[0].Parameter[0]", "value", "manual"] - ["My.Qltest", "D", false, "Map<,>", "(S[],System.Func)", "", "Argument[0].Element", "Argument[1].Parameter[0]", "value", "manual"] - ["My.Qltest", "D", false, "Map<,>", "(S[],System.Func)", "", "Argument[1].ReturnValue", "ReturnValue.Element", "value", "manual"] - ["My.Qltest", "D", false, "Parse", "(System.String,System.Int32)", "", "Argument[0]", "Argument[1]", "taint", "manual"] diff --git a/csharp/ql/test/library-tests/dataflow/global/DataFlowPath.expected b/csharp/ql/test/library-tests/dataflow/global/DataFlowPath.expected index bce1914e42b..767e66301ce 100644 --- a/csharp/ql/test/library-tests/dataflow/global/DataFlowPath.expected +++ b/csharp/ql/test/library-tests/dataflow/global/DataFlowPath.expected @@ -267,7 +267,7 @@ edges | GlobalDataFlow.cs:500:9:500:10 | [post] access to parameter sc : SimpleClass [field field] : String | GlobalDataFlow.cs:514:31:514:32 | [post] access to local variable y1 : SimpleClass [field field] : String | | GlobalDataFlow.cs:500:9:500:10 | [post] access to parameter sc : SimpleClass [field field] : String | GlobalDataFlow.cs:514:36:514:37 | [post] access to local variable y2 : SimpleClass [field field] : String | | GlobalDataFlow.cs:500:9:500:10 | [post] access to parameter sc : SimpleClass [field field] : String | GlobalDataFlow.cs:514:42:514:43 | [post] access to local variable y3 : SimpleClass [field field] : String | -| GlobalDataFlow.cs:500:9:500:10 | [post] access to parameter sc : SimpleClass [field field] : String | GlobalDataFlow.cs:525:33:525:33 | [post] access to local variable x : SimpleClass [field field] : String | +| GlobalDataFlow.cs:500:9:500:10 | [post] access to parameter sc : SimpleClass [field field] : String | GlobalDataFlow.cs:525:33:525:33 | [post] access to local variable x : SubSimpleClass [field field] : String | | GlobalDataFlow.cs:500:9:500:10 | [post] access to parameter sc : SimpleClass [field field] : String | GlobalDataFlow.cs:532:20:532:20 | [post] access to parameter x : SimpleClass [field field] : String | | GlobalDataFlow.cs:500:9:500:10 | [post] access to parameter sc : SimpleClass [field field] : String | GlobalDataFlow.cs:532:25:532:25 | [post] access to local variable y : SimpleClass [field field] : String | | GlobalDataFlow.cs:500:9:500:10 | [post] access to parameter sc : SimpleClass [field field] : String | GlobalDataFlow.cs:544:20:544:20 | [post] access to local variable x : SimpleClass [field field] : String | @@ -286,8 +286,8 @@ edges | GlobalDataFlow.cs:515:15:515:16 | access to local variable y1 : SimpleClass [field field] : String | GlobalDataFlow.cs:515:15:515:22 | access to field field | | GlobalDataFlow.cs:516:15:516:16 | access to local variable y2 : SimpleClass [field field] : String | GlobalDataFlow.cs:516:15:516:22 | access to field field | | GlobalDataFlow.cs:517:15:517:16 | access to local variable y3 : SimpleClass [field field] : String | GlobalDataFlow.cs:517:15:517:22 | access to field field | -| GlobalDataFlow.cs:525:33:525:33 | [post] access to local variable x : SimpleClass [field field] : String | GlobalDataFlow.cs:526:15:526:15 | access to local variable x : SimpleClass [field field] : String | -| GlobalDataFlow.cs:526:15:526:15 | access to local variable x : SimpleClass [field field] : String | GlobalDataFlow.cs:526:15:526:21 | access to field field | +| GlobalDataFlow.cs:525:33:525:33 | [post] access to local variable x : SubSimpleClass [field field] : String | GlobalDataFlow.cs:526:15:526:15 | access to local variable x : SubSimpleClass [field field] : String | +| GlobalDataFlow.cs:526:15:526:15 | access to local variable x : SubSimpleClass [field field] : String | GlobalDataFlow.cs:526:15:526:21 | access to field field | | GlobalDataFlow.cs:532:20:532:20 | [post] access to parameter x : SimpleClass [field field] : String | GlobalDataFlow.cs:533:15:533:15 | access to parameter x : SimpleClass [field field] : String | | GlobalDataFlow.cs:532:25:532:25 | [post] access to local variable y : SimpleClass [field field] : String | GlobalDataFlow.cs:534:15:534:15 | access to local variable y : SimpleClass [field field] : String | | GlobalDataFlow.cs:533:15:533:15 | access to parameter x : SimpleClass [field field] : String | GlobalDataFlow.cs:533:15:533:21 | access to field field | @@ -579,8 +579,8 @@ nodes | GlobalDataFlow.cs:516:15:516:22 | access to field field | semmle.label | access to field field | | GlobalDataFlow.cs:517:15:517:16 | access to local variable y3 : SimpleClass [field field] : String | semmle.label | access to local variable y3 : SimpleClass [field field] : String | | GlobalDataFlow.cs:517:15:517:22 | access to field field | semmle.label | access to field field | -| GlobalDataFlow.cs:525:33:525:33 | [post] access to local variable x : SimpleClass [field field] : String | semmle.label | [post] access to local variable x : SimpleClass [field field] : String | -| GlobalDataFlow.cs:526:15:526:15 | access to local variable x : SimpleClass [field field] : String | semmle.label | access to local variable x : SimpleClass [field field] : String | +| GlobalDataFlow.cs:525:33:525:33 | [post] access to local variable x : SubSimpleClass [field field] : String | semmle.label | [post] access to local variable x : SubSimpleClass [field field] : String | +| GlobalDataFlow.cs:526:15:526:15 | access to local variable x : SubSimpleClass [field field] : String | semmle.label | access to local variable x : SubSimpleClass [field field] : String | | GlobalDataFlow.cs:526:15:526:21 | access to field field | semmle.label | access to field field | | GlobalDataFlow.cs:532:20:532:20 | [post] access to parameter x : SimpleClass [field field] : String | semmle.label | [post] access to parameter x : SimpleClass [field field] : String | | GlobalDataFlow.cs:532:25:532:25 | [post] access to local variable y : SimpleClass [field field] : String | semmle.label | [post] access to local variable y : SimpleClass [field field] : String | diff --git a/csharp/ql/test/library-tests/dataflow/global/TaintTrackingPath.expected b/csharp/ql/test/library-tests/dataflow/global/TaintTrackingPath.expected index 5dae90d82a6..dec8a134712 100644 --- a/csharp/ql/test/library-tests/dataflow/global/TaintTrackingPath.expected +++ b/csharp/ql/test/library-tests/dataflow/global/TaintTrackingPath.expected @@ -293,7 +293,7 @@ edges | GlobalDataFlow.cs:500:9:500:10 | [post] access to parameter sc : SimpleClass [field field] : String | GlobalDataFlow.cs:514:31:514:32 | [post] access to local variable y1 : SimpleClass [field field] : String | | GlobalDataFlow.cs:500:9:500:10 | [post] access to parameter sc : SimpleClass [field field] : String | GlobalDataFlow.cs:514:36:514:37 | [post] access to local variable y2 : SimpleClass [field field] : String | | GlobalDataFlow.cs:500:9:500:10 | [post] access to parameter sc : SimpleClass [field field] : String | GlobalDataFlow.cs:514:42:514:43 | [post] access to local variable y3 : SimpleClass [field field] : String | -| GlobalDataFlow.cs:500:9:500:10 | [post] access to parameter sc : SimpleClass [field field] : String | GlobalDataFlow.cs:525:33:525:33 | [post] access to local variable x : SimpleClass [field field] : String | +| GlobalDataFlow.cs:500:9:500:10 | [post] access to parameter sc : SimpleClass [field field] : String | GlobalDataFlow.cs:525:33:525:33 | [post] access to local variable x : SubSimpleClass [field field] : String | | GlobalDataFlow.cs:500:9:500:10 | [post] access to parameter sc : SimpleClass [field field] : String | GlobalDataFlow.cs:532:20:532:20 | [post] access to parameter x : SimpleClass [field field] : String | | GlobalDataFlow.cs:500:9:500:10 | [post] access to parameter sc : SimpleClass [field field] : String | GlobalDataFlow.cs:532:25:532:25 | [post] access to local variable y : SimpleClass [field field] : String | | GlobalDataFlow.cs:500:9:500:10 | [post] access to parameter sc : SimpleClass [field field] : String | GlobalDataFlow.cs:544:20:544:20 | [post] access to local variable x : SimpleClass [field field] : String | @@ -312,8 +312,8 @@ edges | GlobalDataFlow.cs:515:15:515:16 | access to local variable y1 : SimpleClass [field field] : String | GlobalDataFlow.cs:515:15:515:22 | access to field field | | GlobalDataFlow.cs:516:15:516:16 | access to local variable y2 : SimpleClass [field field] : String | GlobalDataFlow.cs:516:15:516:22 | access to field field | | GlobalDataFlow.cs:517:15:517:16 | access to local variable y3 : SimpleClass [field field] : String | GlobalDataFlow.cs:517:15:517:22 | access to field field | -| GlobalDataFlow.cs:525:33:525:33 | [post] access to local variable x : SimpleClass [field field] : String | GlobalDataFlow.cs:526:15:526:15 | access to local variable x : SimpleClass [field field] : String | -| GlobalDataFlow.cs:526:15:526:15 | access to local variable x : SimpleClass [field field] : String | GlobalDataFlow.cs:526:15:526:21 | access to field field | +| GlobalDataFlow.cs:525:33:525:33 | [post] access to local variable x : SubSimpleClass [field field] : String | GlobalDataFlow.cs:526:15:526:15 | access to local variable x : SubSimpleClass [field field] : String | +| GlobalDataFlow.cs:526:15:526:15 | access to local variable x : SubSimpleClass [field field] : String | GlobalDataFlow.cs:526:15:526:21 | access to field field | | GlobalDataFlow.cs:532:20:532:20 | [post] access to parameter x : SimpleClass [field field] : String | GlobalDataFlow.cs:533:15:533:15 | access to parameter x : SimpleClass [field field] : String | | GlobalDataFlow.cs:532:25:532:25 | [post] access to local variable y : SimpleClass [field field] : String | GlobalDataFlow.cs:534:15:534:15 | access to local variable y : SimpleClass [field field] : String | | GlobalDataFlow.cs:533:15:533:15 | access to parameter x : SimpleClass [field field] : String | GlobalDataFlow.cs:533:15:533:21 | access to field field | @@ -633,8 +633,8 @@ nodes | GlobalDataFlow.cs:516:15:516:22 | access to field field | semmle.label | access to field field | | GlobalDataFlow.cs:517:15:517:16 | access to local variable y3 : SimpleClass [field field] : String | semmle.label | access to local variable y3 : SimpleClass [field field] : String | | GlobalDataFlow.cs:517:15:517:22 | access to field field | semmle.label | access to field field | -| GlobalDataFlow.cs:525:33:525:33 | [post] access to local variable x : SimpleClass [field field] : String | semmle.label | [post] access to local variable x : SimpleClass [field field] : String | -| GlobalDataFlow.cs:526:15:526:15 | access to local variable x : SimpleClass [field field] : String | semmle.label | access to local variable x : SimpleClass [field field] : String | +| GlobalDataFlow.cs:525:33:525:33 | [post] access to local variable x : SubSimpleClass [field field] : String | semmle.label | [post] access to local variable x : SubSimpleClass [field field] : String | +| GlobalDataFlow.cs:526:15:526:15 | access to local variable x : SubSimpleClass [field field] : String | semmle.label | access to local variable x : SubSimpleClass [field field] : String | | GlobalDataFlow.cs:526:15:526:21 | access to field field | semmle.label | access to field field | | GlobalDataFlow.cs:532:20:532:20 | [post] access to parameter x : SimpleClass [field field] : String | semmle.label | [post] access to parameter x : SimpleClass [field field] : String | | GlobalDataFlow.cs:532:25:532:25 | [post] access to local variable y : SimpleClass [field field] : String | semmle.label | [post] access to local variable y : SimpleClass [field field] : String | diff --git a/csharp/ql/test/library-tests/frameworks/EntityFramework/Dataflow.expected b/csharp/ql/test/library-tests/frameworks/EntityFramework/Dataflow.expected index 811f1a04d8b..a9d4895fb46 100644 --- a/csharp/ql/test/library-tests/frameworks/EntityFramework/Dataflow.expected +++ b/csharp/ql/test/library-tests/frameworks/EntityFramework/Dataflow.expected @@ -74,14 +74,14 @@ edges | EntityFramework.cs:196:13:196:23 | [post] access to property Persons : DbSet [element, property Name] : String | EntityFramework.cs:196:13:196:15 | [post] access to local variable ctx : MyContext [property Persons, element, property Name] : String | | EntityFramework.cs:196:29:196:29 | access to parameter p : Person [property Name] : String | EntityFramework.cs:196:13:196:23 | [post] access to property Persons : DbSet [element, property Name] : String | | EntityFramework.cs:197:13:197:15 | access to local variable ctx : MyContext [property Persons, element, property Name] : String | EntityFramework.cs:204:18:204:28 | access to property Persons : DbSet [element, property Name] : String | -| EntityFramework.cs:204:18:204:28 | access to property Persons : DbSet [element, property Name] : String | EntityFramework.cs:204:18:204:36 | call to method First : Object [property Name] : String | -| EntityFramework.cs:204:18:204:36 | call to method First : Object [property Name] : String | EntityFramework.cs:204:18:204:41 | access to property Name | -| EntityFramework.cs:212:18:212:30 | access to property Addresses : DbSet
[element, property Street] : String | EntityFramework.cs:212:18:212:38 | call to method First
: Object [property Street] : String | -| EntityFramework.cs:212:18:212:38 | call to method First
: Object [property Street] : String | EntityFramework.cs:212:18:212:45 | access to property Street | -| EntityFramework.cs:219:18:219:28 | access to property Persons : DbSet [element, property Addresses, element, property Street] : String | EntityFramework.cs:219:18:219:36 | call to method First : Object [property Addresses, element, property Street] : String | -| EntityFramework.cs:219:18:219:36 | call to method First : Object [property Addresses, element, property Street] : String | EntityFramework.cs:219:18:219:46 | access to property Addresses : ICollection
[element, property Street] : String | -| EntityFramework.cs:219:18:219:46 | access to property Addresses : ICollection
[element, property Street] : String | EntityFramework.cs:219:18:219:54 | call to method First
: Object [property Street] : String | -| EntityFramework.cs:219:18:219:54 | call to method First
: Object [property Street] : String | EntityFramework.cs:219:18:219:61 | access to property Street | +| EntityFramework.cs:204:18:204:28 | access to property Persons : DbSet [element, property Name] : String | EntityFramework.cs:204:18:204:36 | call to method First : Person [property Name] : String | +| EntityFramework.cs:204:18:204:36 | call to method First : Person [property Name] : String | EntityFramework.cs:204:18:204:41 | access to property Name | +| EntityFramework.cs:212:18:212:30 | access to property Addresses : DbSet
[element, property Street] : String | EntityFramework.cs:212:18:212:38 | call to method First
: Address [property Street] : String | +| EntityFramework.cs:212:18:212:38 | call to method First
: Address [property Street] : String | EntityFramework.cs:212:18:212:45 | access to property Street | +| EntityFramework.cs:219:18:219:28 | access to property Persons : DbSet [element, property Addresses, element, property Street] : String | EntityFramework.cs:219:18:219:36 | call to method First : Person [property Addresses, element, property Street] : String | +| EntityFramework.cs:219:18:219:36 | call to method First : Person [property Addresses, element, property Street] : String | EntityFramework.cs:219:18:219:46 | access to property Addresses : ICollection
[element, property Street] : String | +| EntityFramework.cs:219:18:219:46 | access to property Addresses : ICollection
[element, property Street] : String | EntityFramework.cs:219:18:219:54 | call to method First
: Address [property Street] : String | +| EntityFramework.cs:219:18:219:54 | call to method First
: Address [property Street] : String | EntityFramework.cs:219:18:219:61 | access to property Street | | EntityFrameworkCore.cs:82:31:82:39 | "tainted" : String | EntityFrameworkCore.cs:83:18:83:28 | access to local variable taintSource | | EntityFrameworkCore.cs:82:31:82:39 | "tainted" : String | EntityFrameworkCore.cs:84:35:84:45 | access to local variable taintSource : String | | EntityFrameworkCore.cs:82:31:82:39 | "tainted" : String | EntityFrameworkCore.cs:85:18:85:42 | (...) ... | @@ -165,14 +165,14 @@ edges | EntityFrameworkCore.cs:229:13:229:23 | [post] access to property Persons : DbSet [element, property Name] : String | EntityFrameworkCore.cs:229:13:229:15 | [post] access to local variable ctx : MyContext [property Persons, element, property Name] : String | | EntityFrameworkCore.cs:229:29:229:29 | access to parameter p : Person [property Name] : String | EntityFrameworkCore.cs:229:13:229:23 | [post] access to property Persons : DbSet [element, property Name] : String | | EntityFrameworkCore.cs:230:13:230:15 | access to local variable ctx : MyContext [property Persons, element, property Name] : String | EntityFrameworkCore.cs:237:18:237:28 | access to property Persons : DbSet [element, property Name] : String | -| EntityFrameworkCore.cs:237:18:237:28 | access to property Persons : DbSet [element, property Name] : String | EntityFrameworkCore.cs:237:18:237:36 | call to method First : Object [property Name] : String | -| EntityFrameworkCore.cs:237:18:237:36 | call to method First : Object [property Name] : String | EntityFrameworkCore.cs:237:18:237:41 | access to property Name | -| EntityFrameworkCore.cs:245:18:245:30 | access to property Addresses : DbSet
[element, property Street] : String | EntityFrameworkCore.cs:245:18:245:38 | call to method First
: Object [property Street] : String | -| EntityFrameworkCore.cs:245:18:245:38 | call to method First
: Object [property Street] : String | EntityFrameworkCore.cs:245:18:245:45 | access to property Street | -| EntityFrameworkCore.cs:252:18:252:28 | access to property Persons : DbSet [element, property Addresses, element, property Street] : String | EntityFrameworkCore.cs:252:18:252:36 | call to method First : Object [property Addresses, element, property Street] : String | -| EntityFrameworkCore.cs:252:18:252:36 | call to method First : Object [property Addresses, element, property Street] : String | EntityFrameworkCore.cs:252:18:252:46 | access to property Addresses : ICollection
[element, property Street] : String | -| EntityFrameworkCore.cs:252:18:252:46 | access to property Addresses : ICollection
[element, property Street] : String | EntityFrameworkCore.cs:252:18:252:54 | call to method First
: Object [property Street] : String | -| EntityFrameworkCore.cs:252:18:252:54 | call to method First
: Object [property Street] : String | EntityFrameworkCore.cs:252:18:252:61 | access to property Street | +| EntityFrameworkCore.cs:237:18:237:28 | access to property Persons : DbSet [element, property Name] : String | EntityFrameworkCore.cs:237:18:237:36 | call to method First : Person [property Name] : String | +| EntityFrameworkCore.cs:237:18:237:36 | call to method First : Person [property Name] : String | EntityFrameworkCore.cs:237:18:237:41 | access to property Name | +| EntityFrameworkCore.cs:245:18:245:30 | access to property Addresses : DbSet
[element, property Street] : String | EntityFrameworkCore.cs:245:18:245:38 | call to method First
: Address [property Street] : String | +| EntityFrameworkCore.cs:245:18:245:38 | call to method First
: Address [property Street] : String | EntityFrameworkCore.cs:245:18:245:45 | access to property Street | +| EntityFrameworkCore.cs:252:18:252:28 | access to property Persons : DbSet [element, property Addresses, element, property Street] : String | EntityFrameworkCore.cs:252:18:252:36 | call to method First : Person [property Addresses, element, property Street] : String | +| EntityFrameworkCore.cs:252:18:252:36 | call to method First : Person [property Addresses, element, property Street] : String | EntityFrameworkCore.cs:252:18:252:46 | access to property Addresses : ICollection
[element, property Street] : String | +| EntityFrameworkCore.cs:252:18:252:46 | access to property Addresses : ICollection
[element, property Street] : String | EntityFrameworkCore.cs:252:18:252:54 | call to method First
: Address [property Street] : String | +| EntityFrameworkCore.cs:252:18:252:54 | call to method First
: Address [property Street] : String | EntityFrameworkCore.cs:252:18:252:61 | access to property Street | nodes | EntityFramework.cs:59:13:62:13 | { ..., ... } : Person [property Name] : String | semmle.label | { ..., ... } : Person [property Name] : String | | EntityFramework.cs:61:24:61:32 | "tainted" : String | semmle.label | "tainted" : String | @@ -237,15 +237,15 @@ nodes | EntityFramework.cs:196:29:196:29 | access to parameter p : Person [property Name] : String | semmle.label | access to parameter p : Person [property Name] : String | | EntityFramework.cs:197:13:197:15 | access to local variable ctx : MyContext [property Persons, element, property Name] : String | semmle.label | access to local variable ctx : MyContext [property Persons, element, property Name] : String | | EntityFramework.cs:204:18:204:28 | access to property Persons : DbSet [element, property Name] : String | semmle.label | access to property Persons : DbSet [element, property Name] : String | -| EntityFramework.cs:204:18:204:36 | call to method First : Object [property Name] : String | semmle.label | call to method First : Object [property Name] : String | +| EntityFramework.cs:204:18:204:36 | call to method First : Person [property Name] : String | semmle.label | call to method First : Person [property Name] : String | | EntityFramework.cs:204:18:204:41 | access to property Name | semmle.label | access to property Name | | EntityFramework.cs:212:18:212:30 | access to property Addresses : DbSet
[element, property Street] : String | semmle.label | access to property Addresses : DbSet
[element, property Street] : String | -| EntityFramework.cs:212:18:212:38 | call to method First
: Object [property Street] : String | semmle.label | call to method First
: Object [property Street] : String | +| EntityFramework.cs:212:18:212:38 | call to method First
: Address [property Street] : String | semmle.label | call to method First
: Address [property Street] : String | | EntityFramework.cs:212:18:212:45 | access to property Street | semmle.label | access to property Street | | EntityFramework.cs:219:18:219:28 | access to property Persons : DbSet [element, property Addresses, element, property Street] : String | semmle.label | access to property Persons : DbSet [element, property Addresses, element, property Street] : String | -| EntityFramework.cs:219:18:219:36 | call to method First : Object [property Addresses, element, property Street] : String | semmle.label | call to method First : Object [property Addresses, element, property Street] : String | +| EntityFramework.cs:219:18:219:36 | call to method First : Person [property Addresses, element, property Street] : String | semmle.label | call to method First : Person [property Addresses, element, property Street] : String | | EntityFramework.cs:219:18:219:46 | access to property Addresses : ICollection
[element, property Street] : String | semmle.label | access to property Addresses : ICollection
[element, property Street] : String | -| EntityFramework.cs:219:18:219:54 | call to method First
: Object [property Street] : String | semmle.label | call to method First
: Object [property Street] : String | +| EntityFramework.cs:219:18:219:54 | call to method First
: Address [property Street] : String | semmle.label | call to method First
: Address [property Street] : String | | EntityFramework.cs:219:18:219:61 | access to property Street | semmle.label | access to property Street | | EntityFrameworkCore.cs:82:31:82:39 | "tainted" : String | semmle.label | "tainted" : String | | EntityFrameworkCore.cs:83:18:83:28 | access to local variable taintSource | semmle.label | access to local variable taintSource | @@ -318,15 +318,15 @@ nodes | EntityFrameworkCore.cs:229:29:229:29 | access to parameter p : Person [property Name] : String | semmle.label | access to parameter p : Person [property Name] : String | | EntityFrameworkCore.cs:230:13:230:15 | access to local variable ctx : MyContext [property Persons, element, property Name] : String | semmle.label | access to local variable ctx : MyContext [property Persons, element, property Name] : String | | EntityFrameworkCore.cs:237:18:237:28 | access to property Persons : DbSet [element, property Name] : String | semmle.label | access to property Persons : DbSet [element, property Name] : String | -| EntityFrameworkCore.cs:237:18:237:36 | call to method First : Object [property Name] : String | semmle.label | call to method First : Object [property Name] : String | +| EntityFrameworkCore.cs:237:18:237:36 | call to method First : Person [property Name] : String | semmle.label | call to method First : Person [property Name] : String | | EntityFrameworkCore.cs:237:18:237:41 | access to property Name | semmle.label | access to property Name | | EntityFrameworkCore.cs:245:18:245:30 | access to property Addresses : DbSet
[element, property Street] : String | semmle.label | access to property Addresses : DbSet
[element, property Street] : String | -| EntityFrameworkCore.cs:245:18:245:38 | call to method First
: Object [property Street] : String | semmle.label | call to method First
: Object [property Street] : String | +| EntityFrameworkCore.cs:245:18:245:38 | call to method First
: Address [property Street] : String | semmle.label | call to method First
: Address [property Street] : String | | EntityFrameworkCore.cs:245:18:245:45 | access to property Street | semmle.label | access to property Street | | EntityFrameworkCore.cs:252:18:252:28 | access to property Persons : DbSet [element, property Addresses, element, property Street] : String | semmle.label | access to property Persons : DbSet [element, property Addresses, element, property Street] : String | -| EntityFrameworkCore.cs:252:18:252:36 | call to method First : Object [property Addresses, element, property Street] : String | semmle.label | call to method First : Object [property Addresses, element, property Street] : String | +| EntityFrameworkCore.cs:252:18:252:36 | call to method First : Person [property Addresses, element, property Street] : String | semmle.label | call to method First : Person [property Addresses, element, property Street] : String | | EntityFrameworkCore.cs:252:18:252:46 | access to property Addresses : ICollection
[element, property Street] : String | semmle.label | access to property Addresses : ICollection
[element, property Street] : String | -| EntityFrameworkCore.cs:252:18:252:54 | call to method First
: Object [property Street] : String | semmle.label | call to method First
: Object [property Street] : String | +| EntityFrameworkCore.cs:252:18:252:54 | call to method First
: Address [property Street] : String | semmle.label | call to method First
: Address [property Street] : String | | EntityFrameworkCore.cs:252:18:252:61 | access to property Street | semmle.label | access to property Street | subpaths #select diff --git a/csharp/ql/test/query-tests/Security Features/CWE-338/InsecureRandomness.expected b/csharp/ql/test/query-tests/Security Features/CWE-338/InsecureRandomness.expected index 4cc2e788074..011ec3faee0 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-338/InsecureRandomness.expected +++ b/csharp/ql/test/query-tests/Security Features/CWE-338/InsecureRandomness.expected @@ -1,10 +1,10 @@ edges -| InsecureRandomness.cs:28:13:28:16 | [post] access to local variable data : Byte[] [element] : Int32 | InsecureRandomness.cs:29:57:29:60 | access to local variable data : Byte[] [element] : Int32 | -| InsecureRandomness.cs:28:23:28:43 | (...) ... : Int32 | InsecureRandomness.cs:28:13:28:16 | [post] access to local variable data : Byte[] [element] : Int32 | -| InsecureRandomness.cs:28:29:28:43 | call to method Next : Int32 | InsecureRandomness.cs:28:23:28:43 | (...) ... : Int32 | +| InsecureRandomness.cs:28:13:28:16 | [post] access to local variable data : Byte[] [element] : Byte | InsecureRandomness.cs:29:57:29:60 | access to local variable data : Byte[] [element] : Byte | +| InsecureRandomness.cs:28:23:28:43 | (...) ... : Byte | InsecureRandomness.cs:28:13:28:16 | [post] access to local variable data : Byte[] [element] : Byte | +| InsecureRandomness.cs:28:29:28:43 | call to method Next : Int32 | InsecureRandomness.cs:28:23:28:43 | (...) ... : Byte | | InsecureRandomness.cs:29:13:29:18 | [post] access to local variable result : StringBuilder [element] : String | InsecureRandomness.cs:31:16:31:21 | access to local variable result : StringBuilder [element] : String | | InsecureRandomness.cs:29:27:29:61 | call to method GetString : String | InsecureRandomness.cs:29:13:29:18 | [post] access to local variable result : StringBuilder [element] : String | -| InsecureRandomness.cs:29:57:29:60 | access to local variable data : Byte[] [element] : Int32 | InsecureRandomness.cs:29:27:29:61 | call to method GetString : String | +| InsecureRandomness.cs:29:57:29:60 | access to local variable data : Byte[] [element] : Byte | InsecureRandomness.cs:29:27:29:61 | call to method GetString : String | | InsecureRandomness.cs:31:16:31:21 | access to local variable result : StringBuilder [element] : String | InsecureRandomness.cs:31:16:31:32 | call to method ToString : String | | InsecureRandomness.cs:31:16:31:32 | call to method ToString : String | InsecureRandomness.cs:12:27:12:50 | call to method InsecureRandomString | | InsecureRandomness.cs:60:31:60:39 | call to method Next : Int32 | InsecureRandomness.cs:62:16:62:21 | access to local variable result : String | @@ -16,12 +16,12 @@ nodes | InsecureRandomness.cs:12:27:12:50 | call to method InsecureRandomString | semmle.label | call to method InsecureRandomString | | InsecureRandomness.cs:13:20:13:56 | call to method InsecureRandomStringFromSelection | semmle.label | call to method InsecureRandomStringFromSelection | | InsecureRandomness.cs:14:20:14:54 | call to method InsecureRandomStringFromIndexer | semmle.label | call to method InsecureRandomStringFromIndexer | -| InsecureRandomness.cs:28:13:28:16 | [post] access to local variable data : Byte[] [element] : Int32 | semmle.label | [post] access to local variable data : Byte[] [element] : Int32 | -| InsecureRandomness.cs:28:23:28:43 | (...) ... : Int32 | semmle.label | (...) ... : Int32 | +| InsecureRandomness.cs:28:13:28:16 | [post] access to local variable data : Byte[] [element] : Byte | semmle.label | [post] access to local variable data : Byte[] [element] : Byte | +| InsecureRandomness.cs:28:23:28:43 | (...) ... : Byte | semmle.label | (...) ... : Byte | | InsecureRandomness.cs:28:29:28:43 | call to method Next : Int32 | semmle.label | call to method Next : Int32 | | InsecureRandomness.cs:29:13:29:18 | [post] access to local variable result : StringBuilder [element] : String | semmle.label | [post] access to local variable result : StringBuilder [element] : String | | InsecureRandomness.cs:29:27:29:61 | call to method GetString : String | semmle.label | call to method GetString : String | -| InsecureRandomness.cs:29:57:29:60 | access to local variable data : Byte[] [element] : Int32 | semmle.label | access to local variable data : Byte[] [element] : Int32 | +| InsecureRandomness.cs:29:57:29:60 | access to local variable data : Byte[] [element] : Byte | semmle.label | access to local variable data : Byte[] [element] : Byte | | InsecureRandomness.cs:31:16:31:21 | access to local variable result : StringBuilder [element] : String | semmle.label | access to local variable result : StringBuilder [element] : String | | InsecureRandomness.cs:31:16:31:32 | call to method ToString : String | semmle.label | call to method ToString : String | | InsecureRandomness.cs:60:31:60:39 | call to method Next : Int32 | semmle.label | call to method Next : Int32 | diff --git a/go/ql/lib/semmle/go/dataflow/internal/DataFlowImpl.qll b/go/ql/lib/semmle/go/dataflow/internal/DataFlowImpl.qll index ddf98ac0f2f..984c5ae2018 100644 --- a/go/ql/lib/semmle/go/dataflow/internal/DataFlowImpl.qll +++ b/go/ql/lib/semmle/go/dataflow/internal/DataFlowImpl.qll @@ -1135,8 +1135,8 @@ module Impl { DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow ); - bindingset[node, state, t, ap] - predicate filter(NodeEx node, FlowState state, Typ t, Ap ap); + bindingset[node, state, t0, ap] + predicate filter(NodeEx node, FlowState state, Typ t0, Ap ap, Typ t); bindingset[typ, contentType] predicate typecheckStore(Typ typ, DataFlowType contentType); @@ -1199,17 +1199,21 @@ module Impl { NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, TypOption argT, ApOption argAp, Typ t, Ap ap, ApApprox apa ) { - fwdFlow0(node, state, cc, summaryCtx, argT, argAp, t, ap, apa) and - PrevStage::revFlow(node, state, apa) and - filter(node, state, t, ap) + fwdFlow1(node, state, cc, summaryCtx, argT, argAp, _, t, ap, apa) } - pragma[inline] - additional predicate fwdFlow( + private predicate fwdFlow1( NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, TypOption argT, - ApOption argAp, Typ t, Ap ap + ApOption argAp, Typ t0, Typ t, Ap ap, ApApprox apa ) { - fwdFlow(node, state, cc, summaryCtx, argT, argAp, t, ap, _) + fwdFlow0(node, state, cc, summaryCtx, argT, argAp, t0, ap, apa) and + PrevStage::revFlow(node, state, apa) and + filter(node, state, t0, ap, t) + } + + pragma[nomagic] + private predicate typeStrengthen(Typ t0, Ap ap, Typ t) { + fwdFlow1(_, _, _, _, _, _, t0, t, ap, _) and t0 != t } pragma[assume_small_delta] @@ -1339,6 +1343,11 @@ module Impl { private predicate fwdFlowConsCand(Typ t2, Ap cons, Content c, Typ t1, Ap tail) { fwdFlowStore(_, t1, tail, c, t2, _, _, _, _, _, _) and cons = apCons(c, t1, tail) + or + exists(Typ t0 | + typeStrengthen(t0, cons, t2) and + fwdFlowConsCand(t0, cons, c, t1, tail) + ) } pragma[nomagic] @@ -1359,7 +1368,7 @@ module Impl { ParamNodeOption summaryCtx, TypOption argT, ApOption argAp ) { exists(ApHeadContent apc | - fwdFlow(node1, state, cc, summaryCtx, argT, argAp, t, ap) and + fwdFlow(node1, state, cc, summaryCtx, argT, argAp, t, ap, _) and apc = getHeadContent(ap) and readStepCand0(node1, apc, c, node2) ) @@ -1520,14 +1529,14 @@ module Impl { 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() @@ -1780,13 +1789,13 @@ module Impl { boolean fwd, int nodes, int fields, int conscand, int states, int tuples ) { fwd = true and - nodes = count(NodeEx node | fwdFlow(node, _, _, _, _, _, _, _)) 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 + states = count(FlowState state | fwdFlow(_, state, _, _, _, _, _, _, _)) and tuples = count(NodeEx n, FlowState state, Cc cc, ParamNodeOption summaryCtx, TypOption argT, - ApOption argAp, Typ t, Ap ap | fwdFlow(n, state, cc, summaryCtx, argT, argAp, t, ap)) + ApOption argAp, Typ t, Ap ap | fwdFlow(n, state, cc, summaryCtx, argT, argAp, t, ap, _)) or fwd = false and nodes = count(NodeEx node | revFlow(node, _, _, _, _)) and @@ -1963,10 +1972,10 @@ module Impl { ) } - bindingset[node, state, t, ap] - predicate filter(NodeEx node, FlowState state, Typ t, Ap ap) { + bindingset[node, state, t0, ap] + predicate filter(NodeEx node, FlowState state, Typ t0, Ap ap, Typ t) { PrevStage::revFlowState(state) and - exists(t) and + t0 = t and exists(ap) and not stateBarrier(node, state) and ( @@ -2197,8 +2206,8 @@ module Impl { import BooleanCallContext predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - DataFlowType t, LocalCc lcc + NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, Typ t, + LocalCc lcc ) { localFlowBigStep(node1, state1, node2, state2, preservesValue, t, _) and exists(lcc) @@ -2218,10 +2227,16 @@ module Impl { ) } - bindingset[node, state, t, ap] - predicate filter(NodeEx node, FlowState state, Typ t, Ap ap) { + bindingset[node, state, t0, ap] + predicate filter(NodeEx node, FlowState state, Typ t0, Ap ap, Typ t) { exists(state) and - (if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), t) else any()) 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 @@ -2241,6 +2256,16 @@ module Impl { import MkStage::Stage } + bindingset[node, t0] + private predicate strengthenType(NodeEx node, DataFlowType t0, DataFlowType t) { + if castingNodeEx(node) + then + exists(DataFlowType nt | nt = node.getDataFlowType() | + if typeStrongerThan(nt, t0) then t = nt else (compatibleTypes(nt, t0) and t = t0) + ) + else t = t0 + } + private module Stage4Param implements MkStage::StageParam { private module PrevStage = Stage3; @@ -2274,8 +2299,8 @@ module Impl { pragma[nomagic] predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - DataFlowType t, LocalCc lcc + 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 @@ -2333,11 +2358,11 @@ module Impl { ) } - bindingset[node, state, t, ap] - predicate filter(NodeEx node, FlowState state, Typ t, Ap ap) { + 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 - (if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), t) else any()) and + strengthenType(node, t0, t) and ( notExpectsContent(node) or @@ -2365,7 +2390,7 @@ module Impl { exists(AccessPathFront apf | Stage4::revFlow(node, state, TReturnCtxMaybeFlowThrough(_), _, apf) and Stage4::fwdFlow(node, state, any(Stage4::CcCall ccc), _, _, TAccessPathFrontSome(argApf), _, - apf) + apf, _) ) } @@ -2579,8 +2604,8 @@ module Impl { import LocalCallContext predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - DataFlowType t, LocalCc lcc + NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, Typ t, + LocalCc lcc ) { localFlowBigStep(node1, state1, node2, state2, preservesValue, t, lcc) and PrevStage::revFlow(node1, pragma[only_bind_into](state1), _) and @@ -2609,9 +2634,9 @@ module Impl { ) } - bindingset[node, state, t, ap] - predicate filter(NodeEx node, FlowState state, Typ t, Ap ap) { - (if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), t) else any()) and + bindingset[node, state, t0, ap] + predicate filter(NodeEx node, FlowState state, Typ t0, Ap ap, Typ t) { + strengthenType(node, t0, t) and exists(state) and exists(ap) } @@ -2632,7 +2657,7 @@ module Impl { 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, _) ) } @@ -2649,7 +2674,7 @@ module Impl { TSummaryCtxSome(ParamNodeEx p, FlowState state, DataFlowType t, AccessPath ap) { exists(AccessPathApprox apa | ap.getApprox() = apa | Stage5::parameterMayFlowThrough(p, apa) and - Stage5::fwdFlow(p, state, _, _, _, _, t, apa) and + Stage5::fwdFlow(p, state, _, _, Option::some(t), _, _, apa, _) and Stage5::revFlow(p, state, _) ) } @@ -2820,9 +2845,7 @@ module Impl { ap = TAccessPathNil() or // ... or a step from an existing PathNode to another node. - pathStep(_, node, state, cc, sc, t, ap) and - Stage5::revFlow(node, state, ap.getApprox()) and - (if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), t) else any()) + pathStep(_, node, state, cc, sc, t, ap) } or TPathNodeSink(NodeEx node, FlowState state) { exists(PathNodeMid sink | @@ -3340,13 +3363,24 @@ module Impl { ap = mid.getAp() } + private predicate pathStep( + PathNodeMid mid, NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, DataFlowType t, + AccessPath ap + ) { + exists(DataFlowType t0 | + pathStep0(mid, node, state, cc, sc, t0, ap) and + Stage5::revFlow(node, state, ap.getApprox()) and + strengthenType(node, t0, t) + ) + } + /** * Holds if data may flow from `mid` to `node`. The last step in or out of * a callable is recorded by `cc`. */ pragma[assume_small_delta] pragma[nomagic] - private predicate pathStep( + private predicate pathStep0( PathNodeMid mid, NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, DataFlowType t, AccessPath ap ) { @@ -3964,7 +3998,7 @@ module Impl { ap = TPartialNil() and exists(explorationLimit()) or - partialPathNodeMk0(node, state, cc, sc1, sc2, sc3, sc4, t, ap) and + partialPathStep(_, node, state, cc, sc1, sc2, sc3, sc4, t, ap) and distSrc(node.getEnclosingCallable()) <= explorationLimit() } or TPartialPathNodeRev( @@ -3990,11 +4024,20 @@ module Impl { } pragma[nomagic] - private predicate partialPathNodeMk0( - NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, - TSummaryCtx3 sc3, TSummaryCtx4 sc4, DataFlowType t, PartialAccessPath ap + private predicate partialPathStep( + PartialPathNodeFwd mid, NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, + TSummaryCtx2 sc2, TSummaryCtx3 sc3, TSummaryCtx4 sc4, DataFlowType t, PartialAccessPath ap ) { - partialPathStep(_, node, state, cc, sc1, sc2, sc3, sc4, t, ap) and + partialPathStep1(mid, node, state, cc, sc1, sc2, sc3, sc4, _, t, ap) + } + + pragma[nomagic] + private predicate partialPathStep1( + PartialPathNodeFwd mid, NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, + TSummaryCtx2 sc2, TSummaryCtx3 sc3, TSummaryCtx4 sc4, DataFlowType t0, DataFlowType t, + PartialAccessPath ap + ) { + partialPathStep0(mid, node, state, cc, sc1, sc2, sc3, sc4, t0, ap) and not fullBarrier(node) and not stateBarrier(node, state) and not clearsContentEx(node, ap.getHead()) and @@ -4002,9 +4045,14 @@ module Impl { notExpectsContent(node) or expectsContentEx(node, ap.getHead()) ) and - if node.asNode() instanceof CastingNode - then compatibleTypes(node.getDataFlowType(), t) - else any() + strengthenType(node, t0, t) + } + + pragma[nomagic] + private predicate partialPathTypeStrengthen( + DataFlowType t0, PartialAccessPath ap, DataFlowType t + ) { + partialPathStep1(_, _, _, _, _, _, _, _, t0, t, ap) and t0 != t } /** @@ -4183,7 +4231,8 @@ module Impl { } } - private predicate partialPathStep( + pragma[nomagic] + private predicate partialPathStep0( PartialPathNodeFwd mid, NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, TSummaryCtx3 sc3, TSummaryCtx4 sc4, DataFlowType t, PartialAccessPath ap ) { @@ -4309,6 +4358,11 @@ module Impl { DataFlowType t1, PartialAccessPath ap1, Content c, DataFlowType t2, PartialAccessPath ap2 ) { partialPathStoreStep(_, t1, ap1, c, _, t2, ap2) + or + exists(DataFlowType t0 | + partialPathTypeStrengthen(t0, ap2, t2) and + apConsFwd(t1, ap1, c, t0, ap2) + ) } pragma[nomagic] diff --git a/go/ql/lib/semmle/go/dataflow/internal/DataFlowPrivate.qll b/go/ql/lib/semmle/go/dataflow/internal/DataFlowPrivate.qll index d45587aa3d4..e0adc9f5790 100644 --- a/go/ql/lib/semmle/go/dataflow/internal/DataFlowPrivate.qll +++ b/go/ql/lib/semmle/go/dataflow/internal/DataFlowPrivate.qll @@ -200,6 +200,8 @@ predicate expectsContent(Node n, ContentSet c) { FlowSummaryImpl::Private::Steps::summaryExpectsContent(n, c) } +predicate typeStrongerThan(DataFlowType t1, DataFlowType t2) { none() } + /** Gets the type of `n` used for type pruning. */ DataFlowType getNodeType(Node n) { result = TTodoDataFlowType() and exists(n) } diff --git a/java/ql/lib/change-notes/2023-06-08-type-strengthening.md b/java/ql/lib/change-notes/2023-06-08-type-strengthening.md new file mode 100644 index 00000000000..60daaa53058 --- /dev/null +++ b/java/ql/lib/change-notes/2023-06-08-type-strengthening.md @@ -0,0 +1,4 @@ +--- +category: majorAnalysis +--- +* The data flow library now performs type strengthening. This increases precision for all data flow queries by excluding paths that can be inferred to be impossible due to incompatible types. diff --git a/java/ql/lib/ext/java.sql.model.yml b/java/ql/lib/ext/java.sql.model.yml index c93a89cfd2c..58985c886b5 100644 --- a/java/ql/lib/ext/java.sql.model.yml +++ b/java/ql/lib/ext/java.sql.model.yml @@ -21,7 +21,6 @@ extensions: extensible: summaryModel data: - ["java.sql", "Connection", True, "nativeSQL", "(String)", "", "Argument[0]", "ReturnValue", "taint", "hq-manual"] - - ["java.sql", "PreparedStatement", True, "setString", "(int,String)", "", "Argument[1]", "Argument[this]", "value", "manual"] - ["java.sql", "ResultSet", True, "getString", "(String)", "", "Argument[this]", "ReturnValue", "taint", "manual"] - addsTo: @@ -31,13 +30,14 @@ extensions: - ["java.sql", "Connection", "createStatement", "()", "summary", "manual"] - ["java.sql", "PreparedStatement", "executeUpdate", "()", "summary", "manual"] - ["java.sql", "PreparedStatement", "executeQuery", "()", "summary", "manual"] + - ["java.sql", "PreparedStatement", "setInt", "(int,int)", "summary", "manual"] + - ["java.sql", "PreparedStatement", "setLong", "(int,long)", "summary", "manual"] + - ["java.sql", "PreparedStatement", "setString", "(int,String)", "summary", "manual"] - ["java.sql", "ResultSet", "next", "()", "summary", "manual"] - ["java.sql", "Statement", "close", "()", "summary", "manual"] # The below APIs have numeric flow and are currently being stored as neutral models. # These may be changed to summary models with kinds "value-numeric" and "taint-numeric" (or similar) in the future. - - ["java.sql", "PreparedStatement", "setInt", "(int,int)", "summary", "manual"] # value-numeric - - ["java.sql", "PreparedStatement", "setLong", "(int,long)", "summary", "manual"] # value-numeric - ["java.sql", "ResultSet", "getInt", "(int)", "summary", "manual"] # taint-numeric - ["java.sql", "ResultSet", "getInt", "(String)", "summary", "manual"] # taint-numeric - ["java.sql", "ResultSet", "getLong", "(String)", "summary", "manual"] # taint-numeric diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl.qll b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl.qll index ddf98ac0f2f..984c5ae2018 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl.qll @@ -1135,8 +1135,8 @@ module Impl { DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow ); - bindingset[node, state, t, ap] - predicate filter(NodeEx node, FlowState state, Typ t, Ap ap); + bindingset[node, state, t0, ap] + predicate filter(NodeEx node, FlowState state, Typ t0, Ap ap, Typ t); bindingset[typ, contentType] predicate typecheckStore(Typ typ, DataFlowType contentType); @@ -1199,17 +1199,21 @@ module Impl { NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, TypOption argT, ApOption argAp, Typ t, Ap ap, ApApprox apa ) { - fwdFlow0(node, state, cc, summaryCtx, argT, argAp, t, ap, apa) and - PrevStage::revFlow(node, state, apa) and - filter(node, state, t, ap) + fwdFlow1(node, state, cc, summaryCtx, argT, argAp, _, t, ap, apa) } - pragma[inline] - additional predicate fwdFlow( + private predicate fwdFlow1( NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, TypOption argT, - ApOption argAp, Typ t, Ap ap + ApOption argAp, Typ t0, Typ t, Ap ap, ApApprox apa ) { - fwdFlow(node, state, cc, summaryCtx, argT, argAp, t, ap, _) + fwdFlow0(node, state, cc, summaryCtx, argT, argAp, t0, ap, apa) and + PrevStage::revFlow(node, state, apa) and + filter(node, state, t0, ap, t) + } + + pragma[nomagic] + private predicate typeStrengthen(Typ t0, Ap ap, Typ t) { + fwdFlow1(_, _, _, _, _, _, t0, t, ap, _) and t0 != t } pragma[assume_small_delta] @@ -1339,6 +1343,11 @@ module Impl { private predicate fwdFlowConsCand(Typ t2, Ap cons, Content c, Typ t1, Ap tail) { fwdFlowStore(_, t1, tail, c, t2, _, _, _, _, _, _) and cons = apCons(c, t1, tail) + or + exists(Typ t0 | + typeStrengthen(t0, cons, t2) and + fwdFlowConsCand(t0, cons, c, t1, tail) + ) } pragma[nomagic] @@ -1359,7 +1368,7 @@ module Impl { ParamNodeOption summaryCtx, TypOption argT, ApOption argAp ) { exists(ApHeadContent apc | - fwdFlow(node1, state, cc, summaryCtx, argT, argAp, t, ap) and + fwdFlow(node1, state, cc, summaryCtx, argT, argAp, t, ap, _) and apc = getHeadContent(ap) and readStepCand0(node1, apc, c, node2) ) @@ -1520,14 +1529,14 @@ module Impl { 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() @@ -1780,13 +1789,13 @@ module Impl { boolean fwd, int nodes, int fields, int conscand, int states, int tuples ) { fwd = true and - nodes = count(NodeEx node | fwdFlow(node, _, _, _, _, _, _, _)) 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 + states = count(FlowState state | fwdFlow(_, state, _, _, _, _, _, _, _)) and tuples = count(NodeEx n, FlowState state, Cc cc, ParamNodeOption summaryCtx, TypOption argT, - ApOption argAp, Typ t, Ap ap | fwdFlow(n, state, cc, summaryCtx, argT, argAp, t, ap)) + ApOption argAp, Typ t, Ap ap | fwdFlow(n, state, cc, summaryCtx, argT, argAp, t, ap, _)) or fwd = false and nodes = count(NodeEx node | revFlow(node, _, _, _, _)) and @@ -1963,10 +1972,10 @@ module Impl { ) } - bindingset[node, state, t, ap] - predicate filter(NodeEx node, FlowState state, Typ t, Ap ap) { + bindingset[node, state, t0, ap] + predicate filter(NodeEx node, FlowState state, Typ t0, Ap ap, Typ t) { PrevStage::revFlowState(state) and - exists(t) and + t0 = t and exists(ap) and not stateBarrier(node, state) and ( @@ -2197,8 +2206,8 @@ module Impl { import BooleanCallContext predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - DataFlowType t, LocalCc lcc + NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, Typ t, + LocalCc lcc ) { localFlowBigStep(node1, state1, node2, state2, preservesValue, t, _) and exists(lcc) @@ -2218,10 +2227,16 @@ module Impl { ) } - bindingset[node, state, t, ap] - predicate filter(NodeEx node, FlowState state, Typ t, Ap ap) { + bindingset[node, state, t0, ap] + predicate filter(NodeEx node, FlowState state, Typ t0, Ap ap, Typ t) { exists(state) and - (if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), t) else any()) 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 @@ -2241,6 +2256,16 @@ module Impl { import MkStage::Stage } + bindingset[node, t0] + private predicate strengthenType(NodeEx node, DataFlowType t0, DataFlowType t) { + if castingNodeEx(node) + then + exists(DataFlowType nt | nt = node.getDataFlowType() | + if typeStrongerThan(nt, t0) then t = nt else (compatibleTypes(nt, t0) and t = t0) + ) + else t = t0 + } + private module Stage4Param implements MkStage::StageParam { private module PrevStage = Stage3; @@ -2274,8 +2299,8 @@ module Impl { pragma[nomagic] predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - DataFlowType t, LocalCc lcc + 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 @@ -2333,11 +2358,11 @@ module Impl { ) } - bindingset[node, state, t, ap] - predicate filter(NodeEx node, FlowState state, Typ t, Ap ap) { + 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 - (if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), t) else any()) and + strengthenType(node, t0, t) and ( notExpectsContent(node) or @@ -2365,7 +2390,7 @@ module Impl { exists(AccessPathFront apf | Stage4::revFlow(node, state, TReturnCtxMaybeFlowThrough(_), _, apf) and Stage4::fwdFlow(node, state, any(Stage4::CcCall ccc), _, _, TAccessPathFrontSome(argApf), _, - apf) + apf, _) ) } @@ -2579,8 +2604,8 @@ module Impl { import LocalCallContext predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - DataFlowType t, LocalCc lcc + NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, Typ t, + LocalCc lcc ) { localFlowBigStep(node1, state1, node2, state2, preservesValue, t, lcc) and PrevStage::revFlow(node1, pragma[only_bind_into](state1), _) and @@ -2609,9 +2634,9 @@ module Impl { ) } - bindingset[node, state, t, ap] - predicate filter(NodeEx node, FlowState state, Typ t, Ap ap) { - (if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), t) else any()) and + bindingset[node, state, t0, ap] + predicate filter(NodeEx node, FlowState state, Typ t0, Ap ap, Typ t) { + strengthenType(node, t0, t) and exists(state) and exists(ap) } @@ -2632,7 +2657,7 @@ module Impl { 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, _) ) } @@ -2649,7 +2674,7 @@ module Impl { TSummaryCtxSome(ParamNodeEx p, FlowState state, DataFlowType t, AccessPath ap) { exists(AccessPathApprox apa | ap.getApprox() = apa | Stage5::parameterMayFlowThrough(p, apa) and - Stage5::fwdFlow(p, state, _, _, _, _, t, apa) and + Stage5::fwdFlow(p, state, _, _, Option::some(t), _, _, apa, _) and Stage5::revFlow(p, state, _) ) } @@ -2820,9 +2845,7 @@ module Impl { ap = TAccessPathNil() or // ... or a step from an existing PathNode to another node. - pathStep(_, node, state, cc, sc, t, ap) and - Stage5::revFlow(node, state, ap.getApprox()) and - (if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), t) else any()) + pathStep(_, node, state, cc, sc, t, ap) } or TPathNodeSink(NodeEx node, FlowState state) { exists(PathNodeMid sink | @@ -3340,13 +3363,24 @@ module Impl { ap = mid.getAp() } + private predicate pathStep( + PathNodeMid mid, NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, DataFlowType t, + AccessPath ap + ) { + exists(DataFlowType t0 | + pathStep0(mid, node, state, cc, sc, t0, ap) and + Stage5::revFlow(node, state, ap.getApprox()) and + strengthenType(node, t0, t) + ) + } + /** * Holds if data may flow from `mid` to `node`. The last step in or out of * a callable is recorded by `cc`. */ pragma[assume_small_delta] pragma[nomagic] - private predicate pathStep( + private predicate pathStep0( PathNodeMid mid, NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, DataFlowType t, AccessPath ap ) { @@ -3964,7 +3998,7 @@ module Impl { ap = TPartialNil() and exists(explorationLimit()) or - partialPathNodeMk0(node, state, cc, sc1, sc2, sc3, sc4, t, ap) and + partialPathStep(_, node, state, cc, sc1, sc2, sc3, sc4, t, ap) and distSrc(node.getEnclosingCallable()) <= explorationLimit() } or TPartialPathNodeRev( @@ -3990,11 +4024,20 @@ module Impl { } pragma[nomagic] - private predicate partialPathNodeMk0( - NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, - TSummaryCtx3 sc3, TSummaryCtx4 sc4, DataFlowType t, PartialAccessPath ap + private predicate partialPathStep( + PartialPathNodeFwd mid, NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, + TSummaryCtx2 sc2, TSummaryCtx3 sc3, TSummaryCtx4 sc4, DataFlowType t, PartialAccessPath ap ) { - partialPathStep(_, node, state, cc, sc1, sc2, sc3, sc4, t, ap) and + partialPathStep1(mid, node, state, cc, sc1, sc2, sc3, sc4, _, t, ap) + } + + pragma[nomagic] + private predicate partialPathStep1( + PartialPathNodeFwd mid, NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, + TSummaryCtx2 sc2, TSummaryCtx3 sc3, TSummaryCtx4 sc4, DataFlowType t0, DataFlowType t, + PartialAccessPath ap + ) { + partialPathStep0(mid, node, state, cc, sc1, sc2, sc3, sc4, t0, ap) and not fullBarrier(node) and not stateBarrier(node, state) and not clearsContentEx(node, ap.getHead()) and @@ -4002,9 +4045,14 @@ module Impl { notExpectsContent(node) or expectsContentEx(node, ap.getHead()) ) and - if node.asNode() instanceof CastingNode - then compatibleTypes(node.getDataFlowType(), t) - else any() + strengthenType(node, t0, t) + } + + pragma[nomagic] + private predicate partialPathTypeStrengthen( + DataFlowType t0, PartialAccessPath ap, DataFlowType t + ) { + partialPathStep1(_, _, _, _, _, _, _, _, t0, t, ap) and t0 != t } /** @@ -4183,7 +4231,8 @@ module Impl { } } - private predicate partialPathStep( + pragma[nomagic] + private predicate partialPathStep0( PartialPathNodeFwd mid, NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, TSummaryCtx3 sc3, TSummaryCtx4 sc4, DataFlowType t, PartialAccessPath ap ) { @@ -4309,6 +4358,11 @@ module Impl { DataFlowType t1, PartialAccessPath ap1, Content c, DataFlowType t2, PartialAccessPath ap2 ) { partialPathStoreStep(_, t1, ap1, c, _, t2, ap2) + or + exists(DataFlowType t0 | + partialPathTypeStrengthen(t0, ap2, t2) and + apConsFwd(t1, ap1, c, t0, ap2) + ) } pragma[nomagic] 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 22f84241c96..01bf90cb7ba 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowPrivate.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowPrivate.qll @@ -176,7 +176,7 @@ predicate expectsContent(Node n, ContentSet c) { * possible flow. A single type is used for all numeric types to account for * numeric conversions, and otherwise the erasure is used. */ -DataFlowType getErasedRepr(Type t) { +RefType getErasedRepr(Type t) { exists(Type e | e = t.getErasure() | if e instanceof NumericOrCharType then result.(BoxedType).getPrimitiveType().getName() = "double" @@ -189,6 +189,13 @@ DataFlowType getErasedRepr(Type t) { t instanceof NullType and result instanceof TypeObject } +class DataFlowType extends SrcRefType { + DataFlowType() { this = getErasedRepr(_) } +} + +pragma[nomagic] +predicate typeStrongerThan(DataFlowType t1, DataFlowType t2) { t1.getASourceSupertype+() = t2 } + pragma[noinline] DataFlowType getNodeType(Node n) { result = getErasedRepr(n.getTypeBound()) @@ -259,8 +266,6 @@ class DataFlowCallable extends TDataFlowCallable { class DataFlowExpr = Expr; -class DataFlowType = RefType; - private newtype TDataFlowCall = TCall(Call c) or TSummaryCall(SummarizedCallable c, Node receiver) { diff --git a/java/ql/src/experimental/Security/CWE/CWE-200/AndroidWebResourceResponse.qll b/java/ql/src/experimental/Security/CWE/CWE-200/AndroidWebResourceResponse.qll index bd177b30213..05055bdfa84 100644 --- a/java/ql/src/experimental/Security/CWE/CWE-200/AndroidWebResourceResponse.qll +++ b/java/ql/src/experimental/Security/CWE/CWE-200/AndroidWebResourceResponse.qll @@ -55,10 +55,14 @@ class WebResourceResponseSink extends DataFlow::Node { } /** - * A value step from the URL argument of `WebView::loadUrl` to the URL parameter of + * A taint step from the URL argument of `WebView::loadUrl` to the URL/WebResourceRequest parameter of * `WebViewClient::shouldInterceptRequest`. + * + * TODO: This ought to be a value step when it is targeting the URL parameter, + * and it ought to check the parameter type in both cases to ensure that we only + * hit the overloads we intend to. */ -private class FetchUrlStep extends AdditionalValueStep { +private class FetchUrlStep extends AdditionalTaintStep { override predicate step(DataFlow::Node pred, DataFlow::Node succ) { exists( // webview.loadUrl(url) -> webview.setWebViewClient(new WebViewClient() { shouldInterceptRequest(view, url) }); diff --git a/java/ql/test/experimental/query-tests/security/CWE-020/Log4jInjectionTest.expected b/java/ql/test/experimental/query-tests/security/CWE-020/Log4jInjectionTest.expected index f3d88d25805..93b2b060685 100644 --- a/java/ql/test/experimental/query-tests/security/CWE-020/Log4jInjectionTest.expected +++ b/java/ql/test/experimental/query-tests/security/CWE-020/Log4jInjectionTest.expected @@ -2075,28 +2075,28 @@ edges | Log4jJndiInjectionTest.java:1085:39:1085:46 | source(...) : String | Log4jJndiInjectionTest.java:1085:25:1085:46 | (...)... | | Log4jJndiInjectionTest.java:1088:47:1088:54 | source(...) : String | Log4jJndiInjectionTest.java:1088:38:1088:54 | (...)... | | Log4jJndiInjectionTest.java:1089:53:1089:60 | source(...) : String | Log4jJndiInjectionTest.java:1089:44:1089:60 | (...)... | -| Log4jJndiInjectionTest.java:1091:13:1091:15 | map [post update] : Map [] : String | Log4jJndiInjectionTest.java:1092:34:1092:36 | map | -| Log4jJndiInjectionTest.java:1091:28:1091:44 | (...)... : String | Log4jJndiInjectionTest.java:1091:13:1091:15 | map [post update] : Map [] : String | +| Log4jJndiInjectionTest.java:1091:13:1091:15 | map [post update] : HashMap [] : String | Log4jJndiInjectionTest.java:1092:34:1092:36 | map | +| Log4jJndiInjectionTest.java:1091:28:1091:44 | (...)... : String | Log4jJndiInjectionTest.java:1091:13:1091:15 | map [post update] : HashMap [] : String | | Log4jJndiInjectionTest.java:1091:37:1091:44 | source(...) : String | Log4jJndiInjectionTest.java:1091:28:1091:44 | (...)... : String | -| Log4jJndiInjectionTest.java:1095:31:1095:88 | with(...) : MapMessage | Log4jJndiInjectionTest.java:1096:26:1096:29 | mmsg | -| Log4jJndiInjectionTest.java:1095:71:1095:87 | (...)... : String | Log4jJndiInjectionTest.java:1095:31:1095:88 | with(...) : MapMessage | +| Log4jJndiInjectionTest.java:1095:31:1095:88 | with(...) : StringMapMessage | Log4jJndiInjectionTest.java:1096:26:1096:29 | mmsg | +| Log4jJndiInjectionTest.java:1095:71:1095:87 | (...)... : String | Log4jJndiInjectionTest.java:1095:31:1095:88 | with(...) : StringMapMessage | | Log4jJndiInjectionTest.java:1095:80:1095:87 | source(...) : String | Log4jJndiInjectionTest.java:1095:71:1095:87 | (...)... : String | -| Log4jJndiInjectionTest.java:1100:13:1100:16 | mmsg [post update] : MapMessage | Log4jJndiInjectionTest.java:1101:26:1101:29 | mmsg | -| Log4jJndiInjectionTest.java:1100:35:1100:51 | (...)... : String | Log4jJndiInjectionTest.java:1100:13:1100:16 | mmsg [post update] : MapMessage | +| Log4jJndiInjectionTest.java:1100:13:1100:16 | mmsg [post update] : StringMapMessage | Log4jJndiInjectionTest.java:1101:26:1101:29 | mmsg | +| Log4jJndiInjectionTest.java:1100:35:1100:51 | (...)... : String | Log4jJndiInjectionTest.java:1100:13:1100:16 | mmsg [post update] : StringMapMessage | | Log4jJndiInjectionTest.java:1100:44:1100:51 | source(...) : String | Log4jJndiInjectionTest.java:1100:35:1100:51 | (...)... : String | -| Log4jJndiInjectionTest.java:1105:13:1105:16 | mmsg [post update] : MapMessage | Log4jJndiInjectionTest.java:1106:26:1106:29 | mmsg | -| Log4jJndiInjectionTest.java:1105:34:1105:50 | (...)... : String | Log4jJndiInjectionTest.java:1105:13:1105:16 | mmsg [post update] : MapMessage | +| Log4jJndiInjectionTest.java:1105:13:1105:16 | mmsg [post update] : StringMapMessage | Log4jJndiInjectionTest.java:1106:26:1106:29 | mmsg | +| Log4jJndiInjectionTest.java:1105:34:1105:50 | (...)... : String | Log4jJndiInjectionTest.java:1105:13:1105:16 | mmsg [post update] : StringMapMessage | | Log4jJndiInjectionTest.java:1105:43:1105:50 | source(...) : String | Log4jJndiInjectionTest.java:1105:34:1105:50 | (...)... : String | -| Log4jJndiInjectionTest.java:1111:13:1111:15 | map [post update] : Map [] : String | Log4jJndiInjectionTest.java:1112:25:1112:27 | map : Map [] : String | -| Log4jJndiInjectionTest.java:1111:33:1111:49 | (...)... : String | Log4jJndiInjectionTest.java:1111:13:1111:15 | map [post update] : Map [] : String | +| Log4jJndiInjectionTest.java:1111:13:1111:15 | map [post update] : HashMap [] : String | Log4jJndiInjectionTest.java:1112:25:1112:27 | map : HashMap [] : String | +| Log4jJndiInjectionTest.java:1111:33:1111:49 | (...)... : String | Log4jJndiInjectionTest.java:1111:13:1111:15 | map [post update] : HashMap [] : String | | Log4jJndiInjectionTest.java:1111:42:1111:49 | source(...) : String | Log4jJndiInjectionTest.java:1111:33:1111:49 | (...)... : String | -| Log4jJndiInjectionTest.java:1112:13:1112:16 | mmsg [post update] : MapMessage | Log4jJndiInjectionTest.java:1113:26:1113:29 | mmsg | -| Log4jJndiInjectionTest.java:1112:25:1112:27 | map : Map [] : String | Log4jJndiInjectionTest.java:1112:13:1112:16 | mmsg [post update] : MapMessage | +| Log4jJndiInjectionTest.java:1112:13:1112:16 | mmsg [post update] : StringMapMessage | Log4jJndiInjectionTest.java:1113:26:1113:29 | mmsg | +| Log4jJndiInjectionTest.java:1112:25:1112:27 | map : HashMap [] : String | Log4jJndiInjectionTest.java:1112:13:1112:16 | mmsg [post update] : StringMapMessage | | Log4jJndiInjectionTest.java:1116:61:1116:68 | source(...) : String | Log4jJndiInjectionTest.java:1116:52:1116:68 | (...)... | | Log4jJndiInjectionTest.java:1117:81:1117:88 | source(...) : String | Log4jJndiInjectionTest.java:1117:72:1117:88 | (...)... | -| Log4jJndiInjectionTest.java:1119:13:1119:15 | map [post update] : Map [] : String | Log4jJndiInjectionTest.java:1120:43:1120:45 | map | -| Log4jJndiInjectionTest.java:1119:13:1119:15 | map [post update] : Map [] : String | Log4jJndiInjectionTest.java:1121:63:1121:65 | map | -| Log4jJndiInjectionTest.java:1119:33:1119:49 | (...)... : String | Log4jJndiInjectionTest.java:1119:13:1119:15 | map [post update] : Map [] : String | +| Log4jJndiInjectionTest.java:1119:13:1119:15 | map [post update] : HashMap [] : String | Log4jJndiInjectionTest.java:1120:43:1120:45 | map | +| Log4jJndiInjectionTest.java:1119:13:1119:15 | map [post update] : HashMap [] : String | Log4jJndiInjectionTest.java:1121:63:1121:65 | map | +| Log4jJndiInjectionTest.java:1119:33:1119:49 | (...)... : String | Log4jJndiInjectionTest.java:1119:13:1119:15 | map [post update] : HashMap [] : String | | Log4jJndiInjectionTest.java:1119:42:1119:49 | source(...) : String | Log4jJndiInjectionTest.java:1119:33:1119:49 | (...)... : String | nodes | Log4jJndiInjectionTest.java:24:16:24:45 | getParameter(...) : String | semmle.label | getParameter(...) : String | @@ -4168,33 +4168,33 @@ nodes | Log4jJndiInjectionTest.java:1088:47:1088:54 | source(...) : String | semmle.label | source(...) : String | | Log4jJndiInjectionTest.java:1089:44:1089:60 | (...)... | semmle.label | (...)... | | Log4jJndiInjectionTest.java:1089:53:1089:60 | source(...) : String | semmle.label | source(...) : String | -| Log4jJndiInjectionTest.java:1091:13:1091:15 | map [post update] : Map [] : String | semmle.label | map [post update] : Map [] : String | +| Log4jJndiInjectionTest.java:1091:13:1091:15 | map [post update] : HashMap [] : String | semmle.label | map [post update] : HashMap [] : String | | Log4jJndiInjectionTest.java:1091:28:1091:44 | (...)... : String | semmle.label | (...)... : String | | Log4jJndiInjectionTest.java:1091:37:1091:44 | source(...) : String | semmle.label | source(...) : String | | Log4jJndiInjectionTest.java:1092:34:1092:36 | map | semmle.label | map | -| Log4jJndiInjectionTest.java:1095:31:1095:88 | with(...) : MapMessage | semmle.label | with(...) : MapMessage | +| Log4jJndiInjectionTest.java:1095:31:1095:88 | with(...) : StringMapMessage | semmle.label | with(...) : StringMapMessage | | Log4jJndiInjectionTest.java:1095:71:1095:87 | (...)... : String | semmle.label | (...)... : String | | Log4jJndiInjectionTest.java:1095:80:1095:87 | source(...) : String | semmle.label | source(...) : String | | Log4jJndiInjectionTest.java:1096:26:1096:29 | mmsg | semmle.label | mmsg | -| Log4jJndiInjectionTest.java:1100:13:1100:16 | mmsg [post update] : MapMessage | semmle.label | mmsg [post update] : MapMessage | +| Log4jJndiInjectionTest.java:1100:13:1100:16 | mmsg [post update] : StringMapMessage | semmle.label | mmsg [post update] : StringMapMessage | | Log4jJndiInjectionTest.java:1100:35:1100:51 | (...)... : String | semmle.label | (...)... : String | | Log4jJndiInjectionTest.java:1100:44:1100:51 | source(...) : String | semmle.label | source(...) : String | | Log4jJndiInjectionTest.java:1101:26:1101:29 | mmsg | semmle.label | mmsg | -| Log4jJndiInjectionTest.java:1105:13:1105:16 | mmsg [post update] : MapMessage | semmle.label | mmsg [post update] : MapMessage | +| Log4jJndiInjectionTest.java:1105:13:1105:16 | mmsg [post update] : StringMapMessage | semmle.label | mmsg [post update] : StringMapMessage | | Log4jJndiInjectionTest.java:1105:34:1105:50 | (...)... : String | semmle.label | (...)... : String | | Log4jJndiInjectionTest.java:1105:43:1105:50 | source(...) : String | semmle.label | source(...) : String | | Log4jJndiInjectionTest.java:1106:26:1106:29 | mmsg | semmle.label | mmsg | -| Log4jJndiInjectionTest.java:1111:13:1111:15 | map [post update] : Map [] : String | semmle.label | map [post update] : Map [] : String | +| Log4jJndiInjectionTest.java:1111:13:1111:15 | map [post update] : HashMap [] : String | semmle.label | map [post update] : HashMap [] : String | | Log4jJndiInjectionTest.java:1111:33:1111:49 | (...)... : String | semmle.label | (...)... : String | | Log4jJndiInjectionTest.java:1111:42:1111:49 | source(...) : String | semmle.label | source(...) : String | -| Log4jJndiInjectionTest.java:1112:13:1112:16 | mmsg [post update] : MapMessage | semmle.label | mmsg [post update] : MapMessage | -| Log4jJndiInjectionTest.java:1112:25:1112:27 | map : Map [] : String | semmle.label | map : Map [] : String | +| Log4jJndiInjectionTest.java:1112:13:1112:16 | mmsg [post update] : StringMapMessage | semmle.label | mmsg [post update] : StringMapMessage | +| Log4jJndiInjectionTest.java:1112:25:1112:27 | map : HashMap [] : String | semmle.label | map : HashMap [] : String | | Log4jJndiInjectionTest.java:1113:26:1113:29 | mmsg | semmle.label | mmsg | | Log4jJndiInjectionTest.java:1116:52:1116:68 | (...)... | semmle.label | (...)... | | Log4jJndiInjectionTest.java:1116:61:1116:68 | source(...) : String | semmle.label | source(...) : String | | Log4jJndiInjectionTest.java:1117:72:1117:88 | (...)... | semmle.label | (...)... | | Log4jJndiInjectionTest.java:1117:81:1117:88 | source(...) : String | semmle.label | source(...) : String | -| Log4jJndiInjectionTest.java:1119:13:1119:15 | map [post update] : Map [] : String | semmle.label | map [post update] : Map [] : String | +| Log4jJndiInjectionTest.java:1119:13:1119:15 | map [post update] : HashMap [] : String | semmle.label | map [post update] : HashMap [] : String | | Log4jJndiInjectionTest.java:1119:33:1119:49 | (...)... : String | semmle.label | (...)... : String | | Log4jJndiInjectionTest.java:1119:42:1119:49 | source(...) : String | semmle.label | source(...) : String | | Log4jJndiInjectionTest.java:1120:43:1120:45 | map | semmle.label | map | diff --git a/java/ql/test/experimental/query-tests/security/CWE-200/InsecureWebResourceResponse.expected b/java/ql/test/experimental/query-tests/security/CWE-200/InsecureWebResourceResponse.expected index 37741e5f605..07ce59763ad 100644 --- a/java/ql/test/experimental/query-tests/security/CWE-200/InsecureWebResourceResponse.expected +++ b/java/ql/test/experimental/query-tests/security/CWE-200/InsecureWebResourceResponse.expected @@ -1,152 +1,152 @@ edges -| InsecureWebResourceResponse.java:28:27:28:37 | getIntent(...) : Intent | InsecureWebResourceResponse.java:28:27:28:64 | getStringExtra(...) : Object | -| InsecureWebResourceResponse.java:28:27:28:64 | getStringExtra(...) : Object | InsecureWebResourceResponse.java:30:25:30:32 | inputUrl : Object | -| InsecureWebResourceResponse.java:28:27:28:64 | getStringExtra(...) : Object | InsecureWebResourceResponse.java:32:25:32:32 | inputUrl : Object | -| InsecureWebResourceResponse.java:28:27:28:64 | getStringExtra(...) : Object | InsecureWebResourceResponse.java:34:25:34:32 | inputUrl : Object | -| InsecureWebResourceResponse.java:28:27:28:64 | getStringExtra(...) : Object | InsecureWebResourceResponse.java:36:26:36:33 | inputUrl : Object | -| InsecureWebResourceResponse.java:28:27:28:64 | getStringExtra(...) : Object | InsecureWebResourceResponse.java:38:26:38:33 | inputUrl : Object | -| InsecureWebResourceResponse.java:28:27:28:64 | getStringExtra(...) : Object | InsecureWebResourceResponse.java:40:25:40:32 | inputUrl : Object | -| InsecureWebResourceResponse.java:28:27:28:64 | getStringExtra(...) : Object | InsecureWebResourceResponse.java:42:25:42:32 | inputUrl : Object | -| InsecureWebResourceResponse.java:28:27:28:64 | getStringExtra(...) : Object | InsecureWebResourceResponse.java:44:26:44:33 | inputUrl : Object | -| InsecureWebResourceResponse.java:30:25:30:32 | inputUrl : Object | InsecureWebResourceResponse.java:59:34:59:43 | url : Object | -| InsecureWebResourceResponse.java:32:25:32:32 | inputUrl : Object | InsecureWebResourceResponse.java:80:34:80:43 | url : Object | -| InsecureWebResourceResponse.java:34:25:34:32 | inputUrl : Object | InsecureWebResourceResponse.java:106:34:106:43 | url : Object | -| InsecureWebResourceResponse.java:36:26:36:33 | inputUrl : Object | InsecureWebResourceResponse.java:131:36:131:45 | url : Object | -| InsecureWebResourceResponse.java:38:26:38:33 | inputUrl : Object | InsecureWebResourceResponse.java:156:35:156:44 | url : Object | -| InsecureWebResourceResponse.java:40:25:40:32 | inputUrl : Object | InsecureWebResourceResponse.java:181:34:181:43 | url : Object | -| InsecureWebResourceResponse.java:42:25:42:32 | inputUrl : Object | InsecureWebResourceResponse.java:188:34:188:43 | url : Object | -| InsecureWebResourceResponse.java:44:26:44:33 | inputUrl : Object | InsecureWebResourceResponse.java:217:35:217:44 | url : Object | -| InsecureWebResourceResponse.java:59:34:59:43 | url : Object | InsecureWebResourceResponse.java:75:20:75:22 | url : Object | -| InsecureWebResourceResponse.java:63:77:63:86 | url : Object | InsecureWebResourceResponse.java:65:41:65:43 | url : Object | +| InsecureWebResourceResponse.java:28:27:28:37 | getIntent(...) : Intent | InsecureWebResourceResponse.java:28:27:28:64 | getStringExtra(...) : String | +| InsecureWebResourceResponse.java:28:27:28:64 | getStringExtra(...) : String | InsecureWebResourceResponse.java:30:25:30:32 | inputUrl : String | +| InsecureWebResourceResponse.java:28:27:28:64 | getStringExtra(...) : String | InsecureWebResourceResponse.java:32:25:32:32 | inputUrl : String | +| InsecureWebResourceResponse.java:28:27:28:64 | getStringExtra(...) : String | InsecureWebResourceResponse.java:34:25:34:32 | inputUrl : String | +| InsecureWebResourceResponse.java:28:27:28:64 | getStringExtra(...) : String | InsecureWebResourceResponse.java:36:26:36:33 | inputUrl : String | +| InsecureWebResourceResponse.java:28:27:28:64 | getStringExtra(...) : String | InsecureWebResourceResponse.java:38:26:38:33 | inputUrl : String | +| InsecureWebResourceResponse.java:28:27:28:64 | getStringExtra(...) : String | InsecureWebResourceResponse.java:40:25:40:32 | inputUrl : String | +| InsecureWebResourceResponse.java:28:27:28:64 | getStringExtra(...) : String | InsecureWebResourceResponse.java:42:25:42:32 | inputUrl : String | +| InsecureWebResourceResponse.java:28:27:28:64 | getStringExtra(...) : String | InsecureWebResourceResponse.java:44:26:44:33 | inputUrl : String | +| InsecureWebResourceResponse.java:30:25:30:32 | inputUrl : String | InsecureWebResourceResponse.java:59:34:59:43 | url : String | +| InsecureWebResourceResponse.java:32:25:32:32 | inputUrl : String | InsecureWebResourceResponse.java:80:34:80:43 | url : String | +| InsecureWebResourceResponse.java:34:25:34:32 | inputUrl : String | InsecureWebResourceResponse.java:106:34:106:43 | url : String | +| InsecureWebResourceResponse.java:36:26:36:33 | inputUrl : String | InsecureWebResourceResponse.java:131:36:131:45 | url : String | +| InsecureWebResourceResponse.java:38:26:38:33 | inputUrl : String | InsecureWebResourceResponse.java:156:35:156:44 | url : String | +| InsecureWebResourceResponse.java:40:25:40:32 | inputUrl : String | InsecureWebResourceResponse.java:181:34:181:43 | url : String | +| InsecureWebResourceResponse.java:42:25:42:32 | inputUrl : String | InsecureWebResourceResponse.java:188:34:188:43 | url : String | +| InsecureWebResourceResponse.java:44:26:44:33 | inputUrl : String | InsecureWebResourceResponse.java:217:35:217:44 | url : String | +| InsecureWebResourceResponse.java:59:34:59:43 | url : String | InsecureWebResourceResponse.java:75:20:75:22 | url : String | +| InsecureWebResourceResponse.java:63:77:63:86 | url : String | InsecureWebResourceResponse.java:65:41:65:43 | url : String | | InsecureWebResourceResponse.java:65:31:65:44 | parse(...) : Uri | InsecureWebResourceResponse.java:66:71:66:73 | uri : Uri | -| InsecureWebResourceResponse.java:65:41:65:43 | url : Object | InsecureWebResourceResponse.java:65:31:65:44 | parse(...) : Uri | +| InsecureWebResourceResponse.java:65:41:65:43 | url : String | InsecureWebResourceResponse.java:65:31:65:44 | parse(...) : Uri | | InsecureWebResourceResponse.java:66:51:66:84 | new FileInputStream(...) : FileInputStream | InsecureWebResourceResponse.java:68:71:68:81 | inputStream | | InsecureWebResourceResponse.java:66:71:66:73 | uri : Uri | InsecureWebResourceResponse.java:66:71:66:83 | getPath(...) : String | | InsecureWebResourceResponse.java:66:71:66:83 | getPath(...) : String | InsecureWebResourceResponse.java:66:51:66:84 | new FileInputStream(...) : FileInputStream | -| InsecureWebResourceResponse.java:75:20:75:22 | url : Object | InsecureWebResourceResponse.java:63:77:63:86 | url : Object | -| InsecureWebResourceResponse.java:75:20:75:22 | url : Object | InsecureWebResourceResponse.java:84:77:84:86 | url : Object | -| InsecureWebResourceResponse.java:75:20:75:22 | url : Object | InsecureWebResourceResponse.java:110:77:110:86 | url : Object | -| InsecureWebResourceResponse.java:75:20:75:22 | url : Object | InsecureWebResourceResponse.java:192:77:192:102 | request : Object | -| InsecureWebResourceResponse.java:75:20:75:22 | url : Object | InsecureWebResourceResponse.java:232:69:232:78 | url : Object | -| InsecureWebResourceResponse.java:80:34:80:43 | url : Object | InsecureWebResourceResponse.java:101:20:101:22 | url : Object | -| InsecureWebResourceResponse.java:84:77:84:86 | url : Object | InsecureWebResourceResponse.java:86:41:86:43 | url : Object | +| InsecureWebResourceResponse.java:75:20:75:22 | url : String | InsecureWebResourceResponse.java:63:77:63:86 | url : String | +| InsecureWebResourceResponse.java:75:20:75:22 | url : String | InsecureWebResourceResponse.java:84:77:84:86 | url : String | +| InsecureWebResourceResponse.java:75:20:75:22 | url : String | InsecureWebResourceResponse.java:110:77:110:86 | url : String | +| InsecureWebResourceResponse.java:75:20:75:22 | url : String | InsecureWebResourceResponse.java:192:77:192:102 | request : WebResourceRequest | +| InsecureWebResourceResponse.java:75:20:75:22 | url : String | InsecureWebResourceResponse.java:232:69:232:78 | url : String | +| InsecureWebResourceResponse.java:80:34:80:43 | url : String | InsecureWebResourceResponse.java:101:20:101:22 | url : String | +| InsecureWebResourceResponse.java:84:77:84:86 | url : String | InsecureWebResourceResponse.java:86:41:86:43 | url : String | | InsecureWebResourceResponse.java:86:31:86:44 | parse(...) : Uri | InsecureWebResourceResponse.java:88:66:88:68 | uri : Uri | -| InsecureWebResourceResponse.java:86:41:86:43 | url : Object | InsecureWebResourceResponse.java:86:31:86:44 | parse(...) : Uri | +| InsecureWebResourceResponse.java:86:41:86:43 | url : String | InsecureWebResourceResponse.java:86:31:86:44 | parse(...) : Uri | | InsecureWebResourceResponse.java:88:42:88:90 | new File(...) : File | InsecureWebResourceResponse.java:89:75:89:83 | cacheFile : File | | InsecureWebResourceResponse.java:88:66:88:68 | uri : Uri | InsecureWebResourceResponse.java:88:66:88:89 | getLastPathSegment(...) : String | | InsecureWebResourceResponse.java:88:66:88:89 | getLastPathSegment(...) : String | InsecureWebResourceResponse.java:88:42:88:90 | new File(...) : File | | InsecureWebResourceResponse.java:89:55:89:84 | new FileInputStream(...) : FileInputStream | InsecureWebResourceResponse.java:91:75:91:85 | inputStream | | InsecureWebResourceResponse.java:89:75:89:83 | cacheFile : File | InsecureWebResourceResponse.java:89:55:89:84 | new FileInputStream(...) : FileInputStream | -| InsecureWebResourceResponse.java:101:20:101:22 | url : Object | InsecureWebResourceResponse.java:63:77:63:86 | url : Object | -| InsecureWebResourceResponse.java:101:20:101:22 | url : Object | InsecureWebResourceResponse.java:84:77:84:86 | url : Object | -| InsecureWebResourceResponse.java:101:20:101:22 | url : Object | InsecureWebResourceResponse.java:110:77:110:86 | url : Object | -| InsecureWebResourceResponse.java:101:20:101:22 | url : Object | InsecureWebResourceResponse.java:192:77:192:102 | request : Object | -| InsecureWebResourceResponse.java:101:20:101:22 | url : Object | InsecureWebResourceResponse.java:232:69:232:78 | url : Object | -| InsecureWebResourceResponse.java:106:34:106:43 | url : Object | InsecureWebResourceResponse.java:127:20:127:22 | url : Object | -| InsecureWebResourceResponse.java:110:77:110:86 | url : Object | InsecureWebResourceResponse.java:112:41:112:43 | url : Object | +| InsecureWebResourceResponse.java:101:20:101:22 | url : String | InsecureWebResourceResponse.java:63:77:63:86 | url : String | +| InsecureWebResourceResponse.java:101:20:101:22 | url : String | InsecureWebResourceResponse.java:84:77:84:86 | url : String | +| InsecureWebResourceResponse.java:101:20:101:22 | url : String | InsecureWebResourceResponse.java:110:77:110:86 | url : String | +| InsecureWebResourceResponse.java:101:20:101:22 | url : String | InsecureWebResourceResponse.java:192:77:192:102 | request : WebResourceRequest | +| InsecureWebResourceResponse.java:101:20:101:22 | url : String | InsecureWebResourceResponse.java:232:69:232:78 | url : String | +| InsecureWebResourceResponse.java:106:34:106:43 | url : String | InsecureWebResourceResponse.java:127:20:127:22 | url : String | +| InsecureWebResourceResponse.java:110:77:110:86 | url : String | InsecureWebResourceResponse.java:112:41:112:43 | url : String | | InsecureWebResourceResponse.java:112:31:112:44 | parse(...) : Uri | InsecureWebResourceResponse.java:113:35:113:37 | uri : Uri | -| InsecureWebResourceResponse.java:112:41:112:43 | url : Object | InsecureWebResourceResponse.java:112:31:112:44 | parse(...) : Uri | +| InsecureWebResourceResponse.java:112:41:112:43 | url : String | InsecureWebResourceResponse.java:112:31:112:44 | parse(...) : Uri | | InsecureWebResourceResponse.java:113:35:113:37 | uri : Uri | InsecureWebResourceResponse.java:113:35:113:47 | getPath(...) : String | | InsecureWebResourceResponse.java:113:35:113:47 | getPath(...) : String | InsecureWebResourceResponse.java:113:35:113:60 | substring(...) : String | | InsecureWebResourceResponse.java:113:35:113:60 | substring(...) : String | InsecureWebResourceResponse.java:115:75:115:78 | path : String | | InsecureWebResourceResponse.java:115:55:115:108 | new FileInputStream(...) : FileInputStream | InsecureWebResourceResponse.java:117:75:117:85 | inputStream | | InsecureWebResourceResponse.java:115:75:115:78 | path : String | InsecureWebResourceResponse.java:115:75:115:107 | substring(...) : String | | InsecureWebResourceResponse.java:115:75:115:107 | substring(...) : String | InsecureWebResourceResponse.java:115:55:115:108 | new FileInputStream(...) : FileInputStream | -| InsecureWebResourceResponse.java:127:20:127:22 | url : Object | InsecureWebResourceResponse.java:63:77:63:86 | url : Object | -| InsecureWebResourceResponse.java:127:20:127:22 | url : Object | InsecureWebResourceResponse.java:84:77:84:86 | url : Object | -| InsecureWebResourceResponse.java:127:20:127:22 | url : Object | InsecureWebResourceResponse.java:110:77:110:86 | url : Object | -| InsecureWebResourceResponse.java:127:20:127:22 | url : Object | InsecureWebResourceResponse.java:192:77:192:102 | request : Object | -| InsecureWebResourceResponse.java:127:20:127:22 | url : Object | InsecureWebResourceResponse.java:232:69:232:78 | url : Object | -| InsecureWebResourceResponse.java:131:36:131:45 | url : Object | InsecureWebResourceResponse.java:152:20:152:22 | url : Object | -| InsecureWebResourceResponse.java:152:20:152:22 | url : Object | InsecureWebResourceResponse.java:63:77:63:86 | url : Object | -| InsecureWebResourceResponse.java:152:20:152:22 | url : Object | InsecureWebResourceResponse.java:84:77:84:86 | url : Object | -| InsecureWebResourceResponse.java:152:20:152:22 | url : Object | InsecureWebResourceResponse.java:110:77:110:86 | url : Object | -| InsecureWebResourceResponse.java:152:20:152:22 | url : Object | InsecureWebResourceResponse.java:192:77:192:102 | request : Object | -| InsecureWebResourceResponse.java:152:20:152:22 | url : Object | InsecureWebResourceResponse.java:232:69:232:78 | url : Object | -| InsecureWebResourceResponse.java:156:35:156:44 | url : Object | InsecureWebResourceResponse.java:177:20:177:22 | url : Object | -| InsecureWebResourceResponse.java:177:20:177:22 | url : Object | InsecureWebResourceResponse.java:63:77:63:86 | url : Object | -| InsecureWebResourceResponse.java:177:20:177:22 | url : Object | InsecureWebResourceResponse.java:84:77:84:86 | url : Object | -| InsecureWebResourceResponse.java:177:20:177:22 | url : Object | InsecureWebResourceResponse.java:110:77:110:86 | url : Object | -| InsecureWebResourceResponse.java:177:20:177:22 | url : Object | InsecureWebResourceResponse.java:192:77:192:102 | request : Object | -| InsecureWebResourceResponse.java:177:20:177:22 | url : Object | InsecureWebResourceResponse.java:232:69:232:78 | url : Object | -| InsecureWebResourceResponse.java:181:34:181:43 | url : Object | InsecureWebResourceResponse.java:184:20:184:22 | url : Object | -| InsecureWebResourceResponse.java:184:20:184:22 | url : Object | InsecureWebResourceResponse.java:63:77:63:86 | url : Object | -| InsecureWebResourceResponse.java:184:20:184:22 | url : Object | InsecureWebResourceResponse.java:84:77:84:86 | url : Object | -| InsecureWebResourceResponse.java:184:20:184:22 | url : Object | InsecureWebResourceResponse.java:110:77:110:86 | url : Object | -| InsecureWebResourceResponse.java:184:20:184:22 | url : Object | InsecureWebResourceResponse.java:192:77:192:102 | request : Object | -| InsecureWebResourceResponse.java:184:20:184:22 | url : Object | InsecureWebResourceResponse.java:232:69:232:78 | url : Object | -| InsecureWebResourceResponse.java:188:34:188:43 | url : Object | InsecureWebResourceResponse.java:209:20:209:22 | url : Object | -| InsecureWebResourceResponse.java:192:77:192:102 | request : Object | InsecureWebResourceResponse.java:194:31:194:37 | request : Object | -| InsecureWebResourceResponse.java:194:31:194:37 | request : Object | InsecureWebResourceResponse.java:194:31:194:46 | getUrl(...) : Uri | +| InsecureWebResourceResponse.java:127:20:127:22 | url : String | InsecureWebResourceResponse.java:63:77:63:86 | url : String | +| InsecureWebResourceResponse.java:127:20:127:22 | url : String | InsecureWebResourceResponse.java:84:77:84:86 | url : String | +| InsecureWebResourceResponse.java:127:20:127:22 | url : String | InsecureWebResourceResponse.java:110:77:110:86 | url : String | +| InsecureWebResourceResponse.java:127:20:127:22 | url : String | InsecureWebResourceResponse.java:192:77:192:102 | request : WebResourceRequest | +| InsecureWebResourceResponse.java:127:20:127:22 | url : String | InsecureWebResourceResponse.java:232:69:232:78 | url : String | +| InsecureWebResourceResponse.java:131:36:131:45 | url : String | InsecureWebResourceResponse.java:152:20:152:22 | url : String | +| InsecureWebResourceResponse.java:152:20:152:22 | url : String | InsecureWebResourceResponse.java:63:77:63:86 | url : String | +| InsecureWebResourceResponse.java:152:20:152:22 | url : String | InsecureWebResourceResponse.java:84:77:84:86 | url : String | +| InsecureWebResourceResponse.java:152:20:152:22 | url : String | InsecureWebResourceResponse.java:110:77:110:86 | url : String | +| InsecureWebResourceResponse.java:152:20:152:22 | url : String | InsecureWebResourceResponse.java:192:77:192:102 | request : WebResourceRequest | +| InsecureWebResourceResponse.java:152:20:152:22 | url : String | InsecureWebResourceResponse.java:232:69:232:78 | url : String | +| InsecureWebResourceResponse.java:156:35:156:44 | url : String | InsecureWebResourceResponse.java:177:20:177:22 | url : String | +| InsecureWebResourceResponse.java:177:20:177:22 | url : String | InsecureWebResourceResponse.java:63:77:63:86 | url : String | +| InsecureWebResourceResponse.java:177:20:177:22 | url : String | InsecureWebResourceResponse.java:84:77:84:86 | url : String | +| InsecureWebResourceResponse.java:177:20:177:22 | url : String | InsecureWebResourceResponse.java:110:77:110:86 | url : String | +| InsecureWebResourceResponse.java:177:20:177:22 | url : String | InsecureWebResourceResponse.java:192:77:192:102 | request : WebResourceRequest | +| InsecureWebResourceResponse.java:177:20:177:22 | url : String | InsecureWebResourceResponse.java:232:69:232:78 | url : String | +| InsecureWebResourceResponse.java:181:34:181:43 | url : String | InsecureWebResourceResponse.java:184:20:184:22 | url : String | +| InsecureWebResourceResponse.java:184:20:184:22 | url : String | InsecureWebResourceResponse.java:63:77:63:86 | url : String | +| InsecureWebResourceResponse.java:184:20:184:22 | url : String | InsecureWebResourceResponse.java:84:77:84:86 | url : String | +| InsecureWebResourceResponse.java:184:20:184:22 | url : String | InsecureWebResourceResponse.java:110:77:110:86 | url : String | +| InsecureWebResourceResponse.java:184:20:184:22 | url : String | InsecureWebResourceResponse.java:192:77:192:102 | request : WebResourceRequest | +| InsecureWebResourceResponse.java:184:20:184:22 | url : String | InsecureWebResourceResponse.java:232:69:232:78 | url : String | +| InsecureWebResourceResponse.java:188:34:188:43 | url : String | InsecureWebResourceResponse.java:209:20:209:22 | url : String | +| InsecureWebResourceResponse.java:192:77:192:102 | request : WebResourceRequest | InsecureWebResourceResponse.java:194:31:194:37 | request : WebResourceRequest | +| InsecureWebResourceResponse.java:194:31:194:37 | request : WebResourceRequest | InsecureWebResourceResponse.java:194:31:194:46 | getUrl(...) : Uri | | InsecureWebResourceResponse.java:194:31:194:46 | getUrl(...) : Uri | InsecureWebResourceResponse.java:196:66:196:68 | uri : Uri | | InsecureWebResourceResponse.java:196:42:196:90 | new File(...) : File | InsecureWebResourceResponse.java:197:75:197:83 | cacheFile : File | | InsecureWebResourceResponse.java:196:66:196:68 | uri : Uri | InsecureWebResourceResponse.java:196:66:196:89 | getLastPathSegment(...) : String | | InsecureWebResourceResponse.java:196:66:196:89 | getLastPathSegment(...) : String | InsecureWebResourceResponse.java:196:42:196:90 | new File(...) : File | | InsecureWebResourceResponse.java:197:55:197:84 | new FileInputStream(...) : FileInputStream | InsecureWebResourceResponse.java:199:75:199:85 | inputStream | | InsecureWebResourceResponse.java:197:75:197:83 | cacheFile : File | InsecureWebResourceResponse.java:197:55:197:84 | new FileInputStream(...) : FileInputStream | -| InsecureWebResourceResponse.java:209:20:209:22 | url : Object | InsecureWebResourceResponse.java:63:77:63:86 | url : Object | -| InsecureWebResourceResponse.java:209:20:209:22 | url : Object | InsecureWebResourceResponse.java:84:77:84:86 | url : Object | -| InsecureWebResourceResponse.java:209:20:209:22 | url : Object | InsecureWebResourceResponse.java:110:77:110:86 | url : Object | -| InsecureWebResourceResponse.java:209:20:209:22 | url : Object | InsecureWebResourceResponse.java:192:77:192:102 | request : Object | -| InsecureWebResourceResponse.java:209:20:209:22 | url : Object | InsecureWebResourceResponse.java:232:69:232:78 | url : Object | -| InsecureWebResourceResponse.java:217:35:217:44 | url : Object | InsecureWebResourceResponse.java:226:20:226:22 | url : Object | -| InsecureWebResourceResponse.java:226:20:226:22 | url : Object | InsecureWebResourceResponse.java:63:77:63:86 | url : Object | -| InsecureWebResourceResponse.java:226:20:226:22 | url : Object | InsecureWebResourceResponse.java:84:77:84:86 | url : Object | -| InsecureWebResourceResponse.java:226:20:226:22 | url : Object | InsecureWebResourceResponse.java:110:77:110:86 | url : Object | -| InsecureWebResourceResponse.java:226:20:226:22 | url : Object | InsecureWebResourceResponse.java:192:77:192:102 | request : Object | -| InsecureWebResourceResponse.java:226:20:226:22 | url : Object | InsecureWebResourceResponse.java:232:69:232:78 | url : Object | -| InsecureWebResourceResponse.java:232:69:232:78 | url : Object | InsecureWebResourceResponse.java:234:33:234:35 | url : Object | +| InsecureWebResourceResponse.java:209:20:209:22 | url : String | InsecureWebResourceResponse.java:63:77:63:86 | url : String | +| InsecureWebResourceResponse.java:209:20:209:22 | url : String | InsecureWebResourceResponse.java:84:77:84:86 | url : String | +| InsecureWebResourceResponse.java:209:20:209:22 | url : String | InsecureWebResourceResponse.java:110:77:110:86 | url : String | +| InsecureWebResourceResponse.java:209:20:209:22 | url : String | InsecureWebResourceResponse.java:192:77:192:102 | request : WebResourceRequest | +| InsecureWebResourceResponse.java:209:20:209:22 | url : String | InsecureWebResourceResponse.java:232:69:232:78 | url : String | +| InsecureWebResourceResponse.java:217:35:217:44 | url : String | InsecureWebResourceResponse.java:226:20:226:22 | url : String | +| InsecureWebResourceResponse.java:226:20:226:22 | url : String | InsecureWebResourceResponse.java:63:77:63:86 | url : String | +| InsecureWebResourceResponse.java:226:20:226:22 | url : String | InsecureWebResourceResponse.java:84:77:84:86 | url : String | +| InsecureWebResourceResponse.java:226:20:226:22 | url : String | InsecureWebResourceResponse.java:110:77:110:86 | url : String | +| InsecureWebResourceResponse.java:226:20:226:22 | url : String | InsecureWebResourceResponse.java:192:77:192:102 | request : WebResourceRequest | +| InsecureWebResourceResponse.java:226:20:226:22 | url : String | InsecureWebResourceResponse.java:232:69:232:78 | url : String | +| InsecureWebResourceResponse.java:232:69:232:78 | url : String | InsecureWebResourceResponse.java:234:33:234:35 | url : String | | InsecureWebResourceResponse.java:234:23:234:36 | parse(...) : Uri | InsecureWebResourceResponse.java:235:63:235:65 | uri : Uri | -| InsecureWebResourceResponse.java:234:33:234:35 | url : Object | InsecureWebResourceResponse.java:234:23:234:36 | parse(...) : Uri | +| InsecureWebResourceResponse.java:234:33:234:35 | url : String | InsecureWebResourceResponse.java:234:23:234:36 | parse(...) : Uri | | InsecureWebResourceResponse.java:235:43:235:76 | new FileInputStream(...) : FileInputStream | InsecureWebResourceResponse.java:237:63:237:73 | inputStream | | InsecureWebResourceResponse.java:235:63:235:65 | uri : Uri | InsecureWebResourceResponse.java:235:63:235:75 | getPath(...) : String | | InsecureWebResourceResponse.java:235:63:235:75 | getPath(...) : String | InsecureWebResourceResponse.java:235:43:235:76 | new FileInputStream(...) : FileInputStream | -| InsecureWebViewActivity.java:27:27:27:37 | getIntent(...) : Intent | InsecureWebViewActivity.java:27:27:27:64 | getStringExtra(...) : Object | -| InsecureWebViewActivity.java:27:27:27:64 | getStringExtra(...) : Object | InsecureWebViewActivity.java:28:20:28:27 | inputUrl : Object | -| InsecureWebViewActivity.java:28:20:28:27 | inputUrl : Object | InsecureWebViewActivity.java:42:28:42:37 | url : Object | -| InsecureWebViewActivity.java:42:28:42:37 | url : Object | InsecureWebViewActivity.java:43:25:43:27 | url : Object | -| InsecureWebViewActivity.java:43:25:43:27 | url : Object | InsecureWebViewActivity.java:53:77:53:86 | url : Object | -| InsecureWebViewActivity.java:53:77:53:86 | url : Object | InsecureWebViewActivity.java:55:41:55:43 | url : Object | +| InsecureWebViewActivity.java:27:27:27:37 | getIntent(...) : Intent | InsecureWebViewActivity.java:27:27:27:64 | getStringExtra(...) : String | +| InsecureWebViewActivity.java:27:27:27:64 | getStringExtra(...) : String | InsecureWebViewActivity.java:28:20:28:27 | inputUrl : String | +| InsecureWebViewActivity.java:28:20:28:27 | inputUrl : String | InsecureWebViewActivity.java:42:28:42:37 | url : String | +| InsecureWebViewActivity.java:42:28:42:37 | url : String | InsecureWebViewActivity.java:43:25:43:27 | url : String | +| InsecureWebViewActivity.java:43:25:43:27 | url : String | InsecureWebViewActivity.java:53:77:53:86 | url : String | +| InsecureWebViewActivity.java:53:77:53:86 | url : String | InsecureWebViewActivity.java:55:41:55:43 | url : String | | InsecureWebViewActivity.java:55:31:55:44 | parse(...) : Uri | InsecureWebViewActivity.java:56:71:56:73 | uri : Uri | -| InsecureWebViewActivity.java:55:41:55:43 | url : Object | InsecureWebViewActivity.java:55:31:55:44 | parse(...) : Uri | +| InsecureWebViewActivity.java:55:41:55:43 | url : String | InsecureWebViewActivity.java:55:31:55:44 | parse(...) : Uri | | InsecureWebViewActivity.java:56:51:56:84 | new FileInputStream(...) : FileInputStream | InsecureWebViewActivity.java:58:71:58:81 | inputStream | | InsecureWebViewActivity.java:56:71:56:73 | uri : Uri | InsecureWebViewActivity.java:56:71:56:83 | getPath(...) : String | | InsecureWebViewActivity.java:56:71:56:83 | getPath(...) : String | InsecureWebViewActivity.java:56:51:56:84 | new FileInputStream(...) : FileInputStream | nodes | InsecureWebResourceResponse.java:28:27:28:37 | getIntent(...) : Intent | semmle.label | getIntent(...) : Intent | -| InsecureWebResourceResponse.java:28:27:28:64 | getStringExtra(...) : Object | semmle.label | getStringExtra(...) : Object | -| InsecureWebResourceResponse.java:30:25:30:32 | inputUrl : Object | semmle.label | inputUrl : Object | -| InsecureWebResourceResponse.java:32:25:32:32 | inputUrl : Object | semmle.label | inputUrl : Object | -| InsecureWebResourceResponse.java:34:25:34:32 | inputUrl : Object | semmle.label | inputUrl : Object | -| InsecureWebResourceResponse.java:36:26:36:33 | inputUrl : Object | semmle.label | inputUrl : Object | -| InsecureWebResourceResponse.java:38:26:38:33 | inputUrl : Object | semmle.label | inputUrl : Object | -| InsecureWebResourceResponse.java:40:25:40:32 | inputUrl : Object | semmle.label | inputUrl : Object | -| InsecureWebResourceResponse.java:42:25:42:32 | inputUrl : Object | semmle.label | inputUrl : Object | -| InsecureWebResourceResponse.java:44:26:44:33 | inputUrl : Object | semmle.label | inputUrl : Object | -| InsecureWebResourceResponse.java:59:34:59:43 | url : Object | semmle.label | url : Object | -| InsecureWebResourceResponse.java:63:77:63:86 | url : Object | semmle.label | url : Object | +| InsecureWebResourceResponse.java:28:27:28:64 | getStringExtra(...) : String | semmle.label | getStringExtra(...) : String | +| InsecureWebResourceResponse.java:30:25:30:32 | inputUrl : String | semmle.label | inputUrl : String | +| InsecureWebResourceResponse.java:32:25:32:32 | inputUrl : String | semmle.label | inputUrl : String | +| InsecureWebResourceResponse.java:34:25:34:32 | inputUrl : String | semmle.label | inputUrl : String | +| InsecureWebResourceResponse.java:36:26:36:33 | inputUrl : String | semmle.label | inputUrl : String | +| InsecureWebResourceResponse.java:38:26:38:33 | inputUrl : String | semmle.label | inputUrl : String | +| InsecureWebResourceResponse.java:40:25:40:32 | inputUrl : String | semmle.label | inputUrl : String | +| InsecureWebResourceResponse.java:42:25:42:32 | inputUrl : String | semmle.label | inputUrl : String | +| InsecureWebResourceResponse.java:44:26:44:33 | inputUrl : String | semmle.label | inputUrl : String | +| InsecureWebResourceResponse.java:59:34:59:43 | url : String | semmle.label | url : String | +| InsecureWebResourceResponse.java:63:77:63:86 | url : String | semmle.label | url : String | | InsecureWebResourceResponse.java:65:31:65:44 | parse(...) : Uri | semmle.label | parse(...) : Uri | -| InsecureWebResourceResponse.java:65:41:65:43 | url : Object | semmle.label | url : Object | +| InsecureWebResourceResponse.java:65:41:65:43 | url : String | semmle.label | url : String | | InsecureWebResourceResponse.java:66:51:66:84 | new FileInputStream(...) : FileInputStream | semmle.label | new FileInputStream(...) : FileInputStream | | InsecureWebResourceResponse.java:66:71:66:73 | uri : Uri | semmle.label | uri : Uri | | InsecureWebResourceResponse.java:66:71:66:83 | getPath(...) : String | semmle.label | getPath(...) : String | | InsecureWebResourceResponse.java:68:71:68:81 | inputStream | semmle.label | inputStream | -| InsecureWebResourceResponse.java:75:20:75:22 | url : Object | semmle.label | url : Object | -| InsecureWebResourceResponse.java:80:34:80:43 | url : Object | semmle.label | url : Object | -| InsecureWebResourceResponse.java:84:77:84:86 | url : Object | semmle.label | url : Object | +| InsecureWebResourceResponse.java:75:20:75:22 | url : String | semmle.label | url : String | +| InsecureWebResourceResponse.java:80:34:80:43 | url : String | semmle.label | url : String | +| InsecureWebResourceResponse.java:84:77:84:86 | url : String | semmle.label | url : String | | InsecureWebResourceResponse.java:86:31:86:44 | parse(...) : Uri | semmle.label | parse(...) : Uri | -| InsecureWebResourceResponse.java:86:41:86:43 | url : Object | semmle.label | url : Object | +| InsecureWebResourceResponse.java:86:41:86:43 | url : String | semmle.label | url : String | | InsecureWebResourceResponse.java:88:42:88:90 | new File(...) : File | semmle.label | new File(...) : File | | InsecureWebResourceResponse.java:88:66:88:68 | uri : Uri | semmle.label | uri : Uri | | InsecureWebResourceResponse.java:88:66:88:89 | getLastPathSegment(...) : String | semmle.label | getLastPathSegment(...) : String | | InsecureWebResourceResponse.java:89:55:89:84 | new FileInputStream(...) : FileInputStream | semmle.label | new FileInputStream(...) : FileInputStream | | InsecureWebResourceResponse.java:89:75:89:83 | cacheFile : File | semmle.label | cacheFile : File | | InsecureWebResourceResponse.java:91:75:91:85 | inputStream | semmle.label | inputStream | -| InsecureWebResourceResponse.java:101:20:101:22 | url : Object | semmle.label | url : Object | -| InsecureWebResourceResponse.java:106:34:106:43 | url : Object | semmle.label | url : Object | -| InsecureWebResourceResponse.java:110:77:110:86 | url : Object | semmle.label | url : Object | +| InsecureWebResourceResponse.java:101:20:101:22 | url : String | semmle.label | url : String | +| InsecureWebResourceResponse.java:106:34:106:43 | url : String | semmle.label | url : String | +| InsecureWebResourceResponse.java:110:77:110:86 | url : String | semmle.label | url : String | | InsecureWebResourceResponse.java:112:31:112:44 | parse(...) : Uri | semmle.label | parse(...) : Uri | -| InsecureWebResourceResponse.java:112:41:112:43 | url : Object | semmle.label | url : Object | +| InsecureWebResourceResponse.java:112:41:112:43 | url : String | semmle.label | url : String | | InsecureWebResourceResponse.java:113:35:113:37 | uri : Uri | semmle.label | uri : Uri | | InsecureWebResourceResponse.java:113:35:113:47 | getPath(...) : String | semmle.label | getPath(...) : String | | InsecureWebResourceResponse.java:113:35:113:60 | substring(...) : String | semmle.label | substring(...) : String | @@ -154,16 +154,16 @@ nodes | InsecureWebResourceResponse.java:115:75:115:78 | path : String | semmle.label | path : String | | InsecureWebResourceResponse.java:115:75:115:107 | substring(...) : String | semmle.label | substring(...) : String | | InsecureWebResourceResponse.java:117:75:117:85 | inputStream | semmle.label | inputStream | -| InsecureWebResourceResponse.java:127:20:127:22 | url : Object | semmle.label | url : Object | -| InsecureWebResourceResponse.java:131:36:131:45 | url : Object | semmle.label | url : Object | -| InsecureWebResourceResponse.java:152:20:152:22 | url : Object | semmle.label | url : Object | -| InsecureWebResourceResponse.java:156:35:156:44 | url : Object | semmle.label | url : Object | -| InsecureWebResourceResponse.java:177:20:177:22 | url : Object | semmle.label | url : Object | -| InsecureWebResourceResponse.java:181:34:181:43 | url : Object | semmle.label | url : Object | -| InsecureWebResourceResponse.java:184:20:184:22 | url : Object | semmle.label | url : Object | -| InsecureWebResourceResponse.java:188:34:188:43 | url : Object | semmle.label | url : Object | -| InsecureWebResourceResponse.java:192:77:192:102 | request : Object | semmle.label | request : Object | -| InsecureWebResourceResponse.java:194:31:194:37 | request : Object | semmle.label | request : Object | +| InsecureWebResourceResponse.java:127:20:127:22 | url : String | semmle.label | url : String | +| InsecureWebResourceResponse.java:131:36:131:45 | url : String | semmle.label | url : String | +| InsecureWebResourceResponse.java:152:20:152:22 | url : String | semmle.label | url : String | +| InsecureWebResourceResponse.java:156:35:156:44 | url : String | semmle.label | url : String | +| InsecureWebResourceResponse.java:177:20:177:22 | url : String | semmle.label | url : String | +| InsecureWebResourceResponse.java:181:34:181:43 | url : String | semmle.label | url : String | +| InsecureWebResourceResponse.java:184:20:184:22 | url : String | semmle.label | url : String | +| InsecureWebResourceResponse.java:188:34:188:43 | url : String | semmle.label | url : String | +| InsecureWebResourceResponse.java:192:77:192:102 | request : WebResourceRequest | semmle.label | request : WebResourceRequest | +| InsecureWebResourceResponse.java:194:31:194:37 | request : WebResourceRequest | semmle.label | request : WebResourceRequest | | InsecureWebResourceResponse.java:194:31:194:46 | getUrl(...) : Uri | semmle.label | getUrl(...) : Uri | | InsecureWebResourceResponse.java:196:42:196:90 | new File(...) : File | semmle.label | new File(...) : File | | InsecureWebResourceResponse.java:196:66:196:68 | uri : Uri | semmle.label | uri : Uri | @@ -171,24 +171,24 @@ nodes | InsecureWebResourceResponse.java:197:55:197:84 | new FileInputStream(...) : FileInputStream | semmle.label | new FileInputStream(...) : FileInputStream | | InsecureWebResourceResponse.java:197:75:197:83 | cacheFile : File | semmle.label | cacheFile : File | | InsecureWebResourceResponse.java:199:75:199:85 | inputStream | semmle.label | inputStream | -| InsecureWebResourceResponse.java:209:20:209:22 | url : Object | semmle.label | url : Object | -| InsecureWebResourceResponse.java:217:35:217:44 | url : Object | semmle.label | url : Object | -| InsecureWebResourceResponse.java:226:20:226:22 | url : Object | semmle.label | url : Object | -| InsecureWebResourceResponse.java:232:69:232:78 | url : Object | semmle.label | url : Object | +| InsecureWebResourceResponse.java:209:20:209:22 | url : String | semmle.label | url : String | +| InsecureWebResourceResponse.java:217:35:217:44 | url : String | semmle.label | url : String | +| InsecureWebResourceResponse.java:226:20:226:22 | url : String | semmle.label | url : String | +| InsecureWebResourceResponse.java:232:69:232:78 | url : String | semmle.label | url : String | | InsecureWebResourceResponse.java:234:23:234:36 | parse(...) : Uri | semmle.label | parse(...) : Uri | -| InsecureWebResourceResponse.java:234:33:234:35 | url : Object | semmle.label | url : Object | +| InsecureWebResourceResponse.java:234:33:234:35 | url : String | semmle.label | url : String | | InsecureWebResourceResponse.java:235:43:235:76 | new FileInputStream(...) : FileInputStream | semmle.label | new FileInputStream(...) : FileInputStream | | InsecureWebResourceResponse.java:235:63:235:65 | uri : Uri | semmle.label | uri : Uri | | InsecureWebResourceResponse.java:235:63:235:75 | getPath(...) : String | semmle.label | getPath(...) : String | | InsecureWebResourceResponse.java:237:63:237:73 | inputStream | semmle.label | inputStream | | InsecureWebViewActivity.java:27:27:27:37 | getIntent(...) : Intent | semmle.label | getIntent(...) : Intent | -| InsecureWebViewActivity.java:27:27:27:64 | getStringExtra(...) : Object | semmle.label | getStringExtra(...) : Object | -| InsecureWebViewActivity.java:28:20:28:27 | inputUrl : Object | semmle.label | inputUrl : Object | -| InsecureWebViewActivity.java:42:28:42:37 | url : Object | semmle.label | url : Object | -| InsecureWebViewActivity.java:43:25:43:27 | url : Object | semmle.label | url : Object | -| InsecureWebViewActivity.java:53:77:53:86 | url : Object | semmle.label | url : Object | +| InsecureWebViewActivity.java:27:27:27:64 | getStringExtra(...) : String | semmle.label | getStringExtra(...) : String | +| InsecureWebViewActivity.java:28:20:28:27 | inputUrl : String | semmle.label | inputUrl : String | +| InsecureWebViewActivity.java:42:28:42:37 | url : String | semmle.label | url : String | +| InsecureWebViewActivity.java:43:25:43:27 | url : String | semmle.label | url : String | +| InsecureWebViewActivity.java:53:77:53:86 | url : String | semmle.label | url : String | | InsecureWebViewActivity.java:55:31:55:44 | parse(...) : Uri | semmle.label | parse(...) : Uri | -| InsecureWebViewActivity.java:55:41:55:43 | url : Object | semmle.label | url : Object | +| InsecureWebViewActivity.java:55:41:55:43 | url : String | semmle.label | url : String | | InsecureWebViewActivity.java:56:51:56:84 | new FileInputStream(...) : FileInputStream | semmle.label | new FileInputStream(...) : FileInputStream | | InsecureWebViewActivity.java:56:71:56:73 | uri : Uri | semmle.label | uri : Uri | | InsecureWebViewActivity.java:56:71:56:83 | getPath(...) : String | semmle.label | getPath(...) : String | diff --git a/java/ql/test/experimental/query-tests/security/CWE-200/SensitiveAndroidFileLeak.expected b/java/ql/test/experimental/query-tests/security/CWE-200/SensitiveAndroidFileLeak.expected index 43a64e4226a..9c5b6ce8b69 100644 --- a/java/ql/test/experimental/query-tests/security/CWE-200/SensitiveAndroidFileLeak.expected +++ b/java/ql/test/experimental/query-tests/security/CWE-200/SensitiveAndroidFileLeak.expected @@ -1,47 +1,47 @@ edges | FileService.java:20:31:20:43 | intent : Intent | FileService.java:21:28:21:33 | intent : Intent | -| FileService.java:21:28:21:33 | intent : Intent | FileService.java:21:28:21:64 | getStringExtra(...) : Object | -| FileService.java:21:28:21:64 | getStringExtra(...) : Object | FileService.java:25:42:25:50 | localPath : Object | +| FileService.java:21:28:21:33 | intent : Intent | FileService.java:21:28:21:64 | getStringExtra(...) : String | +| FileService.java:21:28:21:64 | getStringExtra(...) : String | FileService.java:25:42:25:50 | localPath : String | | FileService.java:25:13:25:51 | makeParamsToExecute(...) : Object[] | FileService.java:40:41:40:55 | params : Object[] | -| FileService.java:25:13:25:51 | makeParamsToExecute(...) : Object[] [[]] : Object | FileService.java:25:13:25:51 | makeParamsToExecute(...) : Object[] | -| FileService.java:25:42:25:50 | localPath : Object | FileService.java:25:13:25:51 | makeParamsToExecute(...) : Object[] [[]] : Object | -| FileService.java:25:42:25:50 | localPath : Object | FileService.java:32:13:32:28 | sourceUri : Object | -| FileService.java:32:13:32:28 | sourceUri : Object | FileService.java:35:17:35:25 | sourceUri : Object | -| FileService.java:34:20:36:13 | {...} : Object[] [[]] : Object | FileService.java:34:20:36:13 | new Object[] : Object[] [[]] : Object | -| FileService.java:35:17:35:25 | sourceUri : Object | FileService.java:34:20:36:13 | {...} : Object[] [[]] : Object | -| FileService.java:40:41:40:55 | params : Object[] | FileService.java:44:33:44:52 | (...)... : Object | -| FileService.java:44:33:44:52 | (...)... : Object | FileService.java:45:53:45:59 | ...[...] | +| FileService.java:25:13:25:51 | makeParamsToExecute(...) : Object[] [[]] : String | FileService.java:25:13:25:51 | makeParamsToExecute(...) : Object[] | +| FileService.java:25:42:25:50 | localPath : String | FileService.java:25:13:25:51 | makeParamsToExecute(...) : Object[] [[]] : String | +| FileService.java:25:42:25:50 | localPath : String | FileService.java:32:13:32:28 | sourceUri : String | +| FileService.java:32:13:32:28 | sourceUri : String | FileService.java:35:17:35:25 | sourceUri : String | +| FileService.java:34:20:36:13 | {...} : Object[] [[]] : String | FileService.java:34:20:36:13 | new Object[] : Object[] [[]] : String | +| FileService.java:35:17:35:25 | sourceUri : String | FileService.java:34:20:36:13 | {...} : Object[] [[]] : String | +| FileService.java:40:41:40:55 | params : Object[] | FileService.java:44:33:44:52 | (...)... : String[] | +| FileService.java:44:33:44:52 | (...)... : String[] | FileService.java:45:53:45:59 | ...[...] | | LeakFileActivity2.java:15:13:15:18 | intent : Intent | LeakFileActivity2.java:16:26:16:31 | intent : Intent | | LeakFileActivity2.java:16:26:16:31 | intent : Intent | FileService.java:20:31:20:43 | intent : Intent | | LeakFileActivity.java:14:35:14:38 | data : Intent | LeakFileActivity.java:18:40:18:59 | contentIntent : Intent | | LeakFileActivity.java:18:40:18:59 | contentIntent : Intent | LeakFileActivity.java:19:31:19:43 | contentIntent : Intent | -| LeakFileActivity.java:19:31:19:43 | contentIntent : Intent | LeakFileActivity.java:19:31:19:53 | getData(...) : Object | -| LeakFileActivity.java:19:31:19:53 | getData(...) : Object | LeakFileActivity.java:21:58:21:72 | streamsToUpload : Object | -| LeakFileActivity.java:21:58:21:72 | streamsToUpload : Object | LeakFileActivity.java:21:58:21:82 | getPath(...) | +| LeakFileActivity.java:19:31:19:43 | contentIntent : Intent | LeakFileActivity.java:19:31:19:53 | getData(...) : Uri | +| LeakFileActivity.java:19:31:19:53 | getData(...) : Uri | LeakFileActivity.java:21:58:21:72 | streamsToUpload : Uri | +| LeakFileActivity.java:21:58:21:72 | streamsToUpload : Uri | LeakFileActivity.java:21:58:21:82 | getPath(...) | nodes | FileService.java:20:31:20:43 | intent : Intent | semmle.label | intent : Intent | | FileService.java:21:28:21:33 | intent : Intent | semmle.label | intent : Intent | -| FileService.java:21:28:21:64 | getStringExtra(...) : Object | semmle.label | getStringExtra(...) : Object | +| FileService.java:21:28:21:64 | getStringExtra(...) : String | semmle.label | getStringExtra(...) : String | | FileService.java:25:13:25:51 | makeParamsToExecute(...) : Object[] | semmle.label | makeParamsToExecute(...) : Object[] | -| FileService.java:25:13:25:51 | makeParamsToExecute(...) : Object[] [[]] : Object | semmle.label | makeParamsToExecute(...) : Object[] [[]] : Object | -| FileService.java:25:42:25:50 | localPath : Object | semmle.label | localPath : Object | -| FileService.java:32:13:32:28 | sourceUri : Object | semmle.label | sourceUri : Object | -| FileService.java:34:20:36:13 | new Object[] : Object[] [[]] : Object | semmle.label | new Object[] : Object[] [[]] : Object | -| FileService.java:34:20:36:13 | {...} : Object[] [[]] : Object | semmle.label | {...} : Object[] [[]] : Object | -| FileService.java:35:17:35:25 | sourceUri : Object | semmle.label | sourceUri : Object | +| FileService.java:25:13:25:51 | makeParamsToExecute(...) : Object[] [[]] : String | semmle.label | makeParamsToExecute(...) : Object[] [[]] : String | +| FileService.java:25:42:25:50 | localPath : String | semmle.label | localPath : String | +| FileService.java:32:13:32:28 | sourceUri : String | semmle.label | sourceUri : String | +| FileService.java:34:20:36:13 | new Object[] : Object[] [[]] : String | semmle.label | new Object[] : Object[] [[]] : String | +| FileService.java:34:20:36:13 | {...} : Object[] [[]] : String | semmle.label | {...} : Object[] [[]] : String | +| FileService.java:35:17:35:25 | sourceUri : String | semmle.label | sourceUri : String | | FileService.java:40:41:40:55 | params : Object[] | semmle.label | params : Object[] | -| FileService.java:44:33:44:52 | (...)... : Object | semmle.label | (...)... : Object | +| FileService.java:44:33:44:52 | (...)... : String[] | semmle.label | (...)... : String[] | | FileService.java:45:53:45:59 | ...[...] | semmle.label | ...[...] | | LeakFileActivity2.java:15:13:15:18 | intent : Intent | semmle.label | intent : Intent | | LeakFileActivity2.java:16:26:16:31 | intent : Intent | semmle.label | intent : Intent | | LeakFileActivity.java:14:35:14:38 | data : Intent | semmle.label | data : Intent | | LeakFileActivity.java:18:40:18:59 | contentIntent : Intent | semmle.label | contentIntent : Intent | | LeakFileActivity.java:19:31:19:43 | contentIntent : Intent | semmle.label | contentIntent : Intent | -| LeakFileActivity.java:19:31:19:53 | getData(...) : Object | semmle.label | getData(...) : Object | -| LeakFileActivity.java:21:58:21:72 | streamsToUpload : Object | semmle.label | streamsToUpload : Object | +| LeakFileActivity.java:19:31:19:53 | getData(...) : Uri | semmle.label | getData(...) : Uri | +| LeakFileActivity.java:21:58:21:72 | streamsToUpload : Uri | semmle.label | streamsToUpload : Uri | | LeakFileActivity.java:21:58:21:82 | getPath(...) | semmle.label | getPath(...) | subpaths -| FileService.java:25:42:25:50 | localPath : Object | FileService.java:32:13:32:28 | sourceUri : Object | FileService.java:34:20:36:13 | new Object[] : Object[] [[]] : Object | FileService.java:25:13:25:51 | makeParamsToExecute(...) : Object[] [[]] : Object | +| FileService.java:25:42:25:50 | localPath : String | FileService.java:32:13:32:28 | sourceUri : String | FileService.java:34:20:36:13 | new Object[] : Object[] [[]] : String | FileService.java:25:13:25:51 | makeParamsToExecute(...) : Object[] [[]] : String | #select | FileService.java:45:53:45:59 | ...[...] | LeakFileActivity2.java:15:13:15:18 | intent : Intent | FileService.java:45:53:45:59 | ...[...] | Leaking arbitrary Android file from $@. | LeakFileActivity2.java:15:13:15:18 | intent | this user input | | FileService.java:45:53:45:59 | ...[...] | LeakFileActivity2.java:16:26:16:31 | intent : Intent | FileService.java:45:53:45:59 | ...[...] | Leaking arbitrary Android file from $@. | LeakFileActivity2.java:16:26:16:31 | intent | this user input | diff --git a/java/ql/test/experimental/query-tests/security/CWE-470/UnsafeReflection.expected b/java/ql/test/experimental/query-tests/security/CWE-470/UnsafeReflection.expected index b6f894c3e5f..606cf994976 100644 --- a/java/ql/test/experimental/query-tests/security/CWE-470/UnsafeReflection.expected +++ b/java/ql/test/experimental/query-tests/security/CWE-470/UnsafeReflection.expected @@ -6,17 +6,17 @@ edges | UnsafeReflection.java:34:33:34:70 | getParameter(...) : String | UnsafeReflection.java:39:58:39:71 | parameterValue | | UnsafeReflection.java:46:24:46:82 | beanIdOrClassName : String | UnsafeReflection.java:53:30:53:46 | beanIdOrClassName : String | | UnsafeReflection.java:46:132:46:168 | body : Map | UnsafeReflection.java:49:37:49:40 | body : Map | -| UnsafeReflection.java:49:23:49:59 | (...)... : Object | UnsafeReflection.java:53:67:53:73 | rawData : Object | +| UnsafeReflection.java:49:23:49:59 | (...)... : List | UnsafeReflection.java:53:67:53:73 | rawData : List | | UnsafeReflection.java:49:37:49:40 | body : Map | UnsafeReflection.java:49:37:49:59 | get(...) : Object | -| UnsafeReflection.java:49:37:49:59 | get(...) : Object | UnsafeReflection.java:49:23:49:59 | (...)... : Object | +| UnsafeReflection.java:49:37:49:59 | get(...) : Object | UnsafeReflection.java:49:23:49:59 | (...)... : List | | UnsafeReflection.java:53:30:53:46 | beanIdOrClassName : String | UnsafeReflection.java:104:34:104:57 | beanIdOrClassName : String | -| UnsafeReflection.java:53:67:53:73 | rawData : Object | UnsafeReflection.java:104:102:104:118 | data : Object | +| UnsafeReflection.java:53:67:53:73 | rawData : List | UnsafeReflection.java:104:102:104:118 | data : List | | UnsafeReflection.java:62:33:62:70 | getParameter(...) : String | UnsafeReflection.java:68:76:68:89 | parameterValue | | UnsafeReflection.java:77:33:77:70 | getParameter(...) : String | UnsafeReflection.java:83:76:83:89 | parameterValue | | UnsafeReflection.java:92:33:92:70 | getParameter(...) : String | UnsafeReflection.java:98:76:98:89 | parameterValue | | UnsafeReflection.java:104:34:104:57 | beanIdOrClassName : String | UnsafeReflection.java:119:21:119:26 | method | | UnsafeReflection.java:104:34:104:57 | beanIdOrClassName : String | UnsafeReflection.java:119:35:119:38 | bean | -| UnsafeReflection.java:104:102:104:118 | data : Object | UnsafeReflection.java:119:41:119:44 | data | +| UnsafeReflection.java:104:102:104:118 | data : List | UnsafeReflection.java:119:41:119:44 | data | nodes | UnsafeReflection.java:21:28:21:60 | getParameter(...) : String | semmle.label | getParameter(...) : String | | UnsafeReflection.java:22:33:22:70 | getParameter(...) : String | semmle.label | getParameter(...) : String | @@ -29,11 +29,11 @@ nodes | UnsafeReflection.java:39:58:39:71 | parameterValue | semmle.label | parameterValue | | UnsafeReflection.java:46:24:46:82 | beanIdOrClassName : String | semmle.label | beanIdOrClassName : String | | UnsafeReflection.java:46:132:46:168 | body : Map | semmle.label | body : Map | -| UnsafeReflection.java:49:23:49:59 | (...)... : Object | semmle.label | (...)... : Object | +| UnsafeReflection.java:49:23:49:59 | (...)... : List | semmle.label | (...)... : List | | UnsafeReflection.java:49:37:49:40 | body : Map | semmle.label | body : Map | | UnsafeReflection.java:49:37:49:59 | get(...) : Object | semmle.label | get(...) : Object | | UnsafeReflection.java:53:30:53:46 | beanIdOrClassName : String | semmle.label | beanIdOrClassName : String | -| UnsafeReflection.java:53:67:53:73 | rawData : Object | semmle.label | rawData : Object | +| UnsafeReflection.java:53:67:53:73 | rawData : List | semmle.label | rawData : List | | UnsafeReflection.java:62:33:62:70 | getParameter(...) : String | semmle.label | getParameter(...) : String | | UnsafeReflection.java:68:76:68:89 | parameterValue | semmle.label | parameterValue | | UnsafeReflection.java:77:33:77:70 | getParameter(...) : String | semmle.label | getParameter(...) : String | @@ -41,7 +41,7 @@ nodes | UnsafeReflection.java:92:33:92:70 | getParameter(...) : String | semmle.label | getParameter(...) : String | | UnsafeReflection.java:98:76:98:89 | parameterValue | semmle.label | parameterValue | | UnsafeReflection.java:104:34:104:57 | beanIdOrClassName : String | semmle.label | beanIdOrClassName : String | -| UnsafeReflection.java:104:102:104:118 | data : Object | semmle.label | data : Object | +| UnsafeReflection.java:104:102:104:118 | data : List | semmle.label | data : List | | UnsafeReflection.java:119:21:119:26 | method | semmle.label | method | | UnsafeReflection.java:119:35:119:38 | bean | semmle.label | bean | | UnsafeReflection.java:119:41:119:44 | data | semmle.label | data | diff --git a/java/ql/test/experimental/query-tests/security/CWE-552/UnsafeUrlForward.expected b/java/ql/test/experimental/query-tests/security/CWE-552/UnsafeUrlForward.expected index a39906b4115..57874f96e18 100644 --- a/java/ql/test/experimental/query-tests/security/CWE-552/UnsafeUrlForward.expected +++ b/java/ql/test/experimental/query-tests/security/CWE-552/UnsafeUrlForward.expected @@ -6,11 +6,11 @@ edges | UnsafeLoadSpringResource.java:108:32:108:77 | fileName : String | UnsafeLoadSpringResource.java:116:51:116:58 | fileName | | UnsafeRequestPath.java:20:17:20:63 | getServletPath(...) : String | UnsafeRequestPath.java:23:33:23:36 | path | | UnsafeResourceGet2.java:16:32:16:79 | getRequestParameterMap(...) : Map | UnsafeResourceGet2.java:17:20:17:25 | params : Map | -| UnsafeResourceGet2.java:17:20:17:25 | params : Map | UnsafeResourceGet2.java:17:20:17:40 | get(...) : Object | -| UnsafeResourceGet2.java:17:20:17:40 | get(...) : Object | UnsafeResourceGet2.java:19:93:19:99 | loadUrl | +| UnsafeResourceGet2.java:17:20:17:25 | params : Map | UnsafeResourceGet2.java:17:20:17:40 | get(...) : String | +| UnsafeResourceGet2.java:17:20:17:40 | get(...) : String | UnsafeResourceGet2.java:19:93:19:99 | loadUrl | | UnsafeResourceGet2.java:32:32:32:79 | getRequestParameterMap(...) : Map | UnsafeResourceGet2.java:33:20:33:25 | params : Map | -| UnsafeResourceGet2.java:33:20:33:25 | params : Map | UnsafeResourceGet2.java:33:20:33:40 | get(...) : Object | -| UnsafeResourceGet2.java:33:20:33:40 | get(...) : Object | UnsafeResourceGet2.java:37:20:37:22 | url | +| UnsafeResourceGet2.java:33:20:33:25 | params : Map | UnsafeResourceGet2.java:33:20:33:40 | get(...) : String | +| UnsafeResourceGet2.java:33:20:33:40 | get(...) : String | UnsafeResourceGet2.java:37:20:37:22 | url | | UnsafeResourceGet.java:32:23:32:56 | getParameter(...) : String | UnsafeResourceGet.java:41:20:41:22 | url | | UnsafeResourceGet.java:111:24:111:58 | getParameter(...) : String | UnsafeResourceGet.java:115:68:115:78 | requestPath | | UnsafeResourceGet.java:143:23:143:56 | getParameter(...) : String | UnsafeResourceGet.java:150:20:150:22 | url | @@ -42,11 +42,11 @@ nodes | UnsafeRequestPath.java:23:33:23:36 | path | semmle.label | path | | UnsafeResourceGet2.java:16:32:16:79 | getRequestParameterMap(...) : Map | semmle.label | getRequestParameterMap(...) : Map | | UnsafeResourceGet2.java:17:20:17:25 | params : Map | semmle.label | params : Map | -| UnsafeResourceGet2.java:17:20:17:40 | get(...) : Object | semmle.label | get(...) : Object | +| UnsafeResourceGet2.java:17:20:17:40 | get(...) : String | semmle.label | get(...) : String | | UnsafeResourceGet2.java:19:93:19:99 | loadUrl | semmle.label | loadUrl | | UnsafeResourceGet2.java:32:32:32:79 | getRequestParameterMap(...) : Map | semmle.label | getRequestParameterMap(...) : Map | | UnsafeResourceGet2.java:33:20:33:25 | params : Map | semmle.label | params : Map | -| UnsafeResourceGet2.java:33:20:33:40 | get(...) : Object | semmle.label | get(...) : Object | +| UnsafeResourceGet2.java:33:20:33:40 | get(...) : String | semmle.label | get(...) : String | | UnsafeResourceGet2.java:37:20:37:22 | url | semmle.label | url | | UnsafeResourceGet.java:32:23:32:56 | getParameter(...) : String | semmle.label | getParameter(...) : String | | UnsafeResourceGet.java:41:20:41:22 | url | semmle.label | url | diff --git a/java/ql/test/experimental/query-tests/security/CWE-598/SensitiveGetQuery.expected b/java/ql/test/experimental/query-tests/security/CWE-598/SensitiveGetQuery.expected index 0c641999e27..28471144374 100644 --- a/java/ql/test/experimental/query-tests/security/CWE-598/SensitiveGetQuery.expected +++ b/java/ql/test/experimental/query-tests/security/CWE-598/SensitiveGetQuery.expected @@ -1,11 +1,11 @@ edges | SensitiveGetQuery2.java:12:13:12:37 | getParameterMap(...) : Map | SensitiveGetQuery2.java:14:30:14:32 | map : Map | -| SensitiveGetQuery2.java:14:21:14:48 | (...)... : Object | SensitiveGetQuery2.java:15:29:15:36 | password | -| SensitiveGetQuery2.java:14:21:14:48 | (...)... : Object | SensitiveGetQuery2.java:15:29:15:36 | password : Object | +| SensitiveGetQuery2.java:14:21:14:48 | (...)... : String | SensitiveGetQuery2.java:15:29:15:36 | password | +| SensitiveGetQuery2.java:14:21:14:48 | (...)... : String | SensitiveGetQuery2.java:15:29:15:36 | password : String | | SensitiveGetQuery2.java:14:30:14:32 | map : Map | SensitiveGetQuery2.java:14:30:14:48 | get(...) : Object | -| SensitiveGetQuery2.java:14:30:14:48 | get(...) : Object | SensitiveGetQuery2.java:14:21:14:48 | (...)... : Object | -| SensitiveGetQuery2.java:15:29:15:36 | password : Object | SensitiveGetQuery2.java:18:40:18:54 | password : Object | -| SensitiveGetQuery2.java:18:40:18:54 | password : Object | SensitiveGetQuery2.java:19:61:19:68 | password | +| SensitiveGetQuery2.java:14:30:14:48 | get(...) : Object | SensitiveGetQuery2.java:14:21:14:48 | (...)... : String | +| SensitiveGetQuery2.java:15:29:15:36 | password : String | SensitiveGetQuery2.java:18:40:18:54 | password : String | +| SensitiveGetQuery2.java:18:40:18:54 | password : String | SensitiveGetQuery2.java:19:61:19:68 | password | | SensitiveGetQuery3.java:12:21:12:60 | getRequestParameter(...) : String | SensitiveGetQuery3.java:13:57:13:64 | password | | SensitiveGetQuery3.java:17:10:17:40 | getParameter(...) : String | SensitiveGetQuery3.java:12:21:12:60 | getRequestParameter(...) : String | | SensitiveGetQuery4.java:14:24:14:66 | getRequestParameter(...) : String | SensitiveGetQuery4.java:16:37:16:47 | accessToken | @@ -16,12 +16,12 @@ edges | SensitiveGetQuery.java:17:40:17:54 | password : String | SensitiveGetQuery.java:18:61:18:68 | password | nodes | SensitiveGetQuery2.java:12:13:12:37 | getParameterMap(...) : Map | semmle.label | getParameterMap(...) : Map | -| SensitiveGetQuery2.java:14:21:14:48 | (...)... : Object | semmle.label | (...)... : Object | +| SensitiveGetQuery2.java:14:21:14:48 | (...)... : String | semmle.label | (...)... : String | | SensitiveGetQuery2.java:14:30:14:32 | map : Map | semmle.label | map : Map | | SensitiveGetQuery2.java:14:30:14:48 | get(...) : Object | semmle.label | get(...) : Object | | SensitiveGetQuery2.java:15:29:15:36 | password | semmle.label | password | -| SensitiveGetQuery2.java:15:29:15:36 | password : Object | semmle.label | password : Object | -| SensitiveGetQuery2.java:18:40:18:54 | password : Object | semmle.label | password : Object | +| SensitiveGetQuery2.java:15:29:15:36 | password : String | semmle.label | password : String | +| SensitiveGetQuery2.java:18:40:18:54 | password : String | semmle.label | password : String | | SensitiveGetQuery2.java:19:61:19:68 | password | semmle.label | password | | SensitiveGetQuery3.java:12:21:12:60 | getRequestParameter(...) : String | semmle.label | getRequestParameter(...) : String | | SensitiveGetQuery3.java:13:57:13:64 | password | semmle.label | password | diff --git a/java/ql/test/experimental/query-tests/security/CWE-755/NFEAndroidDoS.expected b/java/ql/test/experimental/query-tests/security/CWE-755/NFEAndroidDoS.expected index 73657a38158..5f0e5b028f9 100644 --- a/java/ql/test/experimental/query-tests/security/CWE-755/NFEAndroidDoS.expected +++ b/java/ql/test/experimental/query-tests/security/CWE-755/NFEAndroidDoS.expected @@ -1,25 +1,25 @@ edges -| NFEAndroidDoS.java:13:24:13:34 | getIntent(...) : Intent | NFEAndroidDoS.java:13:24:13:61 | getStringExtra(...) : Object | -| NFEAndroidDoS.java:13:24:13:61 | getStringExtra(...) : Object | NFEAndroidDoS.java:14:21:14:51 | parseDouble(...) | -| NFEAndroidDoS.java:22:21:22:31 | getIntent(...) : Intent | NFEAndroidDoS.java:22:21:22:55 | getStringExtra(...) : Object | -| NFEAndroidDoS.java:22:21:22:55 | getStringExtra(...) : Object | NFEAndroidDoS.java:23:15:23:40 | parseInt(...) | -| NFEAndroidDoS.java:25:22:25:32 | getIntent(...) : Intent | NFEAndroidDoS.java:25:22:25:57 | getStringExtra(...) : Object | -| NFEAndroidDoS.java:25:22:25:57 | getStringExtra(...) : Object | NFEAndroidDoS.java:26:16:26:42 | parseInt(...) | -| NFEAndroidDoS.java:43:24:43:34 | getIntent(...) : Intent | NFEAndroidDoS.java:43:24:43:61 | getStringExtra(...) : Object | -| NFEAndroidDoS.java:43:24:43:61 | getStringExtra(...) : Object | NFEAndroidDoS.java:44:21:44:43 | new Double(...) | -| NFEAndroidDoS.java:43:24:43:61 | getStringExtra(...) : Object | NFEAndroidDoS.java:47:21:47:47 | valueOf(...) | +| NFEAndroidDoS.java:13:24:13:34 | getIntent(...) : Intent | NFEAndroidDoS.java:13:24:13:61 | getStringExtra(...) : String | +| NFEAndroidDoS.java:13:24:13:61 | getStringExtra(...) : String | NFEAndroidDoS.java:14:21:14:51 | parseDouble(...) | +| NFEAndroidDoS.java:22:21:22:31 | getIntent(...) : Intent | NFEAndroidDoS.java:22:21:22:55 | getStringExtra(...) : String | +| NFEAndroidDoS.java:22:21:22:55 | getStringExtra(...) : String | NFEAndroidDoS.java:23:15:23:40 | parseInt(...) | +| NFEAndroidDoS.java:25:22:25:32 | getIntent(...) : Intent | NFEAndroidDoS.java:25:22:25:57 | getStringExtra(...) : String | +| NFEAndroidDoS.java:25:22:25:57 | getStringExtra(...) : String | NFEAndroidDoS.java:26:16:26:42 | parseInt(...) | +| NFEAndroidDoS.java:43:24:43:34 | getIntent(...) : Intent | NFEAndroidDoS.java:43:24:43:61 | getStringExtra(...) : String | +| NFEAndroidDoS.java:43:24:43:61 | getStringExtra(...) : String | NFEAndroidDoS.java:44:21:44:43 | new Double(...) | +| NFEAndroidDoS.java:43:24:43:61 | getStringExtra(...) : String | NFEAndroidDoS.java:47:21:47:47 | valueOf(...) | nodes | NFEAndroidDoS.java:13:24:13:34 | getIntent(...) : Intent | semmle.label | getIntent(...) : Intent | -| NFEAndroidDoS.java:13:24:13:61 | getStringExtra(...) : Object | semmle.label | getStringExtra(...) : Object | +| NFEAndroidDoS.java:13:24:13:61 | getStringExtra(...) : String | semmle.label | getStringExtra(...) : String | | NFEAndroidDoS.java:14:21:14:51 | parseDouble(...) | semmle.label | parseDouble(...) | | NFEAndroidDoS.java:22:21:22:31 | getIntent(...) : Intent | semmle.label | getIntent(...) : Intent | -| NFEAndroidDoS.java:22:21:22:55 | getStringExtra(...) : Object | semmle.label | getStringExtra(...) : Object | +| NFEAndroidDoS.java:22:21:22:55 | getStringExtra(...) : String | semmle.label | getStringExtra(...) : String | | NFEAndroidDoS.java:23:15:23:40 | parseInt(...) | semmle.label | parseInt(...) | | NFEAndroidDoS.java:25:22:25:32 | getIntent(...) : Intent | semmle.label | getIntent(...) : Intent | -| NFEAndroidDoS.java:25:22:25:57 | getStringExtra(...) : Object | semmle.label | getStringExtra(...) : Object | +| NFEAndroidDoS.java:25:22:25:57 | getStringExtra(...) : String | semmle.label | getStringExtra(...) : String | | NFEAndroidDoS.java:26:16:26:42 | parseInt(...) | semmle.label | parseInt(...) | | NFEAndroidDoS.java:43:24:43:34 | getIntent(...) : Intent | semmle.label | getIntent(...) : Intent | -| NFEAndroidDoS.java:43:24:43:61 | getStringExtra(...) : Object | semmle.label | getStringExtra(...) : Object | +| NFEAndroidDoS.java:43:24:43:61 | getStringExtra(...) : String | semmle.label | getStringExtra(...) : String | | NFEAndroidDoS.java:44:21:44:43 | new Double(...) | semmle.label | new Double(...) | | NFEAndroidDoS.java:47:21:47:47 | valueOf(...) | semmle.label | valueOf(...) | subpaths diff --git a/java/ql/test/ext/TestModels/Test.java b/java/ql/test/ext/TestModels/Test.java index 83efd12e967..6bbc7a07879 100644 --- a/java/ql/test/ext/TestModels/Test.java +++ b/java/ql/test/ext/TestModels/Test.java @@ -82,7 +82,7 @@ public class Test { Connection con = DriverManager.getConnection(""); PreparedStatement ps1 = con.prepareStatement("UPDATE EMPLOYEES SET NAME = ? WHERE ID = ?"); ps1.setString(1, (String)source()); - sink(ps1); // $hasValueFlow + sink(ps1); // safe // java.util.concurrent.atomic AtomicReference ar = new AtomicReference(source()); diff --git a/java/ql/test/library-tests/frameworks/apache-collections/Test.java b/java/ql/test/library-tests/frameworks/apache-collections/Test.java index 188849457ac..09906405d75 100644 --- a/java/ql/test/library-tests/frameworks/apache-collections/Test.java +++ b/java/ql/test/library-tests/frameworks/apache-collections/Test.java @@ -721,14 +721,14 @@ public class Test { { // "org.apache.commons.collections4;MapUtils;true;getMap;;;MapValue of Argument[0];ReturnValue;value;manual" Map out = null; - Map in = newTreeMapWithMapValue((String)source()); + Map in = newTreeMapWithMapValue((Map)source()); out = MapUtils.getMap(in, null, null); sink(out); // $ hasValueFlow } { // "org.apache.commons.collections4;MapUtils;true;getMap;;;MapValue of Argument[0];ReturnValue;value;manual" Map out = null; - Map in = newTreeMapWithMapValue((String)source()); + Map in = newTreeMapWithMapValue((Map)source()); out = MapUtils.getMap(in, null); sink(out); // $ hasValueFlow } @@ -7257,4 +7257,4 @@ public class Test { } } -} \ No newline at end of file +} diff --git a/java/ql/test/query-tests/Metrics/GeneratedVsManualCoverage/TopJdkApisTest/TopJdkApisTest.expected b/java/ql/test/query-tests/Metrics/GeneratedVsManualCoverage/TopJdkApisTest/TopJdkApisTest.expected index b362ef171f5..4fee1c07e06 100644 --- a/java/ql/test/query-tests/Metrics/GeneratedVsManualCoverage/TopJdkApisTest/TopJdkApisTest.expected +++ b/java/ql/test/query-tests/Metrics/GeneratedVsManualCoverage/TopJdkApisTest/TopJdkApisTest.expected @@ -8,7 +8,7 @@ | java.nio | 0 | 0 | 2 | 3 | 5 | 0.4 | 0.0 | 0.4 | 0.0 | NaN | 0.6 | | java.nio.charset | 0 | 0 | 0 | 1 | 1 | 0.0 | 0.0 | 0.0 | NaN | NaN | 1.0 | | java.nio.file | 0 | 0 | 7 | 1 | 8 | 0.875 | 0.0 | 0.875 | 0.0 | NaN | 0.125 | -| java.sql | 0 | 0 | 2 | 14 | 16 | 0.125 | 0.0 | 0.125 | 0.0 | NaN | 0.875 | +| java.sql | 0 | 0 | 1 | 15 | 16 | 0.0625 | 0.0 | 0.0625 | 0.0 | NaN | 0.9375 | | java.text | 0 | 0 | 0 | 5 | 5 | 0.0 | 0.0 | 0.0 | NaN | NaN | 1.0 | | java.time | 0 | 0 | 0 | 17 | 17 | 0.0 | 0.0 | 0.0 | NaN | NaN | 1.0 | | java.time.chrono | 0 | 0 | 0 | 1 | 1 | 0.0 | 0.0 | 0.0 | NaN | NaN | 1.0 | diff --git a/java/ql/test/query-tests/security/CWE-078/ExecTaintedLocal.expected b/java/ql/test/query-tests/security/CWE-078/ExecTaintedLocal.expected index 2ae893b5d1d..05dd12f9a5b 100644 --- a/java/ql/test/query-tests/security/CWE-078/ExecTaintedLocal.expected +++ b/java/ql/test/query-tests/security/CWE-078/ExecTaintedLocal.expected @@ -5,8 +5,8 @@ edges | Test.java:6:35:6:44 | arg : String | Test.java:22:15:22:27 | ... + ... : String | | Test.java:10:29:10:74 | {...} : String[] [[]] : String | Test.java:10:29:10:74 | new String[] | | Test.java:10:61:10:73 | ... + ... : String | Test.java:10:29:10:74 | {...} : String[] [[]] : String | -| Test.java:16:5:16:7 | cmd [post update] : List [] : String | Test.java:18:29:18:31 | cmd | -| Test.java:16:13:16:25 | ... + ... : String | Test.java:16:5:16:7 | cmd [post update] : List [] : String | +| Test.java:16:5:16:7 | cmd [post update] : ArrayList [] : String | Test.java:18:29:18:31 | cmd | +| Test.java:16:13:16:25 | ... + ... : String | Test.java:16:5:16:7 | cmd [post update] : ArrayList [] : String | | Test.java:22:5:22:8 | cmd1 [post update] : String[] [[]] : String | Test.java:24:29:24:32 | cmd1 | | Test.java:22:15:22:27 | ... + ... : String | Test.java:22:5:22:8 | cmd1 [post update] : String[] [[]] : String | | Test.java:28:38:28:47 | arg : String | Test.java:29:44:29:64 | ... + ... | @@ -20,7 +20,7 @@ nodes | Test.java:10:29:10:74 | new String[] | semmle.label | new String[] | | Test.java:10:29:10:74 | {...} : String[] [[]] : String | semmle.label | {...} : String[] [[]] : String | | Test.java:10:61:10:73 | ... + ... : String | semmle.label | ... + ... : String | -| Test.java:16:5:16:7 | cmd [post update] : List [] : String | semmle.label | cmd [post update] : List [] : String | +| Test.java:16:5:16:7 | cmd [post update] : ArrayList [] : String | semmle.label | cmd [post update] : ArrayList [] : String | | Test.java:16:13:16:25 | ... + ... : String | semmle.label | ... + ... : String | | Test.java:18:29:18:31 | cmd | semmle.label | cmd | | Test.java:22:5:22:8 | cmd1 [post update] : String[] [[]] : String | semmle.label | cmd1 [post update] : String[] [[]] : String | diff --git a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl.qll b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl.qll index ddf98ac0f2f..984c5ae2018 100644 --- a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl.qll +++ b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl.qll @@ -1135,8 +1135,8 @@ module Impl { DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow ); - bindingset[node, state, t, ap] - predicate filter(NodeEx node, FlowState state, Typ t, Ap ap); + bindingset[node, state, t0, ap] + predicate filter(NodeEx node, FlowState state, Typ t0, Ap ap, Typ t); bindingset[typ, contentType] predicate typecheckStore(Typ typ, DataFlowType contentType); @@ -1199,17 +1199,21 @@ module Impl { NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, TypOption argT, ApOption argAp, Typ t, Ap ap, ApApprox apa ) { - fwdFlow0(node, state, cc, summaryCtx, argT, argAp, t, ap, apa) and - PrevStage::revFlow(node, state, apa) and - filter(node, state, t, ap) + fwdFlow1(node, state, cc, summaryCtx, argT, argAp, _, t, ap, apa) } - pragma[inline] - additional predicate fwdFlow( + private predicate fwdFlow1( NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, TypOption argT, - ApOption argAp, Typ t, Ap ap + ApOption argAp, Typ t0, Typ t, Ap ap, ApApprox apa ) { - fwdFlow(node, state, cc, summaryCtx, argT, argAp, t, ap, _) + fwdFlow0(node, state, cc, summaryCtx, argT, argAp, t0, ap, apa) and + PrevStage::revFlow(node, state, apa) and + filter(node, state, t0, ap, t) + } + + pragma[nomagic] + private predicate typeStrengthen(Typ t0, Ap ap, Typ t) { + fwdFlow1(_, _, _, _, _, _, t0, t, ap, _) and t0 != t } pragma[assume_small_delta] @@ -1339,6 +1343,11 @@ module Impl { private predicate fwdFlowConsCand(Typ t2, Ap cons, Content c, Typ t1, Ap tail) { fwdFlowStore(_, t1, tail, c, t2, _, _, _, _, _, _) and cons = apCons(c, t1, tail) + or + exists(Typ t0 | + typeStrengthen(t0, cons, t2) and + fwdFlowConsCand(t0, cons, c, t1, tail) + ) } pragma[nomagic] @@ -1359,7 +1368,7 @@ module Impl { ParamNodeOption summaryCtx, TypOption argT, ApOption argAp ) { exists(ApHeadContent apc | - fwdFlow(node1, state, cc, summaryCtx, argT, argAp, t, ap) and + fwdFlow(node1, state, cc, summaryCtx, argT, argAp, t, ap, _) and apc = getHeadContent(ap) and readStepCand0(node1, apc, c, node2) ) @@ -1520,14 +1529,14 @@ module Impl { 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() @@ -1780,13 +1789,13 @@ module Impl { boolean fwd, int nodes, int fields, int conscand, int states, int tuples ) { fwd = true and - nodes = count(NodeEx node | fwdFlow(node, _, _, _, _, _, _, _)) 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 + states = count(FlowState state | fwdFlow(_, state, _, _, _, _, _, _, _)) and tuples = count(NodeEx n, FlowState state, Cc cc, ParamNodeOption summaryCtx, TypOption argT, - ApOption argAp, Typ t, Ap ap | fwdFlow(n, state, cc, summaryCtx, argT, argAp, t, ap)) + ApOption argAp, Typ t, Ap ap | fwdFlow(n, state, cc, summaryCtx, argT, argAp, t, ap, _)) or fwd = false and nodes = count(NodeEx node | revFlow(node, _, _, _, _)) and @@ -1963,10 +1972,10 @@ module Impl { ) } - bindingset[node, state, t, ap] - predicate filter(NodeEx node, FlowState state, Typ t, Ap ap) { + bindingset[node, state, t0, ap] + predicate filter(NodeEx node, FlowState state, Typ t0, Ap ap, Typ t) { PrevStage::revFlowState(state) and - exists(t) and + t0 = t and exists(ap) and not stateBarrier(node, state) and ( @@ -2197,8 +2206,8 @@ module Impl { import BooleanCallContext predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - DataFlowType t, LocalCc lcc + NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, Typ t, + LocalCc lcc ) { localFlowBigStep(node1, state1, node2, state2, preservesValue, t, _) and exists(lcc) @@ -2218,10 +2227,16 @@ module Impl { ) } - bindingset[node, state, t, ap] - predicate filter(NodeEx node, FlowState state, Typ t, Ap ap) { + bindingset[node, state, t0, ap] + predicate filter(NodeEx node, FlowState state, Typ t0, Ap ap, Typ t) { exists(state) and - (if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), t) else any()) 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 @@ -2241,6 +2256,16 @@ module Impl { import MkStage::Stage } + bindingset[node, t0] + private predicate strengthenType(NodeEx node, DataFlowType t0, DataFlowType t) { + if castingNodeEx(node) + then + exists(DataFlowType nt | nt = node.getDataFlowType() | + if typeStrongerThan(nt, t0) then t = nt else (compatibleTypes(nt, t0) and t = t0) + ) + else t = t0 + } + private module Stage4Param implements MkStage::StageParam { private module PrevStage = Stage3; @@ -2274,8 +2299,8 @@ module Impl { pragma[nomagic] predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - DataFlowType t, LocalCc lcc + 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 @@ -2333,11 +2358,11 @@ module Impl { ) } - bindingset[node, state, t, ap] - predicate filter(NodeEx node, FlowState state, Typ t, Ap ap) { + 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 - (if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), t) else any()) and + strengthenType(node, t0, t) and ( notExpectsContent(node) or @@ -2365,7 +2390,7 @@ module Impl { exists(AccessPathFront apf | Stage4::revFlow(node, state, TReturnCtxMaybeFlowThrough(_), _, apf) and Stage4::fwdFlow(node, state, any(Stage4::CcCall ccc), _, _, TAccessPathFrontSome(argApf), _, - apf) + apf, _) ) } @@ -2579,8 +2604,8 @@ module Impl { import LocalCallContext predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - DataFlowType t, LocalCc lcc + NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, Typ t, + LocalCc lcc ) { localFlowBigStep(node1, state1, node2, state2, preservesValue, t, lcc) and PrevStage::revFlow(node1, pragma[only_bind_into](state1), _) and @@ -2609,9 +2634,9 @@ module Impl { ) } - bindingset[node, state, t, ap] - predicate filter(NodeEx node, FlowState state, Typ t, Ap ap) { - (if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), t) else any()) and + bindingset[node, state, t0, ap] + predicate filter(NodeEx node, FlowState state, Typ t0, Ap ap, Typ t) { + strengthenType(node, t0, t) and exists(state) and exists(ap) } @@ -2632,7 +2657,7 @@ module Impl { 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, _) ) } @@ -2649,7 +2674,7 @@ module Impl { TSummaryCtxSome(ParamNodeEx p, FlowState state, DataFlowType t, AccessPath ap) { exists(AccessPathApprox apa | ap.getApprox() = apa | Stage5::parameterMayFlowThrough(p, apa) and - Stage5::fwdFlow(p, state, _, _, _, _, t, apa) and + Stage5::fwdFlow(p, state, _, _, Option::some(t), _, _, apa, _) and Stage5::revFlow(p, state, _) ) } @@ -2820,9 +2845,7 @@ module Impl { ap = TAccessPathNil() or // ... or a step from an existing PathNode to another node. - pathStep(_, node, state, cc, sc, t, ap) and - Stage5::revFlow(node, state, ap.getApprox()) and - (if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), t) else any()) + pathStep(_, node, state, cc, sc, t, ap) } or TPathNodeSink(NodeEx node, FlowState state) { exists(PathNodeMid sink | @@ -3340,13 +3363,24 @@ module Impl { ap = mid.getAp() } + private predicate pathStep( + PathNodeMid mid, NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, DataFlowType t, + AccessPath ap + ) { + exists(DataFlowType t0 | + pathStep0(mid, node, state, cc, sc, t0, ap) and + Stage5::revFlow(node, state, ap.getApprox()) and + strengthenType(node, t0, t) + ) + } + /** * Holds if data may flow from `mid` to `node`. The last step in or out of * a callable is recorded by `cc`. */ pragma[assume_small_delta] pragma[nomagic] - private predicate pathStep( + private predicate pathStep0( PathNodeMid mid, NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, DataFlowType t, AccessPath ap ) { @@ -3964,7 +3998,7 @@ module Impl { ap = TPartialNil() and exists(explorationLimit()) or - partialPathNodeMk0(node, state, cc, sc1, sc2, sc3, sc4, t, ap) and + partialPathStep(_, node, state, cc, sc1, sc2, sc3, sc4, t, ap) and distSrc(node.getEnclosingCallable()) <= explorationLimit() } or TPartialPathNodeRev( @@ -3990,11 +4024,20 @@ module Impl { } pragma[nomagic] - private predicate partialPathNodeMk0( - NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, - TSummaryCtx3 sc3, TSummaryCtx4 sc4, DataFlowType t, PartialAccessPath ap + private predicate partialPathStep( + PartialPathNodeFwd mid, NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, + TSummaryCtx2 sc2, TSummaryCtx3 sc3, TSummaryCtx4 sc4, DataFlowType t, PartialAccessPath ap ) { - partialPathStep(_, node, state, cc, sc1, sc2, sc3, sc4, t, ap) and + partialPathStep1(mid, node, state, cc, sc1, sc2, sc3, sc4, _, t, ap) + } + + pragma[nomagic] + private predicate partialPathStep1( + PartialPathNodeFwd mid, NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, + TSummaryCtx2 sc2, TSummaryCtx3 sc3, TSummaryCtx4 sc4, DataFlowType t0, DataFlowType t, + PartialAccessPath ap + ) { + partialPathStep0(mid, node, state, cc, sc1, sc2, sc3, sc4, t0, ap) and not fullBarrier(node) and not stateBarrier(node, state) and not clearsContentEx(node, ap.getHead()) and @@ -4002,9 +4045,14 @@ module Impl { notExpectsContent(node) or expectsContentEx(node, ap.getHead()) ) and - if node.asNode() instanceof CastingNode - then compatibleTypes(node.getDataFlowType(), t) - else any() + strengthenType(node, t0, t) + } + + pragma[nomagic] + private predicate partialPathTypeStrengthen( + DataFlowType t0, PartialAccessPath ap, DataFlowType t + ) { + partialPathStep1(_, _, _, _, _, _, _, _, t0, t, ap) and t0 != t } /** @@ -4183,7 +4231,8 @@ module Impl { } } - private predicate partialPathStep( + pragma[nomagic] + private predicate partialPathStep0( PartialPathNodeFwd mid, NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, TSummaryCtx3 sc3, TSummaryCtx4 sc4, DataFlowType t, PartialAccessPath ap ) { @@ -4309,6 +4358,11 @@ module Impl { DataFlowType t1, PartialAccessPath ap1, Content c, DataFlowType t2, PartialAccessPath ap2 ) { partialPathStoreStep(_, t1, ap1, c, _, t2, ap2) + or + exists(DataFlowType t0 | + partialPathTypeStrengthen(t0, ap2, t2) and + apConsFwd(t1, ap1, c, t0, ap2) + ) } pragma[nomagic] diff --git a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowPrivate.qll b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowPrivate.qll index 693a2f13fc4..de493e5bb53 100644 --- a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowPrivate.qll +++ b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowPrivate.qll @@ -502,6 +502,8 @@ class CastNode extends Node { pragma[inline] predicate compatibleTypes(DataFlowType t1, DataFlowType t2) { any() } +predicate typeStrongerThan(DataFlowType t1, DataFlowType t2) { none() } + /** * Gets the type of `node`. */ diff --git a/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImpl.qll b/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImpl.qll index ddf98ac0f2f..984c5ae2018 100644 --- a/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImpl.qll +++ b/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImpl.qll @@ -1135,8 +1135,8 @@ module Impl { DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow ); - bindingset[node, state, t, ap] - predicate filter(NodeEx node, FlowState state, Typ t, Ap ap); + bindingset[node, state, t0, ap] + predicate filter(NodeEx node, FlowState state, Typ t0, Ap ap, Typ t); bindingset[typ, contentType] predicate typecheckStore(Typ typ, DataFlowType contentType); @@ -1199,17 +1199,21 @@ module Impl { NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, TypOption argT, ApOption argAp, Typ t, Ap ap, ApApprox apa ) { - fwdFlow0(node, state, cc, summaryCtx, argT, argAp, t, ap, apa) and - PrevStage::revFlow(node, state, apa) and - filter(node, state, t, ap) + fwdFlow1(node, state, cc, summaryCtx, argT, argAp, _, t, ap, apa) } - pragma[inline] - additional predicate fwdFlow( + private predicate fwdFlow1( NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, TypOption argT, - ApOption argAp, Typ t, Ap ap + ApOption argAp, Typ t0, Typ t, Ap ap, ApApprox apa ) { - fwdFlow(node, state, cc, summaryCtx, argT, argAp, t, ap, _) + fwdFlow0(node, state, cc, summaryCtx, argT, argAp, t0, ap, apa) and + PrevStage::revFlow(node, state, apa) and + filter(node, state, t0, ap, t) + } + + pragma[nomagic] + private predicate typeStrengthen(Typ t0, Ap ap, Typ t) { + fwdFlow1(_, _, _, _, _, _, t0, t, ap, _) and t0 != t } pragma[assume_small_delta] @@ -1339,6 +1343,11 @@ module Impl { private predicate fwdFlowConsCand(Typ t2, Ap cons, Content c, Typ t1, Ap tail) { fwdFlowStore(_, t1, tail, c, t2, _, _, _, _, _, _) and cons = apCons(c, t1, tail) + or + exists(Typ t0 | + typeStrengthen(t0, cons, t2) and + fwdFlowConsCand(t0, cons, c, t1, tail) + ) } pragma[nomagic] @@ -1359,7 +1368,7 @@ module Impl { ParamNodeOption summaryCtx, TypOption argT, ApOption argAp ) { exists(ApHeadContent apc | - fwdFlow(node1, state, cc, summaryCtx, argT, argAp, t, ap) and + fwdFlow(node1, state, cc, summaryCtx, argT, argAp, t, ap, _) and apc = getHeadContent(ap) and readStepCand0(node1, apc, c, node2) ) @@ -1520,14 +1529,14 @@ module Impl { 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() @@ -1780,13 +1789,13 @@ module Impl { boolean fwd, int nodes, int fields, int conscand, int states, int tuples ) { fwd = true and - nodes = count(NodeEx node | fwdFlow(node, _, _, _, _, _, _, _)) 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 + states = count(FlowState state | fwdFlow(_, state, _, _, _, _, _, _, _)) and tuples = count(NodeEx n, FlowState state, Cc cc, ParamNodeOption summaryCtx, TypOption argT, - ApOption argAp, Typ t, Ap ap | fwdFlow(n, state, cc, summaryCtx, argT, argAp, t, ap)) + ApOption argAp, Typ t, Ap ap | fwdFlow(n, state, cc, summaryCtx, argT, argAp, t, ap, _)) or fwd = false and nodes = count(NodeEx node | revFlow(node, _, _, _, _)) and @@ -1963,10 +1972,10 @@ module Impl { ) } - bindingset[node, state, t, ap] - predicate filter(NodeEx node, FlowState state, Typ t, Ap ap) { + bindingset[node, state, t0, ap] + predicate filter(NodeEx node, FlowState state, Typ t0, Ap ap, Typ t) { PrevStage::revFlowState(state) and - exists(t) and + t0 = t and exists(ap) and not stateBarrier(node, state) and ( @@ -2197,8 +2206,8 @@ module Impl { import BooleanCallContext predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - DataFlowType t, LocalCc lcc + NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, Typ t, + LocalCc lcc ) { localFlowBigStep(node1, state1, node2, state2, preservesValue, t, _) and exists(lcc) @@ -2218,10 +2227,16 @@ module Impl { ) } - bindingset[node, state, t, ap] - predicate filter(NodeEx node, FlowState state, Typ t, Ap ap) { + bindingset[node, state, t0, ap] + predicate filter(NodeEx node, FlowState state, Typ t0, Ap ap, Typ t) { exists(state) and - (if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), t) else any()) 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 @@ -2241,6 +2256,16 @@ module Impl { import MkStage::Stage } + bindingset[node, t0] + private predicate strengthenType(NodeEx node, DataFlowType t0, DataFlowType t) { + if castingNodeEx(node) + then + exists(DataFlowType nt | nt = node.getDataFlowType() | + if typeStrongerThan(nt, t0) then t = nt else (compatibleTypes(nt, t0) and t = t0) + ) + else t = t0 + } + private module Stage4Param implements MkStage::StageParam { private module PrevStage = Stage3; @@ -2274,8 +2299,8 @@ module Impl { pragma[nomagic] predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - DataFlowType t, LocalCc lcc + 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 @@ -2333,11 +2358,11 @@ module Impl { ) } - bindingset[node, state, t, ap] - predicate filter(NodeEx node, FlowState state, Typ t, Ap ap) { + 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 - (if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), t) else any()) and + strengthenType(node, t0, t) and ( notExpectsContent(node) or @@ -2365,7 +2390,7 @@ module Impl { exists(AccessPathFront apf | Stage4::revFlow(node, state, TReturnCtxMaybeFlowThrough(_), _, apf) and Stage4::fwdFlow(node, state, any(Stage4::CcCall ccc), _, _, TAccessPathFrontSome(argApf), _, - apf) + apf, _) ) } @@ -2579,8 +2604,8 @@ module Impl { import LocalCallContext predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - DataFlowType t, LocalCc lcc + NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, Typ t, + LocalCc lcc ) { localFlowBigStep(node1, state1, node2, state2, preservesValue, t, lcc) and PrevStage::revFlow(node1, pragma[only_bind_into](state1), _) and @@ -2609,9 +2634,9 @@ module Impl { ) } - bindingset[node, state, t, ap] - predicate filter(NodeEx node, FlowState state, Typ t, Ap ap) { - (if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), t) else any()) and + bindingset[node, state, t0, ap] + predicate filter(NodeEx node, FlowState state, Typ t0, Ap ap, Typ t) { + strengthenType(node, t0, t) and exists(state) and exists(ap) } @@ -2632,7 +2657,7 @@ module Impl { 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, _) ) } @@ -2649,7 +2674,7 @@ module Impl { TSummaryCtxSome(ParamNodeEx p, FlowState state, DataFlowType t, AccessPath ap) { exists(AccessPathApprox apa | ap.getApprox() = apa | Stage5::parameterMayFlowThrough(p, apa) and - Stage5::fwdFlow(p, state, _, _, _, _, t, apa) and + Stage5::fwdFlow(p, state, _, _, Option::some(t), _, _, apa, _) and Stage5::revFlow(p, state, _) ) } @@ -2820,9 +2845,7 @@ module Impl { ap = TAccessPathNil() or // ... or a step from an existing PathNode to another node. - pathStep(_, node, state, cc, sc, t, ap) and - Stage5::revFlow(node, state, ap.getApprox()) and - (if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), t) else any()) + pathStep(_, node, state, cc, sc, t, ap) } or TPathNodeSink(NodeEx node, FlowState state) { exists(PathNodeMid sink | @@ -3340,13 +3363,24 @@ module Impl { ap = mid.getAp() } + private predicate pathStep( + PathNodeMid mid, NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, DataFlowType t, + AccessPath ap + ) { + exists(DataFlowType t0 | + pathStep0(mid, node, state, cc, sc, t0, ap) and + Stage5::revFlow(node, state, ap.getApprox()) and + strengthenType(node, t0, t) + ) + } + /** * Holds if data may flow from `mid` to `node`. The last step in or out of * a callable is recorded by `cc`. */ pragma[assume_small_delta] pragma[nomagic] - private predicate pathStep( + private predicate pathStep0( PathNodeMid mid, NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, DataFlowType t, AccessPath ap ) { @@ -3964,7 +3998,7 @@ module Impl { ap = TPartialNil() and exists(explorationLimit()) or - partialPathNodeMk0(node, state, cc, sc1, sc2, sc3, sc4, t, ap) and + partialPathStep(_, node, state, cc, sc1, sc2, sc3, sc4, t, ap) and distSrc(node.getEnclosingCallable()) <= explorationLimit() } or TPartialPathNodeRev( @@ -3990,11 +4024,20 @@ module Impl { } pragma[nomagic] - private predicate partialPathNodeMk0( - NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, - TSummaryCtx3 sc3, TSummaryCtx4 sc4, DataFlowType t, PartialAccessPath ap + private predicate partialPathStep( + PartialPathNodeFwd mid, NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, + TSummaryCtx2 sc2, TSummaryCtx3 sc3, TSummaryCtx4 sc4, DataFlowType t, PartialAccessPath ap ) { - partialPathStep(_, node, state, cc, sc1, sc2, sc3, sc4, t, ap) and + partialPathStep1(mid, node, state, cc, sc1, sc2, sc3, sc4, _, t, ap) + } + + pragma[nomagic] + private predicate partialPathStep1( + PartialPathNodeFwd mid, NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, + TSummaryCtx2 sc2, TSummaryCtx3 sc3, TSummaryCtx4 sc4, DataFlowType t0, DataFlowType t, + PartialAccessPath ap + ) { + partialPathStep0(mid, node, state, cc, sc1, sc2, sc3, sc4, t0, ap) and not fullBarrier(node) and not stateBarrier(node, state) and not clearsContentEx(node, ap.getHead()) and @@ -4002,9 +4045,14 @@ module Impl { notExpectsContent(node) or expectsContentEx(node, ap.getHead()) ) and - if node.asNode() instanceof CastingNode - then compatibleTypes(node.getDataFlowType(), t) - else any() + strengthenType(node, t0, t) + } + + pragma[nomagic] + private predicate partialPathTypeStrengthen( + DataFlowType t0, PartialAccessPath ap, DataFlowType t + ) { + partialPathStep1(_, _, _, _, _, _, _, _, t0, t, ap) and t0 != t } /** @@ -4183,7 +4231,8 @@ module Impl { } } - private predicate partialPathStep( + pragma[nomagic] + private predicate partialPathStep0( PartialPathNodeFwd mid, NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, TSummaryCtx3 sc3, TSummaryCtx4 sc4, DataFlowType t, PartialAccessPath ap ) { @@ -4309,6 +4358,11 @@ module Impl { DataFlowType t1, PartialAccessPath ap1, Content c, DataFlowType t2, PartialAccessPath ap2 ) { partialPathStoreStep(_, t1, ap1, c, _, t2, ap2) + or + exists(DataFlowType t0 | + partialPathTypeStrengthen(t0, ap2, t2) and + apConsFwd(t1, ap1, c, t0, ap2) + ) } pragma[nomagic] diff --git a/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowPrivate.qll b/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowPrivate.qll index 6a7d87e9bd5..7708eff235a 100644 --- a/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowPrivate.qll +++ b/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowPrivate.qll @@ -1231,6 +1231,8 @@ class DataFlowType extends TDataFlowType { string toString() { result = "" } } +predicate typeStrongerThan(DataFlowType t1, DataFlowType t2) { none() } + /** Gets the type of `n` used for type pruning. */ DataFlowType getNodeType(NodeImpl n) { result = TTodoDataFlowType() and exists(n) } diff --git a/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowImpl.qll b/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowImpl.qll index ddf98ac0f2f..984c5ae2018 100644 --- a/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowImpl.qll +++ b/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowImpl.qll @@ -1135,8 +1135,8 @@ module Impl { DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow ); - bindingset[node, state, t, ap] - predicate filter(NodeEx node, FlowState state, Typ t, Ap ap); + bindingset[node, state, t0, ap] + predicate filter(NodeEx node, FlowState state, Typ t0, Ap ap, Typ t); bindingset[typ, contentType] predicate typecheckStore(Typ typ, DataFlowType contentType); @@ -1199,17 +1199,21 @@ module Impl { NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, TypOption argT, ApOption argAp, Typ t, Ap ap, ApApprox apa ) { - fwdFlow0(node, state, cc, summaryCtx, argT, argAp, t, ap, apa) and - PrevStage::revFlow(node, state, apa) and - filter(node, state, t, ap) + fwdFlow1(node, state, cc, summaryCtx, argT, argAp, _, t, ap, apa) } - pragma[inline] - additional predicate fwdFlow( + private predicate fwdFlow1( NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, TypOption argT, - ApOption argAp, Typ t, Ap ap + ApOption argAp, Typ t0, Typ t, Ap ap, ApApprox apa ) { - fwdFlow(node, state, cc, summaryCtx, argT, argAp, t, ap, _) + fwdFlow0(node, state, cc, summaryCtx, argT, argAp, t0, ap, apa) and + PrevStage::revFlow(node, state, apa) and + filter(node, state, t0, ap, t) + } + + pragma[nomagic] + private predicate typeStrengthen(Typ t0, Ap ap, Typ t) { + fwdFlow1(_, _, _, _, _, _, t0, t, ap, _) and t0 != t } pragma[assume_small_delta] @@ -1339,6 +1343,11 @@ module Impl { private predicate fwdFlowConsCand(Typ t2, Ap cons, Content c, Typ t1, Ap tail) { fwdFlowStore(_, t1, tail, c, t2, _, _, _, _, _, _) and cons = apCons(c, t1, tail) + or + exists(Typ t0 | + typeStrengthen(t0, cons, t2) and + fwdFlowConsCand(t0, cons, c, t1, tail) + ) } pragma[nomagic] @@ -1359,7 +1368,7 @@ module Impl { ParamNodeOption summaryCtx, TypOption argT, ApOption argAp ) { exists(ApHeadContent apc | - fwdFlow(node1, state, cc, summaryCtx, argT, argAp, t, ap) and + fwdFlow(node1, state, cc, summaryCtx, argT, argAp, t, ap, _) and apc = getHeadContent(ap) and readStepCand0(node1, apc, c, node2) ) @@ -1520,14 +1529,14 @@ module Impl { 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() @@ -1780,13 +1789,13 @@ module Impl { boolean fwd, int nodes, int fields, int conscand, int states, int tuples ) { fwd = true and - nodes = count(NodeEx node | fwdFlow(node, _, _, _, _, _, _, _)) 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 + states = count(FlowState state | fwdFlow(_, state, _, _, _, _, _, _, _)) and tuples = count(NodeEx n, FlowState state, Cc cc, ParamNodeOption summaryCtx, TypOption argT, - ApOption argAp, Typ t, Ap ap | fwdFlow(n, state, cc, summaryCtx, argT, argAp, t, ap)) + ApOption argAp, Typ t, Ap ap | fwdFlow(n, state, cc, summaryCtx, argT, argAp, t, ap, _)) or fwd = false and nodes = count(NodeEx node | revFlow(node, _, _, _, _)) and @@ -1963,10 +1972,10 @@ module Impl { ) } - bindingset[node, state, t, ap] - predicate filter(NodeEx node, FlowState state, Typ t, Ap ap) { + bindingset[node, state, t0, ap] + predicate filter(NodeEx node, FlowState state, Typ t0, Ap ap, Typ t) { PrevStage::revFlowState(state) and - exists(t) and + t0 = t and exists(ap) and not stateBarrier(node, state) and ( @@ -2197,8 +2206,8 @@ module Impl { import BooleanCallContext predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - DataFlowType t, LocalCc lcc + NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, Typ t, + LocalCc lcc ) { localFlowBigStep(node1, state1, node2, state2, preservesValue, t, _) and exists(lcc) @@ -2218,10 +2227,16 @@ module Impl { ) } - bindingset[node, state, t, ap] - predicate filter(NodeEx node, FlowState state, Typ t, Ap ap) { + bindingset[node, state, t0, ap] + predicate filter(NodeEx node, FlowState state, Typ t0, Ap ap, Typ t) { exists(state) and - (if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), t) else any()) 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 @@ -2241,6 +2256,16 @@ module Impl { import MkStage::Stage } + bindingset[node, t0] + private predicate strengthenType(NodeEx node, DataFlowType t0, DataFlowType t) { + if castingNodeEx(node) + then + exists(DataFlowType nt | nt = node.getDataFlowType() | + if typeStrongerThan(nt, t0) then t = nt else (compatibleTypes(nt, t0) and t = t0) + ) + else t = t0 + } + private module Stage4Param implements MkStage::StageParam { private module PrevStage = Stage3; @@ -2274,8 +2299,8 @@ module Impl { pragma[nomagic] predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - DataFlowType t, LocalCc lcc + 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 @@ -2333,11 +2358,11 @@ module Impl { ) } - bindingset[node, state, t, ap] - predicate filter(NodeEx node, FlowState state, Typ t, Ap ap) { + 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 - (if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), t) else any()) and + strengthenType(node, t0, t) and ( notExpectsContent(node) or @@ -2365,7 +2390,7 @@ module Impl { exists(AccessPathFront apf | Stage4::revFlow(node, state, TReturnCtxMaybeFlowThrough(_), _, apf) and Stage4::fwdFlow(node, state, any(Stage4::CcCall ccc), _, _, TAccessPathFrontSome(argApf), _, - apf) + apf, _) ) } @@ -2579,8 +2604,8 @@ module Impl { import LocalCallContext predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - DataFlowType t, LocalCc lcc + NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, Typ t, + LocalCc lcc ) { localFlowBigStep(node1, state1, node2, state2, preservesValue, t, lcc) and PrevStage::revFlow(node1, pragma[only_bind_into](state1), _) and @@ -2609,9 +2634,9 @@ module Impl { ) } - bindingset[node, state, t, ap] - predicate filter(NodeEx node, FlowState state, Typ t, Ap ap) { - (if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), t) else any()) and + bindingset[node, state, t0, ap] + predicate filter(NodeEx node, FlowState state, Typ t0, Ap ap, Typ t) { + strengthenType(node, t0, t) and exists(state) and exists(ap) } @@ -2632,7 +2657,7 @@ module Impl { 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, _) ) } @@ -2649,7 +2674,7 @@ module Impl { TSummaryCtxSome(ParamNodeEx p, FlowState state, DataFlowType t, AccessPath ap) { exists(AccessPathApprox apa | ap.getApprox() = apa | Stage5::parameterMayFlowThrough(p, apa) and - Stage5::fwdFlow(p, state, _, _, _, _, t, apa) and + Stage5::fwdFlow(p, state, _, _, Option::some(t), _, _, apa, _) and Stage5::revFlow(p, state, _) ) } @@ -2820,9 +2845,7 @@ module Impl { ap = TAccessPathNil() or // ... or a step from an existing PathNode to another node. - pathStep(_, node, state, cc, sc, t, ap) and - Stage5::revFlow(node, state, ap.getApprox()) and - (if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), t) else any()) + pathStep(_, node, state, cc, sc, t, ap) } or TPathNodeSink(NodeEx node, FlowState state) { exists(PathNodeMid sink | @@ -3340,13 +3363,24 @@ module Impl { ap = mid.getAp() } + private predicate pathStep( + PathNodeMid mid, NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, DataFlowType t, + AccessPath ap + ) { + exists(DataFlowType t0 | + pathStep0(mid, node, state, cc, sc, t0, ap) and + Stage5::revFlow(node, state, ap.getApprox()) and + strengthenType(node, t0, t) + ) + } + /** * Holds if data may flow from `mid` to `node`. The last step in or out of * a callable is recorded by `cc`. */ pragma[assume_small_delta] pragma[nomagic] - private predicate pathStep( + private predicate pathStep0( PathNodeMid mid, NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, DataFlowType t, AccessPath ap ) { @@ -3964,7 +3998,7 @@ module Impl { ap = TPartialNil() and exists(explorationLimit()) or - partialPathNodeMk0(node, state, cc, sc1, sc2, sc3, sc4, t, ap) and + partialPathStep(_, node, state, cc, sc1, sc2, sc3, sc4, t, ap) and distSrc(node.getEnclosingCallable()) <= explorationLimit() } or TPartialPathNodeRev( @@ -3990,11 +4024,20 @@ module Impl { } pragma[nomagic] - private predicate partialPathNodeMk0( - NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, - TSummaryCtx3 sc3, TSummaryCtx4 sc4, DataFlowType t, PartialAccessPath ap + private predicate partialPathStep( + PartialPathNodeFwd mid, NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, + TSummaryCtx2 sc2, TSummaryCtx3 sc3, TSummaryCtx4 sc4, DataFlowType t, PartialAccessPath ap ) { - partialPathStep(_, node, state, cc, sc1, sc2, sc3, sc4, t, ap) and + partialPathStep1(mid, node, state, cc, sc1, sc2, sc3, sc4, _, t, ap) + } + + pragma[nomagic] + private predicate partialPathStep1( + PartialPathNodeFwd mid, NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, + TSummaryCtx2 sc2, TSummaryCtx3 sc3, TSummaryCtx4 sc4, DataFlowType t0, DataFlowType t, + PartialAccessPath ap + ) { + partialPathStep0(mid, node, state, cc, sc1, sc2, sc3, sc4, t0, ap) and not fullBarrier(node) and not stateBarrier(node, state) and not clearsContentEx(node, ap.getHead()) and @@ -4002,9 +4045,14 @@ module Impl { notExpectsContent(node) or expectsContentEx(node, ap.getHead()) ) and - if node.asNode() instanceof CastingNode - then compatibleTypes(node.getDataFlowType(), t) - else any() + strengthenType(node, t0, t) + } + + pragma[nomagic] + private predicate partialPathTypeStrengthen( + DataFlowType t0, PartialAccessPath ap, DataFlowType t + ) { + partialPathStep1(_, _, _, _, _, _, _, _, t0, t, ap) and t0 != t } /** @@ -4183,7 +4231,8 @@ module Impl { } } - private predicate partialPathStep( + pragma[nomagic] + private predicate partialPathStep0( PartialPathNodeFwd mid, NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, TSummaryCtx3 sc3, TSummaryCtx4 sc4, DataFlowType t, PartialAccessPath ap ) { @@ -4309,6 +4358,11 @@ module Impl { DataFlowType t1, PartialAccessPath ap1, Content c, DataFlowType t2, PartialAccessPath ap2 ) { partialPathStoreStep(_, t1, ap1, c, _, t2, ap2) + or + exists(DataFlowType t0 | + partialPathTypeStrengthen(t0, ap2, t2) and + apConsFwd(t1, ap1, c, t0, ap2) + ) } pragma[nomagic] diff --git a/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowPrivate.qll b/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowPrivate.qll index 7b2bc359c9a..ab2bbc050a4 100644 --- a/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowPrivate.qll +++ b/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowPrivate.qll @@ -793,6 +793,8 @@ class DataFlowType extends TDataFlowType { string toString() { result = "" } } +predicate typeStrongerThan(DataFlowType t1, DataFlowType t2) { none() } + /** Gets the type of `n` used for type pruning. */ DataFlowType getNodeType(NodeImpl n) { any() // return the singleton DataFlowType until we support type pruning for Swift