diff --git a/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl.qll b/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl.qll index 6741ccc2f06..1228d00b6ba 100644 --- a/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl.qll +++ b/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl.qll @@ -622,7 +622,11 @@ private predicate parameterFlowThroughAllowed(ParamNodeEx p, ReturnKindExt kind) } private module Stage1 implements StageSig { - class Ap = Unit; + class Ap extends int { + // workaround for bad functionality-induced joins (happens when using `Unit`) + pragma[nomagic] + Ap() { this in [0 .. 1] and this < 1 } + } private class Cc = boolean; @@ -1327,8 +1331,8 @@ private module MkStage { */ pragma[nomagic] additional predicate fwdFlow( - NodeEx node, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - Ap ap, ApApprox apa, Configuration config + NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, + ApApprox apa, Configuration config ) { fwdFlow0(node, state, cc, summaryCtx, argAp, ap, apa, config) and PrevStage::revFlow(node, state, apa, config) and @@ -1337,21 +1341,21 @@ private module MkStage { pragma[inline] additional predicate fwdFlow( - NodeEx node, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - Ap ap, Configuration config + NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, + Configuration config ) { fwdFlow(node, state, cc, summaryCtx, argAp, ap, _, config) } pragma[nomagic] private predicate fwdFlow0( - NodeEx node, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - Ap ap, ApApprox apa, Configuration config + NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, + ApApprox apa, Configuration config ) { sourceNode(node, state, config) and (if hasSourceCallCtx(config) then cc = ccSomeCall() else cc = ccNone()) and argAp = apNone() and - summaryCtx = TParameterPositionNone() and + summaryCtx = TParamNodeNone() and ap = getApNil(node) and apa = getApprox(ap) or @@ -1372,7 +1376,7 @@ private module MkStage { fwdFlow(mid, pragma[only_bind_into](state), _, _, _, ap, apa, pragma[only_bind_into](config)) and jumpStep(mid, node, config) and cc = ccNone() and - summaryCtx = TParameterPositionNone() and + summaryCtx = TParamNodeNone() and argAp = apNone() ) or @@ -1380,7 +1384,7 @@ private module MkStage { fwdFlow(mid, state, _, _, _, nil, pragma[only_bind_into](config)) and additionalJumpStep(mid, node, config) and cc = ccNone() and - summaryCtx = TParameterPositionNone() and + summaryCtx = TParamNodeNone() and argAp = apNone() and ap = getApNil(node) and apa = getApprox(ap) @@ -1390,7 +1394,7 @@ private module MkStage { fwdFlow(mid, state0, _, _, _, nil, pragma[only_bind_into](config)) and additionalJumpStateStep(mid, state0, node, state, config) and cc = ccNone() and - summaryCtx = TParameterPositionNone() and + summaryCtx = TParamNodeNone() and argAp = apNone() and ap = getApNil(node) and apa = getApprox(ap) @@ -1414,10 +1418,10 @@ private module MkStage { fwdFlowIn(_, node, state, _, cc, _, _, ap, apa, config) and if PrevStage::parameterMayFlowThrough(node, apa, config) then ( - summaryCtx = TParameterPositionSome(node.(ParamNodeEx).getPosition()) and + summaryCtx = TParamNodeSome(node.asNode()) and argAp = apSome(ap) ) else ( - summaryCtx = TParameterPositionNone() and argAp = apNone() + summaryCtx = TParamNodeNone() and argAp = apNone() ) or // flow out of a callable @@ -1433,16 +1437,19 @@ private module MkStage { ) or // flow through a callable - exists(DataFlowCall call, ParameterPosition summaryCtx0, Ap argAp0 | - fwdFlowOutFromArg(call, node, state, summaryCtx0, argAp0, ap, apa, config) and - fwdFlowIsEntered(call, cc, summaryCtx, argAp, summaryCtx0, argAp0, config) + exists( + DataFlowCall call, CcCall ccc, RetNodeEx ret, boolean allowsFieldFlow, ApApprox innerArgApa + | + fwdFlowThrough(call, cc, state, ccc, summaryCtx, argAp, ap, apa, ret, innerArgApa, config) and + flowThroughOutOfCall(call, ccc, ret, node, allowsFieldFlow, innerArgApa, apa, config) and + if allowsFieldFlow = false then ap instanceof ApNil else any() ) } pragma[nomagic] private predicate fwdFlowStore( NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, FlowState state, Cc cc, - ParameterPositionOption summaryCtx, ApOption argAp, Configuration config + ParamNodeOption summaryCtx, ApOption argAp, Configuration config ) { exists(DataFlowType contentType, ApApprox apa1 | fwdFlow(node1, state, cc, summaryCtx, argAp, ap1, apa1, config) and @@ -1473,8 +1480,8 @@ private module MkStage { pragma[nomagic] private predicate fwdFlowRead0( - NodeEx node1, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - ApNonNil ap, Configuration config + NodeEx node1, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, ApNonNil ap, + Configuration config ) { fwdFlow(node1, state, cc, summaryCtx, argAp, ap, config) and PrevStage::readStepCand(node1, _, _, config) @@ -1483,7 +1490,7 @@ private module MkStage { pragma[nomagic] private predicate fwdFlowRead( Ap ap, Content c, NodeEx node1, NodeEx node2, FlowState state, Cc cc, - ParameterPositionOption summaryCtx, ApOption argAp, Configuration config + ParamNodeOption summaryCtx, ApOption argAp, Configuration config ) { fwdFlowRead0(node1, state, cc, summaryCtx, argAp, ap, config) and PrevStage::readStepCand(node1, c, node2, config) and @@ -1493,7 +1500,7 @@ private module MkStage { pragma[nomagic] private predicate fwdFlowIn( DataFlowCall call, ParamNodeEx p, FlowState state, Cc outercc, CcCall innercc, - ParameterPositionOption summaryCtx, ApOption argAp, Ap ap, ApApprox apa, Configuration config + ParamNodeOption summaryCtx, ApOption argAp, Ap ap, ApApprox apa, Configuration config ) { exists(ArgNodeEx arg, boolean allowsFieldFlow | fwdFlow(arg, state, outercc, summaryCtx, argAp, ap, apa, config) and @@ -1505,64 +1512,38 @@ private module MkStage { pragma[nomagic] private predicate fwdFlowRetFromArg( - RetNodeEx ret, FlowState state, CcCall ccc, ParameterPosition summaryCtx, ParamNodeEx p, - Ap argAp, ApApprox argApa, Ap ap, ApApprox apa, Configuration config + RetNodeEx ret, FlowState state, CcCall ccc, ParamNodeEx summaryCtx, Ap argAp, ApApprox argApa, + Ap ap, ApApprox apa, Configuration config ) { - exists(DataFlowCallable c, ReturnKindExt kind | + exists(ReturnKindExt kind | fwdFlow(pragma[only_bind_into](ret), state, ccc, - TParameterPositionSome(pragma[only_bind_into](summaryCtx)), apSome(argAp), ap, apa, config) and - getApprox(argAp) = argApa and - c = ret.getEnclosingCallable() and + TParamNodeSome(pragma[only_bind_into](summaryCtx.asNode())), + pragma[only_bind_into](apSome(argAp)), ap, pragma[only_bind_into](apa), + pragma[only_bind_into](config)) and kind = ret.getKind() and - p.isParameterOf(c, pragma[only_bind_into](summaryCtx)) and - parameterFlowThroughAllowed(p, kind) + parameterFlowThroughAllowed(summaryCtx, kind) and + argApa = getApprox(argAp) and + PrevStage::returnMayFlowThrough(ret, argApa, apa, kind, pragma[only_bind_into](config)) ) } pragma[inline] - private predicate fwdFlowInMayFlowThrough( - DataFlowCall call, Cc cc, CcCall innerCc, ParameterPositionOption summaryCtx, ApOption argAp, - ParamNodeEx param, Ap ap, ApApprox apa, Configuration config + private predicate fwdFlowThrough0( + DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, + ApOption argAp, Ap ap, ApApprox apa, RetNodeEx ret, ParamNodeEx innerSummaryCtx, + Ap innerArgAp, ApApprox innerArgApa, Configuration config ) { - fwdFlowIn(call, pragma[only_bind_into](param), _, cc, innerCc, summaryCtx, argAp, ap, - pragma[only_bind_into](apa), pragma[only_bind_into](config)) and - PrevStage::parameterMayFlowThrough(param, apa, config) - } - - // dedup before joining with `flowThroughOutOfCall` - pragma[nomagic] - private predicate fwdFlowInMayFlowThroughProj( - DataFlowCall call, CcCall innerCc, ApApprox apa, Configuration config - ) { - fwdFlowInMayFlowThrough(call, _, innerCc, _, _, _, _, apa, config) - } - - /** - * Same as `flowThroughOutOfCall`, but restricted to calls that are reached - * in the flow covered by `fwdFlow`, where data might flow through the target - * callable and back out at `call`. - */ - pragma[nomagic] - private predicate fwdFlowThroughOutOfCall( - DataFlowCall call, CcCall ccc, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow, - ApApprox argApa, ApApprox apa, Configuration config - ) { - fwdFlowInMayFlowThroughProj(call, ccc, argApa, config) and - flowThroughOutOfCall(call, ccc, ret, out, allowsFieldFlow, argApa, apa, config) + fwdFlowRetFromArg(ret, state, ccc, innerSummaryCtx, innerArgAp, innerArgApa, ap, apa, config) and + fwdFlowIsEntered(call, cc, ccc, summaryCtx, argAp, innerSummaryCtx, innerArgAp, config) } pragma[nomagic] - private predicate fwdFlowOutFromArg( - DataFlowCall call, NodeEx out, FlowState state, ParameterPosition summaryCtx, Ap argAp, Ap ap, - ApApprox apa, Configuration config + private predicate fwdFlowThrough( + DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, + ApOption argAp, Ap ap, ApApprox apa, RetNodeEx ret, ApApprox innerArgApa, Configuration config ) { - exists(RetNodeEx ret, boolean allowsFieldFlow, CcCall ccc, ApApprox argApa | - fwdFlowRetFromArg(pragma[only_bind_into](ret), state, pragma[only_bind_into](ccc), - summaryCtx, _, argAp, pragma[only_bind_into](argApa), ap, pragma[only_bind_into](apa), - config) and - fwdFlowThroughOutOfCall(call, ccc, ret, out, allowsFieldFlow, argApa, apa, config) and - (if allowsFieldFlow = false then ap instanceof ApNil else any()) - ) + fwdFlowThrough0(call, cc, state, ccc, summaryCtx, argAp, ap, apa, ret, _, _, innerArgApa, + config) } /** @@ -1571,12 +1552,14 @@ private module MkStage { */ pragma[nomagic] private predicate fwdFlowIsEntered( - DataFlowCall call, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - ParameterPosition pos, Ap ap, Configuration config + DataFlowCall call, Cc cc, CcCall innerCc, ParamNodeOption summaryCtx, ApOption argAp, + ParamNodeEx p, Ap ap, Configuration config ) { - exists(ParamNodeEx param | - fwdFlowInMayFlowThrough(call, cc, _, summaryCtx, argAp, param, ap, _, config) and - pos = param.getPosition() + exists(ApApprox apa | + fwdFlowIn(call, pragma[only_bind_into](p), _, cc, innerCc, summaryCtx, argAp, ap, + pragma[only_bind_into](apa), pragma[only_bind_into](config)) and + PrevStage::parameterMayFlowThrough(p, apa, config) and + PrevStage::callMayFlowThroughRev(call, pragma[only_bind_into](config)) ) } @@ -1596,23 +1579,31 @@ private module MkStage { fwdFlowConsCand(ap1, c, ap2, config) } + pragma[nomagic] + private predicate returnFlowsThrough0( + DataFlowCall call, FlowState state, CcCall ccc, Ap ap, ApApprox apa, RetNodeEx ret, + ParamNodeEx innerSummaryCtx, Ap innerArgAp, ApApprox innerArgApa, Configuration config + ) { + fwdFlowThrough0(call, _, state, ccc, _, _, ap, apa, ret, innerSummaryCtx, innerArgAp, + innerArgApa, config) + } + pragma[nomagic] private predicate returnFlowsThrough( - RetNodeEx ret, ReturnKindExt kind, FlowState state, CcCall ccc, ParamNodeEx p, Ap argAp, + RetNodeEx ret, ReturnPosition pos, FlowState state, CcCall ccc, ParamNodeEx p, Ap argAp, Ap ap, Configuration config ) { - exists(boolean allowsFieldFlow, ApApprox argApa, ApApprox apa | - fwdFlowRetFromArg(pragma[only_bind_into](ret), state, pragma[only_bind_into](ccc), _, p, - argAp, pragma[only_bind_into](argApa), ap, pragma[only_bind_into](apa), config) and - kind = ret.getKind() and - fwdFlowThroughOutOfCall(_, ccc, ret, _, allowsFieldFlow, argApa, apa, config) and - (if allowsFieldFlow = false then ap instanceof ApNil else any()) + exists(DataFlowCall call, ApApprox apa, boolean allowsFieldFlow, ApApprox innerArgApa | + returnFlowsThrough0(call, state, ccc, ap, apa, ret, p, argAp, innerArgApa, config) and + flowThroughOutOfCall(call, ccc, ret, _, allowsFieldFlow, innerArgApa, apa, config) and + pos = ret.getReturnPosition() and + if allowsFieldFlow = false then ap instanceof ApNil else any() ) } pragma[nomagic] private predicate flowThroughIntoCall( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap argAp, + DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap argAp, Ap ap, Configuration config ) { exists(ApApprox argApa | @@ -1620,7 +1611,7 @@ private module MkStage { allowsFieldFlow, argApa, pragma[only_bind_into](config)) and fwdFlow(arg, _, _, _, _, pragma[only_bind_into](argAp), argApa, pragma[only_bind_into](config)) and - returnFlowsThrough(_, _, _, _, p, pragma[only_bind_into](argAp), _, + returnFlowsThrough(_, _, _, _, p, pragma[only_bind_into](argAp), ap, pragma[only_bind_into](config)) and if allowsFieldFlow = false then argAp instanceof ApNil else any() ) @@ -1639,12 +1630,13 @@ private module MkStage { pragma[nomagic] private predicate flowOutOfCallAp( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, boolean allowsFieldFlow, + DataFlowCall call, RetNodeEx ret, ReturnPosition pos, NodeEx out, boolean allowsFieldFlow, Ap ap, Configuration config ) { exists(ApApprox apa | - flowOutOfCallApa(call, ret, kind, out, allowsFieldFlow, apa, config) and - fwdFlow(ret, _, _, _, _, ap, apa, config) + flowOutOfCallApa(call, ret, _, out, allowsFieldFlow, apa, config) and + fwdFlow(ret, _, _, _, _, ap, apa, config) and + pos = ret.getReturnPosition() ) } @@ -1739,17 +1731,17 @@ private module MkStage { ) or // flow through a callable - exists(DataFlowCall call, ReturnKindExt returnKind0, Ap returnAp0 | - revFlowInToReturn(call, node, state, returnKind0, returnAp0, ap, config) and - revFlowIsReturned(call, returnCtx, returnAp, returnKind0, returnAp0, config) + exists(DataFlowCall call, ParamNodeEx p, ReturnPosition pos, Ap innerReturnAp | + revFlowThrough(call, returnCtx, p, state, pos, returnAp, ap, innerReturnAp, config) and + flowThroughIntoCall(call, node, p, _, ap, innerReturnAp, config) ) or // flow out of a callable - exists(ReturnKindExt kind | - revFlowOut(_, node, kind, state, _, _, ap, config) and - if returnFlowsThrough(node, kind, state, _, _, _, ap, config) + exists(ReturnPosition pos | + revFlowOut(_, node, pos, state, _, _, ap, config) and + if returnFlowsThrough(node, pos, state, _, _, _, ap, config) then ( - returnCtx = TReturnCtxMaybeFlowThrough(kind) and + returnCtx = TReturnCtxMaybeFlowThrough(pos) and returnAp = apSome(ap) ) else ( returnCtx = TReturnCtxNoFlowThrough() and returnAp = apNone() @@ -1782,47 +1774,33 @@ private module MkStage { pragma[nomagic] private predicate revFlowOut( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, FlowState state, ReturnCtx returnCtx, + DataFlowCall call, RetNodeEx ret, ReturnPosition pos, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap, Configuration config ) { exists(NodeEx out, boolean allowsFieldFlow | revFlow(out, state, returnCtx, returnAp, ap, config) and - flowOutOfCallAp(call, ret, kind, out, allowsFieldFlow, ap, config) and + flowOutOfCallAp(call, ret, pos, out, allowsFieldFlow, ap, config) and if allowsFieldFlow = false then ap instanceof ApNil else any() ) } - /** - * Same as `flowThroughIntoCall`, but restricted to calls that are reached - * in the flow covered by `revFlow`, where data might flow through the target - * callable and back out at `call`. - */ - pragma[nomagic] - private predicate revFlowThroughIntoCall( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap argAp, - Configuration config - ) { - flowThroughIntoCall(call, arg, p, allowsFieldFlow, argAp, config) and - revFlowIsReturned(call, _, _, _, _, config) - } - pragma[nomagic] private predicate revFlowParamToReturn( - ParamNodeEx p, FlowState state, ReturnKindExt kind, Ap returnAp, Ap ap, Configuration config + ParamNodeEx p, FlowState state, ReturnPosition pos, Ap returnAp, Ap ap, Configuration config ) { - revFlow(p, state, TReturnCtxMaybeFlowThrough(kind), apSome(returnAp), ap, config) and - parameterFlowThroughAllowed(p, kind) + revFlow(pragma[only_bind_into](p), state, TReturnCtxMaybeFlowThrough(pos), apSome(returnAp), + pragma[only_bind_into](ap), pragma[only_bind_into](config)) and + parameterFlowThroughAllowed(p, pos.getKind()) and + PrevStage::parameterMayFlowThrough(p, getApprox(ap), config) } pragma[nomagic] - private predicate revFlowInToReturn( - DataFlowCall call, ArgNodeEx arg, FlowState state, ReturnKindExt kind, Ap returnAp, Ap ap, - Configuration config + private predicate revFlowThrough( + DataFlowCall call, ReturnCtx returnCtx, ParamNodeEx p, FlowState state, ReturnPosition pos, + ApOption returnAp, Ap ap, Ap innerReturnAp, Configuration config ) { - exists(ParamNodeEx p, boolean allowsFieldFlow | - revFlowParamToReturn(p, state, kind, returnAp, ap, config) and - revFlowThroughIntoCall(call, arg, p, allowsFieldFlow, ap, config) - ) + revFlowParamToReturn(p, state, pos, innerReturnAp, ap, config) and + revFlowIsReturned(call, returnCtx, returnAp, pos, innerReturnAp, config) } /** @@ -1832,12 +1810,12 @@ private module MkStage { */ pragma[nomagic] private predicate revFlowIsReturned( - DataFlowCall call, ReturnCtx returnCtx, ApOption returnAp, ReturnKindExt kind, Ap ap, + DataFlowCall call, ReturnCtx returnCtx, ApOption returnAp, ReturnPosition pos, Ap ap, Configuration config ) { exists(RetNodeEx ret, FlowState state, CcCall ccc | - revFlowOut(call, ret, kind, state, returnCtx, returnAp, ap, config) and - returnFlowsThrough(ret, kind, state, ccc, _, _, ap, config) and + revFlowOut(call, ret, pos, state, returnCtx, returnAp, ap, config) and + returnFlowsThrough(ret, pos, state, ccc, _, _, ap, config) and matchesCall(ccc, call) ) } @@ -1915,17 +1893,17 @@ private module MkStage { pragma[nomagic] private predicate parameterFlowsThroughRev( - ParamNodeEx p, Ap ap, ReturnKindExt kind, Ap returnAp, Configuration config + ParamNodeEx p, Ap ap, ReturnPosition pos, Ap returnAp, Configuration config ) { - revFlow(p, _, TReturnCtxMaybeFlowThrough(kind), apSome(returnAp), ap, config) and - parameterFlowThroughAllowed(p, kind) + revFlow(p, _, TReturnCtxMaybeFlowThrough(pos), apSome(returnAp), ap, config) and + parameterFlowThroughAllowed(p, pos.getKind()) } pragma[nomagic] predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap, Configuration config) { - exists(RetNodeEx ret, ReturnKindExt kind | - returnFlowsThrough(ret, kind, _, _, p, ap, _, config) and - parameterFlowsThroughRev(p, ap, kind, _, config) + exists(RetNodeEx ret, ReturnPosition pos | + returnFlowsThrough(ret, pos, _, _, p, ap, _, config) and + parameterFlowsThroughRev(p, ap, pos, _, config) ) } @@ -1933,20 +1911,21 @@ private module MkStage { predicate returnMayFlowThrough( RetNodeEx ret, Ap argAp, Ap ap, ReturnKindExt kind, Configuration config ) { - exists(ParamNodeEx p | - returnFlowsThrough(ret, kind, _, _, p, argAp, ap, config) and - parameterFlowsThroughRev(p, argAp, kind, ap, config) + exists(ParamNodeEx p, ReturnPosition pos | + returnFlowsThrough(ret, pos, _, _, p, argAp, ap, config) and + parameterFlowsThroughRev(p, argAp, pos, ap, config) and + kind = pos.getKind() ) } pragma[nomagic] - predicate revFlowInToReturnIsReturned( + private predicate revFlowThroughArg( DataFlowCall call, ArgNodeEx arg, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap, Configuration config ) { - exists(ReturnKindExt returnKind0, Ap returnAp0 | - revFlowInToReturn(call, arg, state, returnKind0, returnAp0, ap, config) and - revFlowIsReturned(call, returnCtx, returnAp, returnKind0, returnAp0, config) + exists(ParamNodeEx p, ReturnPosition pos, Ap innerReturnAp | + revFlowThrough(call, returnCtx, p, state, pos, returnAp, ap, innerReturnAp, config) and + flowThroughIntoCall(call, arg, p, _, ap, innerReturnAp, config) ) } @@ -1954,7 +1933,7 @@ private module MkStage { predicate callMayFlowThroughRev(DataFlowCall call, Configuration config) { exists(ArgNodeEx arg, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap | revFlow(arg, state, returnCtx, returnAp, ap, config) and - revFlowInToReturnIsReturned(call, arg, state, returnCtx, returnAp, ap, config) + revFlowThroughArg(call, arg, state, returnCtx, returnAp, ap, config) ) } @@ -1967,8 +1946,9 @@ private module MkStage { conscand = count(TypedContent f0, Ap ap | fwdConsCand(f0, ap, config)) and states = count(FlowState state | fwdFlow(_, state, _, _, _, _, config)) and tuples = - count(NodeEx n, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - Ap ap | fwdFlow(n, state, cc, summaryCtx, argAp, ap, config)) + count(NodeEx n, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap | + fwdFlow(n, state, cc, summaryCtx, argAp, ap, config) + ) or fwd = false and nodes = count(NodeEx node | revFlow(node, _, _, _, _, config)) and @@ -2823,13 +2803,12 @@ private Configuration unbindConf(Configuration conf) { pragma[nomagic] private predicate nodeMayUseSummary0( - NodeEx n, DataFlowCallable c, ParameterPosition pos, FlowState state, AccessPathApprox apa, - Configuration config + NodeEx n, ParamNodeEx p, FlowState state, AccessPathApprox apa, Configuration config ) { exists(AccessPathApprox apa0 | - c = n.getEnclosingCallable() and + Stage5::parameterMayFlowThrough(p, _, _) and Stage5::revFlow(n, state, TReturnCtxMaybeFlowThrough(_), _, apa0, config) and - Stage5::fwdFlow(n, state, any(CallContextCall ccc), TParameterPositionSome(pos), + Stage5::fwdFlow(n, state, any(CallContextCall ccc), TParamNodeSome(p.asNode()), TAccessPathApproxSome(apa), apa0, config) ) } @@ -2838,10 +2817,9 @@ pragma[nomagic] private predicate nodeMayUseSummary( NodeEx n, FlowState state, AccessPathApprox apa, Configuration config ) { - exists(DataFlowCallable c, ParameterPosition pos, ParamNodeEx p | + exists(ParamNodeEx p | Stage5::parameterMayFlowThrough(p, apa, config) and - nodeMayUseSummary0(n, c, pos, state, apa, config) and - p.isParameterOf(c, pos) + nodeMayUseSummary0(n, p, state, apa, config) ) } diff --git a/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl2.qll b/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl2.qll index 6741ccc2f06..1228d00b6ba 100644 --- a/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl2.qll +++ b/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl2.qll @@ -622,7 +622,11 @@ private predicate parameterFlowThroughAllowed(ParamNodeEx p, ReturnKindExt kind) } private module Stage1 implements StageSig { - class Ap = Unit; + class Ap extends int { + // workaround for bad functionality-induced joins (happens when using `Unit`) + pragma[nomagic] + Ap() { this in [0 .. 1] and this < 1 } + } private class Cc = boolean; @@ -1327,8 +1331,8 @@ private module MkStage { */ pragma[nomagic] additional predicate fwdFlow( - NodeEx node, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - Ap ap, ApApprox apa, Configuration config + NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, + ApApprox apa, Configuration config ) { fwdFlow0(node, state, cc, summaryCtx, argAp, ap, apa, config) and PrevStage::revFlow(node, state, apa, config) and @@ -1337,21 +1341,21 @@ private module MkStage { pragma[inline] additional predicate fwdFlow( - NodeEx node, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - Ap ap, Configuration config + NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, + Configuration config ) { fwdFlow(node, state, cc, summaryCtx, argAp, ap, _, config) } pragma[nomagic] private predicate fwdFlow0( - NodeEx node, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - Ap ap, ApApprox apa, Configuration config + NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, + ApApprox apa, Configuration config ) { sourceNode(node, state, config) and (if hasSourceCallCtx(config) then cc = ccSomeCall() else cc = ccNone()) and argAp = apNone() and - summaryCtx = TParameterPositionNone() and + summaryCtx = TParamNodeNone() and ap = getApNil(node) and apa = getApprox(ap) or @@ -1372,7 +1376,7 @@ private module MkStage { fwdFlow(mid, pragma[only_bind_into](state), _, _, _, ap, apa, pragma[only_bind_into](config)) and jumpStep(mid, node, config) and cc = ccNone() and - summaryCtx = TParameterPositionNone() and + summaryCtx = TParamNodeNone() and argAp = apNone() ) or @@ -1380,7 +1384,7 @@ private module MkStage { fwdFlow(mid, state, _, _, _, nil, pragma[only_bind_into](config)) and additionalJumpStep(mid, node, config) and cc = ccNone() and - summaryCtx = TParameterPositionNone() and + summaryCtx = TParamNodeNone() and argAp = apNone() and ap = getApNil(node) and apa = getApprox(ap) @@ -1390,7 +1394,7 @@ private module MkStage { fwdFlow(mid, state0, _, _, _, nil, pragma[only_bind_into](config)) and additionalJumpStateStep(mid, state0, node, state, config) and cc = ccNone() and - summaryCtx = TParameterPositionNone() and + summaryCtx = TParamNodeNone() and argAp = apNone() and ap = getApNil(node) and apa = getApprox(ap) @@ -1414,10 +1418,10 @@ private module MkStage { fwdFlowIn(_, node, state, _, cc, _, _, ap, apa, config) and if PrevStage::parameterMayFlowThrough(node, apa, config) then ( - summaryCtx = TParameterPositionSome(node.(ParamNodeEx).getPosition()) and + summaryCtx = TParamNodeSome(node.asNode()) and argAp = apSome(ap) ) else ( - summaryCtx = TParameterPositionNone() and argAp = apNone() + summaryCtx = TParamNodeNone() and argAp = apNone() ) or // flow out of a callable @@ -1433,16 +1437,19 @@ private module MkStage { ) or // flow through a callable - exists(DataFlowCall call, ParameterPosition summaryCtx0, Ap argAp0 | - fwdFlowOutFromArg(call, node, state, summaryCtx0, argAp0, ap, apa, config) and - fwdFlowIsEntered(call, cc, summaryCtx, argAp, summaryCtx0, argAp0, config) + exists( + DataFlowCall call, CcCall ccc, RetNodeEx ret, boolean allowsFieldFlow, ApApprox innerArgApa + | + fwdFlowThrough(call, cc, state, ccc, summaryCtx, argAp, ap, apa, ret, innerArgApa, config) and + flowThroughOutOfCall(call, ccc, ret, node, allowsFieldFlow, innerArgApa, apa, config) and + if allowsFieldFlow = false then ap instanceof ApNil else any() ) } pragma[nomagic] private predicate fwdFlowStore( NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, FlowState state, Cc cc, - ParameterPositionOption summaryCtx, ApOption argAp, Configuration config + ParamNodeOption summaryCtx, ApOption argAp, Configuration config ) { exists(DataFlowType contentType, ApApprox apa1 | fwdFlow(node1, state, cc, summaryCtx, argAp, ap1, apa1, config) and @@ -1473,8 +1480,8 @@ private module MkStage { pragma[nomagic] private predicate fwdFlowRead0( - NodeEx node1, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - ApNonNil ap, Configuration config + NodeEx node1, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, ApNonNil ap, + Configuration config ) { fwdFlow(node1, state, cc, summaryCtx, argAp, ap, config) and PrevStage::readStepCand(node1, _, _, config) @@ -1483,7 +1490,7 @@ private module MkStage { pragma[nomagic] private predicate fwdFlowRead( Ap ap, Content c, NodeEx node1, NodeEx node2, FlowState state, Cc cc, - ParameterPositionOption summaryCtx, ApOption argAp, Configuration config + ParamNodeOption summaryCtx, ApOption argAp, Configuration config ) { fwdFlowRead0(node1, state, cc, summaryCtx, argAp, ap, config) and PrevStage::readStepCand(node1, c, node2, config) and @@ -1493,7 +1500,7 @@ private module MkStage { pragma[nomagic] private predicate fwdFlowIn( DataFlowCall call, ParamNodeEx p, FlowState state, Cc outercc, CcCall innercc, - ParameterPositionOption summaryCtx, ApOption argAp, Ap ap, ApApprox apa, Configuration config + ParamNodeOption summaryCtx, ApOption argAp, Ap ap, ApApprox apa, Configuration config ) { exists(ArgNodeEx arg, boolean allowsFieldFlow | fwdFlow(arg, state, outercc, summaryCtx, argAp, ap, apa, config) and @@ -1505,64 +1512,38 @@ private module MkStage { pragma[nomagic] private predicate fwdFlowRetFromArg( - RetNodeEx ret, FlowState state, CcCall ccc, ParameterPosition summaryCtx, ParamNodeEx p, - Ap argAp, ApApprox argApa, Ap ap, ApApprox apa, Configuration config + RetNodeEx ret, FlowState state, CcCall ccc, ParamNodeEx summaryCtx, Ap argAp, ApApprox argApa, + Ap ap, ApApprox apa, Configuration config ) { - exists(DataFlowCallable c, ReturnKindExt kind | + exists(ReturnKindExt kind | fwdFlow(pragma[only_bind_into](ret), state, ccc, - TParameterPositionSome(pragma[only_bind_into](summaryCtx)), apSome(argAp), ap, apa, config) and - getApprox(argAp) = argApa and - c = ret.getEnclosingCallable() and + TParamNodeSome(pragma[only_bind_into](summaryCtx.asNode())), + pragma[only_bind_into](apSome(argAp)), ap, pragma[only_bind_into](apa), + pragma[only_bind_into](config)) and kind = ret.getKind() and - p.isParameterOf(c, pragma[only_bind_into](summaryCtx)) and - parameterFlowThroughAllowed(p, kind) + parameterFlowThroughAllowed(summaryCtx, kind) and + argApa = getApprox(argAp) and + PrevStage::returnMayFlowThrough(ret, argApa, apa, kind, pragma[only_bind_into](config)) ) } pragma[inline] - private predicate fwdFlowInMayFlowThrough( - DataFlowCall call, Cc cc, CcCall innerCc, ParameterPositionOption summaryCtx, ApOption argAp, - ParamNodeEx param, Ap ap, ApApprox apa, Configuration config + private predicate fwdFlowThrough0( + DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, + ApOption argAp, Ap ap, ApApprox apa, RetNodeEx ret, ParamNodeEx innerSummaryCtx, + Ap innerArgAp, ApApprox innerArgApa, Configuration config ) { - fwdFlowIn(call, pragma[only_bind_into](param), _, cc, innerCc, summaryCtx, argAp, ap, - pragma[only_bind_into](apa), pragma[only_bind_into](config)) and - PrevStage::parameterMayFlowThrough(param, apa, config) - } - - // dedup before joining with `flowThroughOutOfCall` - pragma[nomagic] - private predicate fwdFlowInMayFlowThroughProj( - DataFlowCall call, CcCall innerCc, ApApprox apa, Configuration config - ) { - fwdFlowInMayFlowThrough(call, _, innerCc, _, _, _, _, apa, config) - } - - /** - * Same as `flowThroughOutOfCall`, but restricted to calls that are reached - * in the flow covered by `fwdFlow`, where data might flow through the target - * callable and back out at `call`. - */ - pragma[nomagic] - private predicate fwdFlowThroughOutOfCall( - DataFlowCall call, CcCall ccc, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow, - ApApprox argApa, ApApprox apa, Configuration config - ) { - fwdFlowInMayFlowThroughProj(call, ccc, argApa, config) and - flowThroughOutOfCall(call, ccc, ret, out, allowsFieldFlow, argApa, apa, config) + fwdFlowRetFromArg(ret, state, ccc, innerSummaryCtx, innerArgAp, innerArgApa, ap, apa, config) and + fwdFlowIsEntered(call, cc, ccc, summaryCtx, argAp, innerSummaryCtx, innerArgAp, config) } pragma[nomagic] - private predicate fwdFlowOutFromArg( - DataFlowCall call, NodeEx out, FlowState state, ParameterPosition summaryCtx, Ap argAp, Ap ap, - ApApprox apa, Configuration config + private predicate fwdFlowThrough( + DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, + ApOption argAp, Ap ap, ApApprox apa, RetNodeEx ret, ApApprox innerArgApa, Configuration config ) { - exists(RetNodeEx ret, boolean allowsFieldFlow, CcCall ccc, ApApprox argApa | - fwdFlowRetFromArg(pragma[only_bind_into](ret), state, pragma[only_bind_into](ccc), - summaryCtx, _, argAp, pragma[only_bind_into](argApa), ap, pragma[only_bind_into](apa), - config) and - fwdFlowThroughOutOfCall(call, ccc, ret, out, allowsFieldFlow, argApa, apa, config) and - (if allowsFieldFlow = false then ap instanceof ApNil else any()) - ) + fwdFlowThrough0(call, cc, state, ccc, summaryCtx, argAp, ap, apa, ret, _, _, innerArgApa, + config) } /** @@ -1571,12 +1552,14 @@ private module MkStage { */ pragma[nomagic] private predicate fwdFlowIsEntered( - DataFlowCall call, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - ParameterPosition pos, Ap ap, Configuration config + DataFlowCall call, Cc cc, CcCall innerCc, ParamNodeOption summaryCtx, ApOption argAp, + ParamNodeEx p, Ap ap, Configuration config ) { - exists(ParamNodeEx param | - fwdFlowInMayFlowThrough(call, cc, _, summaryCtx, argAp, param, ap, _, config) and - pos = param.getPosition() + exists(ApApprox apa | + fwdFlowIn(call, pragma[only_bind_into](p), _, cc, innerCc, summaryCtx, argAp, ap, + pragma[only_bind_into](apa), pragma[only_bind_into](config)) and + PrevStage::parameterMayFlowThrough(p, apa, config) and + PrevStage::callMayFlowThroughRev(call, pragma[only_bind_into](config)) ) } @@ -1596,23 +1579,31 @@ private module MkStage { fwdFlowConsCand(ap1, c, ap2, config) } + pragma[nomagic] + private predicate returnFlowsThrough0( + DataFlowCall call, FlowState state, CcCall ccc, Ap ap, ApApprox apa, RetNodeEx ret, + ParamNodeEx innerSummaryCtx, Ap innerArgAp, ApApprox innerArgApa, Configuration config + ) { + fwdFlowThrough0(call, _, state, ccc, _, _, ap, apa, ret, innerSummaryCtx, innerArgAp, + innerArgApa, config) + } + pragma[nomagic] private predicate returnFlowsThrough( - RetNodeEx ret, ReturnKindExt kind, FlowState state, CcCall ccc, ParamNodeEx p, Ap argAp, + RetNodeEx ret, ReturnPosition pos, FlowState state, CcCall ccc, ParamNodeEx p, Ap argAp, Ap ap, Configuration config ) { - exists(boolean allowsFieldFlow, ApApprox argApa, ApApprox apa | - fwdFlowRetFromArg(pragma[only_bind_into](ret), state, pragma[only_bind_into](ccc), _, p, - argAp, pragma[only_bind_into](argApa), ap, pragma[only_bind_into](apa), config) and - kind = ret.getKind() and - fwdFlowThroughOutOfCall(_, ccc, ret, _, allowsFieldFlow, argApa, apa, config) and - (if allowsFieldFlow = false then ap instanceof ApNil else any()) + exists(DataFlowCall call, ApApprox apa, boolean allowsFieldFlow, ApApprox innerArgApa | + returnFlowsThrough0(call, state, ccc, ap, apa, ret, p, argAp, innerArgApa, config) and + flowThroughOutOfCall(call, ccc, ret, _, allowsFieldFlow, innerArgApa, apa, config) and + pos = ret.getReturnPosition() and + if allowsFieldFlow = false then ap instanceof ApNil else any() ) } pragma[nomagic] private predicate flowThroughIntoCall( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap argAp, + DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap argAp, Ap ap, Configuration config ) { exists(ApApprox argApa | @@ -1620,7 +1611,7 @@ private module MkStage { allowsFieldFlow, argApa, pragma[only_bind_into](config)) and fwdFlow(arg, _, _, _, _, pragma[only_bind_into](argAp), argApa, pragma[only_bind_into](config)) and - returnFlowsThrough(_, _, _, _, p, pragma[only_bind_into](argAp), _, + returnFlowsThrough(_, _, _, _, p, pragma[only_bind_into](argAp), ap, pragma[only_bind_into](config)) and if allowsFieldFlow = false then argAp instanceof ApNil else any() ) @@ -1639,12 +1630,13 @@ private module MkStage { pragma[nomagic] private predicate flowOutOfCallAp( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, boolean allowsFieldFlow, + DataFlowCall call, RetNodeEx ret, ReturnPosition pos, NodeEx out, boolean allowsFieldFlow, Ap ap, Configuration config ) { exists(ApApprox apa | - flowOutOfCallApa(call, ret, kind, out, allowsFieldFlow, apa, config) and - fwdFlow(ret, _, _, _, _, ap, apa, config) + flowOutOfCallApa(call, ret, _, out, allowsFieldFlow, apa, config) and + fwdFlow(ret, _, _, _, _, ap, apa, config) and + pos = ret.getReturnPosition() ) } @@ -1739,17 +1731,17 @@ private module MkStage { ) or // flow through a callable - exists(DataFlowCall call, ReturnKindExt returnKind0, Ap returnAp0 | - revFlowInToReturn(call, node, state, returnKind0, returnAp0, ap, config) and - revFlowIsReturned(call, returnCtx, returnAp, returnKind0, returnAp0, config) + exists(DataFlowCall call, ParamNodeEx p, ReturnPosition pos, Ap innerReturnAp | + revFlowThrough(call, returnCtx, p, state, pos, returnAp, ap, innerReturnAp, config) and + flowThroughIntoCall(call, node, p, _, ap, innerReturnAp, config) ) or // flow out of a callable - exists(ReturnKindExt kind | - revFlowOut(_, node, kind, state, _, _, ap, config) and - if returnFlowsThrough(node, kind, state, _, _, _, ap, config) + exists(ReturnPosition pos | + revFlowOut(_, node, pos, state, _, _, ap, config) and + if returnFlowsThrough(node, pos, state, _, _, _, ap, config) then ( - returnCtx = TReturnCtxMaybeFlowThrough(kind) and + returnCtx = TReturnCtxMaybeFlowThrough(pos) and returnAp = apSome(ap) ) else ( returnCtx = TReturnCtxNoFlowThrough() and returnAp = apNone() @@ -1782,47 +1774,33 @@ private module MkStage { pragma[nomagic] private predicate revFlowOut( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, FlowState state, ReturnCtx returnCtx, + DataFlowCall call, RetNodeEx ret, ReturnPosition pos, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap, Configuration config ) { exists(NodeEx out, boolean allowsFieldFlow | revFlow(out, state, returnCtx, returnAp, ap, config) and - flowOutOfCallAp(call, ret, kind, out, allowsFieldFlow, ap, config) and + flowOutOfCallAp(call, ret, pos, out, allowsFieldFlow, ap, config) and if allowsFieldFlow = false then ap instanceof ApNil else any() ) } - /** - * Same as `flowThroughIntoCall`, but restricted to calls that are reached - * in the flow covered by `revFlow`, where data might flow through the target - * callable and back out at `call`. - */ - pragma[nomagic] - private predicate revFlowThroughIntoCall( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap argAp, - Configuration config - ) { - flowThroughIntoCall(call, arg, p, allowsFieldFlow, argAp, config) and - revFlowIsReturned(call, _, _, _, _, config) - } - pragma[nomagic] private predicate revFlowParamToReturn( - ParamNodeEx p, FlowState state, ReturnKindExt kind, Ap returnAp, Ap ap, Configuration config + ParamNodeEx p, FlowState state, ReturnPosition pos, Ap returnAp, Ap ap, Configuration config ) { - revFlow(p, state, TReturnCtxMaybeFlowThrough(kind), apSome(returnAp), ap, config) and - parameterFlowThroughAllowed(p, kind) + revFlow(pragma[only_bind_into](p), state, TReturnCtxMaybeFlowThrough(pos), apSome(returnAp), + pragma[only_bind_into](ap), pragma[only_bind_into](config)) and + parameterFlowThroughAllowed(p, pos.getKind()) and + PrevStage::parameterMayFlowThrough(p, getApprox(ap), config) } pragma[nomagic] - private predicate revFlowInToReturn( - DataFlowCall call, ArgNodeEx arg, FlowState state, ReturnKindExt kind, Ap returnAp, Ap ap, - Configuration config + private predicate revFlowThrough( + DataFlowCall call, ReturnCtx returnCtx, ParamNodeEx p, FlowState state, ReturnPosition pos, + ApOption returnAp, Ap ap, Ap innerReturnAp, Configuration config ) { - exists(ParamNodeEx p, boolean allowsFieldFlow | - revFlowParamToReturn(p, state, kind, returnAp, ap, config) and - revFlowThroughIntoCall(call, arg, p, allowsFieldFlow, ap, config) - ) + revFlowParamToReturn(p, state, pos, innerReturnAp, ap, config) and + revFlowIsReturned(call, returnCtx, returnAp, pos, innerReturnAp, config) } /** @@ -1832,12 +1810,12 @@ private module MkStage { */ pragma[nomagic] private predicate revFlowIsReturned( - DataFlowCall call, ReturnCtx returnCtx, ApOption returnAp, ReturnKindExt kind, Ap ap, + DataFlowCall call, ReturnCtx returnCtx, ApOption returnAp, ReturnPosition pos, Ap ap, Configuration config ) { exists(RetNodeEx ret, FlowState state, CcCall ccc | - revFlowOut(call, ret, kind, state, returnCtx, returnAp, ap, config) and - returnFlowsThrough(ret, kind, state, ccc, _, _, ap, config) and + revFlowOut(call, ret, pos, state, returnCtx, returnAp, ap, config) and + returnFlowsThrough(ret, pos, state, ccc, _, _, ap, config) and matchesCall(ccc, call) ) } @@ -1915,17 +1893,17 @@ private module MkStage { pragma[nomagic] private predicate parameterFlowsThroughRev( - ParamNodeEx p, Ap ap, ReturnKindExt kind, Ap returnAp, Configuration config + ParamNodeEx p, Ap ap, ReturnPosition pos, Ap returnAp, Configuration config ) { - revFlow(p, _, TReturnCtxMaybeFlowThrough(kind), apSome(returnAp), ap, config) and - parameterFlowThroughAllowed(p, kind) + revFlow(p, _, TReturnCtxMaybeFlowThrough(pos), apSome(returnAp), ap, config) and + parameterFlowThroughAllowed(p, pos.getKind()) } pragma[nomagic] predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap, Configuration config) { - exists(RetNodeEx ret, ReturnKindExt kind | - returnFlowsThrough(ret, kind, _, _, p, ap, _, config) and - parameterFlowsThroughRev(p, ap, kind, _, config) + exists(RetNodeEx ret, ReturnPosition pos | + returnFlowsThrough(ret, pos, _, _, p, ap, _, config) and + parameterFlowsThroughRev(p, ap, pos, _, config) ) } @@ -1933,20 +1911,21 @@ private module MkStage { predicate returnMayFlowThrough( RetNodeEx ret, Ap argAp, Ap ap, ReturnKindExt kind, Configuration config ) { - exists(ParamNodeEx p | - returnFlowsThrough(ret, kind, _, _, p, argAp, ap, config) and - parameterFlowsThroughRev(p, argAp, kind, ap, config) + exists(ParamNodeEx p, ReturnPosition pos | + returnFlowsThrough(ret, pos, _, _, p, argAp, ap, config) and + parameterFlowsThroughRev(p, argAp, pos, ap, config) and + kind = pos.getKind() ) } pragma[nomagic] - predicate revFlowInToReturnIsReturned( + private predicate revFlowThroughArg( DataFlowCall call, ArgNodeEx arg, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap, Configuration config ) { - exists(ReturnKindExt returnKind0, Ap returnAp0 | - revFlowInToReturn(call, arg, state, returnKind0, returnAp0, ap, config) and - revFlowIsReturned(call, returnCtx, returnAp, returnKind0, returnAp0, config) + exists(ParamNodeEx p, ReturnPosition pos, Ap innerReturnAp | + revFlowThrough(call, returnCtx, p, state, pos, returnAp, ap, innerReturnAp, config) and + flowThroughIntoCall(call, arg, p, _, ap, innerReturnAp, config) ) } @@ -1954,7 +1933,7 @@ private module MkStage { predicate callMayFlowThroughRev(DataFlowCall call, Configuration config) { exists(ArgNodeEx arg, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap | revFlow(arg, state, returnCtx, returnAp, ap, config) and - revFlowInToReturnIsReturned(call, arg, state, returnCtx, returnAp, ap, config) + revFlowThroughArg(call, arg, state, returnCtx, returnAp, ap, config) ) } @@ -1967,8 +1946,9 @@ private module MkStage { conscand = count(TypedContent f0, Ap ap | fwdConsCand(f0, ap, config)) and states = count(FlowState state | fwdFlow(_, state, _, _, _, _, config)) and tuples = - count(NodeEx n, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - Ap ap | fwdFlow(n, state, cc, summaryCtx, argAp, ap, config)) + count(NodeEx n, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap | + fwdFlow(n, state, cc, summaryCtx, argAp, ap, config) + ) or fwd = false and nodes = count(NodeEx node | revFlow(node, _, _, _, _, config)) and @@ -2823,13 +2803,12 @@ private Configuration unbindConf(Configuration conf) { pragma[nomagic] private predicate nodeMayUseSummary0( - NodeEx n, DataFlowCallable c, ParameterPosition pos, FlowState state, AccessPathApprox apa, - Configuration config + NodeEx n, ParamNodeEx p, FlowState state, AccessPathApprox apa, Configuration config ) { exists(AccessPathApprox apa0 | - c = n.getEnclosingCallable() and + Stage5::parameterMayFlowThrough(p, _, _) and Stage5::revFlow(n, state, TReturnCtxMaybeFlowThrough(_), _, apa0, config) and - Stage5::fwdFlow(n, state, any(CallContextCall ccc), TParameterPositionSome(pos), + Stage5::fwdFlow(n, state, any(CallContextCall ccc), TParamNodeSome(p.asNode()), TAccessPathApproxSome(apa), apa0, config) ) } @@ -2838,10 +2817,9 @@ pragma[nomagic] private predicate nodeMayUseSummary( NodeEx n, FlowState state, AccessPathApprox apa, Configuration config ) { - exists(DataFlowCallable c, ParameterPosition pos, ParamNodeEx p | + exists(ParamNodeEx p | Stage5::parameterMayFlowThrough(p, apa, config) and - nodeMayUseSummary0(n, c, pos, state, apa, config) and - p.isParameterOf(c, pos) + nodeMayUseSummary0(n, p, state, apa, config) ) } diff --git a/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl3.qll b/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl3.qll index 6741ccc2f06..1228d00b6ba 100644 --- a/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl3.qll +++ b/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl3.qll @@ -622,7 +622,11 @@ private predicate parameterFlowThroughAllowed(ParamNodeEx p, ReturnKindExt kind) } private module Stage1 implements StageSig { - class Ap = Unit; + class Ap extends int { + // workaround for bad functionality-induced joins (happens when using `Unit`) + pragma[nomagic] + Ap() { this in [0 .. 1] and this < 1 } + } private class Cc = boolean; @@ -1327,8 +1331,8 @@ private module MkStage { */ pragma[nomagic] additional predicate fwdFlow( - NodeEx node, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - Ap ap, ApApprox apa, Configuration config + NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, + ApApprox apa, Configuration config ) { fwdFlow0(node, state, cc, summaryCtx, argAp, ap, apa, config) and PrevStage::revFlow(node, state, apa, config) and @@ -1337,21 +1341,21 @@ private module MkStage { pragma[inline] additional predicate fwdFlow( - NodeEx node, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - Ap ap, Configuration config + NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, + Configuration config ) { fwdFlow(node, state, cc, summaryCtx, argAp, ap, _, config) } pragma[nomagic] private predicate fwdFlow0( - NodeEx node, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - Ap ap, ApApprox apa, Configuration config + NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, + ApApprox apa, Configuration config ) { sourceNode(node, state, config) and (if hasSourceCallCtx(config) then cc = ccSomeCall() else cc = ccNone()) and argAp = apNone() and - summaryCtx = TParameterPositionNone() and + summaryCtx = TParamNodeNone() and ap = getApNil(node) and apa = getApprox(ap) or @@ -1372,7 +1376,7 @@ private module MkStage { fwdFlow(mid, pragma[only_bind_into](state), _, _, _, ap, apa, pragma[only_bind_into](config)) and jumpStep(mid, node, config) and cc = ccNone() and - summaryCtx = TParameterPositionNone() and + summaryCtx = TParamNodeNone() and argAp = apNone() ) or @@ -1380,7 +1384,7 @@ private module MkStage { fwdFlow(mid, state, _, _, _, nil, pragma[only_bind_into](config)) and additionalJumpStep(mid, node, config) and cc = ccNone() and - summaryCtx = TParameterPositionNone() and + summaryCtx = TParamNodeNone() and argAp = apNone() and ap = getApNil(node) and apa = getApprox(ap) @@ -1390,7 +1394,7 @@ private module MkStage { fwdFlow(mid, state0, _, _, _, nil, pragma[only_bind_into](config)) and additionalJumpStateStep(mid, state0, node, state, config) and cc = ccNone() and - summaryCtx = TParameterPositionNone() and + summaryCtx = TParamNodeNone() and argAp = apNone() and ap = getApNil(node) and apa = getApprox(ap) @@ -1414,10 +1418,10 @@ private module MkStage { fwdFlowIn(_, node, state, _, cc, _, _, ap, apa, config) and if PrevStage::parameterMayFlowThrough(node, apa, config) then ( - summaryCtx = TParameterPositionSome(node.(ParamNodeEx).getPosition()) and + summaryCtx = TParamNodeSome(node.asNode()) and argAp = apSome(ap) ) else ( - summaryCtx = TParameterPositionNone() and argAp = apNone() + summaryCtx = TParamNodeNone() and argAp = apNone() ) or // flow out of a callable @@ -1433,16 +1437,19 @@ private module MkStage { ) or // flow through a callable - exists(DataFlowCall call, ParameterPosition summaryCtx0, Ap argAp0 | - fwdFlowOutFromArg(call, node, state, summaryCtx0, argAp0, ap, apa, config) and - fwdFlowIsEntered(call, cc, summaryCtx, argAp, summaryCtx0, argAp0, config) + exists( + DataFlowCall call, CcCall ccc, RetNodeEx ret, boolean allowsFieldFlow, ApApprox innerArgApa + | + fwdFlowThrough(call, cc, state, ccc, summaryCtx, argAp, ap, apa, ret, innerArgApa, config) and + flowThroughOutOfCall(call, ccc, ret, node, allowsFieldFlow, innerArgApa, apa, config) and + if allowsFieldFlow = false then ap instanceof ApNil else any() ) } pragma[nomagic] private predicate fwdFlowStore( NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, FlowState state, Cc cc, - ParameterPositionOption summaryCtx, ApOption argAp, Configuration config + ParamNodeOption summaryCtx, ApOption argAp, Configuration config ) { exists(DataFlowType contentType, ApApprox apa1 | fwdFlow(node1, state, cc, summaryCtx, argAp, ap1, apa1, config) and @@ -1473,8 +1480,8 @@ private module MkStage { pragma[nomagic] private predicate fwdFlowRead0( - NodeEx node1, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - ApNonNil ap, Configuration config + NodeEx node1, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, ApNonNil ap, + Configuration config ) { fwdFlow(node1, state, cc, summaryCtx, argAp, ap, config) and PrevStage::readStepCand(node1, _, _, config) @@ -1483,7 +1490,7 @@ private module MkStage { pragma[nomagic] private predicate fwdFlowRead( Ap ap, Content c, NodeEx node1, NodeEx node2, FlowState state, Cc cc, - ParameterPositionOption summaryCtx, ApOption argAp, Configuration config + ParamNodeOption summaryCtx, ApOption argAp, Configuration config ) { fwdFlowRead0(node1, state, cc, summaryCtx, argAp, ap, config) and PrevStage::readStepCand(node1, c, node2, config) and @@ -1493,7 +1500,7 @@ private module MkStage { pragma[nomagic] private predicate fwdFlowIn( DataFlowCall call, ParamNodeEx p, FlowState state, Cc outercc, CcCall innercc, - ParameterPositionOption summaryCtx, ApOption argAp, Ap ap, ApApprox apa, Configuration config + ParamNodeOption summaryCtx, ApOption argAp, Ap ap, ApApprox apa, Configuration config ) { exists(ArgNodeEx arg, boolean allowsFieldFlow | fwdFlow(arg, state, outercc, summaryCtx, argAp, ap, apa, config) and @@ -1505,64 +1512,38 @@ private module MkStage { pragma[nomagic] private predicate fwdFlowRetFromArg( - RetNodeEx ret, FlowState state, CcCall ccc, ParameterPosition summaryCtx, ParamNodeEx p, - Ap argAp, ApApprox argApa, Ap ap, ApApprox apa, Configuration config + RetNodeEx ret, FlowState state, CcCall ccc, ParamNodeEx summaryCtx, Ap argAp, ApApprox argApa, + Ap ap, ApApprox apa, Configuration config ) { - exists(DataFlowCallable c, ReturnKindExt kind | + exists(ReturnKindExt kind | fwdFlow(pragma[only_bind_into](ret), state, ccc, - TParameterPositionSome(pragma[only_bind_into](summaryCtx)), apSome(argAp), ap, apa, config) and - getApprox(argAp) = argApa and - c = ret.getEnclosingCallable() and + TParamNodeSome(pragma[only_bind_into](summaryCtx.asNode())), + pragma[only_bind_into](apSome(argAp)), ap, pragma[only_bind_into](apa), + pragma[only_bind_into](config)) and kind = ret.getKind() and - p.isParameterOf(c, pragma[only_bind_into](summaryCtx)) and - parameterFlowThroughAllowed(p, kind) + parameterFlowThroughAllowed(summaryCtx, kind) and + argApa = getApprox(argAp) and + PrevStage::returnMayFlowThrough(ret, argApa, apa, kind, pragma[only_bind_into](config)) ) } pragma[inline] - private predicate fwdFlowInMayFlowThrough( - DataFlowCall call, Cc cc, CcCall innerCc, ParameterPositionOption summaryCtx, ApOption argAp, - ParamNodeEx param, Ap ap, ApApprox apa, Configuration config + private predicate fwdFlowThrough0( + DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, + ApOption argAp, Ap ap, ApApprox apa, RetNodeEx ret, ParamNodeEx innerSummaryCtx, + Ap innerArgAp, ApApprox innerArgApa, Configuration config ) { - fwdFlowIn(call, pragma[only_bind_into](param), _, cc, innerCc, summaryCtx, argAp, ap, - pragma[only_bind_into](apa), pragma[only_bind_into](config)) and - PrevStage::parameterMayFlowThrough(param, apa, config) - } - - // dedup before joining with `flowThroughOutOfCall` - pragma[nomagic] - private predicate fwdFlowInMayFlowThroughProj( - DataFlowCall call, CcCall innerCc, ApApprox apa, Configuration config - ) { - fwdFlowInMayFlowThrough(call, _, innerCc, _, _, _, _, apa, config) - } - - /** - * Same as `flowThroughOutOfCall`, but restricted to calls that are reached - * in the flow covered by `fwdFlow`, where data might flow through the target - * callable and back out at `call`. - */ - pragma[nomagic] - private predicate fwdFlowThroughOutOfCall( - DataFlowCall call, CcCall ccc, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow, - ApApprox argApa, ApApprox apa, Configuration config - ) { - fwdFlowInMayFlowThroughProj(call, ccc, argApa, config) and - flowThroughOutOfCall(call, ccc, ret, out, allowsFieldFlow, argApa, apa, config) + fwdFlowRetFromArg(ret, state, ccc, innerSummaryCtx, innerArgAp, innerArgApa, ap, apa, config) and + fwdFlowIsEntered(call, cc, ccc, summaryCtx, argAp, innerSummaryCtx, innerArgAp, config) } pragma[nomagic] - private predicate fwdFlowOutFromArg( - DataFlowCall call, NodeEx out, FlowState state, ParameterPosition summaryCtx, Ap argAp, Ap ap, - ApApprox apa, Configuration config + private predicate fwdFlowThrough( + DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, + ApOption argAp, Ap ap, ApApprox apa, RetNodeEx ret, ApApprox innerArgApa, Configuration config ) { - exists(RetNodeEx ret, boolean allowsFieldFlow, CcCall ccc, ApApprox argApa | - fwdFlowRetFromArg(pragma[only_bind_into](ret), state, pragma[only_bind_into](ccc), - summaryCtx, _, argAp, pragma[only_bind_into](argApa), ap, pragma[only_bind_into](apa), - config) and - fwdFlowThroughOutOfCall(call, ccc, ret, out, allowsFieldFlow, argApa, apa, config) and - (if allowsFieldFlow = false then ap instanceof ApNil else any()) - ) + fwdFlowThrough0(call, cc, state, ccc, summaryCtx, argAp, ap, apa, ret, _, _, innerArgApa, + config) } /** @@ -1571,12 +1552,14 @@ private module MkStage { */ pragma[nomagic] private predicate fwdFlowIsEntered( - DataFlowCall call, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - ParameterPosition pos, Ap ap, Configuration config + DataFlowCall call, Cc cc, CcCall innerCc, ParamNodeOption summaryCtx, ApOption argAp, + ParamNodeEx p, Ap ap, Configuration config ) { - exists(ParamNodeEx param | - fwdFlowInMayFlowThrough(call, cc, _, summaryCtx, argAp, param, ap, _, config) and - pos = param.getPosition() + exists(ApApprox apa | + fwdFlowIn(call, pragma[only_bind_into](p), _, cc, innerCc, summaryCtx, argAp, ap, + pragma[only_bind_into](apa), pragma[only_bind_into](config)) and + PrevStage::parameterMayFlowThrough(p, apa, config) and + PrevStage::callMayFlowThroughRev(call, pragma[only_bind_into](config)) ) } @@ -1596,23 +1579,31 @@ private module MkStage { fwdFlowConsCand(ap1, c, ap2, config) } + pragma[nomagic] + private predicate returnFlowsThrough0( + DataFlowCall call, FlowState state, CcCall ccc, Ap ap, ApApprox apa, RetNodeEx ret, + ParamNodeEx innerSummaryCtx, Ap innerArgAp, ApApprox innerArgApa, Configuration config + ) { + fwdFlowThrough0(call, _, state, ccc, _, _, ap, apa, ret, innerSummaryCtx, innerArgAp, + innerArgApa, config) + } + pragma[nomagic] private predicate returnFlowsThrough( - RetNodeEx ret, ReturnKindExt kind, FlowState state, CcCall ccc, ParamNodeEx p, Ap argAp, + RetNodeEx ret, ReturnPosition pos, FlowState state, CcCall ccc, ParamNodeEx p, Ap argAp, Ap ap, Configuration config ) { - exists(boolean allowsFieldFlow, ApApprox argApa, ApApprox apa | - fwdFlowRetFromArg(pragma[only_bind_into](ret), state, pragma[only_bind_into](ccc), _, p, - argAp, pragma[only_bind_into](argApa), ap, pragma[only_bind_into](apa), config) and - kind = ret.getKind() and - fwdFlowThroughOutOfCall(_, ccc, ret, _, allowsFieldFlow, argApa, apa, config) and - (if allowsFieldFlow = false then ap instanceof ApNil else any()) + exists(DataFlowCall call, ApApprox apa, boolean allowsFieldFlow, ApApprox innerArgApa | + returnFlowsThrough0(call, state, ccc, ap, apa, ret, p, argAp, innerArgApa, config) and + flowThroughOutOfCall(call, ccc, ret, _, allowsFieldFlow, innerArgApa, apa, config) and + pos = ret.getReturnPosition() and + if allowsFieldFlow = false then ap instanceof ApNil else any() ) } pragma[nomagic] private predicate flowThroughIntoCall( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap argAp, + DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap argAp, Ap ap, Configuration config ) { exists(ApApprox argApa | @@ -1620,7 +1611,7 @@ private module MkStage { allowsFieldFlow, argApa, pragma[only_bind_into](config)) and fwdFlow(arg, _, _, _, _, pragma[only_bind_into](argAp), argApa, pragma[only_bind_into](config)) and - returnFlowsThrough(_, _, _, _, p, pragma[only_bind_into](argAp), _, + returnFlowsThrough(_, _, _, _, p, pragma[only_bind_into](argAp), ap, pragma[only_bind_into](config)) and if allowsFieldFlow = false then argAp instanceof ApNil else any() ) @@ -1639,12 +1630,13 @@ private module MkStage { pragma[nomagic] private predicate flowOutOfCallAp( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, boolean allowsFieldFlow, + DataFlowCall call, RetNodeEx ret, ReturnPosition pos, NodeEx out, boolean allowsFieldFlow, Ap ap, Configuration config ) { exists(ApApprox apa | - flowOutOfCallApa(call, ret, kind, out, allowsFieldFlow, apa, config) and - fwdFlow(ret, _, _, _, _, ap, apa, config) + flowOutOfCallApa(call, ret, _, out, allowsFieldFlow, apa, config) and + fwdFlow(ret, _, _, _, _, ap, apa, config) and + pos = ret.getReturnPosition() ) } @@ -1739,17 +1731,17 @@ private module MkStage { ) or // flow through a callable - exists(DataFlowCall call, ReturnKindExt returnKind0, Ap returnAp0 | - revFlowInToReturn(call, node, state, returnKind0, returnAp0, ap, config) and - revFlowIsReturned(call, returnCtx, returnAp, returnKind0, returnAp0, config) + exists(DataFlowCall call, ParamNodeEx p, ReturnPosition pos, Ap innerReturnAp | + revFlowThrough(call, returnCtx, p, state, pos, returnAp, ap, innerReturnAp, config) and + flowThroughIntoCall(call, node, p, _, ap, innerReturnAp, config) ) or // flow out of a callable - exists(ReturnKindExt kind | - revFlowOut(_, node, kind, state, _, _, ap, config) and - if returnFlowsThrough(node, kind, state, _, _, _, ap, config) + exists(ReturnPosition pos | + revFlowOut(_, node, pos, state, _, _, ap, config) and + if returnFlowsThrough(node, pos, state, _, _, _, ap, config) then ( - returnCtx = TReturnCtxMaybeFlowThrough(kind) and + returnCtx = TReturnCtxMaybeFlowThrough(pos) and returnAp = apSome(ap) ) else ( returnCtx = TReturnCtxNoFlowThrough() and returnAp = apNone() @@ -1782,47 +1774,33 @@ private module MkStage { pragma[nomagic] private predicate revFlowOut( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, FlowState state, ReturnCtx returnCtx, + DataFlowCall call, RetNodeEx ret, ReturnPosition pos, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap, Configuration config ) { exists(NodeEx out, boolean allowsFieldFlow | revFlow(out, state, returnCtx, returnAp, ap, config) and - flowOutOfCallAp(call, ret, kind, out, allowsFieldFlow, ap, config) and + flowOutOfCallAp(call, ret, pos, out, allowsFieldFlow, ap, config) and if allowsFieldFlow = false then ap instanceof ApNil else any() ) } - /** - * Same as `flowThroughIntoCall`, but restricted to calls that are reached - * in the flow covered by `revFlow`, where data might flow through the target - * callable and back out at `call`. - */ - pragma[nomagic] - private predicate revFlowThroughIntoCall( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap argAp, - Configuration config - ) { - flowThroughIntoCall(call, arg, p, allowsFieldFlow, argAp, config) and - revFlowIsReturned(call, _, _, _, _, config) - } - pragma[nomagic] private predicate revFlowParamToReturn( - ParamNodeEx p, FlowState state, ReturnKindExt kind, Ap returnAp, Ap ap, Configuration config + ParamNodeEx p, FlowState state, ReturnPosition pos, Ap returnAp, Ap ap, Configuration config ) { - revFlow(p, state, TReturnCtxMaybeFlowThrough(kind), apSome(returnAp), ap, config) and - parameterFlowThroughAllowed(p, kind) + revFlow(pragma[only_bind_into](p), state, TReturnCtxMaybeFlowThrough(pos), apSome(returnAp), + pragma[only_bind_into](ap), pragma[only_bind_into](config)) and + parameterFlowThroughAllowed(p, pos.getKind()) and + PrevStage::parameterMayFlowThrough(p, getApprox(ap), config) } pragma[nomagic] - private predicate revFlowInToReturn( - DataFlowCall call, ArgNodeEx arg, FlowState state, ReturnKindExt kind, Ap returnAp, Ap ap, - Configuration config + private predicate revFlowThrough( + DataFlowCall call, ReturnCtx returnCtx, ParamNodeEx p, FlowState state, ReturnPosition pos, + ApOption returnAp, Ap ap, Ap innerReturnAp, Configuration config ) { - exists(ParamNodeEx p, boolean allowsFieldFlow | - revFlowParamToReturn(p, state, kind, returnAp, ap, config) and - revFlowThroughIntoCall(call, arg, p, allowsFieldFlow, ap, config) - ) + revFlowParamToReturn(p, state, pos, innerReturnAp, ap, config) and + revFlowIsReturned(call, returnCtx, returnAp, pos, innerReturnAp, config) } /** @@ -1832,12 +1810,12 @@ private module MkStage { */ pragma[nomagic] private predicate revFlowIsReturned( - DataFlowCall call, ReturnCtx returnCtx, ApOption returnAp, ReturnKindExt kind, Ap ap, + DataFlowCall call, ReturnCtx returnCtx, ApOption returnAp, ReturnPosition pos, Ap ap, Configuration config ) { exists(RetNodeEx ret, FlowState state, CcCall ccc | - revFlowOut(call, ret, kind, state, returnCtx, returnAp, ap, config) and - returnFlowsThrough(ret, kind, state, ccc, _, _, ap, config) and + revFlowOut(call, ret, pos, state, returnCtx, returnAp, ap, config) and + returnFlowsThrough(ret, pos, state, ccc, _, _, ap, config) and matchesCall(ccc, call) ) } @@ -1915,17 +1893,17 @@ private module MkStage { pragma[nomagic] private predicate parameterFlowsThroughRev( - ParamNodeEx p, Ap ap, ReturnKindExt kind, Ap returnAp, Configuration config + ParamNodeEx p, Ap ap, ReturnPosition pos, Ap returnAp, Configuration config ) { - revFlow(p, _, TReturnCtxMaybeFlowThrough(kind), apSome(returnAp), ap, config) and - parameterFlowThroughAllowed(p, kind) + revFlow(p, _, TReturnCtxMaybeFlowThrough(pos), apSome(returnAp), ap, config) and + parameterFlowThroughAllowed(p, pos.getKind()) } pragma[nomagic] predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap, Configuration config) { - exists(RetNodeEx ret, ReturnKindExt kind | - returnFlowsThrough(ret, kind, _, _, p, ap, _, config) and - parameterFlowsThroughRev(p, ap, kind, _, config) + exists(RetNodeEx ret, ReturnPosition pos | + returnFlowsThrough(ret, pos, _, _, p, ap, _, config) and + parameterFlowsThroughRev(p, ap, pos, _, config) ) } @@ -1933,20 +1911,21 @@ private module MkStage { predicate returnMayFlowThrough( RetNodeEx ret, Ap argAp, Ap ap, ReturnKindExt kind, Configuration config ) { - exists(ParamNodeEx p | - returnFlowsThrough(ret, kind, _, _, p, argAp, ap, config) and - parameterFlowsThroughRev(p, argAp, kind, ap, config) + exists(ParamNodeEx p, ReturnPosition pos | + returnFlowsThrough(ret, pos, _, _, p, argAp, ap, config) and + parameterFlowsThroughRev(p, argAp, pos, ap, config) and + kind = pos.getKind() ) } pragma[nomagic] - predicate revFlowInToReturnIsReturned( + private predicate revFlowThroughArg( DataFlowCall call, ArgNodeEx arg, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap, Configuration config ) { - exists(ReturnKindExt returnKind0, Ap returnAp0 | - revFlowInToReturn(call, arg, state, returnKind0, returnAp0, ap, config) and - revFlowIsReturned(call, returnCtx, returnAp, returnKind0, returnAp0, config) + exists(ParamNodeEx p, ReturnPosition pos, Ap innerReturnAp | + revFlowThrough(call, returnCtx, p, state, pos, returnAp, ap, innerReturnAp, config) and + flowThroughIntoCall(call, arg, p, _, ap, innerReturnAp, config) ) } @@ -1954,7 +1933,7 @@ private module MkStage { predicate callMayFlowThroughRev(DataFlowCall call, Configuration config) { exists(ArgNodeEx arg, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap | revFlow(arg, state, returnCtx, returnAp, ap, config) and - revFlowInToReturnIsReturned(call, arg, state, returnCtx, returnAp, ap, config) + revFlowThroughArg(call, arg, state, returnCtx, returnAp, ap, config) ) } @@ -1967,8 +1946,9 @@ private module MkStage { conscand = count(TypedContent f0, Ap ap | fwdConsCand(f0, ap, config)) and states = count(FlowState state | fwdFlow(_, state, _, _, _, _, config)) and tuples = - count(NodeEx n, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - Ap ap | fwdFlow(n, state, cc, summaryCtx, argAp, ap, config)) + count(NodeEx n, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap | + fwdFlow(n, state, cc, summaryCtx, argAp, ap, config) + ) or fwd = false and nodes = count(NodeEx node | revFlow(node, _, _, _, _, config)) and @@ -2823,13 +2803,12 @@ private Configuration unbindConf(Configuration conf) { pragma[nomagic] private predicate nodeMayUseSummary0( - NodeEx n, DataFlowCallable c, ParameterPosition pos, FlowState state, AccessPathApprox apa, - Configuration config + NodeEx n, ParamNodeEx p, FlowState state, AccessPathApprox apa, Configuration config ) { exists(AccessPathApprox apa0 | - c = n.getEnclosingCallable() and + Stage5::parameterMayFlowThrough(p, _, _) and Stage5::revFlow(n, state, TReturnCtxMaybeFlowThrough(_), _, apa0, config) and - Stage5::fwdFlow(n, state, any(CallContextCall ccc), TParameterPositionSome(pos), + Stage5::fwdFlow(n, state, any(CallContextCall ccc), TParamNodeSome(p.asNode()), TAccessPathApproxSome(apa), apa0, config) ) } @@ -2838,10 +2817,9 @@ pragma[nomagic] private predicate nodeMayUseSummary( NodeEx n, FlowState state, AccessPathApprox apa, Configuration config ) { - exists(DataFlowCallable c, ParameterPosition pos, ParamNodeEx p | + exists(ParamNodeEx p | Stage5::parameterMayFlowThrough(p, apa, config) and - nodeMayUseSummary0(n, c, pos, state, apa, config) and - p.isParameterOf(c, pos) + nodeMayUseSummary0(n, p, state, apa, config) ) } diff --git a/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl4.qll b/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl4.qll index 6741ccc2f06..1228d00b6ba 100644 --- a/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl4.qll +++ b/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl4.qll @@ -622,7 +622,11 @@ private predicate parameterFlowThroughAllowed(ParamNodeEx p, ReturnKindExt kind) } private module Stage1 implements StageSig { - class Ap = Unit; + class Ap extends int { + // workaround for bad functionality-induced joins (happens when using `Unit`) + pragma[nomagic] + Ap() { this in [0 .. 1] and this < 1 } + } private class Cc = boolean; @@ -1327,8 +1331,8 @@ private module MkStage { */ pragma[nomagic] additional predicate fwdFlow( - NodeEx node, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - Ap ap, ApApprox apa, Configuration config + NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, + ApApprox apa, Configuration config ) { fwdFlow0(node, state, cc, summaryCtx, argAp, ap, apa, config) and PrevStage::revFlow(node, state, apa, config) and @@ -1337,21 +1341,21 @@ private module MkStage { pragma[inline] additional predicate fwdFlow( - NodeEx node, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - Ap ap, Configuration config + NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, + Configuration config ) { fwdFlow(node, state, cc, summaryCtx, argAp, ap, _, config) } pragma[nomagic] private predicate fwdFlow0( - NodeEx node, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - Ap ap, ApApprox apa, Configuration config + NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, + ApApprox apa, Configuration config ) { sourceNode(node, state, config) and (if hasSourceCallCtx(config) then cc = ccSomeCall() else cc = ccNone()) and argAp = apNone() and - summaryCtx = TParameterPositionNone() and + summaryCtx = TParamNodeNone() and ap = getApNil(node) and apa = getApprox(ap) or @@ -1372,7 +1376,7 @@ private module MkStage { fwdFlow(mid, pragma[only_bind_into](state), _, _, _, ap, apa, pragma[only_bind_into](config)) and jumpStep(mid, node, config) and cc = ccNone() and - summaryCtx = TParameterPositionNone() and + summaryCtx = TParamNodeNone() and argAp = apNone() ) or @@ -1380,7 +1384,7 @@ private module MkStage { fwdFlow(mid, state, _, _, _, nil, pragma[only_bind_into](config)) and additionalJumpStep(mid, node, config) and cc = ccNone() and - summaryCtx = TParameterPositionNone() and + summaryCtx = TParamNodeNone() and argAp = apNone() and ap = getApNil(node) and apa = getApprox(ap) @@ -1390,7 +1394,7 @@ private module MkStage { fwdFlow(mid, state0, _, _, _, nil, pragma[only_bind_into](config)) and additionalJumpStateStep(mid, state0, node, state, config) and cc = ccNone() and - summaryCtx = TParameterPositionNone() and + summaryCtx = TParamNodeNone() and argAp = apNone() and ap = getApNil(node) and apa = getApprox(ap) @@ -1414,10 +1418,10 @@ private module MkStage { fwdFlowIn(_, node, state, _, cc, _, _, ap, apa, config) and if PrevStage::parameterMayFlowThrough(node, apa, config) then ( - summaryCtx = TParameterPositionSome(node.(ParamNodeEx).getPosition()) and + summaryCtx = TParamNodeSome(node.asNode()) and argAp = apSome(ap) ) else ( - summaryCtx = TParameterPositionNone() and argAp = apNone() + summaryCtx = TParamNodeNone() and argAp = apNone() ) or // flow out of a callable @@ -1433,16 +1437,19 @@ private module MkStage { ) or // flow through a callable - exists(DataFlowCall call, ParameterPosition summaryCtx0, Ap argAp0 | - fwdFlowOutFromArg(call, node, state, summaryCtx0, argAp0, ap, apa, config) and - fwdFlowIsEntered(call, cc, summaryCtx, argAp, summaryCtx0, argAp0, config) + exists( + DataFlowCall call, CcCall ccc, RetNodeEx ret, boolean allowsFieldFlow, ApApprox innerArgApa + | + fwdFlowThrough(call, cc, state, ccc, summaryCtx, argAp, ap, apa, ret, innerArgApa, config) and + flowThroughOutOfCall(call, ccc, ret, node, allowsFieldFlow, innerArgApa, apa, config) and + if allowsFieldFlow = false then ap instanceof ApNil else any() ) } pragma[nomagic] private predicate fwdFlowStore( NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, FlowState state, Cc cc, - ParameterPositionOption summaryCtx, ApOption argAp, Configuration config + ParamNodeOption summaryCtx, ApOption argAp, Configuration config ) { exists(DataFlowType contentType, ApApprox apa1 | fwdFlow(node1, state, cc, summaryCtx, argAp, ap1, apa1, config) and @@ -1473,8 +1480,8 @@ private module MkStage { pragma[nomagic] private predicate fwdFlowRead0( - NodeEx node1, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - ApNonNil ap, Configuration config + NodeEx node1, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, ApNonNil ap, + Configuration config ) { fwdFlow(node1, state, cc, summaryCtx, argAp, ap, config) and PrevStage::readStepCand(node1, _, _, config) @@ -1483,7 +1490,7 @@ private module MkStage { pragma[nomagic] private predicate fwdFlowRead( Ap ap, Content c, NodeEx node1, NodeEx node2, FlowState state, Cc cc, - ParameterPositionOption summaryCtx, ApOption argAp, Configuration config + ParamNodeOption summaryCtx, ApOption argAp, Configuration config ) { fwdFlowRead0(node1, state, cc, summaryCtx, argAp, ap, config) and PrevStage::readStepCand(node1, c, node2, config) and @@ -1493,7 +1500,7 @@ private module MkStage { pragma[nomagic] private predicate fwdFlowIn( DataFlowCall call, ParamNodeEx p, FlowState state, Cc outercc, CcCall innercc, - ParameterPositionOption summaryCtx, ApOption argAp, Ap ap, ApApprox apa, Configuration config + ParamNodeOption summaryCtx, ApOption argAp, Ap ap, ApApprox apa, Configuration config ) { exists(ArgNodeEx arg, boolean allowsFieldFlow | fwdFlow(arg, state, outercc, summaryCtx, argAp, ap, apa, config) and @@ -1505,64 +1512,38 @@ private module MkStage { pragma[nomagic] private predicate fwdFlowRetFromArg( - RetNodeEx ret, FlowState state, CcCall ccc, ParameterPosition summaryCtx, ParamNodeEx p, - Ap argAp, ApApprox argApa, Ap ap, ApApprox apa, Configuration config + RetNodeEx ret, FlowState state, CcCall ccc, ParamNodeEx summaryCtx, Ap argAp, ApApprox argApa, + Ap ap, ApApprox apa, Configuration config ) { - exists(DataFlowCallable c, ReturnKindExt kind | + exists(ReturnKindExt kind | fwdFlow(pragma[only_bind_into](ret), state, ccc, - TParameterPositionSome(pragma[only_bind_into](summaryCtx)), apSome(argAp), ap, apa, config) and - getApprox(argAp) = argApa and - c = ret.getEnclosingCallable() and + TParamNodeSome(pragma[only_bind_into](summaryCtx.asNode())), + pragma[only_bind_into](apSome(argAp)), ap, pragma[only_bind_into](apa), + pragma[only_bind_into](config)) and kind = ret.getKind() and - p.isParameterOf(c, pragma[only_bind_into](summaryCtx)) and - parameterFlowThroughAllowed(p, kind) + parameterFlowThroughAllowed(summaryCtx, kind) and + argApa = getApprox(argAp) and + PrevStage::returnMayFlowThrough(ret, argApa, apa, kind, pragma[only_bind_into](config)) ) } pragma[inline] - private predicate fwdFlowInMayFlowThrough( - DataFlowCall call, Cc cc, CcCall innerCc, ParameterPositionOption summaryCtx, ApOption argAp, - ParamNodeEx param, Ap ap, ApApprox apa, Configuration config + private predicate fwdFlowThrough0( + DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, + ApOption argAp, Ap ap, ApApprox apa, RetNodeEx ret, ParamNodeEx innerSummaryCtx, + Ap innerArgAp, ApApprox innerArgApa, Configuration config ) { - fwdFlowIn(call, pragma[only_bind_into](param), _, cc, innerCc, summaryCtx, argAp, ap, - pragma[only_bind_into](apa), pragma[only_bind_into](config)) and - PrevStage::parameterMayFlowThrough(param, apa, config) - } - - // dedup before joining with `flowThroughOutOfCall` - pragma[nomagic] - private predicate fwdFlowInMayFlowThroughProj( - DataFlowCall call, CcCall innerCc, ApApprox apa, Configuration config - ) { - fwdFlowInMayFlowThrough(call, _, innerCc, _, _, _, _, apa, config) - } - - /** - * Same as `flowThroughOutOfCall`, but restricted to calls that are reached - * in the flow covered by `fwdFlow`, where data might flow through the target - * callable and back out at `call`. - */ - pragma[nomagic] - private predicate fwdFlowThroughOutOfCall( - DataFlowCall call, CcCall ccc, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow, - ApApprox argApa, ApApprox apa, Configuration config - ) { - fwdFlowInMayFlowThroughProj(call, ccc, argApa, config) and - flowThroughOutOfCall(call, ccc, ret, out, allowsFieldFlow, argApa, apa, config) + fwdFlowRetFromArg(ret, state, ccc, innerSummaryCtx, innerArgAp, innerArgApa, ap, apa, config) and + fwdFlowIsEntered(call, cc, ccc, summaryCtx, argAp, innerSummaryCtx, innerArgAp, config) } pragma[nomagic] - private predicate fwdFlowOutFromArg( - DataFlowCall call, NodeEx out, FlowState state, ParameterPosition summaryCtx, Ap argAp, Ap ap, - ApApprox apa, Configuration config + private predicate fwdFlowThrough( + DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, + ApOption argAp, Ap ap, ApApprox apa, RetNodeEx ret, ApApprox innerArgApa, Configuration config ) { - exists(RetNodeEx ret, boolean allowsFieldFlow, CcCall ccc, ApApprox argApa | - fwdFlowRetFromArg(pragma[only_bind_into](ret), state, pragma[only_bind_into](ccc), - summaryCtx, _, argAp, pragma[only_bind_into](argApa), ap, pragma[only_bind_into](apa), - config) and - fwdFlowThroughOutOfCall(call, ccc, ret, out, allowsFieldFlow, argApa, apa, config) and - (if allowsFieldFlow = false then ap instanceof ApNil else any()) - ) + fwdFlowThrough0(call, cc, state, ccc, summaryCtx, argAp, ap, apa, ret, _, _, innerArgApa, + config) } /** @@ -1571,12 +1552,14 @@ private module MkStage { */ pragma[nomagic] private predicate fwdFlowIsEntered( - DataFlowCall call, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - ParameterPosition pos, Ap ap, Configuration config + DataFlowCall call, Cc cc, CcCall innerCc, ParamNodeOption summaryCtx, ApOption argAp, + ParamNodeEx p, Ap ap, Configuration config ) { - exists(ParamNodeEx param | - fwdFlowInMayFlowThrough(call, cc, _, summaryCtx, argAp, param, ap, _, config) and - pos = param.getPosition() + exists(ApApprox apa | + fwdFlowIn(call, pragma[only_bind_into](p), _, cc, innerCc, summaryCtx, argAp, ap, + pragma[only_bind_into](apa), pragma[only_bind_into](config)) and + PrevStage::parameterMayFlowThrough(p, apa, config) and + PrevStage::callMayFlowThroughRev(call, pragma[only_bind_into](config)) ) } @@ -1596,23 +1579,31 @@ private module MkStage { fwdFlowConsCand(ap1, c, ap2, config) } + pragma[nomagic] + private predicate returnFlowsThrough0( + DataFlowCall call, FlowState state, CcCall ccc, Ap ap, ApApprox apa, RetNodeEx ret, + ParamNodeEx innerSummaryCtx, Ap innerArgAp, ApApprox innerArgApa, Configuration config + ) { + fwdFlowThrough0(call, _, state, ccc, _, _, ap, apa, ret, innerSummaryCtx, innerArgAp, + innerArgApa, config) + } + pragma[nomagic] private predicate returnFlowsThrough( - RetNodeEx ret, ReturnKindExt kind, FlowState state, CcCall ccc, ParamNodeEx p, Ap argAp, + RetNodeEx ret, ReturnPosition pos, FlowState state, CcCall ccc, ParamNodeEx p, Ap argAp, Ap ap, Configuration config ) { - exists(boolean allowsFieldFlow, ApApprox argApa, ApApprox apa | - fwdFlowRetFromArg(pragma[only_bind_into](ret), state, pragma[only_bind_into](ccc), _, p, - argAp, pragma[only_bind_into](argApa), ap, pragma[only_bind_into](apa), config) and - kind = ret.getKind() and - fwdFlowThroughOutOfCall(_, ccc, ret, _, allowsFieldFlow, argApa, apa, config) and - (if allowsFieldFlow = false then ap instanceof ApNil else any()) + exists(DataFlowCall call, ApApprox apa, boolean allowsFieldFlow, ApApprox innerArgApa | + returnFlowsThrough0(call, state, ccc, ap, apa, ret, p, argAp, innerArgApa, config) and + flowThroughOutOfCall(call, ccc, ret, _, allowsFieldFlow, innerArgApa, apa, config) and + pos = ret.getReturnPosition() and + if allowsFieldFlow = false then ap instanceof ApNil else any() ) } pragma[nomagic] private predicate flowThroughIntoCall( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap argAp, + DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap argAp, Ap ap, Configuration config ) { exists(ApApprox argApa | @@ -1620,7 +1611,7 @@ private module MkStage { allowsFieldFlow, argApa, pragma[only_bind_into](config)) and fwdFlow(arg, _, _, _, _, pragma[only_bind_into](argAp), argApa, pragma[only_bind_into](config)) and - returnFlowsThrough(_, _, _, _, p, pragma[only_bind_into](argAp), _, + returnFlowsThrough(_, _, _, _, p, pragma[only_bind_into](argAp), ap, pragma[only_bind_into](config)) and if allowsFieldFlow = false then argAp instanceof ApNil else any() ) @@ -1639,12 +1630,13 @@ private module MkStage { pragma[nomagic] private predicate flowOutOfCallAp( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, boolean allowsFieldFlow, + DataFlowCall call, RetNodeEx ret, ReturnPosition pos, NodeEx out, boolean allowsFieldFlow, Ap ap, Configuration config ) { exists(ApApprox apa | - flowOutOfCallApa(call, ret, kind, out, allowsFieldFlow, apa, config) and - fwdFlow(ret, _, _, _, _, ap, apa, config) + flowOutOfCallApa(call, ret, _, out, allowsFieldFlow, apa, config) and + fwdFlow(ret, _, _, _, _, ap, apa, config) and + pos = ret.getReturnPosition() ) } @@ -1739,17 +1731,17 @@ private module MkStage { ) or // flow through a callable - exists(DataFlowCall call, ReturnKindExt returnKind0, Ap returnAp0 | - revFlowInToReturn(call, node, state, returnKind0, returnAp0, ap, config) and - revFlowIsReturned(call, returnCtx, returnAp, returnKind0, returnAp0, config) + exists(DataFlowCall call, ParamNodeEx p, ReturnPosition pos, Ap innerReturnAp | + revFlowThrough(call, returnCtx, p, state, pos, returnAp, ap, innerReturnAp, config) and + flowThroughIntoCall(call, node, p, _, ap, innerReturnAp, config) ) or // flow out of a callable - exists(ReturnKindExt kind | - revFlowOut(_, node, kind, state, _, _, ap, config) and - if returnFlowsThrough(node, kind, state, _, _, _, ap, config) + exists(ReturnPosition pos | + revFlowOut(_, node, pos, state, _, _, ap, config) and + if returnFlowsThrough(node, pos, state, _, _, _, ap, config) then ( - returnCtx = TReturnCtxMaybeFlowThrough(kind) and + returnCtx = TReturnCtxMaybeFlowThrough(pos) and returnAp = apSome(ap) ) else ( returnCtx = TReturnCtxNoFlowThrough() and returnAp = apNone() @@ -1782,47 +1774,33 @@ private module MkStage { pragma[nomagic] private predicate revFlowOut( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, FlowState state, ReturnCtx returnCtx, + DataFlowCall call, RetNodeEx ret, ReturnPosition pos, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap, Configuration config ) { exists(NodeEx out, boolean allowsFieldFlow | revFlow(out, state, returnCtx, returnAp, ap, config) and - flowOutOfCallAp(call, ret, kind, out, allowsFieldFlow, ap, config) and + flowOutOfCallAp(call, ret, pos, out, allowsFieldFlow, ap, config) and if allowsFieldFlow = false then ap instanceof ApNil else any() ) } - /** - * Same as `flowThroughIntoCall`, but restricted to calls that are reached - * in the flow covered by `revFlow`, where data might flow through the target - * callable and back out at `call`. - */ - pragma[nomagic] - private predicate revFlowThroughIntoCall( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap argAp, - Configuration config - ) { - flowThroughIntoCall(call, arg, p, allowsFieldFlow, argAp, config) and - revFlowIsReturned(call, _, _, _, _, config) - } - pragma[nomagic] private predicate revFlowParamToReturn( - ParamNodeEx p, FlowState state, ReturnKindExt kind, Ap returnAp, Ap ap, Configuration config + ParamNodeEx p, FlowState state, ReturnPosition pos, Ap returnAp, Ap ap, Configuration config ) { - revFlow(p, state, TReturnCtxMaybeFlowThrough(kind), apSome(returnAp), ap, config) and - parameterFlowThroughAllowed(p, kind) + revFlow(pragma[only_bind_into](p), state, TReturnCtxMaybeFlowThrough(pos), apSome(returnAp), + pragma[only_bind_into](ap), pragma[only_bind_into](config)) and + parameterFlowThroughAllowed(p, pos.getKind()) and + PrevStage::parameterMayFlowThrough(p, getApprox(ap), config) } pragma[nomagic] - private predicate revFlowInToReturn( - DataFlowCall call, ArgNodeEx arg, FlowState state, ReturnKindExt kind, Ap returnAp, Ap ap, - Configuration config + private predicate revFlowThrough( + DataFlowCall call, ReturnCtx returnCtx, ParamNodeEx p, FlowState state, ReturnPosition pos, + ApOption returnAp, Ap ap, Ap innerReturnAp, Configuration config ) { - exists(ParamNodeEx p, boolean allowsFieldFlow | - revFlowParamToReturn(p, state, kind, returnAp, ap, config) and - revFlowThroughIntoCall(call, arg, p, allowsFieldFlow, ap, config) - ) + revFlowParamToReturn(p, state, pos, innerReturnAp, ap, config) and + revFlowIsReturned(call, returnCtx, returnAp, pos, innerReturnAp, config) } /** @@ -1832,12 +1810,12 @@ private module MkStage { */ pragma[nomagic] private predicate revFlowIsReturned( - DataFlowCall call, ReturnCtx returnCtx, ApOption returnAp, ReturnKindExt kind, Ap ap, + DataFlowCall call, ReturnCtx returnCtx, ApOption returnAp, ReturnPosition pos, Ap ap, Configuration config ) { exists(RetNodeEx ret, FlowState state, CcCall ccc | - revFlowOut(call, ret, kind, state, returnCtx, returnAp, ap, config) and - returnFlowsThrough(ret, kind, state, ccc, _, _, ap, config) and + revFlowOut(call, ret, pos, state, returnCtx, returnAp, ap, config) and + returnFlowsThrough(ret, pos, state, ccc, _, _, ap, config) and matchesCall(ccc, call) ) } @@ -1915,17 +1893,17 @@ private module MkStage { pragma[nomagic] private predicate parameterFlowsThroughRev( - ParamNodeEx p, Ap ap, ReturnKindExt kind, Ap returnAp, Configuration config + ParamNodeEx p, Ap ap, ReturnPosition pos, Ap returnAp, Configuration config ) { - revFlow(p, _, TReturnCtxMaybeFlowThrough(kind), apSome(returnAp), ap, config) and - parameterFlowThroughAllowed(p, kind) + revFlow(p, _, TReturnCtxMaybeFlowThrough(pos), apSome(returnAp), ap, config) and + parameterFlowThroughAllowed(p, pos.getKind()) } pragma[nomagic] predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap, Configuration config) { - exists(RetNodeEx ret, ReturnKindExt kind | - returnFlowsThrough(ret, kind, _, _, p, ap, _, config) and - parameterFlowsThroughRev(p, ap, kind, _, config) + exists(RetNodeEx ret, ReturnPosition pos | + returnFlowsThrough(ret, pos, _, _, p, ap, _, config) and + parameterFlowsThroughRev(p, ap, pos, _, config) ) } @@ -1933,20 +1911,21 @@ private module MkStage { predicate returnMayFlowThrough( RetNodeEx ret, Ap argAp, Ap ap, ReturnKindExt kind, Configuration config ) { - exists(ParamNodeEx p | - returnFlowsThrough(ret, kind, _, _, p, argAp, ap, config) and - parameterFlowsThroughRev(p, argAp, kind, ap, config) + exists(ParamNodeEx p, ReturnPosition pos | + returnFlowsThrough(ret, pos, _, _, p, argAp, ap, config) and + parameterFlowsThroughRev(p, argAp, pos, ap, config) and + kind = pos.getKind() ) } pragma[nomagic] - predicate revFlowInToReturnIsReturned( + private predicate revFlowThroughArg( DataFlowCall call, ArgNodeEx arg, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap, Configuration config ) { - exists(ReturnKindExt returnKind0, Ap returnAp0 | - revFlowInToReturn(call, arg, state, returnKind0, returnAp0, ap, config) and - revFlowIsReturned(call, returnCtx, returnAp, returnKind0, returnAp0, config) + exists(ParamNodeEx p, ReturnPosition pos, Ap innerReturnAp | + revFlowThrough(call, returnCtx, p, state, pos, returnAp, ap, innerReturnAp, config) and + flowThroughIntoCall(call, arg, p, _, ap, innerReturnAp, config) ) } @@ -1954,7 +1933,7 @@ private module MkStage { predicate callMayFlowThroughRev(DataFlowCall call, Configuration config) { exists(ArgNodeEx arg, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap | revFlow(arg, state, returnCtx, returnAp, ap, config) and - revFlowInToReturnIsReturned(call, arg, state, returnCtx, returnAp, ap, config) + revFlowThroughArg(call, arg, state, returnCtx, returnAp, ap, config) ) } @@ -1967,8 +1946,9 @@ private module MkStage { conscand = count(TypedContent f0, Ap ap | fwdConsCand(f0, ap, config)) and states = count(FlowState state | fwdFlow(_, state, _, _, _, _, config)) and tuples = - count(NodeEx n, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - Ap ap | fwdFlow(n, state, cc, summaryCtx, argAp, ap, config)) + count(NodeEx n, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap | + fwdFlow(n, state, cc, summaryCtx, argAp, ap, config) + ) or fwd = false and nodes = count(NodeEx node | revFlow(node, _, _, _, _, config)) and @@ -2823,13 +2803,12 @@ private Configuration unbindConf(Configuration conf) { pragma[nomagic] private predicate nodeMayUseSummary0( - NodeEx n, DataFlowCallable c, ParameterPosition pos, FlowState state, AccessPathApprox apa, - Configuration config + NodeEx n, ParamNodeEx p, FlowState state, AccessPathApprox apa, Configuration config ) { exists(AccessPathApprox apa0 | - c = n.getEnclosingCallable() and + Stage5::parameterMayFlowThrough(p, _, _) and Stage5::revFlow(n, state, TReturnCtxMaybeFlowThrough(_), _, apa0, config) and - Stage5::fwdFlow(n, state, any(CallContextCall ccc), TParameterPositionSome(pos), + Stage5::fwdFlow(n, state, any(CallContextCall ccc), TParamNodeSome(p.asNode()), TAccessPathApproxSome(apa), apa0, config) ) } @@ -2838,10 +2817,9 @@ pragma[nomagic] private predicate nodeMayUseSummary( NodeEx n, FlowState state, AccessPathApprox apa, Configuration config ) { - exists(DataFlowCallable c, ParameterPosition pos, ParamNodeEx p | + exists(ParamNodeEx p | Stage5::parameterMayFlowThrough(p, apa, config) and - nodeMayUseSummary0(n, c, pos, state, apa, config) and - p.isParameterOf(c, pos) + nodeMayUseSummary0(n, p, state, apa, config) ) } diff --git a/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowImplCommon.qll b/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowImplCommon.qll index c66aefced8d..9aa6a529a5b 100644 --- a/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowImplCommon.qll +++ b/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowImplCommon.qll @@ -916,15 +916,15 @@ private module Cached { TDataFlowCallSome(DataFlowCall call) cached - newtype TParameterPositionOption = - TParameterPositionNone() or - TParameterPositionSome(ParameterPosition pos) + newtype TParamNodeOption = + TParamNodeNone() or + TParamNodeSome(ParamNode p) cached newtype TReturnCtx = TReturnCtxNone() or TReturnCtxNoFlowThrough() or - TReturnCtxMaybeFlowThrough(ReturnKindExt kind) + TReturnCtxMaybeFlowThrough(ReturnPosition pos) cached newtype TTypedContentApprox = @@ -1343,15 +1343,15 @@ class DataFlowCallOption extends TDataFlowCallOption { } } -/** An optional `ParameterPosition`. */ -class ParameterPositionOption extends TParameterPositionOption { +/** An optional `ParamNode`. */ +class ParamNodeOption extends TParamNodeOption { string toString() { - this = TParameterPositionNone() and + this = TParamNodeNone() and result = "(none)" or - exists(ParameterPosition pos | - this = TParameterPositionSome(pos) and - result = pos.toString() + exists(ParamNode p | + this = TParamNodeSome(p) and + result = p.toString() ) } } @@ -1363,7 +1363,7 @@ class ParameterPositionOption extends TParameterPositionOption { * * - `TReturnCtxNone()`: no return flow. * - `TReturnCtxNoFlowThrough()`: return flow, but flow through is not possible. - * - `TReturnCtxMaybeFlowThrough(ReturnKindExt kind)`: return flow, of kind `kind`, and + * - `TReturnCtxMaybeFlowThrough(ReturnPosition pos)`: return flow, of kind `pos`, and * flow through may be possible. */ class ReturnCtx extends TReturnCtx { @@ -1374,9 +1374,9 @@ class ReturnCtx extends TReturnCtx { this = TReturnCtxNoFlowThrough() and result = "(no flow through)" or - exists(ReturnKindExt kind | - this = TReturnCtxMaybeFlowThrough(kind) and - result = kind.toString() + exists(ReturnPosition pos | + this = TReturnCtxMaybeFlowThrough(pos) and + result = pos.toString() ) } } diff --git a/cpp/ql/lib/semmle/code/cpp/dataflow/old/internal/DataFlowImpl.qll b/cpp/ql/lib/semmle/code/cpp/dataflow/old/internal/DataFlowImpl.qll index 6741ccc2f06..1228d00b6ba 100644 --- a/cpp/ql/lib/semmle/code/cpp/dataflow/old/internal/DataFlowImpl.qll +++ b/cpp/ql/lib/semmle/code/cpp/dataflow/old/internal/DataFlowImpl.qll @@ -622,7 +622,11 @@ private predicate parameterFlowThroughAllowed(ParamNodeEx p, ReturnKindExt kind) } private module Stage1 implements StageSig { - class Ap = Unit; + class Ap extends int { + // workaround for bad functionality-induced joins (happens when using `Unit`) + pragma[nomagic] + Ap() { this in [0 .. 1] and this < 1 } + } private class Cc = boolean; @@ -1327,8 +1331,8 @@ private module MkStage { */ pragma[nomagic] additional predicate fwdFlow( - NodeEx node, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - Ap ap, ApApprox apa, Configuration config + NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, + ApApprox apa, Configuration config ) { fwdFlow0(node, state, cc, summaryCtx, argAp, ap, apa, config) and PrevStage::revFlow(node, state, apa, config) and @@ -1337,21 +1341,21 @@ private module MkStage { pragma[inline] additional predicate fwdFlow( - NodeEx node, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - Ap ap, Configuration config + NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, + Configuration config ) { fwdFlow(node, state, cc, summaryCtx, argAp, ap, _, config) } pragma[nomagic] private predicate fwdFlow0( - NodeEx node, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - Ap ap, ApApprox apa, Configuration config + NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, + ApApprox apa, Configuration config ) { sourceNode(node, state, config) and (if hasSourceCallCtx(config) then cc = ccSomeCall() else cc = ccNone()) and argAp = apNone() and - summaryCtx = TParameterPositionNone() and + summaryCtx = TParamNodeNone() and ap = getApNil(node) and apa = getApprox(ap) or @@ -1372,7 +1376,7 @@ private module MkStage { fwdFlow(mid, pragma[only_bind_into](state), _, _, _, ap, apa, pragma[only_bind_into](config)) and jumpStep(mid, node, config) and cc = ccNone() and - summaryCtx = TParameterPositionNone() and + summaryCtx = TParamNodeNone() and argAp = apNone() ) or @@ -1380,7 +1384,7 @@ private module MkStage { fwdFlow(mid, state, _, _, _, nil, pragma[only_bind_into](config)) and additionalJumpStep(mid, node, config) and cc = ccNone() and - summaryCtx = TParameterPositionNone() and + summaryCtx = TParamNodeNone() and argAp = apNone() and ap = getApNil(node) and apa = getApprox(ap) @@ -1390,7 +1394,7 @@ private module MkStage { fwdFlow(mid, state0, _, _, _, nil, pragma[only_bind_into](config)) and additionalJumpStateStep(mid, state0, node, state, config) and cc = ccNone() and - summaryCtx = TParameterPositionNone() and + summaryCtx = TParamNodeNone() and argAp = apNone() and ap = getApNil(node) and apa = getApprox(ap) @@ -1414,10 +1418,10 @@ private module MkStage { fwdFlowIn(_, node, state, _, cc, _, _, ap, apa, config) and if PrevStage::parameterMayFlowThrough(node, apa, config) then ( - summaryCtx = TParameterPositionSome(node.(ParamNodeEx).getPosition()) and + summaryCtx = TParamNodeSome(node.asNode()) and argAp = apSome(ap) ) else ( - summaryCtx = TParameterPositionNone() and argAp = apNone() + summaryCtx = TParamNodeNone() and argAp = apNone() ) or // flow out of a callable @@ -1433,16 +1437,19 @@ private module MkStage { ) or // flow through a callable - exists(DataFlowCall call, ParameterPosition summaryCtx0, Ap argAp0 | - fwdFlowOutFromArg(call, node, state, summaryCtx0, argAp0, ap, apa, config) and - fwdFlowIsEntered(call, cc, summaryCtx, argAp, summaryCtx0, argAp0, config) + exists( + DataFlowCall call, CcCall ccc, RetNodeEx ret, boolean allowsFieldFlow, ApApprox innerArgApa + | + fwdFlowThrough(call, cc, state, ccc, summaryCtx, argAp, ap, apa, ret, innerArgApa, config) and + flowThroughOutOfCall(call, ccc, ret, node, allowsFieldFlow, innerArgApa, apa, config) and + if allowsFieldFlow = false then ap instanceof ApNil else any() ) } pragma[nomagic] private predicate fwdFlowStore( NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, FlowState state, Cc cc, - ParameterPositionOption summaryCtx, ApOption argAp, Configuration config + ParamNodeOption summaryCtx, ApOption argAp, Configuration config ) { exists(DataFlowType contentType, ApApprox apa1 | fwdFlow(node1, state, cc, summaryCtx, argAp, ap1, apa1, config) and @@ -1473,8 +1480,8 @@ private module MkStage { pragma[nomagic] private predicate fwdFlowRead0( - NodeEx node1, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - ApNonNil ap, Configuration config + NodeEx node1, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, ApNonNil ap, + Configuration config ) { fwdFlow(node1, state, cc, summaryCtx, argAp, ap, config) and PrevStage::readStepCand(node1, _, _, config) @@ -1483,7 +1490,7 @@ private module MkStage { pragma[nomagic] private predicate fwdFlowRead( Ap ap, Content c, NodeEx node1, NodeEx node2, FlowState state, Cc cc, - ParameterPositionOption summaryCtx, ApOption argAp, Configuration config + ParamNodeOption summaryCtx, ApOption argAp, Configuration config ) { fwdFlowRead0(node1, state, cc, summaryCtx, argAp, ap, config) and PrevStage::readStepCand(node1, c, node2, config) and @@ -1493,7 +1500,7 @@ private module MkStage { pragma[nomagic] private predicate fwdFlowIn( DataFlowCall call, ParamNodeEx p, FlowState state, Cc outercc, CcCall innercc, - ParameterPositionOption summaryCtx, ApOption argAp, Ap ap, ApApprox apa, Configuration config + ParamNodeOption summaryCtx, ApOption argAp, Ap ap, ApApprox apa, Configuration config ) { exists(ArgNodeEx arg, boolean allowsFieldFlow | fwdFlow(arg, state, outercc, summaryCtx, argAp, ap, apa, config) and @@ -1505,64 +1512,38 @@ private module MkStage { pragma[nomagic] private predicate fwdFlowRetFromArg( - RetNodeEx ret, FlowState state, CcCall ccc, ParameterPosition summaryCtx, ParamNodeEx p, - Ap argAp, ApApprox argApa, Ap ap, ApApprox apa, Configuration config + RetNodeEx ret, FlowState state, CcCall ccc, ParamNodeEx summaryCtx, Ap argAp, ApApprox argApa, + Ap ap, ApApprox apa, Configuration config ) { - exists(DataFlowCallable c, ReturnKindExt kind | + exists(ReturnKindExt kind | fwdFlow(pragma[only_bind_into](ret), state, ccc, - TParameterPositionSome(pragma[only_bind_into](summaryCtx)), apSome(argAp), ap, apa, config) and - getApprox(argAp) = argApa and - c = ret.getEnclosingCallable() and + TParamNodeSome(pragma[only_bind_into](summaryCtx.asNode())), + pragma[only_bind_into](apSome(argAp)), ap, pragma[only_bind_into](apa), + pragma[only_bind_into](config)) and kind = ret.getKind() and - p.isParameterOf(c, pragma[only_bind_into](summaryCtx)) and - parameterFlowThroughAllowed(p, kind) + parameterFlowThroughAllowed(summaryCtx, kind) and + argApa = getApprox(argAp) and + PrevStage::returnMayFlowThrough(ret, argApa, apa, kind, pragma[only_bind_into](config)) ) } pragma[inline] - private predicate fwdFlowInMayFlowThrough( - DataFlowCall call, Cc cc, CcCall innerCc, ParameterPositionOption summaryCtx, ApOption argAp, - ParamNodeEx param, Ap ap, ApApprox apa, Configuration config + private predicate fwdFlowThrough0( + DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, + ApOption argAp, Ap ap, ApApprox apa, RetNodeEx ret, ParamNodeEx innerSummaryCtx, + Ap innerArgAp, ApApprox innerArgApa, Configuration config ) { - fwdFlowIn(call, pragma[only_bind_into](param), _, cc, innerCc, summaryCtx, argAp, ap, - pragma[only_bind_into](apa), pragma[only_bind_into](config)) and - PrevStage::parameterMayFlowThrough(param, apa, config) - } - - // dedup before joining with `flowThroughOutOfCall` - pragma[nomagic] - private predicate fwdFlowInMayFlowThroughProj( - DataFlowCall call, CcCall innerCc, ApApprox apa, Configuration config - ) { - fwdFlowInMayFlowThrough(call, _, innerCc, _, _, _, _, apa, config) - } - - /** - * Same as `flowThroughOutOfCall`, but restricted to calls that are reached - * in the flow covered by `fwdFlow`, where data might flow through the target - * callable and back out at `call`. - */ - pragma[nomagic] - private predicate fwdFlowThroughOutOfCall( - DataFlowCall call, CcCall ccc, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow, - ApApprox argApa, ApApprox apa, Configuration config - ) { - fwdFlowInMayFlowThroughProj(call, ccc, argApa, config) and - flowThroughOutOfCall(call, ccc, ret, out, allowsFieldFlow, argApa, apa, config) + fwdFlowRetFromArg(ret, state, ccc, innerSummaryCtx, innerArgAp, innerArgApa, ap, apa, config) and + fwdFlowIsEntered(call, cc, ccc, summaryCtx, argAp, innerSummaryCtx, innerArgAp, config) } pragma[nomagic] - private predicate fwdFlowOutFromArg( - DataFlowCall call, NodeEx out, FlowState state, ParameterPosition summaryCtx, Ap argAp, Ap ap, - ApApprox apa, Configuration config + private predicate fwdFlowThrough( + DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, + ApOption argAp, Ap ap, ApApprox apa, RetNodeEx ret, ApApprox innerArgApa, Configuration config ) { - exists(RetNodeEx ret, boolean allowsFieldFlow, CcCall ccc, ApApprox argApa | - fwdFlowRetFromArg(pragma[only_bind_into](ret), state, pragma[only_bind_into](ccc), - summaryCtx, _, argAp, pragma[only_bind_into](argApa), ap, pragma[only_bind_into](apa), - config) and - fwdFlowThroughOutOfCall(call, ccc, ret, out, allowsFieldFlow, argApa, apa, config) and - (if allowsFieldFlow = false then ap instanceof ApNil else any()) - ) + fwdFlowThrough0(call, cc, state, ccc, summaryCtx, argAp, ap, apa, ret, _, _, innerArgApa, + config) } /** @@ -1571,12 +1552,14 @@ private module MkStage { */ pragma[nomagic] private predicate fwdFlowIsEntered( - DataFlowCall call, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - ParameterPosition pos, Ap ap, Configuration config + DataFlowCall call, Cc cc, CcCall innerCc, ParamNodeOption summaryCtx, ApOption argAp, + ParamNodeEx p, Ap ap, Configuration config ) { - exists(ParamNodeEx param | - fwdFlowInMayFlowThrough(call, cc, _, summaryCtx, argAp, param, ap, _, config) and - pos = param.getPosition() + exists(ApApprox apa | + fwdFlowIn(call, pragma[only_bind_into](p), _, cc, innerCc, summaryCtx, argAp, ap, + pragma[only_bind_into](apa), pragma[only_bind_into](config)) and + PrevStage::parameterMayFlowThrough(p, apa, config) and + PrevStage::callMayFlowThroughRev(call, pragma[only_bind_into](config)) ) } @@ -1596,23 +1579,31 @@ private module MkStage { fwdFlowConsCand(ap1, c, ap2, config) } + pragma[nomagic] + private predicate returnFlowsThrough0( + DataFlowCall call, FlowState state, CcCall ccc, Ap ap, ApApprox apa, RetNodeEx ret, + ParamNodeEx innerSummaryCtx, Ap innerArgAp, ApApprox innerArgApa, Configuration config + ) { + fwdFlowThrough0(call, _, state, ccc, _, _, ap, apa, ret, innerSummaryCtx, innerArgAp, + innerArgApa, config) + } + pragma[nomagic] private predicate returnFlowsThrough( - RetNodeEx ret, ReturnKindExt kind, FlowState state, CcCall ccc, ParamNodeEx p, Ap argAp, + RetNodeEx ret, ReturnPosition pos, FlowState state, CcCall ccc, ParamNodeEx p, Ap argAp, Ap ap, Configuration config ) { - exists(boolean allowsFieldFlow, ApApprox argApa, ApApprox apa | - fwdFlowRetFromArg(pragma[only_bind_into](ret), state, pragma[only_bind_into](ccc), _, p, - argAp, pragma[only_bind_into](argApa), ap, pragma[only_bind_into](apa), config) and - kind = ret.getKind() and - fwdFlowThroughOutOfCall(_, ccc, ret, _, allowsFieldFlow, argApa, apa, config) and - (if allowsFieldFlow = false then ap instanceof ApNil else any()) + exists(DataFlowCall call, ApApprox apa, boolean allowsFieldFlow, ApApprox innerArgApa | + returnFlowsThrough0(call, state, ccc, ap, apa, ret, p, argAp, innerArgApa, config) and + flowThroughOutOfCall(call, ccc, ret, _, allowsFieldFlow, innerArgApa, apa, config) and + pos = ret.getReturnPosition() and + if allowsFieldFlow = false then ap instanceof ApNil else any() ) } pragma[nomagic] private predicate flowThroughIntoCall( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap argAp, + DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap argAp, Ap ap, Configuration config ) { exists(ApApprox argApa | @@ -1620,7 +1611,7 @@ private module MkStage { allowsFieldFlow, argApa, pragma[only_bind_into](config)) and fwdFlow(arg, _, _, _, _, pragma[only_bind_into](argAp), argApa, pragma[only_bind_into](config)) and - returnFlowsThrough(_, _, _, _, p, pragma[only_bind_into](argAp), _, + returnFlowsThrough(_, _, _, _, p, pragma[only_bind_into](argAp), ap, pragma[only_bind_into](config)) and if allowsFieldFlow = false then argAp instanceof ApNil else any() ) @@ -1639,12 +1630,13 @@ private module MkStage { pragma[nomagic] private predicate flowOutOfCallAp( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, boolean allowsFieldFlow, + DataFlowCall call, RetNodeEx ret, ReturnPosition pos, NodeEx out, boolean allowsFieldFlow, Ap ap, Configuration config ) { exists(ApApprox apa | - flowOutOfCallApa(call, ret, kind, out, allowsFieldFlow, apa, config) and - fwdFlow(ret, _, _, _, _, ap, apa, config) + flowOutOfCallApa(call, ret, _, out, allowsFieldFlow, apa, config) and + fwdFlow(ret, _, _, _, _, ap, apa, config) and + pos = ret.getReturnPosition() ) } @@ -1739,17 +1731,17 @@ private module MkStage { ) or // flow through a callable - exists(DataFlowCall call, ReturnKindExt returnKind0, Ap returnAp0 | - revFlowInToReturn(call, node, state, returnKind0, returnAp0, ap, config) and - revFlowIsReturned(call, returnCtx, returnAp, returnKind0, returnAp0, config) + exists(DataFlowCall call, ParamNodeEx p, ReturnPosition pos, Ap innerReturnAp | + revFlowThrough(call, returnCtx, p, state, pos, returnAp, ap, innerReturnAp, config) and + flowThroughIntoCall(call, node, p, _, ap, innerReturnAp, config) ) or // flow out of a callable - exists(ReturnKindExt kind | - revFlowOut(_, node, kind, state, _, _, ap, config) and - if returnFlowsThrough(node, kind, state, _, _, _, ap, config) + exists(ReturnPosition pos | + revFlowOut(_, node, pos, state, _, _, ap, config) and + if returnFlowsThrough(node, pos, state, _, _, _, ap, config) then ( - returnCtx = TReturnCtxMaybeFlowThrough(kind) and + returnCtx = TReturnCtxMaybeFlowThrough(pos) and returnAp = apSome(ap) ) else ( returnCtx = TReturnCtxNoFlowThrough() and returnAp = apNone() @@ -1782,47 +1774,33 @@ private module MkStage { pragma[nomagic] private predicate revFlowOut( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, FlowState state, ReturnCtx returnCtx, + DataFlowCall call, RetNodeEx ret, ReturnPosition pos, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap, Configuration config ) { exists(NodeEx out, boolean allowsFieldFlow | revFlow(out, state, returnCtx, returnAp, ap, config) and - flowOutOfCallAp(call, ret, kind, out, allowsFieldFlow, ap, config) and + flowOutOfCallAp(call, ret, pos, out, allowsFieldFlow, ap, config) and if allowsFieldFlow = false then ap instanceof ApNil else any() ) } - /** - * Same as `flowThroughIntoCall`, but restricted to calls that are reached - * in the flow covered by `revFlow`, where data might flow through the target - * callable and back out at `call`. - */ - pragma[nomagic] - private predicate revFlowThroughIntoCall( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap argAp, - Configuration config - ) { - flowThroughIntoCall(call, arg, p, allowsFieldFlow, argAp, config) and - revFlowIsReturned(call, _, _, _, _, config) - } - pragma[nomagic] private predicate revFlowParamToReturn( - ParamNodeEx p, FlowState state, ReturnKindExt kind, Ap returnAp, Ap ap, Configuration config + ParamNodeEx p, FlowState state, ReturnPosition pos, Ap returnAp, Ap ap, Configuration config ) { - revFlow(p, state, TReturnCtxMaybeFlowThrough(kind), apSome(returnAp), ap, config) and - parameterFlowThroughAllowed(p, kind) + revFlow(pragma[only_bind_into](p), state, TReturnCtxMaybeFlowThrough(pos), apSome(returnAp), + pragma[only_bind_into](ap), pragma[only_bind_into](config)) and + parameterFlowThroughAllowed(p, pos.getKind()) and + PrevStage::parameterMayFlowThrough(p, getApprox(ap), config) } pragma[nomagic] - private predicate revFlowInToReturn( - DataFlowCall call, ArgNodeEx arg, FlowState state, ReturnKindExt kind, Ap returnAp, Ap ap, - Configuration config + private predicate revFlowThrough( + DataFlowCall call, ReturnCtx returnCtx, ParamNodeEx p, FlowState state, ReturnPosition pos, + ApOption returnAp, Ap ap, Ap innerReturnAp, Configuration config ) { - exists(ParamNodeEx p, boolean allowsFieldFlow | - revFlowParamToReturn(p, state, kind, returnAp, ap, config) and - revFlowThroughIntoCall(call, arg, p, allowsFieldFlow, ap, config) - ) + revFlowParamToReturn(p, state, pos, innerReturnAp, ap, config) and + revFlowIsReturned(call, returnCtx, returnAp, pos, innerReturnAp, config) } /** @@ -1832,12 +1810,12 @@ private module MkStage { */ pragma[nomagic] private predicate revFlowIsReturned( - DataFlowCall call, ReturnCtx returnCtx, ApOption returnAp, ReturnKindExt kind, Ap ap, + DataFlowCall call, ReturnCtx returnCtx, ApOption returnAp, ReturnPosition pos, Ap ap, Configuration config ) { exists(RetNodeEx ret, FlowState state, CcCall ccc | - revFlowOut(call, ret, kind, state, returnCtx, returnAp, ap, config) and - returnFlowsThrough(ret, kind, state, ccc, _, _, ap, config) and + revFlowOut(call, ret, pos, state, returnCtx, returnAp, ap, config) and + returnFlowsThrough(ret, pos, state, ccc, _, _, ap, config) and matchesCall(ccc, call) ) } @@ -1915,17 +1893,17 @@ private module MkStage { pragma[nomagic] private predicate parameterFlowsThroughRev( - ParamNodeEx p, Ap ap, ReturnKindExt kind, Ap returnAp, Configuration config + ParamNodeEx p, Ap ap, ReturnPosition pos, Ap returnAp, Configuration config ) { - revFlow(p, _, TReturnCtxMaybeFlowThrough(kind), apSome(returnAp), ap, config) and - parameterFlowThroughAllowed(p, kind) + revFlow(p, _, TReturnCtxMaybeFlowThrough(pos), apSome(returnAp), ap, config) and + parameterFlowThroughAllowed(p, pos.getKind()) } pragma[nomagic] predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap, Configuration config) { - exists(RetNodeEx ret, ReturnKindExt kind | - returnFlowsThrough(ret, kind, _, _, p, ap, _, config) and - parameterFlowsThroughRev(p, ap, kind, _, config) + exists(RetNodeEx ret, ReturnPosition pos | + returnFlowsThrough(ret, pos, _, _, p, ap, _, config) and + parameterFlowsThroughRev(p, ap, pos, _, config) ) } @@ -1933,20 +1911,21 @@ private module MkStage { predicate returnMayFlowThrough( RetNodeEx ret, Ap argAp, Ap ap, ReturnKindExt kind, Configuration config ) { - exists(ParamNodeEx p | - returnFlowsThrough(ret, kind, _, _, p, argAp, ap, config) and - parameterFlowsThroughRev(p, argAp, kind, ap, config) + exists(ParamNodeEx p, ReturnPosition pos | + returnFlowsThrough(ret, pos, _, _, p, argAp, ap, config) and + parameterFlowsThroughRev(p, argAp, pos, ap, config) and + kind = pos.getKind() ) } pragma[nomagic] - predicate revFlowInToReturnIsReturned( + private predicate revFlowThroughArg( DataFlowCall call, ArgNodeEx arg, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap, Configuration config ) { - exists(ReturnKindExt returnKind0, Ap returnAp0 | - revFlowInToReturn(call, arg, state, returnKind0, returnAp0, ap, config) and - revFlowIsReturned(call, returnCtx, returnAp, returnKind0, returnAp0, config) + exists(ParamNodeEx p, ReturnPosition pos, Ap innerReturnAp | + revFlowThrough(call, returnCtx, p, state, pos, returnAp, ap, innerReturnAp, config) and + flowThroughIntoCall(call, arg, p, _, ap, innerReturnAp, config) ) } @@ -1954,7 +1933,7 @@ private module MkStage { predicate callMayFlowThroughRev(DataFlowCall call, Configuration config) { exists(ArgNodeEx arg, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap | revFlow(arg, state, returnCtx, returnAp, ap, config) and - revFlowInToReturnIsReturned(call, arg, state, returnCtx, returnAp, ap, config) + revFlowThroughArg(call, arg, state, returnCtx, returnAp, ap, config) ) } @@ -1967,8 +1946,9 @@ private module MkStage { conscand = count(TypedContent f0, Ap ap | fwdConsCand(f0, ap, config)) and states = count(FlowState state | fwdFlow(_, state, _, _, _, _, config)) and tuples = - count(NodeEx n, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - Ap ap | fwdFlow(n, state, cc, summaryCtx, argAp, ap, config)) + count(NodeEx n, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap | + fwdFlow(n, state, cc, summaryCtx, argAp, ap, config) + ) or fwd = false and nodes = count(NodeEx node | revFlow(node, _, _, _, _, config)) and @@ -2823,13 +2803,12 @@ private Configuration unbindConf(Configuration conf) { pragma[nomagic] private predicate nodeMayUseSummary0( - NodeEx n, DataFlowCallable c, ParameterPosition pos, FlowState state, AccessPathApprox apa, - Configuration config + NodeEx n, ParamNodeEx p, FlowState state, AccessPathApprox apa, Configuration config ) { exists(AccessPathApprox apa0 | - c = n.getEnclosingCallable() and + Stage5::parameterMayFlowThrough(p, _, _) and Stage5::revFlow(n, state, TReturnCtxMaybeFlowThrough(_), _, apa0, config) and - Stage5::fwdFlow(n, state, any(CallContextCall ccc), TParameterPositionSome(pos), + Stage5::fwdFlow(n, state, any(CallContextCall ccc), TParamNodeSome(p.asNode()), TAccessPathApproxSome(apa), apa0, config) ) } @@ -2838,10 +2817,9 @@ pragma[nomagic] private predicate nodeMayUseSummary( NodeEx n, FlowState state, AccessPathApprox apa, Configuration config ) { - exists(DataFlowCallable c, ParameterPosition pos, ParamNodeEx p | + exists(ParamNodeEx p | Stage5::parameterMayFlowThrough(p, apa, config) and - nodeMayUseSummary0(n, c, pos, state, apa, config) and - p.isParameterOf(c, pos) + nodeMayUseSummary0(n, p, state, apa, config) ) } diff --git a/cpp/ql/lib/semmle/code/cpp/dataflow/old/internal/DataFlowImpl2.qll b/cpp/ql/lib/semmle/code/cpp/dataflow/old/internal/DataFlowImpl2.qll index 6741ccc2f06..1228d00b6ba 100644 --- a/cpp/ql/lib/semmle/code/cpp/dataflow/old/internal/DataFlowImpl2.qll +++ b/cpp/ql/lib/semmle/code/cpp/dataflow/old/internal/DataFlowImpl2.qll @@ -622,7 +622,11 @@ private predicate parameterFlowThroughAllowed(ParamNodeEx p, ReturnKindExt kind) } private module Stage1 implements StageSig { - class Ap = Unit; + class Ap extends int { + // workaround for bad functionality-induced joins (happens when using `Unit`) + pragma[nomagic] + Ap() { this in [0 .. 1] and this < 1 } + } private class Cc = boolean; @@ -1327,8 +1331,8 @@ private module MkStage { */ pragma[nomagic] additional predicate fwdFlow( - NodeEx node, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - Ap ap, ApApprox apa, Configuration config + NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, + ApApprox apa, Configuration config ) { fwdFlow0(node, state, cc, summaryCtx, argAp, ap, apa, config) and PrevStage::revFlow(node, state, apa, config) and @@ -1337,21 +1341,21 @@ private module MkStage { pragma[inline] additional predicate fwdFlow( - NodeEx node, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - Ap ap, Configuration config + NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, + Configuration config ) { fwdFlow(node, state, cc, summaryCtx, argAp, ap, _, config) } pragma[nomagic] private predicate fwdFlow0( - NodeEx node, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - Ap ap, ApApprox apa, Configuration config + NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, + ApApprox apa, Configuration config ) { sourceNode(node, state, config) and (if hasSourceCallCtx(config) then cc = ccSomeCall() else cc = ccNone()) and argAp = apNone() and - summaryCtx = TParameterPositionNone() and + summaryCtx = TParamNodeNone() and ap = getApNil(node) and apa = getApprox(ap) or @@ -1372,7 +1376,7 @@ private module MkStage { fwdFlow(mid, pragma[only_bind_into](state), _, _, _, ap, apa, pragma[only_bind_into](config)) and jumpStep(mid, node, config) and cc = ccNone() and - summaryCtx = TParameterPositionNone() and + summaryCtx = TParamNodeNone() and argAp = apNone() ) or @@ -1380,7 +1384,7 @@ private module MkStage { fwdFlow(mid, state, _, _, _, nil, pragma[only_bind_into](config)) and additionalJumpStep(mid, node, config) and cc = ccNone() and - summaryCtx = TParameterPositionNone() and + summaryCtx = TParamNodeNone() and argAp = apNone() and ap = getApNil(node) and apa = getApprox(ap) @@ -1390,7 +1394,7 @@ private module MkStage { fwdFlow(mid, state0, _, _, _, nil, pragma[only_bind_into](config)) and additionalJumpStateStep(mid, state0, node, state, config) and cc = ccNone() and - summaryCtx = TParameterPositionNone() and + summaryCtx = TParamNodeNone() and argAp = apNone() and ap = getApNil(node) and apa = getApprox(ap) @@ -1414,10 +1418,10 @@ private module MkStage { fwdFlowIn(_, node, state, _, cc, _, _, ap, apa, config) and if PrevStage::parameterMayFlowThrough(node, apa, config) then ( - summaryCtx = TParameterPositionSome(node.(ParamNodeEx).getPosition()) and + summaryCtx = TParamNodeSome(node.asNode()) and argAp = apSome(ap) ) else ( - summaryCtx = TParameterPositionNone() and argAp = apNone() + summaryCtx = TParamNodeNone() and argAp = apNone() ) or // flow out of a callable @@ -1433,16 +1437,19 @@ private module MkStage { ) or // flow through a callable - exists(DataFlowCall call, ParameterPosition summaryCtx0, Ap argAp0 | - fwdFlowOutFromArg(call, node, state, summaryCtx0, argAp0, ap, apa, config) and - fwdFlowIsEntered(call, cc, summaryCtx, argAp, summaryCtx0, argAp0, config) + exists( + DataFlowCall call, CcCall ccc, RetNodeEx ret, boolean allowsFieldFlow, ApApprox innerArgApa + | + fwdFlowThrough(call, cc, state, ccc, summaryCtx, argAp, ap, apa, ret, innerArgApa, config) and + flowThroughOutOfCall(call, ccc, ret, node, allowsFieldFlow, innerArgApa, apa, config) and + if allowsFieldFlow = false then ap instanceof ApNil else any() ) } pragma[nomagic] private predicate fwdFlowStore( NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, FlowState state, Cc cc, - ParameterPositionOption summaryCtx, ApOption argAp, Configuration config + ParamNodeOption summaryCtx, ApOption argAp, Configuration config ) { exists(DataFlowType contentType, ApApprox apa1 | fwdFlow(node1, state, cc, summaryCtx, argAp, ap1, apa1, config) and @@ -1473,8 +1480,8 @@ private module MkStage { pragma[nomagic] private predicate fwdFlowRead0( - NodeEx node1, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - ApNonNil ap, Configuration config + NodeEx node1, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, ApNonNil ap, + Configuration config ) { fwdFlow(node1, state, cc, summaryCtx, argAp, ap, config) and PrevStage::readStepCand(node1, _, _, config) @@ -1483,7 +1490,7 @@ private module MkStage { pragma[nomagic] private predicate fwdFlowRead( Ap ap, Content c, NodeEx node1, NodeEx node2, FlowState state, Cc cc, - ParameterPositionOption summaryCtx, ApOption argAp, Configuration config + ParamNodeOption summaryCtx, ApOption argAp, Configuration config ) { fwdFlowRead0(node1, state, cc, summaryCtx, argAp, ap, config) and PrevStage::readStepCand(node1, c, node2, config) and @@ -1493,7 +1500,7 @@ private module MkStage { pragma[nomagic] private predicate fwdFlowIn( DataFlowCall call, ParamNodeEx p, FlowState state, Cc outercc, CcCall innercc, - ParameterPositionOption summaryCtx, ApOption argAp, Ap ap, ApApprox apa, Configuration config + ParamNodeOption summaryCtx, ApOption argAp, Ap ap, ApApprox apa, Configuration config ) { exists(ArgNodeEx arg, boolean allowsFieldFlow | fwdFlow(arg, state, outercc, summaryCtx, argAp, ap, apa, config) and @@ -1505,64 +1512,38 @@ private module MkStage { pragma[nomagic] private predicate fwdFlowRetFromArg( - RetNodeEx ret, FlowState state, CcCall ccc, ParameterPosition summaryCtx, ParamNodeEx p, - Ap argAp, ApApprox argApa, Ap ap, ApApprox apa, Configuration config + RetNodeEx ret, FlowState state, CcCall ccc, ParamNodeEx summaryCtx, Ap argAp, ApApprox argApa, + Ap ap, ApApprox apa, Configuration config ) { - exists(DataFlowCallable c, ReturnKindExt kind | + exists(ReturnKindExt kind | fwdFlow(pragma[only_bind_into](ret), state, ccc, - TParameterPositionSome(pragma[only_bind_into](summaryCtx)), apSome(argAp), ap, apa, config) and - getApprox(argAp) = argApa and - c = ret.getEnclosingCallable() and + TParamNodeSome(pragma[only_bind_into](summaryCtx.asNode())), + pragma[only_bind_into](apSome(argAp)), ap, pragma[only_bind_into](apa), + pragma[only_bind_into](config)) and kind = ret.getKind() and - p.isParameterOf(c, pragma[only_bind_into](summaryCtx)) and - parameterFlowThroughAllowed(p, kind) + parameterFlowThroughAllowed(summaryCtx, kind) and + argApa = getApprox(argAp) and + PrevStage::returnMayFlowThrough(ret, argApa, apa, kind, pragma[only_bind_into](config)) ) } pragma[inline] - private predicate fwdFlowInMayFlowThrough( - DataFlowCall call, Cc cc, CcCall innerCc, ParameterPositionOption summaryCtx, ApOption argAp, - ParamNodeEx param, Ap ap, ApApprox apa, Configuration config + private predicate fwdFlowThrough0( + DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, + ApOption argAp, Ap ap, ApApprox apa, RetNodeEx ret, ParamNodeEx innerSummaryCtx, + Ap innerArgAp, ApApprox innerArgApa, Configuration config ) { - fwdFlowIn(call, pragma[only_bind_into](param), _, cc, innerCc, summaryCtx, argAp, ap, - pragma[only_bind_into](apa), pragma[only_bind_into](config)) and - PrevStage::parameterMayFlowThrough(param, apa, config) - } - - // dedup before joining with `flowThroughOutOfCall` - pragma[nomagic] - private predicate fwdFlowInMayFlowThroughProj( - DataFlowCall call, CcCall innerCc, ApApprox apa, Configuration config - ) { - fwdFlowInMayFlowThrough(call, _, innerCc, _, _, _, _, apa, config) - } - - /** - * Same as `flowThroughOutOfCall`, but restricted to calls that are reached - * in the flow covered by `fwdFlow`, where data might flow through the target - * callable and back out at `call`. - */ - pragma[nomagic] - private predicate fwdFlowThroughOutOfCall( - DataFlowCall call, CcCall ccc, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow, - ApApprox argApa, ApApprox apa, Configuration config - ) { - fwdFlowInMayFlowThroughProj(call, ccc, argApa, config) and - flowThroughOutOfCall(call, ccc, ret, out, allowsFieldFlow, argApa, apa, config) + fwdFlowRetFromArg(ret, state, ccc, innerSummaryCtx, innerArgAp, innerArgApa, ap, apa, config) and + fwdFlowIsEntered(call, cc, ccc, summaryCtx, argAp, innerSummaryCtx, innerArgAp, config) } pragma[nomagic] - private predicate fwdFlowOutFromArg( - DataFlowCall call, NodeEx out, FlowState state, ParameterPosition summaryCtx, Ap argAp, Ap ap, - ApApprox apa, Configuration config + private predicate fwdFlowThrough( + DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, + ApOption argAp, Ap ap, ApApprox apa, RetNodeEx ret, ApApprox innerArgApa, Configuration config ) { - exists(RetNodeEx ret, boolean allowsFieldFlow, CcCall ccc, ApApprox argApa | - fwdFlowRetFromArg(pragma[only_bind_into](ret), state, pragma[only_bind_into](ccc), - summaryCtx, _, argAp, pragma[only_bind_into](argApa), ap, pragma[only_bind_into](apa), - config) and - fwdFlowThroughOutOfCall(call, ccc, ret, out, allowsFieldFlow, argApa, apa, config) and - (if allowsFieldFlow = false then ap instanceof ApNil else any()) - ) + fwdFlowThrough0(call, cc, state, ccc, summaryCtx, argAp, ap, apa, ret, _, _, innerArgApa, + config) } /** @@ -1571,12 +1552,14 @@ private module MkStage { */ pragma[nomagic] private predicate fwdFlowIsEntered( - DataFlowCall call, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - ParameterPosition pos, Ap ap, Configuration config + DataFlowCall call, Cc cc, CcCall innerCc, ParamNodeOption summaryCtx, ApOption argAp, + ParamNodeEx p, Ap ap, Configuration config ) { - exists(ParamNodeEx param | - fwdFlowInMayFlowThrough(call, cc, _, summaryCtx, argAp, param, ap, _, config) and - pos = param.getPosition() + exists(ApApprox apa | + fwdFlowIn(call, pragma[only_bind_into](p), _, cc, innerCc, summaryCtx, argAp, ap, + pragma[only_bind_into](apa), pragma[only_bind_into](config)) and + PrevStage::parameterMayFlowThrough(p, apa, config) and + PrevStage::callMayFlowThroughRev(call, pragma[only_bind_into](config)) ) } @@ -1596,23 +1579,31 @@ private module MkStage { fwdFlowConsCand(ap1, c, ap2, config) } + pragma[nomagic] + private predicate returnFlowsThrough0( + DataFlowCall call, FlowState state, CcCall ccc, Ap ap, ApApprox apa, RetNodeEx ret, + ParamNodeEx innerSummaryCtx, Ap innerArgAp, ApApprox innerArgApa, Configuration config + ) { + fwdFlowThrough0(call, _, state, ccc, _, _, ap, apa, ret, innerSummaryCtx, innerArgAp, + innerArgApa, config) + } + pragma[nomagic] private predicate returnFlowsThrough( - RetNodeEx ret, ReturnKindExt kind, FlowState state, CcCall ccc, ParamNodeEx p, Ap argAp, + RetNodeEx ret, ReturnPosition pos, FlowState state, CcCall ccc, ParamNodeEx p, Ap argAp, Ap ap, Configuration config ) { - exists(boolean allowsFieldFlow, ApApprox argApa, ApApprox apa | - fwdFlowRetFromArg(pragma[only_bind_into](ret), state, pragma[only_bind_into](ccc), _, p, - argAp, pragma[only_bind_into](argApa), ap, pragma[only_bind_into](apa), config) and - kind = ret.getKind() and - fwdFlowThroughOutOfCall(_, ccc, ret, _, allowsFieldFlow, argApa, apa, config) and - (if allowsFieldFlow = false then ap instanceof ApNil else any()) + exists(DataFlowCall call, ApApprox apa, boolean allowsFieldFlow, ApApprox innerArgApa | + returnFlowsThrough0(call, state, ccc, ap, apa, ret, p, argAp, innerArgApa, config) and + flowThroughOutOfCall(call, ccc, ret, _, allowsFieldFlow, innerArgApa, apa, config) and + pos = ret.getReturnPosition() and + if allowsFieldFlow = false then ap instanceof ApNil else any() ) } pragma[nomagic] private predicate flowThroughIntoCall( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap argAp, + DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap argAp, Ap ap, Configuration config ) { exists(ApApprox argApa | @@ -1620,7 +1611,7 @@ private module MkStage { allowsFieldFlow, argApa, pragma[only_bind_into](config)) and fwdFlow(arg, _, _, _, _, pragma[only_bind_into](argAp), argApa, pragma[only_bind_into](config)) and - returnFlowsThrough(_, _, _, _, p, pragma[only_bind_into](argAp), _, + returnFlowsThrough(_, _, _, _, p, pragma[only_bind_into](argAp), ap, pragma[only_bind_into](config)) and if allowsFieldFlow = false then argAp instanceof ApNil else any() ) @@ -1639,12 +1630,13 @@ private module MkStage { pragma[nomagic] private predicate flowOutOfCallAp( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, boolean allowsFieldFlow, + DataFlowCall call, RetNodeEx ret, ReturnPosition pos, NodeEx out, boolean allowsFieldFlow, Ap ap, Configuration config ) { exists(ApApprox apa | - flowOutOfCallApa(call, ret, kind, out, allowsFieldFlow, apa, config) and - fwdFlow(ret, _, _, _, _, ap, apa, config) + flowOutOfCallApa(call, ret, _, out, allowsFieldFlow, apa, config) and + fwdFlow(ret, _, _, _, _, ap, apa, config) and + pos = ret.getReturnPosition() ) } @@ -1739,17 +1731,17 @@ private module MkStage { ) or // flow through a callable - exists(DataFlowCall call, ReturnKindExt returnKind0, Ap returnAp0 | - revFlowInToReturn(call, node, state, returnKind0, returnAp0, ap, config) and - revFlowIsReturned(call, returnCtx, returnAp, returnKind0, returnAp0, config) + exists(DataFlowCall call, ParamNodeEx p, ReturnPosition pos, Ap innerReturnAp | + revFlowThrough(call, returnCtx, p, state, pos, returnAp, ap, innerReturnAp, config) and + flowThroughIntoCall(call, node, p, _, ap, innerReturnAp, config) ) or // flow out of a callable - exists(ReturnKindExt kind | - revFlowOut(_, node, kind, state, _, _, ap, config) and - if returnFlowsThrough(node, kind, state, _, _, _, ap, config) + exists(ReturnPosition pos | + revFlowOut(_, node, pos, state, _, _, ap, config) and + if returnFlowsThrough(node, pos, state, _, _, _, ap, config) then ( - returnCtx = TReturnCtxMaybeFlowThrough(kind) and + returnCtx = TReturnCtxMaybeFlowThrough(pos) and returnAp = apSome(ap) ) else ( returnCtx = TReturnCtxNoFlowThrough() and returnAp = apNone() @@ -1782,47 +1774,33 @@ private module MkStage { pragma[nomagic] private predicate revFlowOut( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, FlowState state, ReturnCtx returnCtx, + DataFlowCall call, RetNodeEx ret, ReturnPosition pos, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap, Configuration config ) { exists(NodeEx out, boolean allowsFieldFlow | revFlow(out, state, returnCtx, returnAp, ap, config) and - flowOutOfCallAp(call, ret, kind, out, allowsFieldFlow, ap, config) and + flowOutOfCallAp(call, ret, pos, out, allowsFieldFlow, ap, config) and if allowsFieldFlow = false then ap instanceof ApNil else any() ) } - /** - * Same as `flowThroughIntoCall`, but restricted to calls that are reached - * in the flow covered by `revFlow`, where data might flow through the target - * callable and back out at `call`. - */ - pragma[nomagic] - private predicate revFlowThroughIntoCall( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap argAp, - Configuration config - ) { - flowThroughIntoCall(call, arg, p, allowsFieldFlow, argAp, config) and - revFlowIsReturned(call, _, _, _, _, config) - } - pragma[nomagic] private predicate revFlowParamToReturn( - ParamNodeEx p, FlowState state, ReturnKindExt kind, Ap returnAp, Ap ap, Configuration config + ParamNodeEx p, FlowState state, ReturnPosition pos, Ap returnAp, Ap ap, Configuration config ) { - revFlow(p, state, TReturnCtxMaybeFlowThrough(kind), apSome(returnAp), ap, config) and - parameterFlowThroughAllowed(p, kind) + revFlow(pragma[only_bind_into](p), state, TReturnCtxMaybeFlowThrough(pos), apSome(returnAp), + pragma[only_bind_into](ap), pragma[only_bind_into](config)) and + parameterFlowThroughAllowed(p, pos.getKind()) and + PrevStage::parameterMayFlowThrough(p, getApprox(ap), config) } pragma[nomagic] - private predicate revFlowInToReturn( - DataFlowCall call, ArgNodeEx arg, FlowState state, ReturnKindExt kind, Ap returnAp, Ap ap, - Configuration config + private predicate revFlowThrough( + DataFlowCall call, ReturnCtx returnCtx, ParamNodeEx p, FlowState state, ReturnPosition pos, + ApOption returnAp, Ap ap, Ap innerReturnAp, Configuration config ) { - exists(ParamNodeEx p, boolean allowsFieldFlow | - revFlowParamToReturn(p, state, kind, returnAp, ap, config) and - revFlowThroughIntoCall(call, arg, p, allowsFieldFlow, ap, config) - ) + revFlowParamToReturn(p, state, pos, innerReturnAp, ap, config) and + revFlowIsReturned(call, returnCtx, returnAp, pos, innerReturnAp, config) } /** @@ -1832,12 +1810,12 @@ private module MkStage { */ pragma[nomagic] private predicate revFlowIsReturned( - DataFlowCall call, ReturnCtx returnCtx, ApOption returnAp, ReturnKindExt kind, Ap ap, + DataFlowCall call, ReturnCtx returnCtx, ApOption returnAp, ReturnPosition pos, Ap ap, Configuration config ) { exists(RetNodeEx ret, FlowState state, CcCall ccc | - revFlowOut(call, ret, kind, state, returnCtx, returnAp, ap, config) and - returnFlowsThrough(ret, kind, state, ccc, _, _, ap, config) and + revFlowOut(call, ret, pos, state, returnCtx, returnAp, ap, config) and + returnFlowsThrough(ret, pos, state, ccc, _, _, ap, config) and matchesCall(ccc, call) ) } @@ -1915,17 +1893,17 @@ private module MkStage { pragma[nomagic] private predicate parameterFlowsThroughRev( - ParamNodeEx p, Ap ap, ReturnKindExt kind, Ap returnAp, Configuration config + ParamNodeEx p, Ap ap, ReturnPosition pos, Ap returnAp, Configuration config ) { - revFlow(p, _, TReturnCtxMaybeFlowThrough(kind), apSome(returnAp), ap, config) and - parameterFlowThroughAllowed(p, kind) + revFlow(p, _, TReturnCtxMaybeFlowThrough(pos), apSome(returnAp), ap, config) and + parameterFlowThroughAllowed(p, pos.getKind()) } pragma[nomagic] predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap, Configuration config) { - exists(RetNodeEx ret, ReturnKindExt kind | - returnFlowsThrough(ret, kind, _, _, p, ap, _, config) and - parameterFlowsThroughRev(p, ap, kind, _, config) + exists(RetNodeEx ret, ReturnPosition pos | + returnFlowsThrough(ret, pos, _, _, p, ap, _, config) and + parameterFlowsThroughRev(p, ap, pos, _, config) ) } @@ -1933,20 +1911,21 @@ private module MkStage { predicate returnMayFlowThrough( RetNodeEx ret, Ap argAp, Ap ap, ReturnKindExt kind, Configuration config ) { - exists(ParamNodeEx p | - returnFlowsThrough(ret, kind, _, _, p, argAp, ap, config) and - parameterFlowsThroughRev(p, argAp, kind, ap, config) + exists(ParamNodeEx p, ReturnPosition pos | + returnFlowsThrough(ret, pos, _, _, p, argAp, ap, config) and + parameterFlowsThroughRev(p, argAp, pos, ap, config) and + kind = pos.getKind() ) } pragma[nomagic] - predicate revFlowInToReturnIsReturned( + private predicate revFlowThroughArg( DataFlowCall call, ArgNodeEx arg, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap, Configuration config ) { - exists(ReturnKindExt returnKind0, Ap returnAp0 | - revFlowInToReturn(call, arg, state, returnKind0, returnAp0, ap, config) and - revFlowIsReturned(call, returnCtx, returnAp, returnKind0, returnAp0, config) + exists(ParamNodeEx p, ReturnPosition pos, Ap innerReturnAp | + revFlowThrough(call, returnCtx, p, state, pos, returnAp, ap, innerReturnAp, config) and + flowThroughIntoCall(call, arg, p, _, ap, innerReturnAp, config) ) } @@ -1954,7 +1933,7 @@ private module MkStage { predicate callMayFlowThroughRev(DataFlowCall call, Configuration config) { exists(ArgNodeEx arg, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap | revFlow(arg, state, returnCtx, returnAp, ap, config) and - revFlowInToReturnIsReturned(call, arg, state, returnCtx, returnAp, ap, config) + revFlowThroughArg(call, arg, state, returnCtx, returnAp, ap, config) ) } @@ -1967,8 +1946,9 @@ private module MkStage { conscand = count(TypedContent f0, Ap ap | fwdConsCand(f0, ap, config)) and states = count(FlowState state | fwdFlow(_, state, _, _, _, _, config)) and tuples = - count(NodeEx n, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - Ap ap | fwdFlow(n, state, cc, summaryCtx, argAp, ap, config)) + count(NodeEx n, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap | + fwdFlow(n, state, cc, summaryCtx, argAp, ap, config) + ) or fwd = false and nodes = count(NodeEx node | revFlow(node, _, _, _, _, config)) and @@ -2823,13 +2803,12 @@ private Configuration unbindConf(Configuration conf) { pragma[nomagic] private predicate nodeMayUseSummary0( - NodeEx n, DataFlowCallable c, ParameterPosition pos, FlowState state, AccessPathApprox apa, - Configuration config + NodeEx n, ParamNodeEx p, FlowState state, AccessPathApprox apa, Configuration config ) { exists(AccessPathApprox apa0 | - c = n.getEnclosingCallable() and + Stage5::parameterMayFlowThrough(p, _, _) and Stage5::revFlow(n, state, TReturnCtxMaybeFlowThrough(_), _, apa0, config) and - Stage5::fwdFlow(n, state, any(CallContextCall ccc), TParameterPositionSome(pos), + Stage5::fwdFlow(n, state, any(CallContextCall ccc), TParamNodeSome(p.asNode()), TAccessPathApproxSome(apa), apa0, config) ) } @@ -2838,10 +2817,9 @@ pragma[nomagic] private predicate nodeMayUseSummary( NodeEx n, FlowState state, AccessPathApprox apa, Configuration config ) { - exists(DataFlowCallable c, ParameterPosition pos, ParamNodeEx p | + exists(ParamNodeEx p | Stage5::parameterMayFlowThrough(p, apa, config) and - nodeMayUseSummary0(n, c, pos, state, apa, config) and - p.isParameterOf(c, pos) + nodeMayUseSummary0(n, p, state, apa, config) ) } diff --git a/cpp/ql/lib/semmle/code/cpp/dataflow/old/internal/DataFlowImpl3.qll b/cpp/ql/lib/semmle/code/cpp/dataflow/old/internal/DataFlowImpl3.qll index 6741ccc2f06..1228d00b6ba 100644 --- a/cpp/ql/lib/semmle/code/cpp/dataflow/old/internal/DataFlowImpl3.qll +++ b/cpp/ql/lib/semmle/code/cpp/dataflow/old/internal/DataFlowImpl3.qll @@ -622,7 +622,11 @@ private predicate parameterFlowThroughAllowed(ParamNodeEx p, ReturnKindExt kind) } private module Stage1 implements StageSig { - class Ap = Unit; + class Ap extends int { + // workaround for bad functionality-induced joins (happens when using `Unit`) + pragma[nomagic] + Ap() { this in [0 .. 1] and this < 1 } + } private class Cc = boolean; @@ -1327,8 +1331,8 @@ private module MkStage { */ pragma[nomagic] additional predicate fwdFlow( - NodeEx node, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - Ap ap, ApApprox apa, Configuration config + NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, + ApApprox apa, Configuration config ) { fwdFlow0(node, state, cc, summaryCtx, argAp, ap, apa, config) and PrevStage::revFlow(node, state, apa, config) and @@ -1337,21 +1341,21 @@ private module MkStage { pragma[inline] additional predicate fwdFlow( - NodeEx node, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - Ap ap, Configuration config + NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, + Configuration config ) { fwdFlow(node, state, cc, summaryCtx, argAp, ap, _, config) } pragma[nomagic] private predicate fwdFlow0( - NodeEx node, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - Ap ap, ApApprox apa, Configuration config + NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, + ApApprox apa, Configuration config ) { sourceNode(node, state, config) and (if hasSourceCallCtx(config) then cc = ccSomeCall() else cc = ccNone()) and argAp = apNone() and - summaryCtx = TParameterPositionNone() and + summaryCtx = TParamNodeNone() and ap = getApNil(node) and apa = getApprox(ap) or @@ -1372,7 +1376,7 @@ private module MkStage { fwdFlow(mid, pragma[only_bind_into](state), _, _, _, ap, apa, pragma[only_bind_into](config)) and jumpStep(mid, node, config) and cc = ccNone() and - summaryCtx = TParameterPositionNone() and + summaryCtx = TParamNodeNone() and argAp = apNone() ) or @@ -1380,7 +1384,7 @@ private module MkStage { fwdFlow(mid, state, _, _, _, nil, pragma[only_bind_into](config)) and additionalJumpStep(mid, node, config) and cc = ccNone() and - summaryCtx = TParameterPositionNone() and + summaryCtx = TParamNodeNone() and argAp = apNone() and ap = getApNil(node) and apa = getApprox(ap) @@ -1390,7 +1394,7 @@ private module MkStage { fwdFlow(mid, state0, _, _, _, nil, pragma[only_bind_into](config)) and additionalJumpStateStep(mid, state0, node, state, config) and cc = ccNone() and - summaryCtx = TParameterPositionNone() and + summaryCtx = TParamNodeNone() and argAp = apNone() and ap = getApNil(node) and apa = getApprox(ap) @@ -1414,10 +1418,10 @@ private module MkStage { fwdFlowIn(_, node, state, _, cc, _, _, ap, apa, config) and if PrevStage::parameterMayFlowThrough(node, apa, config) then ( - summaryCtx = TParameterPositionSome(node.(ParamNodeEx).getPosition()) and + summaryCtx = TParamNodeSome(node.asNode()) and argAp = apSome(ap) ) else ( - summaryCtx = TParameterPositionNone() and argAp = apNone() + summaryCtx = TParamNodeNone() and argAp = apNone() ) or // flow out of a callable @@ -1433,16 +1437,19 @@ private module MkStage { ) or // flow through a callable - exists(DataFlowCall call, ParameterPosition summaryCtx0, Ap argAp0 | - fwdFlowOutFromArg(call, node, state, summaryCtx0, argAp0, ap, apa, config) and - fwdFlowIsEntered(call, cc, summaryCtx, argAp, summaryCtx0, argAp0, config) + exists( + DataFlowCall call, CcCall ccc, RetNodeEx ret, boolean allowsFieldFlow, ApApprox innerArgApa + | + fwdFlowThrough(call, cc, state, ccc, summaryCtx, argAp, ap, apa, ret, innerArgApa, config) and + flowThroughOutOfCall(call, ccc, ret, node, allowsFieldFlow, innerArgApa, apa, config) and + if allowsFieldFlow = false then ap instanceof ApNil else any() ) } pragma[nomagic] private predicate fwdFlowStore( NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, FlowState state, Cc cc, - ParameterPositionOption summaryCtx, ApOption argAp, Configuration config + ParamNodeOption summaryCtx, ApOption argAp, Configuration config ) { exists(DataFlowType contentType, ApApprox apa1 | fwdFlow(node1, state, cc, summaryCtx, argAp, ap1, apa1, config) and @@ -1473,8 +1480,8 @@ private module MkStage { pragma[nomagic] private predicate fwdFlowRead0( - NodeEx node1, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - ApNonNil ap, Configuration config + NodeEx node1, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, ApNonNil ap, + Configuration config ) { fwdFlow(node1, state, cc, summaryCtx, argAp, ap, config) and PrevStage::readStepCand(node1, _, _, config) @@ -1483,7 +1490,7 @@ private module MkStage { pragma[nomagic] private predicate fwdFlowRead( Ap ap, Content c, NodeEx node1, NodeEx node2, FlowState state, Cc cc, - ParameterPositionOption summaryCtx, ApOption argAp, Configuration config + ParamNodeOption summaryCtx, ApOption argAp, Configuration config ) { fwdFlowRead0(node1, state, cc, summaryCtx, argAp, ap, config) and PrevStage::readStepCand(node1, c, node2, config) and @@ -1493,7 +1500,7 @@ private module MkStage { pragma[nomagic] private predicate fwdFlowIn( DataFlowCall call, ParamNodeEx p, FlowState state, Cc outercc, CcCall innercc, - ParameterPositionOption summaryCtx, ApOption argAp, Ap ap, ApApprox apa, Configuration config + ParamNodeOption summaryCtx, ApOption argAp, Ap ap, ApApprox apa, Configuration config ) { exists(ArgNodeEx arg, boolean allowsFieldFlow | fwdFlow(arg, state, outercc, summaryCtx, argAp, ap, apa, config) and @@ -1505,64 +1512,38 @@ private module MkStage { pragma[nomagic] private predicate fwdFlowRetFromArg( - RetNodeEx ret, FlowState state, CcCall ccc, ParameterPosition summaryCtx, ParamNodeEx p, - Ap argAp, ApApprox argApa, Ap ap, ApApprox apa, Configuration config + RetNodeEx ret, FlowState state, CcCall ccc, ParamNodeEx summaryCtx, Ap argAp, ApApprox argApa, + Ap ap, ApApprox apa, Configuration config ) { - exists(DataFlowCallable c, ReturnKindExt kind | + exists(ReturnKindExt kind | fwdFlow(pragma[only_bind_into](ret), state, ccc, - TParameterPositionSome(pragma[only_bind_into](summaryCtx)), apSome(argAp), ap, apa, config) and - getApprox(argAp) = argApa and - c = ret.getEnclosingCallable() and + TParamNodeSome(pragma[only_bind_into](summaryCtx.asNode())), + pragma[only_bind_into](apSome(argAp)), ap, pragma[only_bind_into](apa), + pragma[only_bind_into](config)) and kind = ret.getKind() and - p.isParameterOf(c, pragma[only_bind_into](summaryCtx)) and - parameterFlowThroughAllowed(p, kind) + parameterFlowThroughAllowed(summaryCtx, kind) and + argApa = getApprox(argAp) and + PrevStage::returnMayFlowThrough(ret, argApa, apa, kind, pragma[only_bind_into](config)) ) } pragma[inline] - private predicate fwdFlowInMayFlowThrough( - DataFlowCall call, Cc cc, CcCall innerCc, ParameterPositionOption summaryCtx, ApOption argAp, - ParamNodeEx param, Ap ap, ApApprox apa, Configuration config + private predicate fwdFlowThrough0( + DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, + ApOption argAp, Ap ap, ApApprox apa, RetNodeEx ret, ParamNodeEx innerSummaryCtx, + Ap innerArgAp, ApApprox innerArgApa, Configuration config ) { - fwdFlowIn(call, pragma[only_bind_into](param), _, cc, innerCc, summaryCtx, argAp, ap, - pragma[only_bind_into](apa), pragma[only_bind_into](config)) and - PrevStage::parameterMayFlowThrough(param, apa, config) - } - - // dedup before joining with `flowThroughOutOfCall` - pragma[nomagic] - private predicate fwdFlowInMayFlowThroughProj( - DataFlowCall call, CcCall innerCc, ApApprox apa, Configuration config - ) { - fwdFlowInMayFlowThrough(call, _, innerCc, _, _, _, _, apa, config) - } - - /** - * Same as `flowThroughOutOfCall`, but restricted to calls that are reached - * in the flow covered by `fwdFlow`, where data might flow through the target - * callable and back out at `call`. - */ - pragma[nomagic] - private predicate fwdFlowThroughOutOfCall( - DataFlowCall call, CcCall ccc, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow, - ApApprox argApa, ApApprox apa, Configuration config - ) { - fwdFlowInMayFlowThroughProj(call, ccc, argApa, config) and - flowThroughOutOfCall(call, ccc, ret, out, allowsFieldFlow, argApa, apa, config) + fwdFlowRetFromArg(ret, state, ccc, innerSummaryCtx, innerArgAp, innerArgApa, ap, apa, config) and + fwdFlowIsEntered(call, cc, ccc, summaryCtx, argAp, innerSummaryCtx, innerArgAp, config) } pragma[nomagic] - private predicate fwdFlowOutFromArg( - DataFlowCall call, NodeEx out, FlowState state, ParameterPosition summaryCtx, Ap argAp, Ap ap, - ApApprox apa, Configuration config + private predicate fwdFlowThrough( + DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, + ApOption argAp, Ap ap, ApApprox apa, RetNodeEx ret, ApApprox innerArgApa, Configuration config ) { - exists(RetNodeEx ret, boolean allowsFieldFlow, CcCall ccc, ApApprox argApa | - fwdFlowRetFromArg(pragma[only_bind_into](ret), state, pragma[only_bind_into](ccc), - summaryCtx, _, argAp, pragma[only_bind_into](argApa), ap, pragma[only_bind_into](apa), - config) and - fwdFlowThroughOutOfCall(call, ccc, ret, out, allowsFieldFlow, argApa, apa, config) and - (if allowsFieldFlow = false then ap instanceof ApNil else any()) - ) + fwdFlowThrough0(call, cc, state, ccc, summaryCtx, argAp, ap, apa, ret, _, _, innerArgApa, + config) } /** @@ -1571,12 +1552,14 @@ private module MkStage { */ pragma[nomagic] private predicate fwdFlowIsEntered( - DataFlowCall call, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - ParameterPosition pos, Ap ap, Configuration config + DataFlowCall call, Cc cc, CcCall innerCc, ParamNodeOption summaryCtx, ApOption argAp, + ParamNodeEx p, Ap ap, Configuration config ) { - exists(ParamNodeEx param | - fwdFlowInMayFlowThrough(call, cc, _, summaryCtx, argAp, param, ap, _, config) and - pos = param.getPosition() + exists(ApApprox apa | + fwdFlowIn(call, pragma[only_bind_into](p), _, cc, innerCc, summaryCtx, argAp, ap, + pragma[only_bind_into](apa), pragma[only_bind_into](config)) and + PrevStage::parameterMayFlowThrough(p, apa, config) and + PrevStage::callMayFlowThroughRev(call, pragma[only_bind_into](config)) ) } @@ -1596,23 +1579,31 @@ private module MkStage { fwdFlowConsCand(ap1, c, ap2, config) } + pragma[nomagic] + private predicate returnFlowsThrough0( + DataFlowCall call, FlowState state, CcCall ccc, Ap ap, ApApprox apa, RetNodeEx ret, + ParamNodeEx innerSummaryCtx, Ap innerArgAp, ApApprox innerArgApa, Configuration config + ) { + fwdFlowThrough0(call, _, state, ccc, _, _, ap, apa, ret, innerSummaryCtx, innerArgAp, + innerArgApa, config) + } + pragma[nomagic] private predicate returnFlowsThrough( - RetNodeEx ret, ReturnKindExt kind, FlowState state, CcCall ccc, ParamNodeEx p, Ap argAp, + RetNodeEx ret, ReturnPosition pos, FlowState state, CcCall ccc, ParamNodeEx p, Ap argAp, Ap ap, Configuration config ) { - exists(boolean allowsFieldFlow, ApApprox argApa, ApApprox apa | - fwdFlowRetFromArg(pragma[only_bind_into](ret), state, pragma[only_bind_into](ccc), _, p, - argAp, pragma[only_bind_into](argApa), ap, pragma[only_bind_into](apa), config) and - kind = ret.getKind() and - fwdFlowThroughOutOfCall(_, ccc, ret, _, allowsFieldFlow, argApa, apa, config) and - (if allowsFieldFlow = false then ap instanceof ApNil else any()) + exists(DataFlowCall call, ApApprox apa, boolean allowsFieldFlow, ApApprox innerArgApa | + returnFlowsThrough0(call, state, ccc, ap, apa, ret, p, argAp, innerArgApa, config) and + flowThroughOutOfCall(call, ccc, ret, _, allowsFieldFlow, innerArgApa, apa, config) and + pos = ret.getReturnPosition() and + if allowsFieldFlow = false then ap instanceof ApNil else any() ) } pragma[nomagic] private predicate flowThroughIntoCall( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap argAp, + DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap argAp, Ap ap, Configuration config ) { exists(ApApprox argApa | @@ -1620,7 +1611,7 @@ private module MkStage { allowsFieldFlow, argApa, pragma[only_bind_into](config)) and fwdFlow(arg, _, _, _, _, pragma[only_bind_into](argAp), argApa, pragma[only_bind_into](config)) and - returnFlowsThrough(_, _, _, _, p, pragma[only_bind_into](argAp), _, + returnFlowsThrough(_, _, _, _, p, pragma[only_bind_into](argAp), ap, pragma[only_bind_into](config)) and if allowsFieldFlow = false then argAp instanceof ApNil else any() ) @@ -1639,12 +1630,13 @@ private module MkStage { pragma[nomagic] private predicate flowOutOfCallAp( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, boolean allowsFieldFlow, + DataFlowCall call, RetNodeEx ret, ReturnPosition pos, NodeEx out, boolean allowsFieldFlow, Ap ap, Configuration config ) { exists(ApApprox apa | - flowOutOfCallApa(call, ret, kind, out, allowsFieldFlow, apa, config) and - fwdFlow(ret, _, _, _, _, ap, apa, config) + flowOutOfCallApa(call, ret, _, out, allowsFieldFlow, apa, config) and + fwdFlow(ret, _, _, _, _, ap, apa, config) and + pos = ret.getReturnPosition() ) } @@ -1739,17 +1731,17 @@ private module MkStage { ) or // flow through a callable - exists(DataFlowCall call, ReturnKindExt returnKind0, Ap returnAp0 | - revFlowInToReturn(call, node, state, returnKind0, returnAp0, ap, config) and - revFlowIsReturned(call, returnCtx, returnAp, returnKind0, returnAp0, config) + exists(DataFlowCall call, ParamNodeEx p, ReturnPosition pos, Ap innerReturnAp | + revFlowThrough(call, returnCtx, p, state, pos, returnAp, ap, innerReturnAp, config) and + flowThroughIntoCall(call, node, p, _, ap, innerReturnAp, config) ) or // flow out of a callable - exists(ReturnKindExt kind | - revFlowOut(_, node, kind, state, _, _, ap, config) and - if returnFlowsThrough(node, kind, state, _, _, _, ap, config) + exists(ReturnPosition pos | + revFlowOut(_, node, pos, state, _, _, ap, config) and + if returnFlowsThrough(node, pos, state, _, _, _, ap, config) then ( - returnCtx = TReturnCtxMaybeFlowThrough(kind) and + returnCtx = TReturnCtxMaybeFlowThrough(pos) and returnAp = apSome(ap) ) else ( returnCtx = TReturnCtxNoFlowThrough() and returnAp = apNone() @@ -1782,47 +1774,33 @@ private module MkStage { pragma[nomagic] private predicate revFlowOut( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, FlowState state, ReturnCtx returnCtx, + DataFlowCall call, RetNodeEx ret, ReturnPosition pos, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap, Configuration config ) { exists(NodeEx out, boolean allowsFieldFlow | revFlow(out, state, returnCtx, returnAp, ap, config) and - flowOutOfCallAp(call, ret, kind, out, allowsFieldFlow, ap, config) and + flowOutOfCallAp(call, ret, pos, out, allowsFieldFlow, ap, config) and if allowsFieldFlow = false then ap instanceof ApNil else any() ) } - /** - * Same as `flowThroughIntoCall`, but restricted to calls that are reached - * in the flow covered by `revFlow`, where data might flow through the target - * callable and back out at `call`. - */ - pragma[nomagic] - private predicate revFlowThroughIntoCall( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap argAp, - Configuration config - ) { - flowThroughIntoCall(call, arg, p, allowsFieldFlow, argAp, config) and - revFlowIsReturned(call, _, _, _, _, config) - } - pragma[nomagic] private predicate revFlowParamToReturn( - ParamNodeEx p, FlowState state, ReturnKindExt kind, Ap returnAp, Ap ap, Configuration config + ParamNodeEx p, FlowState state, ReturnPosition pos, Ap returnAp, Ap ap, Configuration config ) { - revFlow(p, state, TReturnCtxMaybeFlowThrough(kind), apSome(returnAp), ap, config) and - parameterFlowThroughAllowed(p, kind) + revFlow(pragma[only_bind_into](p), state, TReturnCtxMaybeFlowThrough(pos), apSome(returnAp), + pragma[only_bind_into](ap), pragma[only_bind_into](config)) and + parameterFlowThroughAllowed(p, pos.getKind()) and + PrevStage::parameterMayFlowThrough(p, getApprox(ap), config) } pragma[nomagic] - private predicate revFlowInToReturn( - DataFlowCall call, ArgNodeEx arg, FlowState state, ReturnKindExt kind, Ap returnAp, Ap ap, - Configuration config + private predicate revFlowThrough( + DataFlowCall call, ReturnCtx returnCtx, ParamNodeEx p, FlowState state, ReturnPosition pos, + ApOption returnAp, Ap ap, Ap innerReturnAp, Configuration config ) { - exists(ParamNodeEx p, boolean allowsFieldFlow | - revFlowParamToReturn(p, state, kind, returnAp, ap, config) and - revFlowThroughIntoCall(call, arg, p, allowsFieldFlow, ap, config) - ) + revFlowParamToReturn(p, state, pos, innerReturnAp, ap, config) and + revFlowIsReturned(call, returnCtx, returnAp, pos, innerReturnAp, config) } /** @@ -1832,12 +1810,12 @@ private module MkStage { */ pragma[nomagic] private predicate revFlowIsReturned( - DataFlowCall call, ReturnCtx returnCtx, ApOption returnAp, ReturnKindExt kind, Ap ap, + DataFlowCall call, ReturnCtx returnCtx, ApOption returnAp, ReturnPosition pos, Ap ap, Configuration config ) { exists(RetNodeEx ret, FlowState state, CcCall ccc | - revFlowOut(call, ret, kind, state, returnCtx, returnAp, ap, config) and - returnFlowsThrough(ret, kind, state, ccc, _, _, ap, config) and + revFlowOut(call, ret, pos, state, returnCtx, returnAp, ap, config) and + returnFlowsThrough(ret, pos, state, ccc, _, _, ap, config) and matchesCall(ccc, call) ) } @@ -1915,17 +1893,17 @@ private module MkStage { pragma[nomagic] private predicate parameterFlowsThroughRev( - ParamNodeEx p, Ap ap, ReturnKindExt kind, Ap returnAp, Configuration config + ParamNodeEx p, Ap ap, ReturnPosition pos, Ap returnAp, Configuration config ) { - revFlow(p, _, TReturnCtxMaybeFlowThrough(kind), apSome(returnAp), ap, config) and - parameterFlowThroughAllowed(p, kind) + revFlow(p, _, TReturnCtxMaybeFlowThrough(pos), apSome(returnAp), ap, config) and + parameterFlowThroughAllowed(p, pos.getKind()) } pragma[nomagic] predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap, Configuration config) { - exists(RetNodeEx ret, ReturnKindExt kind | - returnFlowsThrough(ret, kind, _, _, p, ap, _, config) and - parameterFlowsThroughRev(p, ap, kind, _, config) + exists(RetNodeEx ret, ReturnPosition pos | + returnFlowsThrough(ret, pos, _, _, p, ap, _, config) and + parameterFlowsThroughRev(p, ap, pos, _, config) ) } @@ -1933,20 +1911,21 @@ private module MkStage { predicate returnMayFlowThrough( RetNodeEx ret, Ap argAp, Ap ap, ReturnKindExt kind, Configuration config ) { - exists(ParamNodeEx p | - returnFlowsThrough(ret, kind, _, _, p, argAp, ap, config) and - parameterFlowsThroughRev(p, argAp, kind, ap, config) + exists(ParamNodeEx p, ReturnPosition pos | + returnFlowsThrough(ret, pos, _, _, p, argAp, ap, config) and + parameterFlowsThroughRev(p, argAp, pos, ap, config) and + kind = pos.getKind() ) } pragma[nomagic] - predicate revFlowInToReturnIsReturned( + private predicate revFlowThroughArg( DataFlowCall call, ArgNodeEx arg, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap, Configuration config ) { - exists(ReturnKindExt returnKind0, Ap returnAp0 | - revFlowInToReturn(call, arg, state, returnKind0, returnAp0, ap, config) and - revFlowIsReturned(call, returnCtx, returnAp, returnKind0, returnAp0, config) + exists(ParamNodeEx p, ReturnPosition pos, Ap innerReturnAp | + revFlowThrough(call, returnCtx, p, state, pos, returnAp, ap, innerReturnAp, config) and + flowThroughIntoCall(call, arg, p, _, ap, innerReturnAp, config) ) } @@ -1954,7 +1933,7 @@ private module MkStage { predicate callMayFlowThroughRev(DataFlowCall call, Configuration config) { exists(ArgNodeEx arg, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap | revFlow(arg, state, returnCtx, returnAp, ap, config) and - revFlowInToReturnIsReturned(call, arg, state, returnCtx, returnAp, ap, config) + revFlowThroughArg(call, arg, state, returnCtx, returnAp, ap, config) ) } @@ -1967,8 +1946,9 @@ private module MkStage { conscand = count(TypedContent f0, Ap ap | fwdConsCand(f0, ap, config)) and states = count(FlowState state | fwdFlow(_, state, _, _, _, _, config)) and tuples = - count(NodeEx n, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - Ap ap | fwdFlow(n, state, cc, summaryCtx, argAp, ap, config)) + count(NodeEx n, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap | + fwdFlow(n, state, cc, summaryCtx, argAp, ap, config) + ) or fwd = false and nodes = count(NodeEx node | revFlow(node, _, _, _, _, config)) and @@ -2823,13 +2803,12 @@ private Configuration unbindConf(Configuration conf) { pragma[nomagic] private predicate nodeMayUseSummary0( - NodeEx n, DataFlowCallable c, ParameterPosition pos, FlowState state, AccessPathApprox apa, - Configuration config + NodeEx n, ParamNodeEx p, FlowState state, AccessPathApprox apa, Configuration config ) { exists(AccessPathApprox apa0 | - c = n.getEnclosingCallable() and + Stage5::parameterMayFlowThrough(p, _, _) and Stage5::revFlow(n, state, TReturnCtxMaybeFlowThrough(_), _, apa0, config) and - Stage5::fwdFlow(n, state, any(CallContextCall ccc), TParameterPositionSome(pos), + Stage5::fwdFlow(n, state, any(CallContextCall ccc), TParamNodeSome(p.asNode()), TAccessPathApproxSome(apa), apa0, config) ) } @@ -2838,10 +2817,9 @@ pragma[nomagic] private predicate nodeMayUseSummary( NodeEx n, FlowState state, AccessPathApprox apa, Configuration config ) { - exists(DataFlowCallable c, ParameterPosition pos, ParamNodeEx p | + exists(ParamNodeEx p | Stage5::parameterMayFlowThrough(p, apa, config) and - nodeMayUseSummary0(n, c, pos, state, apa, config) and - p.isParameterOf(c, pos) + nodeMayUseSummary0(n, p, state, apa, config) ) } diff --git a/cpp/ql/lib/semmle/code/cpp/dataflow/old/internal/DataFlowImpl4.qll b/cpp/ql/lib/semmle/code/cpp/dataflow/old/internal/DataFlowImpl4.qll index 6741ccc2f06..1228d00b6ba 100644 --- a/cpp/ql/lib/semmle/code/cpp/dataflow/old/internal/DataFlowImpl4.qll +++ b/cpp/ql/lib/semmle/code/cpp/dataflow/old/internal/DataFlowImpl4.qll @@ -622,7 +622,11 @@ private predicate parameterFlowThroughAllowed(ParamNodeEx p, ReturnKindExt kind) } private module Stage1 implements StageSig { - class Ap = Unit; + class Ap extends int { + // workaround for bad functionality-induced joins (happens when using `Unit`) + pragma[nomagic] + Ap() { this in [0 .. 1] and this < 1 } + } private class Cc = boolean; @@ -1327,8 +1331,8 @@ private module MkStage { */ pragma[nomagic] additional predicate fwdFlow( - NodeEx node, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - Ap ap, ApApprox apa, Configuration config + NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, + ApApprox apa, Configuration config ) { fwdFlow0(node, state, cc, summaryCtx, argAp, ap, apa, config) and PrevStage::revFlow(node, state, apa, config) and @@ -1337,21 +1341,21 @@ private module MkStage { pragma[inline] additional predicate fwdFlow( - NodeEx node, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - Ap ap, Configuration config + NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, + Configuration config ) { fwdFlow(node, state, cc, summaryCtx, argAp, ap, _, config) } pragma[nomagic] private predicate fwdFlow0( - NodeEx node, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - Ap ap, ApApprox apa, Configuration config + NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, + ApApprox apa, Configuration config ) { sourceNode(node, state, config) and (if hasSourceCallCtx(config) then cc = ccSomeCall() else cc = ccNone()) and argAp = apNone() and - summaryCtx = TParameterPositionNone() and + summaryCtx = TParamNodeNone() and ap = getApNil(node) and apa = getApprox(ap) or @@ -1372,7 +1376,7 @@ private module MkStage { fwdFlow(mid, pragma[only_bind_into](state), _, _, _, ap, apa, pragma[only_bind_into](config)) and jumpStep(mid, node, config) and cc = ccNone() and - summaryCtx = TParameterPositionNone() and + summaryCtx = TParamNodeNone() and argAp = apNone() ) or @@ -1380,7 +1384,7 @@ private module MkStage { fwdFlow(mid, state, _, _, _, nil, pragma[only_bind_into](config)) and additionalJumpStep(mid, node, config) and cc = ccNone() and - summaryCtx = TParameterPositionNone() and + summaryCtx = TParamNodeNone() and argAp = apNone() and ap = getApNil(node) and apa = getApprox(ap) @@ -1390,7 +1394,7 @@ private module MkStage { fwdFlow(mid, state0, _, _, _, nil, pragma[only_bind_into](config)) and additionalJumpStateStep(mid, state0, node, state, config) and cc = ccNone() and - summaryCtx = TParameterPositionNone() and + summaryCtx = TParamNodeNone() and argAp = apNone() and ap = getApNil(node) and apa = getApprox(ap) @@ -1414,10 +1418,10 @@ private module MkStage { fwdFlowIn(_, node, state, _, cc, _, _, ap, apa, config) and if PrevStage::parameterMayFlowThrough(node, apa, config) then ( - summaryCtx = TParameterPositionSome(node.(ParamNodeEx).getPosition()) and + summaryCtx = TParamNodeSome(node.asNode()) and argAp = apSome(ap) ) else ( - summaryCtx = TParameterPositionNone() and argAp = apNone() + summaryCtx = TParamNodeNone() and argAp = apNone() ) or // flow out of a callable @@ -1433,16 +1437,19 @@ private module MkStage { ) or // flow through a callable - exists(DataFlowCall call, ParameterPosition summaryCtx0, Ap argAp0 | - fwdFlowOutFromArg(call, node, state, summaryCtx0, argAp0, ap, apa, config) and - fwdFlowIsEntered(call, cc, summaryCtx, argAp, summaryCtx0, argAp0, config) + exists( + DataFlowCall call, CcCall ccc, RetNodeEx ret, boolean allowsFieldFlow, ApApprox innerArgApa + | + fwdFlowThrough(call, cc, state, ccc, summaryCtx, argAp, ap, apa, ret, innerArgApa, config) and + flowThroughOutOfCall(call, ccc, ret, node, allowsFieldFlow, innerArgApa, apa, config) and + if allowsFieldFlow = false then ap instanceof ApNil else any() ) } pragma[nomagic] private predicate fwdFlowStore( NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, FlowState state, Cc cc, - ParameterPositionOption summaryCtx, ApOption argAp, Configuration config + ParamNodeOption summaryCtx, ApOption argAp, Configuration config ) { exists(DataFlowType contentType, ApApprox apa1 | fwdFlow(node1, state, cc, summaryCtx, argAp, ap1, apa1, config) and @@ -1473,8 +1480,8 @@ private module MkStage { pragma[nomagic] private predicate fwdFlowRead0( - NodeEx node1, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - ApNonNil ap, Configuration config + NodeEx node1, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, ApNonNil ap, + Configuration config ) { fwdFlow(node1, state, cc, summaryCtx, argAp, ap, config) and PrevStage::readStepCand(node1, _, _, config) @@ -1483,7 +1490,7 @@ private module MkStage { pragma[nomagic] private predicate fwdFlowRead( Ap ap, Content c, NodeEx node1, NodeEx node2, FlowState state, Cc cc, - ParameterPositionOption summaryCtx, ApOption argAp, Configuration config + ParamNodeOption summaryCtx, ApOption argAp, Configuration config ) { fwdFlowRead0(node1, state, cc, summaryCtx, argAp, ap, config) and PrevStage::readStepCand(node1, c, node2, config) and @@ -1493,7 +1500,7 @@ private module MkStage { pragma[nomagic] private predicate fwdFlowIn( DataFlowCall call, ParamNodeEx p, FlowState state, Cc outercc, CcCall innercc, - ParameterPositionOption summaryCtx, ApOption argAp, Ap ap, ApApprox apa, Configuration config + ParamNodeOption summaryCtx, ApOption argAp, Ap ap, ApApprox apa, Configuration config ) { exists(ArgNodeEx arg, boolean allowsFieldFlow | fwdFlow(arg, state, outercc, summaryCtx, argAp, ap, apa, config) and @@ -1505,64 +1512,38 @@ private module MkStage { pragma[nomagic] private predicate fwdFlowRetFromArg( - RetNodeEx ret, FlowState state, CcCall ccc, ParameterPosition summaryCtx, ParamNodeEx p, - Ap argAp, ApApprox argApa, Ap ap, ApApprox apa, Configuration config + RetNodeEx ret, FlowState state, CcCall ccc, ParamNodeEx summaryCtx, Ap argAp, ApApprox argApa, + Ap ap, ApApprox apa, Configuration config ) { - exists(DataFlowCallable c, ReturnKindExt kind | + exists(ReturnKindExt kind | fwdFlow(pragma[only_bind_into](ret), state, ccc, - TParameterPositionSome(pragma[only_bind_into](summaryCtx)), apSome(argAp), ap, apa, config) and - getApprox(argAp) = argApa and - c = ret.getEnclosingCallable() and + TParamNodeSome(pragma[only_bind_into](summaryCtx.asNode())), + pragma[only_bind_into](apSome(argAp)), ap, pragma[only_bind_into](apa), + pragma[only_bind_into](config)) and kind = ret.getKind() and - p.isParameterOf(c, pragma[only_bind_into](summaryCtx)) and - parameterFlowThroughAllowed(p, kind) + parameterFlowThroughAllowed(summaryCtx, kind) and + argApa = getApprox(argAp) and + PrevStage::returnMayFlowThrough(ret, argApa, apa, kind, pragma[only_bind_into](config)) ) } pragma[inline] - private predicate fwdFlowInMayFlowThrough( - DataFlowCall call, Cc cc, CcCall innerCc, ParameterPositionOption summaryCtx, ApOption argAp, - ParamNodeEx param, Ap ap, ApApprox apa, Configuration config + private predicate fwdFlowThrough0( + DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, + ApOption argAp, Ap ap, ApApprox apa, RetNodeEx ret, ParamNodeEx innerSummaryCtx, + Ap innerArgAp, ApApprox innerArgApa, Configuration config ) { - fwdFlowIn(call, pragma[only_bind_into](param), _, cc, innerCc, summaryCtx, argAp, ap, - pragma[only_bind_into](apa), pragma[only_bind_into](config)) and - PrevStage::parameterMayFlowThrough(param, apa, config) - } - - // dedup before joining with `flowThroughOutOfCall` - pragma[nomagic] - private predicate fwdFlowInMayFlowThroughProj( - DataFlowCall call, CcCall innerCc, ApApprox apa, Configuration config - ) { - fwdFlowInMayFlowThrough(call, _, innerCc, _, _, _, _, apa, config) - } - - /** - * Same as `flowThroughOutOfCall`, but restricted to calls that are reached - * in the flow covered by `fwdFlow`, where data might flow through the target - * callable and back out at `call`. - */ - pragma[nomagic] - private predicate fwdFlowThroughOutOfCall( - DataFlowCall call, CcCall ccc, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow, - ApApprox argApa, ApApprox apa, Configuration config - ) { - fwdFlowInMayFlowThroughProj(call, ccc, argApa, config) and - flowThroughOutOfCall(call, ccc, ret, out, allowsFieldFlow, argApa, apa, config) + fwdFlowRetFromArg(ret, state, ccc, innerSummaryCtx, innerArgAp, innerArgApa, ap, apa, config) and + fwdFlowIsEntered(call, cc, ccc, summaryCtx, argAp, innerSummaryCtx, innerArgAp, config) } pragma[nomagic] - private predicate fwdFlowOutFromArg( - DataFlowCall call, NodeEx out, FlowState state, ParameterPosition summaryCtx, Ap argAp, Ap ap, - ApApprox apa, Configuration config + private predicate fwdFlowThrough( + DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, + ApOption argAp, Ap ap, ApApprox apa, RetNodeEx ret, ApApprox innerArgApa, Configuration config ) { - exists(RetNodeEx ret, boolean allowsFieldFlow, CcCall ccc, ApApprox argApa | - fwdFlowRetFromArg(pragma[only_bind_into](ret), state, pragma[only_bind_into](ccc), - summaryCtx, _, argAp, pragma[only_bind_into](argApa), ap, pragma[only_bind_into](apa), - config) and - fwdFlowThroughOutOfCall(call, ccc, ret, out, allowsFieldFlow, argApa, apa, config) and - (if allowsFieldFlow = false then ap instanceof ApNil else any()) - ) + fwdFlowThrough0(call, cc, state, ccc, summaryCtx, argAp, ap, apa, ret, _, _, innerArgApa, + config) } /** @@ -1571,12 +1552,14 @@ private module MkStage { */ pragma[nomagic] private predicate fwdFlowIsEntered( - DataFlowCall call, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - ParameterPosition pos, Ap ap, Configuration config + DataFlowCall call, Cc cc, CcCall innerCc, ParamNodeOption summaryCtx, ApOption argAp, + ParamNodeEx p, Ap ap, Configuration config ) { - exists(ParamNodeEx param | - fwdFlowInMayFlowThrough(call, cc, _, summaryCtx, argAp, param, ap, _, config) and - pos = param.getPosition() + exists(ApApprox apa | + fwdFlowIn(call, pragma[only_bind_into](p), _, cc, innerCc, summaryCtx, argAp, ap, + pragma[only_bind_into](apa), pragma[only_bind_into](config)) and + PrevStage::parameterMayFlowThrough(p, apa, config) and + PrevStage::callMayFlowThroughRev(call, pragma[only_bind_into](config)) ) } @@ -1596,23 +1579,31 @@ private module MkStage { fwdFlowConsCand(ap1, c, ap2, config) } + pragma[nomagic] + private predicate returnFlowsThrough0( + DataFlowCall call, FlowState state, CcCall ccc, Ap ap, ApApprox apa, RetNodeEx ret, + ParamNodeEx innerSummaryCtx, Ap innerArgAp, ApApprox innerArgApa, Configuration config + ) { + fwdFlowThrough0(call, _, state, ccc, _, _, ap, apa, ret, innerSummaryCtx, innerArgAp, + innerArgApa, config) + } + pragma[nomagic] private predicate returnFlowsThrough( - RetNodeEx ret, ReturnKindExt kind, FlowState state, CcCall ccc, ParamNodeEx p, Ap argAp, + RetNodeEx ret, ReturnPosition pos, FlowState state, CcCall ccc, ParamNodeEx p, Ap argAp, Ap ap, Configuration config ) { - exists(boolean allowsFieldFlow, ApApprox argApa, ApApprox apa | - fwdFlowRetFromArg(pragma[only_bind_into](ret), state, pragma[only_bind_into](ccc), _, p, - argAp, pragma[only_bind_into](argApa), ap, pragma[only_bind_into](apa), config) and - kind = ret.getKind() and - fwdFlowThroughOutOfCall(_, ccc, ret, _, allowsFieldFlow, argApa, apa, config) and - (if allowsFieldFlow = false then ap instanceof ApNil else any()) + exists(DataFlowCall call, ApApprox apa, boolean allowsFieldFlow, ApApprox innerArgApa | + returnFlowsThrough0(call, state, ccc, ap, apa, ret, p, argAp, innerArgApa, config) and + flowThroughOutOfCall(call, ccc, ret, _, allowsFieldFlow, innerArgApa, apa, config) and + pos = ret.getReturnPosition() and + if allowsFieldFlow = false then ap instanceof ApNil else any() ) } pragma[nomagic] private predicate flowThroughIntoCall( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap argAp, + DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap argAp, Ap ap, Configuration config ) { exists(ApApprox argApa | @@ -1620,7 +1611,7 @@ private module MkStage { allowsFieldFlow, argApa, pragma[only_bind_into](config)) and fwdFlow(arg, _, _, _, _, pragma[only_bind_into](argAp), argApa, pragma[only_bind_into](config)) and - returnFlowsThrough(_, _, _, _, p, pragma[only_bind_into](argAp), _, + returnFlowsThrough(_, _, _, _, p, pragma[only_bind_into](argAp), ap, pragma[only_bind_into](config)) and if allowsFieldFlow = false then argAp instanceof ApNil else any() ) @@ -1639,12 +1630,13 @@ private module MkStage { pragma[nomagic] private predicate flowOutOfCallAp( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, boolean allowsFieldFlow, + DataFlowCall call, RetNodeEx ret, ReturnPosition pos, NodeEx out, boolean allowsFieldFlow, Ap ap, Configuration config ) { exists(ApApprox apa | - flowOutOfCallApa(call, ret, kind, out, allowsFieldFlow, apa, config) and - fwdFlow(ret, _, _, _, _, ap, apa, config) + flowOutOfCallApa(call, ret, _, out, allowsFieldFlow, apa, config) and + fwdFlow(ret, _, _, _, _, ap, apa, config) and + pos = ret.getReturnPosition() ) } @@ -1739,17 +1731,17 @@ private module MkStage { ) or // flow through a callable - exists(DataFlowCall call, ReturnKindExt returnKind0, Ap returnAp0 | - revFlowInToReturn(call, node, state, returnKind0, returnAp0, ap, config) and - revFlowIsReturned(call, returnCtx, returnAp, returnKind0, returnAp0, config) + exists(DataFlowCall call, ParamNodeEx p, ReturnPosition pos, Ap innerReturnAp | + revFlowThrough(call, returnCtx, p, state, pos, returnAp, ap, innerReturnAp, config) and + flowThroughIntoCall(call, node, p, _, ap, innerReturnAp, config) ) or // flow out of a callable - exists(ReturnKindExt kind | - revFlowOut(_, node, kind, state, _, _, ap, config) and - if returnFlowsThrough(node, kind, state, _, _, _, ap, config) + exists(ReturnPosition pos | + revFlowOut(_, node, pos, state, _, _, ap, config) and + if returnFlowsThrough(node, pos, state, _, _, _, ap, config) then ( - returnCtx = TReturnCtxMaybeFlowThrough(kind) and + returnCtx = TReturnCtxMaybeFlowThrough(pos) and returnAp = apSome(ap) ) else ( returnCtx = TReturnCtxNoFlowThrough() and returnAp = apNone() @@ -1782,47 +1774,33 @@ private module MkStage { pragma[nomagic] private predicate revFlowOut( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, FlowState state, ReturnCtx returnCtx, + DataFlowCall call, RetNodeEx ret, ReturnPosition pos, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap, Configuration config ) { exists(NodeEx out, boolean allowsFieldFlow | revFlow(out, state, returnCtx, returnAp, ap, config) and - flowOutOfCallAp(call, ret, kind, out, allowsFieldFlow, ap, config) and + flowOutOfCallAp(call, ret, pos, out, allowsFieldFlow, ap, config) and if allowsFieldFlow = false then ap instanceof ApNil else any() ) } - /** - * Same as `flowThroughIntoCall`, but restricted to calls that are reached - * in the flow covered by `revFlow`, where data might flow through the target - * callable and back out at `call`. - */ - pragma[nomagic] - private predicate revFlowThroughIntoCall( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap argAp, - Configuration config - ) { - flowThroughIntoCall(call, arg, p, allowsFieldFlow, argAp, config) and - revFlowIsReturned(call, _, _, _, _, config) - } - pragma[nomagic] private predicate revFlowParamToReturn( - ParamNodeEx p, FlowState state, ReturnKindExt kind, Ap returnAp, Ap ap, Configuration config + ParamNodeEx p, FlowState state, ReturnPosition pos, Ap returnAp, Ap ap, Configuration config ) { - revFlow(p, state, TReturnCtxMaybeFlowThrough(kind), apSome(returnAp), ap, config) and - parameterFlowThroughAllowed(p, kind) + revFlow(pragma[only_bind_into](p), state, TReturnCtxMaybeFlowThrough(pos), apSome(returnAp), + pragma[only_bind_into](ap), pragma[only_bind_into](config)) and + parameterFlowThroughAllowed(p, pos.getKind()) and + PrevStage::parameterMayFlowThrough(p, getApprox(ap), config) } pragma[nomagic] - private predicate revFlowInToReturn( - DataFlowCall call, ArgNodeEx arg, FlowState state, ReturnKindExt kind, Ap returnAp, Ap ap, - Configuration config + private predicate revFlowThrough( + DataFlowCall call, ReturnCtx returnCtx, ParamNodeEx p, FlowState state, ReturnPosition pos, + ApOption returnAp, Ap ap, Ap innerReturnAp, Configuration config ) { - exists(ParamNodeEx p, boolean allowsFieldFlow | - revFlowParamToReturn(p, state, kind, returnAp, ap, config) and - revFlowThroughIntoCall(call, arg, p, allowsFieldFlow, ap, config) - ) + revFlowParamToReturn(p, state, pos, innerReturnAp, ap, config) and + revFlowIsReturned(call, returnCtx, returnAp, pos, innerReturnAp, config) } /** @@ -1832,12 +1810,12 @@ private module MkStage { */ pragma[nomagic] private predicate revFlowIsReturned( - DataFlowCall call, ReturnCtx returnCtx, ApOption returnAp, ReturnKindExt kind, Ap ap, + DataFlowCall call, ReturnCtx returnCtx, ApOption returnAp, ReturnPosition pos, Ap ap, Configuration config ) { exists(RetNodeEx ret, FlowState state, CcCall ccc | - revFlowOut(call, ret, kind, state, returnCtx, returnAp, ap, config) and - returnFlowsThrough(ret, kind, state, ccc, _, _, ap, config) and + revFlowOut(call, ret, pos, state, returnCtx, returnAp, ap, config) and + returnFlowsThrough(ret, pos, state, ccc, _, _, ap, config) and matchesCall(ccc, call) ) } @@ -1915,17 +1893,17 @@ private module MkStage { pragma[nomagic] private predicate parameterFlowsThroughRev( - ParamNodeEx p, Ap ap, ReturnKindExt kind, Ap returnAp, Configuration config + ParamNodeEx p, Ap ap, ReturnPosition pos, Ap returnAp, Configuration config ) { - revFlow(p, _, TReturnCtxMaybeFlowThrough(kind), apSome(returnAp), ap, config) and - parameterFlowThroughAllowed(p, kind) + revFlow(p, _, TReturnCtxMaybeFlowThrough(pos), apSome(returnAp), ap, config) and + parameterFlowThroughAllowed(p, pos.getKind()) } pragma[nomagic] predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap, Configuration config) { - exists(RetNodeEx ret, ReturnKindExt kind | - returnFlowsThrough(ret, kind, _, _, p, ap, _, config) and - parameterFlowsThroughRev(p, ap, kind, _, config) + exists(RetNodeEx ret, ReturnPosition pos | + returnFlowsThrough(ret, pos, _, _, p, ap, _, config) and + parameterFlowsThroughRev(p, ap, pos, _, config) ) } @@ -1933,20 +1911,21 @@ private module MkStage { predicate returnMayFlowThrough( RetNodeEx ret, Ap argAp, Ap ap, ReturnKindExt kind, Configuration config ) { - exists(ParamNodeEx p | - returnFlowsThrough(ret, kind, _, _, p, argAp, ap, config) and - parameterFlowsThroughRev(p, argAp, kind, ap, config) + exists(ParamNodeEx p, ReturnPosition pos | + returnFlowsThrough(ret, pos, _, _, p, argAp, ap, config) and + parameterFlowsThroughRev(p, argAp, pos, ap, config) and + kind = pos.getKind() ) } pragma[nomagic] - predicate revFlowInToReturnIsReturned( + private predicate revFlowThroughArg( DataFlowCall call, ArgNodeEx arg, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap, Configuration config ) { - exists(ReturnKindExt returnKind0, Ap returnAp0 | - revFlowInToReturn(call, arg, state, returnKind0, returnAp0, ap, config) and - revFlowIsReturned(call, returnCtx, returnAp, returnKind0, returnAp0, config) + exists(ParamNodeEx p, ReturnPosition pos, Ap innerReturnAp | + revFlowThrough(call, returnCtx, p, state, pos, returnAp, ap, innerReturnAp, config) and + flowThroughIntoCall(call, arg, p, _, ap, innerReturnAp, config) ) } @@ -1954,7 +1933,7 @@ private module MkStage { predicate callMayFlowThroughRev(DataFlowCall call, Configuration config) { exists(ArgNodeEx arg, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap | revFlow(arg, state, returnCtx, returnAp, ap, config) and - revFlowInToReturnIsReturned(call, arg, state, returnCtx, returnAp, ap, config) + revFlowThroughArg(call, arg, state, returnCtx, returnAp, ap, config) ) } @@ -1967,8 +1946,9 @@ private module MkStage { conscand = count(TypedContent f0, Ap ap | fwdConsCand(f0, ap, config)) and states = count(FlowState state | fwdFlow(_, state, _, _, _, _, config)) and tuples = - count(NodeEx n, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - Ap ap | fwdFlow(n, state, cc, summaryCtx, argAp, ap, config)) + count(NodeEx n, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap | + fwdFlow(n, state, cc, summaryCtx, argAp, ap, config) + ) or fwd = false and nodes = count(NodeEx node | revFlow(node, _, _, _, _, config)) and @@ -2823,13 +2803,12 @@ private Configuration unbindConf(Configuration conf) { pragma[nomagic] private predicate nodeMayUseSummary0( - NodeEx n, DataFlowCallable c, ParameterPosition pos, FlowState state, AccessPathApprox apa, - Configuration config + NodeEx n, ParamNodeEx p, FlowState state, AccessPathApprox apa, Configuration config ) { exists(AccessPathApprox apa0 | - c = n.getEnclosingCallable() and + Stage5::parameterMayFlowThrough(p, _, _) and Stage5::revFlow(n, state, TReturnCtxMaybeFlowThrough(_), _, apa0, config) and - Stage5::fwdFlow(n, state, any(CallContextCall ccc), TParameterPositionSome(pos), + Stage5::fwdFlow(n, state, any(CallContextCall ccc), TParamNodeSome(p.asNode()), TAccessPathApproxSome(apa), apa0, config) ) } @@ -2838,10 +2817,9 @@ pragma[nomagic] private predicate nodeMayUseSummary( NodeEx n, FlowState state, AccessPathApprox apa, Configuration config ) { - exists(DataFlowCallable c, ParameterPosition pos, ParamNodeEx p | + exists(ParamNodeEx p | Stage5::parameterMayFlowThrough(p, apa, config) and - nodeMayUseSummary0(n, c, pos, state, apa, config) and - p.isParameterOf(c, pos) + nodeMayUseSummary0(n, p, state, apa, config) ) } diff --git a/cpp/ql/lib/semmle/code/cpp/dataflow/old/internal/DataFlowImplCommon.qll b/cpp/ql/lib/semmle/code/cpp/dataflow/old/internal/DataFlowImplCommon.qll index c66aefced8d..9aa6a529a5b 100644 --- a/cpp/ql/lib/semmle/code/cpp/dataflow/old/internal/DataFlowImplCommon.qll +++ b/cpp/ql/lib/semmle/code/cpp/dataflow/old/internal/DataFlowImplCommon.qll @@ -916,15 +916,15 @@ private module Cached { TDataFlowCallSome(DataFlowCall call) cached - newtype TParameterPositionOption = - TParameterPositionNone() or - TParameterPositionSome(ParameterPosition pos) + newtype TParamNodeOption = + TParamNodeNone() or + TParamNodeSome(ParamNode p) cached newtype TReturnCtx = TReturnCtxNone() or TReturnCtxNoFlowThrough() or - TReturnCtxMaybeFlowThrough(ReturnKindExt kind) + TReturnCtxMaybeFlowThrough(ReturnPosition pos) cached newtype TTypedContentApprox = @@ -1343,15 +1343,15 @@ class DataFlowCallOption extends TDataFlowCallOption { } } -/** An optional `ParameterPosition`. */ -class ParameterPositionOption extends TParameterPositionOption { +/** An optional `ParamNode`. */ +class ParamNodeOption extends TParamNodeOption { string toString() { - this = TParameterPositionNone() and + this = TParamNodeNone() and result = "(none)" or - exists(ParameterPosition pos | - this = TParameterPositionSome(pos) and - result = pos.toString() + exists(ParamNode p | + this = TParamNodeSome(p) and + result = p.toString() ) } } @@ -1363,7 +1363,7 @@ class ParameterPositionOption extends TParameterPositionOption { * * - `TReturnCtxNone()`: no return flow. * - `TReturnCtxNoFlowThrough()`: return flow, but flow through is not possible. - * - `TReturnCtxMaybeFlowThrough(ReturnKindExt kind)`: return flow, of kind `kind`, and + * - `TReturnCtxMaybeFlowThrough(ReturnPosition pos)`: return flow, of kind `pos`, and * flow through may be possible. */ class ReturnCtx extends TReturnCtx { @@ -1374,9 +1374,9 @@ class ReturnCtx extends TReturnCtx { this = TReturnCtxNoFlowThrough() and result = "(no flow through)" or - exists(ReturnKindExt kind | - this = TReturnCtxMaybeFlowThrough(kind) and - result = kind.toString() + exists(ReturnPosition pos | + this = TReturnCtxMaybeFlowThrough(pos) and + result = pos.toString() ) } } diff --git a/cpp/ql/lib/semmle/code/cpp/dataflow/old/internal/DataFlowImplLocal.qll b/cpp/ql/lib/semmle/code/cpp/dataflow/old/internal/DataFlowImplLocal.qll index 6741ccc2f06..1228d00b6ba 100644 --- a/cpp/ql/lib/semmle/code/cpp/dataflow/old/internal/DataFlowImplLocal.qll +++ b/cpp/ql/lib/semmle/code/cpp/dataflow/old/internal/DataFlowImplLocal.qll @@ -622,7 +622,11 @@ private predicate parameterFlowThroughAllowed(ParamNodeEx p, ReturnKindExt kind) } private module Stage1 implements StageSig { - class Ap = Unit; + class Ap extends int { + // workaround for bad functionality-induced joins (happens when using `Unit`) + pragma[nomagic] + Ap() { this in [0 .. 1] and this < 1 } + } private class Cc = boolean; @@ -1327,8 +1331,8 @@ private module MkStage { */ pragma[nomagic] additional predicate fwdFlow( - NodeEx node, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - Ap ap, ApApprox apa, Configuration config + NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, + ApApprox apa, Configuration config ) { fwdFlow0(node, state, cc, summaryCtx, argAp, ap, apa, config) and PrevStage::revFlow(node, state, apa, config) and @@ -1337,21 +1341,21 @@ private module MkStage { pragma[inline] additional predicate fwdFlow( - NodeEx node, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - Ap ap, Configuration config + NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, + Configuration config ) { fwdFlow(node, state, cc, summaryCtx, argAp, ap, _, config) } pragma[nomagic] private predicate fwdFlow0( - NodeEx node, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - Ap ap, ApApprox apa, Configuration config + NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, + ApApprox apa, Configuration config ) { sourceNode(node, state, config) and (if hasSourceCallCtx(config) then cc = ccSomeCall() else cc = ccNone()) and argAp = apNone() and - summaryCtx = TParameterPositionNone() and + summaryCtx = TParamNodeNone() and ap = getApNil(node) and apa = getApprox(ap) or @@ -1372,7 +1376,7 @@ private module MkStage { fwdFlow(mid, pragma[only_bind_into](state), _, _, _, ap, apa, pragma[only_bind_into](config)) and jumpStep(mid, node, config) and cc = ccNone() and - summaryCtx = TParameterPositionNone() and + summaryCtx = TParamNodeNone() and argAp = apNone() ) or @@ -1380,7 +1384,7 @@ private module MkStage { fwdFlow(mid, state, _, _, _, nil, pragma[only_bind_into](config)) and additionalJumpStep(mid, node, config) and cc = ccNone() and - summaryCtx = TParameterPositionNone() and + summaryCtx = TParamNodeNone() and argAp = apNone() and ap = getApNil(node) and apa = getApprox(ap) @@ -1390,7 +1394,7 @@ private module MkStage { fwdFlow(mid, state0, _, _, _, nil, pragma[only_bind_into](config)) and additionalJumpStateStep(mid, state0, node, state, config) and cc = ccNone() and - summaryCtx = TParameterPositionNone() and + summaryCtx = TParamNodeNone() and argAp = apNone() and ap = getApNil(node) and apa = getApprox(ap) @@ -1414,10 +1418,10 @@ private module MkStage { fwdFlowIn(_, node, state, _, cc, _, _, ap, apa, config) and if PrevStage::parameterMayFlowThrough(node, apa, config) then ( - summaryCtx = TParameterPositionSome(node.(ParamNodeEx).getPosition()) and + summaryCtx = TParamNodeSome(node.asNode()) and argAp = apSome(ap) ) else ( - summaryCtx = TParameterPositionNone() and argAp = apNone() + summaryCtx = TParamNodeNone() and argAp = apNone() ) or // flow out of a callable @@ -1433,16 +1437,19 @@ private module MkStage { ) or // flow through a callable - exists(DataFlowCall call, ParameterPosition summaryCtx0, Ap argAp0 | - fwdFlowOutFromArg(call, node, state, summaryCtx0, argAp0, ap, apa, config) and - fwdFlowIsEntered(call, cc, summaryCtx, argAp, summaryCtx0, argAp0, config) + exists( + DataFlowCall call, CcCall ccc, RetNodeEx ret, boolean allowsFieldFlow, ApApprox innerArgApa + | + fwdFlowThrough(call, cc, state, ccc, summaryCtx, argAp, ap, apa, ret, innerArgApa, config) and + flowThroughOutOfCall(call, ccc, ret, node, allowsFieldFlow, innerArgApa, apa, config) and + if allowsFieldFlow = false then ap instanceof ApNil else any() ) } pragma[nomagic] private predicate fwdFlowStore( NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, FlowState state, Cc cc, - ParameterPositionOption summaryCtx, ApOption argAp, Configuration config + ParamNodeOption summaryCtx, ApOption argAp, Configuration config ) { exists(DataFlowType contentType, ApApprox apa1 | fwdFlow(node1, state, cc, summaryCtx, argAp, ap1, apa1, config) and @@ -1473,8 +1480,8 @@ private module MkStage { pragma[nomagic] private predicate fwdFlowRead0( - NodeEx node1, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - ApNonNil ap, Configuration config + NodeEx node1, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, ApNonNil ap, + Configuration config ) { fwdFlow(node1, state, cc, summaryCtx, argAp, ap, config) and PrevStage::readStepCand(node1, _, _, config) @@ -1483,7 +1490,7 @@ private module MkStage { pragma[nomagic] private predicate fwdFlowRead( Ap ap, Content c, NodeEx node1, NodeEx node2, FlowState state, Cc cc, - ParameterPositionOption summaryCtx, ApOption argAp, Configuration config + ParamNodeOption summaryCtx, ApOption argAp, Configuration config ) { fwdFlowRead0(node1, state, cc, summaryCtx, argAp, ap, config) and PrevStage::readStepCand(node1, c, node2, config) and @@ -1493,7 +1500,7 @@ private module MkStage { pragma[nomagic] private predicate fwdFlowIn( DataFlowCall call, ParamNodeEx p, FlowState state, Cc outercc, CcCall innercc, - ParameterPositionOption summaryCtx, ApOption argAp, Ap ap, ApApprox apa, Configuration config + ParamNodeOption summaryCtx, ApOption argAp, Ap ap, ApApprox apa, Configuration config ) { exists(ArgNodeEx arg, boolean allowsFieldFlow | fwdFlow(arg, state, outercc, summaryCtx, argAp, ap, apa, config) and @@ -1505,64 +1512,38 @@ private module MkStage { pragma[nomagic] private predicate fwdFlowRetFromArg( - RetNodeEx ret, FlowState state, CcCall ccc, ParameterPosition summaryCtx, ParamNodeEx p, - Ap argAp, ApApprox argApa, Ap ap, ApApprox apa, Configuration config + RetNodeEx ret, FlowState state, CcCall ccc, ParamNodeEx summaryCtx, Ap argAp, ApApprox argApa, + Ap ap, ApApprox apa, Configuration config ) { - exists(DataFlowCallable c, ReturnKindExt kind | + exists(ReturnKindExt kind | fwdFlow(pragma[only_bind_into](ret), state, ccc, - TParameterPositionSome(pragma[only_bind_into](summaryCtx)), apSome(argAp), ap, apa, config) and - getApprox(argAp) = argApa and - c = ret.getEnclosingCallable() and + TParamNodeSome(pragma[only_bind_into](summaryCtx.asNode())), + pragma[only_bind_into](apSome(argAp)), ap, pragma[only_bind_into](apa), + pragma[only_bind_into](config)) and kind = ret.getKind() and - p.isParameterOf(c, pragma[only_bind_into](summaryCtx)) and - parameterFlowThroughAllowed(p, kind) + parameterFlowThroughAllowed(summaryCtx, kind) and + argApa = getApprox(argAp) and + PrevStage::returnMayFlowThrough(ret, argApa, apa, kind, pragma[only_bind_into](config)) ) } pragma[inline] - private predicate fwdFlowInMayFlowThrough( - DataFlowCall call, Cc cc, CcCall innerCc, ParameterPositionOption summaryCtx, ApOption argAp, - ParamNodeEx param, Ap ap, ApApprox apa, Configuration config + private predicate fwdFlowThrough0( + DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, + ApOption argAp, Ap ap, ApApprox apa, RetNodeEx ret, ParamNodeEx innerSummaryCtx, + Ap innerArgAp, ApApprox innerArgApa, Configuration config ) { - fwdFlowIn(call, pragma[only_bind_into](param), _, cc, innerCc, summaryCtx, argAp, ap, - pragma[only_bind_into](apa), pragma[only_bind_into](config)) and - PrevStage::parameterMayFlowThrough(param, apa, config) - } - - // dedup before joining with `flowThroughOutOfCall` - pragma[nomagic] - private predicate fwdFlowInMayFlowThroughProj( - DataFlowCall call, CcCall innerCc, ApApprox apa, Configuration config - ) { - fwdFlowInMayFlowThrough(call, _, innerCc, _, _, _, _, apa, config) - } - - /** - * Same as `flowThroughOutOfCall`, but restricted to calls that are reached - * in the flow covered by `fwdFlow`, where data might flow through the target - * callable and back out at `call`. - */ - pragma[nomagic] - private predicate fwdFlowThroughOutOfCall( - DataFlowCall call, CcCall ccc, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow, - ApApprox argApa, ApApprox apa, Configuration config - ) { - fwdFlowInMayFlowThroughProj(call, ccc, argApa, config) and - flowThroughOutOfCall(call, ccc, ret, out, allowsFieldFlow, argApa, apa, config) + fwdFlowRetFromArg(ret, state, ccc, innerSummaryCtx, innerArgAp, innerArgApa, ap, apa, config) and + fwdFlowIsEntered(call, cc, ccc, summaryCtx, argAp, innerSummaryCtx, innerArgAp, config) } pragma[nomagic] - private predicate fwdFlowOutFromArg( - DataFlowCall call, NodeEx out, FlowState state, ParameterPosition summaryCtx, Ap argAp, Ap ap, - ApApprox apa, Configuration config + private predicate fwdFlowThrough( + DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, + ApOption argAp, Ap ap, ApApprox apa, RetNodeEx ret, ApApprox innerArgApa, Configuration config ) { - exists(RetNodeEx ret, boolean allowsFieldFlow, CcCall ccc, ApApprox argApa | - fwdFlowRetFromArg(pragma[only_bind_into](ret), state, pragma[only_bind_into](ccc), - summaryCtx, _, argAp, pragma[only_bind_into](argApa), ap, pragma[only_bind_into](apa), - config) and - fwdFlowThroughOutOfCall(call, ccc, ret, out, allowsFieldFlow, argApa, apa, config) and - (if allowsFieldFlow = false then ap instanceof ApNil else any()) - ) + fwdFlowThrough0(call, cc, state, ccc, summaryCtx, argAp, ap, apa, ret, _, _, innerArgApa, + config) } /** @@ -1571,12 +1552,14 @@ private module MkStage { */ pragma[nomagic] private predicate fwdFlowIsEntered( - DataFlowCall call, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - ParameterPosition pos, Ap ap, Configuration config + DataFlowCall call, Cc cc, CcCall innerCc, ParamNodeOption summaryCtx, ApOption argAp, + ParamNodeEx p, Ap ap, Configuration config ) { - exists(ParamNodeEx param | - fwdFlowInMayFlowThrough(call, cc, _, summaryCtx, argAp, param, ap, _, config) and - pos = param.getPosition() + exists(ApApprox apa | + fwdFlowIn(call, pragma[only_bind_into](p), _, cc, innerCc, summaryCtx, argAp, ap, + pragma[only_bind_into](apa), pragma[only_bind_into](config)) and + PrevStage::parameterMayFlowThrough(p, apa, config) and + PrevStage::callMayFlowThroughRev(call, pragma[only_bind_into](config)) ) } @@ -1596,23 +1579,31 @@ private module MkStage { fwdFlowConsCand(ap1, c, ap2, config) } + pragma[nomagic] + private predicate returnFlowsThrough0( + DataFlowCall call, FlowState state, CcCall ccc, Ap ap, ApApprox apa, RetNodeEx ret, + ParamNodeEx innerSummaryCtx, Ap innerArgAp, ApApprox innerArgApa, Configuration config + ) { + fwdFlowThrough0(call, _, state, ccc, _, _, ap, apa, ret, innerSummaryCtx, innerArgAp, + innerArgApa, config) + } + pragma[nomagic] private predicate returnFlowsThrough( - RetNodeEx ret, ReturnKindExt kind, FlowState state, CcCall ccc, ParamNodeEx p, Ap argAp, + RetNodeEx ret, ReturnPosition pos, FlowState state, CcCall ccc, ParamNodeEx p, Ap argAp, Ap ap, Configuration config ) { - exists(boolean allowsFieldFlow, ApApprox argApa, ApApprox apa | - fwdFlowRetFromArg(pragma[only_bind_into](ret), state, pragma[only_bind_into](ccc), _, p, - argAp, pragma[only_bind_into](argApa), ap, pragma[only_bind_into](apa), config) and - kind = ret.getKind() and - fwdFlowThroughOutOfCall(_, ccc, ret, _, allowsFieldFlow, argApa, apa, config) and - (if allowsFieldFlow = false then ap instanceof ApNil else any()) + exists(DataFlowCall call, ApApprox apa, boolean allowsFieldFlow, ApApprox innerArgApa | + returnFlowsThrough0(call, state, ccc, ap, apa, ret, p, argAp, innerArgApa, config) and + flowThroughOutOfCall(call, ccc, ret, _, allowsFieldFlow, innerArgApa, apa, config) and + pos = ret.getReturnPosition() and + if allowsFieldFlow = false then ap instanceof ApNil else any() ) } pragma[nomagic] private predicate flowThroughIntoCall( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap argAp, + DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap argAp, Ap ap, Configuration config ) { exists(ApApprox argApa | @@ -1620,7 +1611,7 @@ private module MkStage { allowsFieldFlow, argApa, pragma[only_bind_into](config)) and fwdFlow(arg, _, _, _, _, pragma[only_bind_into](argAp), argApa, pragma[only_bind_into](config)) and - returnFlowsThrough(_, _, _, _, p, pragma[only_bind_into](argAp), _, + returnFlowsThrough(_, _, _, _, p, pragma[only_bind_into](argAp), ap, pragma[only_bind_into](config)) and if allowsFieldFlow = false then argAp instanceof ApNil else any() ) @@ -1639,12 +1630,13 @@ private module MkStage { pragma[nomagic] private predicate flowOutOfCallAp( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, boolean allowsFieldFlow, + DataFlowCall call, RetNodeEx ret, ReturnPosition pos, NodeEx out, boolean allowsFieldFlow, Ap ap, Configuration config ) { exists(ApApprox apa | - flowOutOfCallApa(call, ret, kind, out, allowsFieldFlow, apa, config) and - fwdFlow(ret, _, _, _, _, ap, apa, config) + flowOutOfCallApa(call, ret, _, out, allowsFieldFlow, apa, config) and + fwdFlow(ret, _, _, _, _, ap, apa, config) and + pos = ret.getReturnPosition() ) } @@ -1739,17 +1731,17 @@ private module MkStage { ) or // flow through a callable - exists(DataFlowCall call, ReturnKindExt returnKind0, Ap returnAp0 | - revFlowInToReturn(call, node, state, returnKind0, returnAp0, ap, config) and - revFlowIsReturned(call, returnCtx, returnAp, returnKind0, returnAp0, config) + exists(DataFlowCall call, ParamNodeEx p, ReturnPosition pos, Ap innerReturnAp | + revFlowThrough(call, returnCtx, p, state, pos, returnAp, ap, innerReturnAp, config) and + flowThroughIntoCall(call, node, p, _, ap, innerReturnAp, config) ) or // flow out of a callable - exists(ReturnKindExt kind | - revFlowOut(_, node, kind, state, _, _, ap, config) and - if returnFlowsThrough(node, kind, state, _, _, _, ap, config) + exists(ReturnPosition pos | + revFlowOut(_, node, pos, state, _, _, ap, config) and + if returnFlowsThrough(node, pos, state, _, _, _, ap, config) then ( - returnCtx = TReturnCtxMaybeFlowThrough(kind) and + returnCtx = TReturnCtxMaybeFlowThrough(pos) and returnAp = apSome(ap) ) else ( returnCtx = TReturnCtxNoFlowThrough() and returnAp = apNone() @@ -1782,47 +1774,33 @@ private module MkStage { pragma[nomagic] private predicate revFlowOut( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, FlowState state, ReturnCtx returnCtx, + DataFlowCall call, RetNodeEx ret, ReturnPosition pos, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap, Configuration config ) { exists(NodeEx out, boolean allowsFieldFlow | revFlow(out, state, returnCtx, returnAp, ap, config) and - flowOutOfCallAp(call, ret, kind, out, allowsFieldFlow, ap, config) and + flowOutOfCallAp(call, ret, pos, out, allowsFieldFlow, ap, config) and if allowsFieldFlow = false then ap instanceof ApNil else any() ) } - /** - * Same as `flowThroughIntoCall`, but restricted to calls that are reached - * in the flow covered by `revFlow`, where data might flow through the target - * callable and back out at `call`. - */ - pragma[nomagic] - private predicate revFlowThroughIntoCall( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap argAp, - Configuration config - ) { - flowThroughIntoCall(call, arg, p, allowsFieldFlow, argAp, config) and - revFlowIsReturned(call, _, _, _, _, config) - } - pragma[nomagic] private predicate revFlowParamToReturn( - ParamNodeEx p, FlowState state, ReturnKindExt kind, Ap returnAp, Ap ap, Configuration config + ParamNodeEx p, FlowState state, ReturnPosition pos, Ap returnAp, Ap ap, Configuration config ) { - revFlow(p, state, TReturnCtxMaybeFlowThrough(kind), apSome(returnAp), ap, config) and - parameterFlowThroughAllowed(p, kind) + revFlow(pragma[only_bind_into](p), state, TReturnCtxMaybeFlowThrough(pos), apSome(returnAp), + pragma[only_bind_into](ap), pragma[only_bind_into](config)) and + parameterFlowThroughAllowed(p, pos.getKind()) and + PrevStage::parameterMayFlowThrough(p, getApprox(ap), config) } pragma[nomagic] - private predicate revFlowInToReturn( - DataFlowCall call, ArgNodeEx arg, FlowState state, ReturnKindExt kind, Ap returnAp, Ap ap, - Configuration config + private predicate revFlowThrough( + DataFlowCall call, ReturnCtx returnCtx, ParamNodeEx p, FlowState state, ReturnPosition pos, + ApOption returnAp, Ap ap, Ap innerReturnAp, Configuration config ) { - exists(ParamNodeEx p, boolean allowsFieldFlow | - revFlowParamToReturn(p, state, kind, returnAp, ap, config) and - revFlowThroughIntoCall(call, arg, p, allowsFieldFlow, ap, config) - ) + revFlowParamToReturn(p, state, pos, innerReturnAp, ap, config) and + revFlowIsReturned(call, returnCtx, returnAp, pos, innerReturnAp, config) } /** @@ -1832,12 +1810,12 @@ private module MkStage { */ pragma[nomagic] private predicate revFlowIsReturned( - DataFlowCall call, ReturnCtx returnCtx, ApOption returnAp, ReturnKindExt kind, Ap ap, + DataFlowCall call, ReturnCtx returnCtx, ApOption returnAp, ReturnPosition pos, Ap ap, Configuration config ) { exists(RetNodeEx ret, FlowState state, CcCall ccc | - revFlowOut(call, ret, kind, state, returnCtx, returnAp, ap, config) and - returnFlowsThrough(ret, kind, state, ccc, _, _, ap, config) and + revFlowOut(call, ret, pos, state, returnCtx, returnAp, ap, config) and + returnFlowsThrough(ret, pos, state, ccc, _, _, ap, config) and matchesCall(ccc, call) ) } @@ -1915,17 +1893,17 @@ private module MkStage { pragma[nomagic] private predicate parameterFlowsThroughRev( - ParamNodeEx p, Ap ap, ReturnKindExt kind, Ap returnAp, Configuration config + ParamNodeEx p, Ap ap, ReturnPosition pos, Ap returnAp, Configuration config ) { - revFlow(p, _, TReturnCtxMaybeFlowThrough(kind), apSome(returnAp), ap, config) and - parameterFlowThroughAllowed(p, kind) + revFlow(p, _, TReturnCtxMaybeFlowThrough(pos), apSome(returnAp), ap, config) and + parameterFlowThroughAllowed(p, pos.getKind()) } pragma[nomagic] predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap, Configuration config) { - exists(RetNodeEx ret, ReturnKindExt kind | - returnFlowsThrough(ret, kind, _, _, p, ap, _, config) and - parameterFlowsThroughRev(p, ap, kind, _, config) + exists(RetNodeEx ret, ReturnPosition pos | + returnFlowsThrough(ret, pos, _, _, p, ap, _, config) and + parameterFlowsThroughRev(p, ap, pos, _, config) ) } @@ -1933,20 +1911,21 @@ private module MkStage { predicate returnMayFlowThrough( RetNodeEx ret, Ap argAp, Ap ap, ReturnKindExt kind, Configuration config ) { - exists(ParamNodeEx p | - returnFlowsThrough(ret, kind, _, _, p, argAp, ap, config) and - parameterFlowsThroughRev(p, argAp, kind, ap, config) + exists(ParamNodeEx p, ReturnPosition pos | + returnFlowsThrough(ret, pos, _, _, p, argAp, ap, config) and + parameterFlowsThroughRev(p, argAp, pos, ap, config) and + kind = pos.getKind() ) } pragma[nomagic] - predicate revFlowInToReturnIsReturned( + private predicate revFlowThroughArg( DataFlowCall call, ArgNodeEx arg, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap, Configuration config ) { - exists(ReturnKindExt returnKind0, Ap returnAp0 | - revFlowInToReturn(call, arg, state, returnKind0, returnAp0, ap, config) and - revFlowIsReturned(call, returnCtx, returnAp, returnKind0, returnAp0, config) + exists(ParamNodeEx p, ReturnPosition pos, Ap innerReturnAp | + revFlowThrough(call, returnCtx, p, state, pos, returnAp, ap, innerReturnAp, config) and + flowThroughIntoCall(call, arg, p, _, ap, innerReturnAp, config) ) } @@ -1954,7 +1933,7 @@ private module MkStage { predicate callMayFlowThroughRev(DataFlowCall call, Configuration config) { exists(ArgNodeEx arg, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap | revFlow(arg, state, returnCtx, returnAp, ap, config) and - revFlowInToReturnIsReturned(call, arg, state, returnCtx, returnAp, ap, config) + revFlowThroughArg(call, arg, state, returnCtx, returnAp, ap, config) ) } @@ -1967,8 +1946,9 @@ private module MkStage { conscand = count(TypedContent f0, Ap ap | fwdConsCand(f0, ap, config)) and states = count(FlowState state | fwdFlow(_, state, _, _, _, _, config)) and tuples = - count(NodeEx n, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - Ap ap | fwdFlow(n, state, cc, summaryCtx, argAp, ap, config)) + count(NodeEx n, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap | + fwdFlow(n, state, cc, summaryCtx, argAp, ap, config) + ) or fwd = false and nodes = count(NodeEx node | revFlow(node, _, _, _, _, config)) and @@ -2823,13 +2803,12 @@ private Configuration unbindConf(Configuration conf) { pragma[nomagic] private predicate nodeMayUseSummary0( - NodeEx n, DataFlowCallable c, ParameterPosition pos, FlowState state, AccessPathApprox apa, - Configuration config + NodeEx n, ParamNodeEx p, FlowState state, AccessPathApprox apa, Configuration config ) { exists(AccessPathApprox apa0 | - c = n.getEnclosingCallable() and + Stage5::parameterMayFlowThrough(p, _, _) and Stage5::revFlow(n, state, TReturnCtxMaybeFlowThrough(_), _, apa0, config) and - Stage5::fwdFlow(n, state, any(CallContextCall ccc), TParameterPositionSome(pos), + Stage5::fwdFlow(n, state, any(CallContextCall ccc), TParamNodeSome(p.asNode()), TAccessPathApproxSome(apa), apa0, config) ) } @@ -2838,10 +2817,9 @@ pragma[nomagic] private predicate nodeMayUseSummary( NodeEx n, FlowState state, AccessPathApprox apa, Configuration config ) { - exists(DataFlowCallable c, ParameterPosition pos, ParamNodeEx p | + exists(ParamNodeEx p | Stage5::parameterMayFlowThrough(p, apa, config) and - nodeMayUseSummary0(n, c, pos, state, apa, config) and - p.isParameterOf(c, pos) + nodeMayUseSummary0(n, p, state, apa, config) ) } 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 6741ccc2f06..1228d00b6ba 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 @@ -622,7 +622,11 @@ private predicate parameterFlowThroughAllowed(ParamNodeEx p, ReturnKindExt kind) } private module Stage1 implements StageSig { - class Ap = Unit; + class Ap extends int { + // workaround for bad functionality-induced joins (happens when using `Unit`) + pragma[nomagic] + Ap() { this in [0 .. 1] and this < 1 } + } private class Cc = boolean; @@ -1327,8 +1331,8 @@ private module MkStage { */ pragma[nomagic] additional predicate fwdFlow( - NodeEx node, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - Ap ap, ApApprox apa, Configuration config + NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, + ApApprox apa, Configuration config ) { fwdFlow0(node, state, cc, summaryCtx, argAp, ap, apa, config) and PrevStage::revFlow(node, state, apa, config) and @@ -1337,21 +1341,21 @@ private module MkStage { pragma[inline] additional predicate fwdFlow( - NodeEx node, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - Ap ap, Configuration config + NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, + Configuration config ) { fwdFlow(node, state, cc, summaryCtx, argAp, ap, _, config) } pragma[nomagic] private predicate fwdFlow0( - NodeEx node, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - Ap ap, ApApprox apa, Configuration config + NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, + ApApprox apa, Configuration config ) { sourceNode(node, state, config) and (if hasSourceCallCtx(config) then cc = ccSomeCall() else cc = ccNone()) and argAp = apNone() and - summaryCtx = TParameterPositionNone() and + summaryCtx = TParamNodeNone() and ap = getApNil(node) and apa = getApprox(ap) or @@ -1372,7 +1376,7 @@ private module MkStage { fwdFlow(mid, pragma[only_bind_into](state), _, _, _, ap, apa, pragma[only_bind_into](config)) and jumpStep(mid, node, config) and cc = ccNone() and - summaryCtx = TParameterPositionNone() and + summaryCtx = TParamNodeNone() and argAp = apNone() ) or @@ -1380,7 +1384,7 @@ private module MkStage { fwdFlow(mid, state, _, _, _, nil, pragma[only_bind_into](config)) and additionalJumpStep(mid, node, config) and cc = ccNone() and - summaryCtx = TParameterPositionNone() and + summaryCtx = TParamNodeNone() and argAp = apNone() and ap = getApNil(node) and apa = getApprox(ap) @@ -1390,7 +1394,7 @@ private module MkStage { fwdFlow(mid, state0, _, _, _, nil, pragma[only_bind_into](config)) and additionalJumpStateStep(mid, state0, node, state, config) and cc = ccNone() and - summaryCtx = TParameterPositionNone() and + summaryCtx = TParamNodeNone() and argAp = apNone() and ap = getApNil(node) and apa = getApprox(ap) @@ -1414,10 +1418,10 @@ private module MkStage { fwdFlowIn(_, node, state, _, cc, _, _, ap, apa, config) and if PrevStage::parameterMayFlowThrough(node, apa, config) then ( - summaryCtx = TParameterPositionSome(node.(ParamNodeEx).getPosition()) and + summaryCtx = TParamNodeSome(node.asNode()) and argAp = apSome(ap) ) else ( - summaryCtx = TParameterPositionNone() and argAp = apNone() + summaryCtx = TParamNodeNone() and argAp = apNone() ) or // flow out of a callable @@ -1433,16 +1437,19 @@ private module MkStage { ) or // flow through a callable - exists(DataFlowCall call, ParameterPosition summaryCtx0, Ap argAp0 | - fwdFlowOutFromArg(call, node, state, summaryCtx0, argAp0, ap, apa, config) and - fwdFlowIsEntered(call, cc, summaryCtx, argAp, summaryCtx0, argAp0, config) + exists( + DataFlowCall call, CcCall ccc, RetNodeEx ret, boolean allowsFieldFlow, ApApprox innerArgApa + | + fwdFlowThrough(call, cc, state, ccc, summaryCtx, argAp, ap, apa, ret, innerArgApa, config) and + flowThroughOutOfCall(call, ccc, ret, node, allowsFieldFlow, innerArgApa, apa, config) and + if allowsFieldFlow = false then ap instanceof ApNil else any() ) } pragma[nomagic] private predicate fwdFlowStore( NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, FlowState state, Cc cc, - ParameterPositionOption summaryCtx, ApOption argAp, Configuration config + ParamNodeOption summaryCtx, ApOption argAp, Configuration config ) { exists(DataFlowType contentType, ApApprox apa1 | fwdFlow(node1, state, cc, summaryCtx, argAp, ap1, apa1, config) and @@ -1473,8 +1480,8 @@ private module MkStage { pragma[nomagic] private predicate fwdFlowRead0( - NodeEx node1, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - ApNonNil ap, Configuration config + NodeEx node1, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, ApNonNil ap, + Configuration config ) { fwdFlow(node1, state, cc, summaryCtx, argAp, ap, config) and PrevStage::readStepCand(node1, _, _, config) @@ -1483,7 +1490,7 @@ private module MkStage { pragma[nomagic] private predicate fwdFlowRead( Ap ap, Content c, NodeEx node1, NodeEx node2, FlowState state, Cc cc, - ParameterPositionOption summaryCtx, ApOption argAp, Configuration config + ParamNodeOption summaryCtx, ApOption argAp, Configuration config ) { fwdFlowRead0(node1, state, cc, summaryCtx, argAp, ap, config) and PrevStage::readStepCand(node1, c, node2, config) and @@ -1493,7 +1500,7 @@ private module MkStage { pragma[nomagic] private predicate fwdFlowIn( DataFlowCall call, ParamNodeEx p, FlowState state, Cc outercc, CcCall innercc, - ParameterPositionOption summaryCtx, ApOption argAp, Ap ap, ApApprox apa, Configuration config + ParamNodeOption summaryCtx, ApOption argAp, Ap ap, ApApprox apa, Configuration config ) { exists(ArgNodeEx arg, boolean allowsFieldFlow | fwdFlow(arg, state, outercc, summaryCtx, argAp, ap, apa, config) and @@ -1505,64 +1512,38 @@ private module MkStage { pragma[nomagic] private predicate fwdFlowRetFromArg( - RetNodeEx ret, FlowState state, CcCall ccc, ParameterPosition summaryCtx, ParamNodeEx p, - Ap argAp, ApApprox argApa, Ap ap, ApApprox apa, Configuration config + RetNodeEx ret, FlowState state, CcCall ccc, ParamNodeEx summaryCtx, Ap argAp, ApApprox argApa, + Ap ap, ApApprox apa, Configuration config ) { - exists(DataFlowCallable c, ReturnKindExt kind | + exists(ReturnKindExt kind | fwdFlow(pragma[only_bind_into](ret), state, ccc, - TParameterPositionSome(pragma[only_bind_into](summaryCtx)), apSome(argAp), ap, apa, config) and - getApprox(argAp) = argApa and - c = ret.getEnclosingCallable() and + TParamNodeSome(pragma[only_bind_into](summaryCtx.asNode())), + pragma[only_bind_into](apSome(argAp)), ap, pragma[only_bind_into](apa), + pragma[only_bind_into](config)) and kind = ret.getKind() and - p.isParameterOf(c, pragma[only_bind_into](summaryCtx)) and - parameterFlowThroughAllowed(p, kind) + parameterFlowThroughAllowed(summaryCtx, kind) and + argApa = getApprox(argAp) and + PrevStage::returnMayFlowThrough(ret, argApa, apa, kind, pragma[only_bind_into](config)) ) } pragma[inline] - private predicate fwdFlowInMayFlowThrough( - DataFlowCall call, Cc cc, CcCall innerCc, ParameterPositionOption summaryCtx, ApOption argAp, - ParamNodeEx param, Ap ap, ApApprox apa, Configuration config + private predicate fwdFlowThrough0( + DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, + ApOption argAp, Ap ap, ApApprox apa, RetNodeEx ret, ParamNodeEx innerSummaryCtx, + Ap innerArgAp, ApApprox innerArgApa, Configuration config ) { - fwdFlowIn(call, pragma[only_bind_into](param), _, cc, innerCc, summaryCtx, argAp, ap, - pragma[only_bind_into](apa), pragma[only_bind_into](config)) and - PrevStage::parameterMayFlowThrough(param, apa, config) - } - - // dedup before joining with `flowThroughOutOfCall` - pragma[nomagic] - private predicate fwdFlowInMayFlowThroughProj( - DataFlowCall call, CcCall innerCc, ApApprox apa, Configuration config - ) { - fwdFlowInMayFlowThrough(call, _, innerCc, _, _, _, _, apa, config) - } - - /** - * Same as `flowThroughOutOfCall`, but restricted to calls that are reached - * in the flow covered by `fwdFlow`, where data might flow through the target - * callable and back out at `call`. - */ - pragma[nomagic] - private predicate fwdFlowThroughOutOfCall( - DataFlowCall call, CcCall ccc, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow, - ApApprox argApa, ApApprox apa, Configuration config - ) { - fwdFlowInMayFlowThroughProj(call, ccc, argApa, config) and - flowThroughOutOfCall(call, ccc, ret, out, allowsFieldFlow, argApa, apa, config) + fwdFlowRetFromArg(ret, state, ccc, innerSummaryCtx, innerArgAp, innerArgApa, ap, apa, config) and + fwdFlowIsEntered(call, cc, ccc, summaryCtx, argAp, innerSummaryCtx, innerArgAp, config) } pragma[nomagic] - private predicate fwdFlowOutFromArg( - DataFlowCall call, NodeEx out, FlowState state, ParameterPosition summaryCtx, Ap argAp, Ap ap, - ApApprox apa, Configuration config + private predicate fwdFlowThrough( + DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, + ApOption argAp, Ap ap, ApApprox apa, RetNodeEx ret, ApApprox innerArgApa, Configuration config ) { - exists(RetNodeEx ret, boolean allowsFieldFlow, CcCall ccc, ApApprox argApa | - fwdFlowRetFromArg(pragma[only_bind_into](ret), state, pragma[only_bind_into](ccc), - summaryCtx, _, argAp, pragma[only_bind_into](argApa), ap, pragma[only_bind_into](apa), - config) and - fwdFlowThroughOutOfCall(call, ccc, ret, out, allowsFieldFlow, argApa, apa, config) and - (if allowsFieldFlow = false then ap instanceof ApNil else any()) - ) + fwdFlowThrough0(call, cc, state, ccc, summaryCtx, argAp, ap, apa, ret, _, _, innerArgApa, + config) } /** @@ -1571,12 +1552,14 @@ private module MkStage { */ pragma[nomagic] private predicate fwdFlowIsEntered( - DataFlowCall call, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - ParameterPosition pos, Ap ap, Configuration config + DataFlowCall call, Cc cc, CcCall innerCc, ParamNodeOption summaryCtx, ApOption argAp, + ParamNodeEx p, Ap ap, Configuration config ) { - exists(ParamNodeEx param | - fwdFlowInMayFlowThrough(call, cc, _, summaryCtx, argAp, param, ap, _, config) and - pos = param.getPosition() + exists(ApApprox apa | + fwdFlowIn(call, pragma[only_bind_into](p), _, cc, innerCc, summaryCtx, argAp, ap, + pragma[only_bind_into](apa), pragma[only_bind_into](config)) and + PrevStage::parameterMayFlowThrough(p, apa, config) and + PrevStage::callMayFlowThroughRev(call, pragma[only_bind_into](config)) ) } @@ -1596,23 +1579,31 @@ private module MkStage { fwdFlowConsCand(ap1, c, ap2, config) } + pragma[nomagic] + private predicate returnFlowsThrough0( + DataFlowCall call, FlowState state, CcCall ccc, Ap ap, ApApprox apa, RetNodeEx ret, + ParamNodeEx innerSummaryCtx, Ap innerArgAp, ApApprox innerArgApa, Configuration config + ) { + fwdFlowThrough0(call, _, state, ccc, _, _, ap, apa, ret, innerSummaryCtx, innerArgAp, + innerArgApa, config) + } + pragma[nomagic] private predicate returnFlowsThrough( - RetNodeEx ret, ReturnKindExt kind, FlowState state, CcCall ccc, ParamNodeEx p, Ap argAp, + RetNodeEx ret, ReturnPosition pos, FlowState state, CcCall ccc, ParamNodeEx p, Ap argAp, Ap ap, Configuration config ) { - exists(boolean allowsFieldFlow, ApApprox argApa, ApApprox apa | - fwdFlowRetFromArg(pragma[only_bind_into](ret), state, pragma[only_bind_into](ccc), _, p, - argAp, pragma[only_bind_into](argApa), ap, pragma[only_bind_into](apa), config) and - kind = ret.getKind() and - fwdFlowThroughOutOfCall(_, ccc, ret, _, allowsFieldFlow, argApa, apa, config) and - (if allowsFieldFlow = false then ap instanceof ApNil else any()) + exists(DataFlowCall call, ApApprox apa, boolean allowsFieldFlow, ApApprox innerArgApa | + returnFlowsThrough0(call, state, ccc, ap, apa, ret, p, argAp, innerArgApa, config) and + flowThroughOutOfCall(call, ccc, ret, _, allowsFieldFlow, innerArgApa, apa, config) and + pos = ret.getReturnPosition() and + if allowsFieldFlow = false then ap instanceof ApNil else any() ) } pragma[nomagic] private predicate flowThroughIntoCall( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap argAp, + DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap argAp, Ap ap, Configuration config ) { exists(ApApprox argApa | @@ -1620,7 +1611,7 @@ private module MkStage { allowsFieldFlow, argApa, pragma[only_bind_into](config)) and fwdFlow(arg, _, _, _, _, pragma[only_bind_into](argAp), argApa, pragma[only_bind_into](config)) and - returnFlowsThrough(_, _, _, _, p, pragma[only_bind_into](argAp), _, + returnFlowsThrough(_, _, _, _, p, pragma[only_bind_into](argAp), ap, pragma[only_bind_into](config)) and if allowsFieldFlow = false then argAp instanceof ApNil else any() ) @@ -1639,12 +1630,13 @@ private module MkStage { pragma[nomagic] private predicate flowOutOfCallAp( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, boolean allowsFieldFlow, + DataFlowCall call, RetNodeEx ret, ReturnPosition pos, NodeEx out, boolean allowsFieldFlow, Ap ap, Configuration config ) { exists(ApApprox apa | - flowOutOfCallApa(call, ret, kind, out, allowsFieldFlow, apa, config) and - fwdFlow(ret, _, _, _, _, ap, apa, config) + flowOutOfCallApa(call, ret, _, out, allowsFieldFlow, apa, config) and + fwdFlow(ret, _, _, _, _, ap, apa, config) and + pos = ret.getReturnPosition() ) } @@ -1739,17 +1731,17 @@ private module MkStage { ) or // flow through a callable - exists(DataFlowCall call, ReturnKindExt returnKind0, Ap returnAp0 | - revFlowInToReturn(call, node, state, returnKind0, returnAp0, ap, config) and - revFlowIsReturned(call, returnCtx, returnAp, returnKind0, returnAp0, config) + exists(DataFlowCall call, ParamNodeEx p, ReturnPosition pos, Ap innerReturnAp | + revFlowThrough(call, returnCtx, p, state, pos, returnAp, ap, innerReturnAp, config) and + flowThroughIntoCall(call, node, p, _, ap, innerReturnAp, config) ) or // flow out of a callable - exists(ReturnKindExt kind | - revFlowOut(_, node, kind, state, _, _, ap, config) and - if returnFlowsThrough(node, kind, state, _, _, _, ap, config) + exists(ReturnPosition pos | + revFlowOut(_, node, pos, state, _, _, ap, config) and + if returnFlowsThrough(node, pos, state, _, _, _, ap, config) then ( - returnCtx = TReturnCtxMaybeFlowThrough(kind) and + returnCtx = TReturnCtxMaybeFlowThrough(pos) and returnAp = apSome(ap) ) else ( returnCtx = TReturnCtxNoFlowThrough() and returnAp = apNone() @@ -1782,47 +1774,33 @@ private module MkStage { pragma[nomagic] private predicate revFlowOut( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, FlowState state, ReturnCtx returnCtx, + DataFlowCall call, RetNodeEx ret, ReturnPosition pos, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap, Configuration config ) { exists(NodeEx out, boolean allowsFieldFlow | revFlow(out, state, returnCtx, returnAp, ap, config) and - flowOutOfCallAp(call, ret, kind, out, allowsFieldFlow, ap, config) and + flowOutOfCallAp(call, ret, pos, out, allowsFieldFlow, ap, config) and if allowsFieldFlow = false then ap instanceof ApNil else any() ) } - /** - * Same as `flowThroughIntoCall`, but restricted to calls that are reached - * in the flow covered by `revFlow`, where data might flow through the target - * callable and back out at `call`. - */ - pragma[nomagic] - private predicate revFlowThroughIntoCall( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap argAp, - Configuration config - ) { - flowThroughIntoCall(call, arg, p, allowsFieldFlow, argAp, config) and - revFlowIsReturned(call, _, _, _, _, config) - } - pragma[nomagic] private predicate revFlowParamToReturn( - ParamNodeEx p, FlowState state, ReturnKindExt kind, Ap returnAp, Ap ap, Configuration config + ParamNodeEx p, FlowState state, ReturnPosition pos, Ap returnAp, Ap ap, Configuration config ) { - revFlow(p, state, TReturnCtxMaybeFlowThrough(kind), apSome(returnAp), ap, config) and - parameterFlowThroughAllowed(p, kind) + revFlow(pragma[only_bind_into](p), state, TReturnCtxMaybeFlowThrough(pos), apSome(returnAp), + pragma[only_bind_into](ap), pragma[only_bind_into](config)) and + parameterFlowThroughAllowed(p, pos.getKind()) and + PrevStage::parameterMayFlowThrough(p, getApprox(ap), config) } pragma[nomagic] - private predicate revFlowInToReturn( - DataFlowCall call, ArgNodeEx arg, FlowState state, ReturnKindExt kind, Ap returnAp, Ap ap, - Configuration config + private predicate revFlowThrough( + DataFlowCall call, ReturnCtx returnCtx, ParamNodeEx p, FlowState state, ReturnPosition pos, + ApOption returnAp, Ap ap, Ap innerReturnAp, Configuration config ) { - exists(ParamNodeEx p, boolean allowsFieldFlow | - revFlowParamToReturn(p, state, kind, returnAp, ap, config) and - revFlowThroughIntoCall(call, arg, p, allowsFieldFlow, ap, config) - ) + revFlowParamToReturn(p, state, pos, innerReturnAp, ap, config) and + revFlowIsReturned(call, returnCtx, returnAp, pos, innerReturnAp, config) } /** @@ -1832,12 +1810,12 @@ private module MkStage { */ pragma[nomagic] private predicate revFlowIsReturned( - DataFlowCall call, ReturnCtx returnCtx, ApOption returnAp, ReturnKindExt kind, Ap ap, + DataFlowCall call, ReturnCtx returnCtx, ApOption returnAp, ReturnPosition pos, Ap ap, Configuration config ) { exists(RetNodeEx ret, FlowState state, CcCall ccc | - revFlowOut(call, ret, kind, state, returnCtx, returnAp, ap, config) and - returnFlowsThrough(ret, kind, state, ccc, _, _, ap, config) and + revFlowOut(call, ret, pos, state, returnCtx, returnAp, ap, config) and + returnFlowsThrough(ret, pos, state, ccc, _, _, ap, config) and matchesCall(ccc, call) ) } @@ -1915,17 +1893,17 @@ private module MkStage { pragma[nomagic] private predicate parameterFlowsThroughRev( - ParamNodeEx p, Ap ap, ReturnKindExt kind, Ap returnAp, Configuration config + ParamNodeEx p, Ap ap, ReturnPosition pos, Ap returnAp, Configuration config ) { - revFlow(p, _, TReturnCtxMaybeFlowThrough(kind), apSome(returnAp), ap, config) and - parameterFlowThroughAllowed(p, kind) + revFlow(p, _, TReturnCtxMaybeFlowThrough(pos), apSome(returnAp), ap, config) and + parameterFlowThroughAllowed(p, pos.getKind()) } pragma[nomagic] predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap, Configuration config) { - exists(RetNodeEx ret, ReturnKindExt kind | - returnFlowsThrough(ret, kind, _, _, p, ap, _, config) and - parameterFlowsThroughRev(p, ap, kind, _, config) + exists(RetNodeEx ret, ReturnPosition pos | + returnFlowsThrough(ret, pos, _, _, p, ap, _, config) and + parameterFlowsThroughRev(p, ap, pos, _, config) ) } @@ -1933,20 +1911,21 @@ private module MkStage { predicate returnMayFlowThrough( RetNodeEx ret, Ap argAp, Ap ap, ReturnKindExt kind, Configuration config ) { - exists(ParamNodeEx p | - returnFlowsThrough(ret, kind, _, _, p, argAp, ap, config) and - parameterFlowsThroughRev(p, argAp, kind, ap, config) + exists(ParamNodeEx p, ReturnPosition pos | + returnFlowsThrough(ret, pos, _, _, p, argAp, ap, config) and + parameterFlowsThroughRev(p, argAp, pos, ap, config) and + kind = pos.getKind() ) } pragma[nomagic] - predicate revFlowInToReturnIsReturned( + private predicate revFlowThroughArg( DataFlowCall call, ArgNodeEx arg, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap, Configuration config ) { - exists(ReturnKindExt returnKind0, Ap returnAp0 | - revFlowInToReturn(call, arg, state, returnKind0, returnAp0, ap, config) and - revFlowIsReturned(call, returnCtx, returnAp, returnKind0, returnAp0, config) + exists(ParamNodeEx p, ReturnPosition pos, Ap innerReturnAp | + revFlowThrough(call, returnCtx, p, state, pos, returnAp, ap, innerReturnAp, config) and + flowThroughIntoCall(call, arg, p, _, ap, innerReturnAp, config) ) } @@ -1954,7 +1933,7 @@ private module MkStage { predicate callMayFlowThroughRev(DataFlowCall call, Configuration config) { exists(ArgNodeEx arg, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap | revFlow(arg, state, returnCtx, returnAp, ap, config) and - revFlowInToReturnIsReturned(call, arg, state, returnCtx, returnAp, ap, config) + revFlowThroughArg(call, arg, state, returnCtx, returnAp, ap, config) ) } @@ -1967,8 +1946,9 @@ private module MkStage { conscand = count(TypedContent f0, Ap ap | fwdConsCand(f0, ap, config)) and states = count(FlowState state | fwdFlow(_, state, _, _, _, _, config)) and tuples = - count(NodeEx n, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - Ap ap | fwdFlow(n, state, cc, summaryCtx, argAp, ap, config)) + count(NodeEx n, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap | + fwdFlow(n, state, cc, summaryCtx, argAp, ap, config) + ) or fwd = false and nodes = count(NodeEx node | revFlow(node, _, _, _, _, config)) and @@ -2823,13 +2803,12 @@ private Configuration unbindConf(Configuration conf) { pragma[nomagic] private predicate nodeMayUseSummary0( - NodeEx n, DataFlowCallable c, ParameterPosition pos, FlowState state, AccessPathApprox apa, - Configuration config + NodeEx n, ParamNodeEx p, FlowState state, AccessPathApprox apa, Configuration config ) { exists(AccessPathApprox apa0 | - c = n.getEnclosingCallable() and + Stage5::parameterMayFlowThrough(p, _, _) and Stage5::revFlow(n, state, TReturnCtxMaybeFlowThrough(_), _, apa0, config) and - Stage5::fwdFlow(n, state, any(CallContextCall ccc), TParameterPositionSome(pos), + Stage5::fwdFlow(n, state, any(CallContextCall ccc), TParamNodeSome(p.asNode()), TAccessPathApproxSome(apa), apa0, config) ) } @@ -2838,10 +2817,9 @@ pragma[nomagic] private predicate nodeMayUseSummary( NodeEx n, FlowState state, AccessPathApprox apa, Configuration config ) { - exists(DataFlowCallable c, ParameterPosition pos, ParamNodeEx p | + exists(ParamNodeEx p | Stage5::parameterMayFlowThrough(p, apa, config) and - nodeMayUseSummary0(n, c, pos, state, apa, config) and - p.isParameterOf(c, pos) + nodeMayUseSummary0(n, p, state, apa, config) ) } diff --git a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl2.qll b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl2.qll index 6741ccc2f06..1228d00b6ba 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl2.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl2.qll @@ -622,7 +622,11 @@ private predicate parameterFlowThroughAllowed(ParamNodeEx p, ReturnKindExt kind) } private module Stage1 implements StageSig { - class Ap = Unit; + class Ap extends int { + // workaround for bad functionality-induced joins (happens when using `Unit`) + pragma[nomagic] + Ap() { this in [0 .. 1] and this < 1 } + } private class Cc = boolean; @@ -1327,8 +1331,8 @@ private module MkStage { */ pragma[nomagic] additional predicate fwdFlow( - NodeEx node, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - Ap ap, ApApprox apa, Configuration config + NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, + ApApprox apa, Configuration config ) { fwdFlow0(node, state, cc, summaryCtx, argAp, ap, apa, config) and PrevStage::revFlow(node, state, apa, config) and @@ -1337,21 +1341,21 @@ private module MkStage { pragma[inline] additional predicate fwdFlow( - NodeEx node, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - Ap ap, Configuration config + NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, + Configuration config ) { fwdFlow(node, state, cc, summaryCtx, argAp, ap, _, config) } pragma[nomagic] private predicate fwdFlow0( - NodeEx node, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - Ap ap, ApApprox apa, Configuration config + NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, + ApApprox apa, Configuration config ) { sourceNode(node, state, config) and (if hasSourceCallCtx(config) then cc = ccSomeCall() else cc = ccNone()) and argAp = apNone() and - summaryCtx = TParameterPositionNone() and + summaryCtx = TParamNodeNone() and ap = getApNil(node) and apa = getApprox(ap) or @@ -1372,7 +1376,7 @@ private module MkStage { fwdFlow(mid, pragma[only_bind_into](state), _, _, _, ap, apa, pragma[only_bind_into](config)) and jumpStep(mid, node, config) and cc = ccNone() and - summaryCtx = TParameterPositionNone() and + summaryCtx = TParamNodeNone() and argAp = apNone() ) or @@ -1380,7 +1384,7 @@ private module MkStage { fwdFlow(mid, state, _, _, _, nil, pragma[only_bind_into](config)) and additionalJumpStep(mid, node, config) and cc = ccNone() and - summaryCtx = TParameterPositionNone() and + summaryCtx = TParamNodeNone() and argAp = apNone() and ap = getApNil(node) and apa = getApprox(ap) @@ -1390,7 +1394,7 @@ private module MkStage { fwdFlow(mid, state0, _, _, _, nil, pragma[only_bind_into](config)) and additionalJumpStateStep(mid, state0, node, state, config) and cc = ccNone() and - summaryCtx = TParameterPositionNone() and + summaryCtx = TParamNodeNone() and argAp = apNone() and ap = getApNil(node) and apa = getApprox(ap) @@ -1414,10 +1418,10 @@ private module MkStage { fwdFlowIn(_, node, state, _, cc, _, _, ap, apa, config) and if PrevStage::parameterMayFlowThrough(node, apa, config) then ( - summaryCtx = TParameterPositionSome(node.(ParamNodeEx).getPosition()) and + summaryCtx = TParamNodeSome(node.asNode()) and argAp = apSome(ap) ) else ( - summaryCtx = TParameterPositionNone() and argAp = apNone() + summaryCtx = TParamNodeNone() and argAp = apNone() ) or // flow out of a callable @@ -1433,16 +1437,19 @@ private module MkStage { ) or // flow through a callable - exists(DataFlowCall call, ParameterPosition summaryCtx0, Ap argAp0 | - fwdFlowOutFromArg(call, node, state, summaryCtx0, argAp0, ap, apa, config) and - fwdFlowIsEntered(call, cc, summaryCtx, argAp, summaryCtx0, argAp0, config) + exists( + DataFlowCall call, CcCall ccc, RetNodeEx ret, boolean allowsFieldFlow, ApApprox innerArgApa + | + fwdFlowThrough(call, cc, state, ccc, summaryCtx, argAp, ap, apa, ret, innerArgApa, config) and + flowThroughOutOfCall(call, ccc, ret, node, allowsFieldFlow, innerArgApa, apa, config) and + if allowsFieldFlow = false then ap instanceof ApNil else any() ) } pragma[nomagic] private predicate fwdFlowStore( NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, FlowState state, Cc cc, - ParameterPositionOption summaryCtx, ApOption argAp, Configuration config + ParamNodeOption summaryCtx, ApOption argAp, Configuration config ) { exists(DataFlowType contentType, ApApprox apa1 | fwdFlow(node1, state, cc, summaryCtx, argAp, ap1, apa1, config) and @@ -1473,8 +1480,8 @@ private module MkStage { pragma[nomagic] private predicate fwdFlowRead0( - NodeEx node1, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - ApNonNil ap, Configuration config + NodeEx node1, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, ApNonNil ap, + Configuration config ) { fwdFlow(node1, state, cc, summaryCtx, argAp, ap, config) and PrevStage::readStepCand(node1, _, _, config) @@ -1483,7 +1490,7 @@ private module MkStage { pragma[nomagic] private predicate fwdFlowRead( Ap ap, Content c, NodeEx node1, NodeEx node2, FlowState state, Cc cc, - ParameterPositionOption summaryCtx, ApOption argAp, Configuration config + ParamNodeOption summaryCtx, ApOption argAp, Configuration config ) { fwdFlowRead0(node1, state, cc, summaryCtx, argAp, ap, config) and PrevStage::readStepCand(node1, c, node2, config) and @@ -1493,7 +1500,7 @@ private module MkStage { pragma[nomagic] private predicate fwdFlowIn( DataFlowCall call, ParamNodeEx p, FlowState state, Cc outercc, CcCall innercc, - ParameterPositionOption summaryCtx, ApOption argAp, Ap ap, ApApprox apa, Configuration config + ParamNodeOption summaryCtx, ApOption argAp, Ap ap, ApApprox apa, Configuration config ) { exists(ArgNodeEx arg, boolean allowsFieldFlow | fwdFlow(arg, state, outercc, summaryCtx, argAp, ap, apa, config) and @@ -1505,64 +1512,38 @@ private module MkStage { pragma[nomagic] private predicate fwdFlowRetFromArg( - RetNodeEx ret, FlowState state, CcCall ccc, ParameterPosition summaryCtx, ParamNodeEx p, - Ap argAp, ApApprox argApa, Ap ap, ApApprox apa, Configuration config + RetNodeEx ret, FlowState state, CcCall ccc, ParamNodeEx summaryCtx, Ap argAp, ApApprox argApa, + Ap ap, ApApprox apa, Configuration config ) { - exists(DataFlowCallable c, ReturnKindExt kind | + exists(ReturnKindExt kind | fwdFlow(pragma[only_bind_into](ret), state, ccc, - TParameterPositionSome(pragma[only_bind_into](summaryCtx)), apSome(argAp), ap, apa, config) and - getApprox(argAp) = argApa and - c = ret.getEnclosingCallable() and + TParamNodeSome(pragma[only_bind_into](summaryCtx.asNode())), + pragma[only_bind_into](apSome(argAp)), ap, pragma[only_bind_into](apa), + pragma[only_bind_into](config)) and kind = ret.getKind() and - p.isParameterOf(c, pragma[only_bind_into](summaryCtx)) and - parameterFlowThroughAllowed(p, kind) + parameterFlowThroughAllowed(summaryCtx, kind) and + argApa = getApprox(argAp) and + PrevStage::returnMayFlowThrough(ret, argApa, apa, kind, pragma[only_bind_into](config)) ) } pragma[inline] - private predicate fwdFlowInMayFlowThrough( - DataFlowCall call, Cc cc, CcCall innerCc, ParameterPositionOption summaryCtx, ApOption argAp, - ParamNodeEx param, Ap ap, ApApprox apa, Configuration config + private predicate fwdFlowThrough0( + DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, + ApOption argAp, Ap ap, ApApprox apa, RetNodeEx ret, ParamNodeEx innerSummaryCtx, + Ap innerArgAp, ApApprox innerArgApa, Configuration config ) { - fwdFlowIn(call, pragma[only_bind_into](param), _, cc, innerCc, summaryCtx, argAp, ap, - pragma[only_bind_into](apa), pragma[only_bind_into](config)) and - PrevStage::parameterMayFlowThrough(param, apa, config) - } - - // dedup before joining with `flowThroughOutOfCall` - pragma[nomagic] - private predicate fwdFlowInMayFlowThroughProj( - DataFlowCall call, CcCall innerCc, ApApprox apa, Configuration config - ) { - fwdFlowInMayFlowThrough(call, _, innerCc, _, _, _, _, apa, config) - } - - /** - * Same as `flowThroughOutOfCall`, but restricted to calls that are reached - * in the flow covered by `fwdFlow`, where data might flow through the target - * callable and back out at `call`. - */ - pragma[nomagic] - private predicate fwdFlowThroughOutOfCall( - DataFlowCall call, CcCall ccc, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow, - ApApprox argApa, ApApprox apa, Configuration config - ) { - fwdFlowInMayFlowThroughProj(call, ccc, argApa, config) and - flowThroughOutOfCall(call, ccc, ret, out, allowsFieldFlow, argApa, apa, config) + fwdFlowRetFromArg(ret, state, ccc, innerSummaryCtx, innerArgAp, innerArgApa, ap, apa, config) and + fwdFlowIsEntered(call, cc, ccc, summaryCtx, argAp, innerSummaryCtx, innerArgAp, config) } pragma[nomagic] - private predicate fwdFlowOutFromArg( - DataFlowCall call, NodeEx out, FlowState state, ParameterPosition summaryCtx, Ap argAp, Ap ap, - ApApprox apa, Configuration config + private predicate fwdFlowThrough( + DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, + ApOption argAp, Ap ap, ApApprox apa, RetNodeEx ret, ApApprox innerArgApa, Configuration config ) { - exists(RetNodeEx ret, boolean allowsFieldFlow, CcCall ccc, ApApprox argApa | - fwdFlowRetFromArg(pragma[only_bind_into](ret), state, pragma[only_bind_into](ccc), - summaryCtx, _, argAp, pragma[only_bind_into](argApa), ap, pragma[only_bind_into](apa), - config) and - fwdFlowThroughOutOfCall(call, ccc, ret, out, allowsFieldFlow, argApa, apa, config) and - (if allowsFieldFlow = false then ap instanceof ApNil else any()) - ) + fwdFlowThrough0(call, cc, state, ccc, summaryCtx, argAp, ap, apa, ret, _, _, innerArgApa, + config) } /** @@ -1571,12 +1552,14 @@ private module MkStage { */ pragma[nomagic] private predicate fwdFlowIsEntered( - DataFlowCall call, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - ParameterPosition pos, Ap ap, Configuration config + DataFlowCall call, Cc cc, CcCall innerCc, ParamNodeOption summaryCtx, ApOption argAp, + ParamNodeEx p, Ap ap, Configuration config ) { - exists(ParamNodeEx param | - fwdFlowInMayFlowThrough(call, cc, _, summaryCtx, argAp, param, ap, _, config) and - pos = param.getPosition() + exists(ApApprox apa | + fwdFlowIn(call, pragma[only_bind_into](p), _, cc, innerCc, summaryCtx, argAp, ap, + pragma[only_bind_into](apa), pragma[only_bind_into](config)) and + PrevStage::parameterMayFlowThrough(p, apa, config) and + PrevStage::callMayFlowThroughRev(call, pragma[only_bind_into](config)) ) } @@ -1596,23 +1579,31 @@ private module MkStage { fwdFlowConsCand(ap1, c, ap2, config) } + pragma[nomagic] + private predicate returnFlowsThrough0( + DataFlowCall call, FlowState state, CcCall ccc, Ap ap, ApApprox apa, RetNodeEx ret, + ParamNodeEx innerSummaryCtx, Ap innerArgAp, ApApprox innerArgApa, Configuration config + ) { + fwdFlowThrough0(call, _, state, ccc, _, _, ap, apa, ret, innerSummaryCtx, innerArgAp, + innerArgApa, config) + } + pragma[nomagic] private predicate returnFlowsThrough( - RetNodeEx ret, ReturnKindExt kind, FlowState state, CcCall ccc, ParamNodeEx p, Ap argAp, + RetNodeEx ret, ReturnPosition pos, FlowState state, CcCall ccc, ParamNodeEx p, Ap argAp, Ap ap, Configuration config ) { - exists(boolean allowsFieldFlow, ApApprox argApa, ApApprox apa | - fwdFlowRetFromArg(pragma[only_bind_into](ret), state, pragma[only_bind_into](ccc), _, p, - argAp, pragma[only_bind_into](argApa), ap, pragma[only_bind_into](apa), config) and - kind = ret.getKind() and - fwdFlowThroughOutOfCall(_, ccc, ret, _, allowsFieldFlow, argApa, apa, config) and - (if allowsFieldFlow = false then ap instanceof ApNil else any()) + exists(DataFlowCall call, ApApprox apa, boolean allowsFieldFlow, ApApprox innerArgApa | + returnFlowsThrough0(call, state, ccc, ap, apa, ret, p, argAp, innerArgApa, config) and + flowThroughOutOfCall(call, ccc, ret, _, allowsFieldFlow, innerArgApa, apa, config) and + pos = ret.getReturnPosition() and + if allowsFieldFlow = false then ap instanceof ApNil else any() ) } pragma[nomagic] private predicate flowThroughIntoCall( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap argAp, + DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap argAp, Ap ap, Configuration config ) { exists(ApApprox argApa | @@ -1620,7 +1611,7 @@ private module MkStage { allowsFieldFlow, argApa, pragma[only_bind_into](config)) and fwdFlow(arg, _, _, _, _, pragma[only_bind_into](argAp), argApa, pragma[only_bind_into](config)) and - returnFlowsThrough(_, _, _, _, p, pragma[only_bind_into](argAp), _, + returnFlowsThrough(_, _, _, _, p, pragma[only_bind_into](argAp), ap, pragma[only_bind_into](config)) and if allowsFieldFlow = false then argAp instanceof ApNil else any() ) @@ -1639,12 +1630,13 @@ private module MkStage { pragma[nomagic] private predicate flowOutOfCallAp( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, boolean allowsFieldFlow, + DataFlowCall call, RetNodeEx ret, ReturnPosition pos, NodeEx out, boolean allowsFieldFlow, Ap ap, Configuration config ) { exists(ApApprox apa | - flowOutOfCallApa(call, ret, kind, out, allowsFieldFlow, apa, config) and - fwdFlow(ret, _, _, _, _, ap, apa, config) + flowOutOfCallApa(call, ret, _, out, allowsFieldFlow, apa, config) and + fwdFlow(ret, _, _, _, _, ap, apa, config) and + pos = ret.getReturnPosition() ) } @@ -1739,17 +1731,17 @@ private module MkStage { ) or // flow through a callable - exists(DataFlowCall call, ReturnKindExt returnKind0, Ap returnAp0 | - revFlowInToReturn(call, node, state, returnKind0, returnAp0, ap, config) and - revFlowIsReturned(call, returnCtx, returnAp, returnKind0, returnAp0, config) + exists(DataFlowCall call, ParamNodeEx p, ReturnPosition pos, Ap innerReturnAp | + revFlowThrough(call, returnCtx, p, state, pos, returnAp, ap, innerReturnAp, config) and + flowThroughIntoCall(call, node, p, _, ap, innerReturnAp, config) ) or // flow out of a callable - exists(ReturnKindExt kind | - revFlowOut(_, node, kind, state, _, _, ap, config) and - if returnFlowsThrough(node, kind, state, _, _, _, ap, config) + exists(ReturnPosition pos | + revFlowOut(_, node, pos, state, _, _, ap, config) and + if returnFlowsThrough(node, pos, state, _, _, _, ap, config) then ( - returnCtx = TReturnCtxMaybeFlowThrough(kind) and + returnCtx = TReturnCtxMaybeFlowThrough(pos) and returnAp = apSome(ap) ) else ( returnCtx = TReturnCtxNoFlowThrough() and returnAp = apNone() @@ -1782,47 +1774,33 @@ private module MkStage { pragma[nomagic] private predicate revFlowOut( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, FlowState state, ReturnCtx returnCtx, + DataFlowCall call, RetNodeEx ret, ReturnPosition pos, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap, Configuration config ) { exists(NodeEx out, boolean allowsFieldFlow | revFlow(out, state, returnCtx, returnAp, ap, config) and - flowOutOfCallAp(call, ret, kind, out, allowsFieldFlow, ap, config) and + flowOutOfCallAp(call, ret, pos, out, allowsFieldFlow, ap, config) and if allowsFieldFlow = false then ap instanceof ApNil else any() ) } - /** - * Same as `flowThroughIntoCall`, but restricted to calls that are reached - * in the flow covered by `revFlow`, where data might flow through the target - * callable and back out at `call`. - */ - pragma[nomagic] - private predicate revFlowThroughIntoCall( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap argAp, - Configuration config - ) { - flowThroughIntoCall(call, arg, p, allowsFieldFlow, argAp, config) and - revFlowIsReturned(call, _, _, _, _, config) - } - pragma[nomagic] private predicate revFlowParamToReturn( - ParamNodeEx p, FlowState state, ReturnKindExt kind, Ap returnAp, Ap ap, Configuration config + ParamNodeEx p, FlowState state, ReturnPosition pos, Ap returnAp, Ap ap, Configuration config ) { - revFlow(p, state, TReturnCtxMaybeFlowThrough(kind), apSome(returnAp), ap, config) and - parameterFlowThroughAllowed(p, kind) + revFlow(pragma[only_bind_into](p), state, TReturnCtxMaybeFlowThrough(pos), apSome(returnAp), + pragma[only_bind_into](ap), pragma[only_bind_into](config)) and + parameterFlowThroughAllowed(p, pos.getKind()) and + PrevStage::parameterMayFlowThrough(p, getApprox(ap), config) } pragma[nomagic] - private predicate revFlowInToReturn( - DataFlowCall call, ArgNodeEx arg, FlowState state, ReturnKindExt kind, Ap returnAp, Ap ap, - Configuration config + private predicate revFlowThrough( + DataFlowCall call, ReturnCtx returnCtx, ParamNodeEx p, FlowState state, ReturnPosition pos, + ApOption returnAp, Ap ap, Ap innerReturnAp, Configuration config ) { - exists(ParamNodeEx p, boolean allowsFieldFlow | - revFlowParamToReturn(p, state, kind, returnAp, ap, config) and - revFlowThroughIntoCall(call, arg, p, allowsFieldFlow, ap, config) - ) + revFlowParamToReturn(p, state, pos, innerReturnAp, ap, config) and + revFlowIsReturned(call, returnCtx, returnAp, pos, innerReturnAp, config) } /** @@ -1832,12 +1810,12 @@ private module MkStage { */ pragma[nomagic] private predicate revFlowIsReturned( - DataFlowCall call, ReturnCtx returnCtx, ApOption returnAp, ReturnKindExt kind, Ap ap, + DataFlowCall call, ReturnCtx returnCtx, ApOption returnAp, ReturnPosition pos, Ap ap, Configuration config ) { exists(RetNodeEx ret, FlowState state, CcCall ccc | - revFlowOut(call, ret, kind, state, returnCtx, returnAp, ap, config) and - returnFlowsThrough(ret, kind, state, ccc, _, _, ap, config) and + revFlowOut(call, ret, pos, state, returnCtx, returnAp, ap, config) and + returnFlowsThrough(ret, pos, state, ccc, _, _, ap, config) and matchesCall(ccc, call) ) } @@ -1915,17 +1893,17 @@ private module MkStage { pragma[nomagic] private predicate parameterFlowsThroughRev( - ParamNodeEx p, Ap ap, ReturnKindExt kind, Ap returnAp, Configuration config + ParamNodeEx p, Ap ap, ReturnPosition pos, Ap returnAp, Configuration config ) { - revFlow(p, _, TReturnCtxMaybeFlowThrough(kind), apSome(returnAp), ap, config) and - parameterFlowThroughAllowed(p, kind) + revFlow(p, _, TReturnCtxMaybeFlowThrough(pos), apSome(returnAp), ap, config) and + parameterFlowThroughAllowed(p, pos.getKind()) } pragma[nomagic] predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap, Configuration config) { - exists(RetNodeEx ret, ReturnKindExt kind | - returnFlowsThrough(ret, kind, _, _, p, ap, _, config) and - parameterFlowsThroughRev(p, ap, kind, _, config) + exists(RetNodeEx ret, ReturnPosition pos | + returnFlowsThrough(ret, pos, _, _, p, ap, _, config) and + parameterFlowsThroughRev(p, ap, pos, _, config) ) } @@ -1933,20 +1911,21 @@ private module MkStage { predicate returnMayFlowThrough( RetNodeEx ret, Ap argAp, Ap ap, ReturnKindExt kind, Configuration config ) { - exists(ParamNodeEx p | - returnFlowsThrough(ret, kind, _, _, p, argAp, ap, config) and - parameterFlowsThroughRev(p, argAp, kind, ap, config) + exists(ParamNodeEx p, ReturnPosition pos | + returnFlowsThrough(ret, pos, _, _, p, argAp, ap, config) and + parameterFlowsThroughRev(p, argAp, pos, ap, config) and + kind = pos.getKind() ) } pragma[nomagic] - predicate revFlowInToReturnIsReturned( + private predicate revFlowThroughArg( DataFlowCall call, ArgNodeEx arg, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap, Configuration config ) { - exists(ReturnKindExt returnKind0, Ap returnAp0 | - revFlowInToReturn(call, arg, state, returnKind0, returnAp0, ap, config) and - revFlowIsReturned(call, returnCtx, returnAp, returnKind0, returnAp0, config) + exists(ParamNodeEx p, ReturnPosition pos, Ap innerReturnAp | + revFlowThrough(call, returnCtx, p, state, pos, returnAp, ap, innerReturnAp, config) and + flowThroughIntoCall(call, arg, p, _, ap, innerReturnAp, config) ) } @@ -1954,7 +1933,7 @@ private module MkStage { predicate callMayFlowThroughRev(DataFlowCall call, Configuration config) { exists(ArgNodeEx arg, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap | revFlow(arg, state, returnCtx, returnAp, ap, config) and - revFlowInToReturnIsReturned(call, arg, state, returnCtx, returnAp, ap, config) + revFlowThroughArg(call, arg, state, returnCtx, returnAp, ap, config) ) } @@ -1967,8 +1946,9 @@ private module MkStage { conscand = count(TypedContent f0, Ap ap | fwdConsCand(f0, ap, config)) and states = count(FlowState state | fwdFlow(_, state, _, _, _, _, config)) and tuples = - count(NodeEx n, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - Ap ap | fwdFlow(n, state, cc, summaryCtx, argAp, ap, config)) + count(NodeEx n, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap | + fwdFlow(n, state, cc, summaryCtx, argAp, ap, config) + ) or fwd = false and nodes = count(NodeEx node | revFlow(node, _, _, _, _, config)) and @@ -2823,13 +2803,12 @@ private Configuration unbindConf(Configuration conf) { pragma[nomagic] private predicate nodeMayUseSummary0( - NodeEx n, DataFlowCallable c, ParameterPosition pos, FlowState state, AccessPathApprox apa, - Configuration config + NodeEx n, ParamNodeEx p, FlowState state, AccessPathApprox apa, Configuration config ) { exists(AccessPathApprox apa0 | - c = n.getEnclosingCallable() and + Stage5::parameterMayFlowThrough(p, _, _) and Stage5::revFlow(n, state, TReturnCtxMaybeFlowThrough(_), _, apa0, config) and - Stage5::fwdFlow(n, state, any(CallContextCall ccc), TParameterPositionSome(pos), + Stage5::fwdFlow(n, state, any(CallContextCall ccc), TParamNodeSome(p.asNode()), TAccessPathApproxSome(apa), apa0, config) ) } @@ -2838,10 +2817,9 @@ pragma[nomagic] private predicate nodeMayUseSummary( NodeEx n, FlowState state, AccessPathApprox apa, Configuration config ) { - exists(DataFlowCallable c, ParameterPosition pos, ParamNodeEx p | + exists(ParamNodeEx p | Stage5::parameterMayFlowThrough(p, apa, config) and - nodeMayUseSummary0(n, c, pos, state, apa, config) and - p.isParameterOf(c, pos) + nodeMayUseSummary0(n, p, state, apa, config) ) } diff --git a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl3.qll b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl3.qll index 6741ccc2f06..1228d00b6ba 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl3.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl3.qll @@ -622,7 +622,11 @@ private predicate parameterFlowThroughAllowed(ParamNodeEx p, ReturnKindExt kind) } private module Stage1 implements StageSig { - class Ap = Unit; + class Ap extends int { + // workaround for bad functionality-induced joins (happens when using `Unit`) + pragma[nomagic] + Ap() { this in [0 .. 1] and this < 1 } + } private class Cc = boolean; @@ -1327,8 +1331,8 @@ private module MkStage { */ pragma[nomagic] additional predicate fwdFlow( - NodeEx node, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - Ap ap, ApApprox apa, Configuration config + NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, + ApApprox apa, Configuration config ) { fwdFlow0(node, state, cc, summaryCtx, argAp, ap, apa, config) and PrevStage::revFlow(node, state, apa, config) and @@ -1337,21 +1341,21 @@ private module MkStage { pragma[inline] additional predicate fwdFlow( - NodeEx node, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - Ap ap, Configuration config + NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, + Configuration config ) { fwdFlow(node, state, cc, summaryCtx, argAp, ap, _, config) } pragma[nomagic] private predicate fwdFlow0( - NodeEx node, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - Ap ap, ApApprox apa, Configuration config + NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, + ApApprox apa, Configuration config ) { sourceNode(node, state, config) and (if hasSourceCallCtx(config) then cc = ccSomeCall() else cc = ccNone()) and argAp = apNone() and - summaryCtx = TParameterPositionNone() and + summaryCtx = TParamNodeNone() and ap = getApNil(node) and apa = getApprox(ap) or @@ -1372,7 +1376,7 @@ private module MkStage { fwdFlow(mid, pragma[only_bind_into](state), _, _, _, ap, apa, pragma[only_bind_into](config)) and jumpStep(mid, node, config) and cc = ccNone() and - summaryCtx = TParameterPositionNone() and + summaryCtx = TParamNodeNone() and argAp = apNone() ) or @@ -1380,7 +1384,7 @@ private module MkStage { fwdFlow(mid, state, _, _, _, nil, pragma[only_bind_into](config)) and additionalJumpStep(mid, node, config) and cc = ccNone() and - summaryCtx = TParameterPositionNone() and + summaryCtx = TParamNodeNone() and argAp = apNone() and ap = getApNil(node) and apa = getApprox(ap) @@ -1390,7 +1394,7 @@ private module MkStage { fwdFlow(mid, state0, _, _, _, nil, pragma[only_bind_into](config)) and additionalJumpStateStep(mid, state0, node, state, config) and cc = ccNone() and - summaryCtx = TParameterPositionNone() and + summaryCtx = TParamNodeNone() and argAp = apNone() and ap = getApNil(node) and apa = getApprox(ap) @@ -1414,10 +1418,10 @@ private module MkStage { fwdFlowIn(_, node, state, _, cc, _, _, ap, apa, config) and if PrevStage::parameterMayFlowThrough(node, apa, config) then ( - summaryCtx = TParameterPositionSome(node.(ParamNodeEx).getPosition()) and + summaryCtx = TParamNodeSome(node.asNode()) and argAp = apSome(ap) ) else ( - summaryCtx = TParameterPositionNone() and argAp = apNone() + summaryCtx = TParamNodeNone() and argAp = apNone() ) or // flow out of a callable @@ -1433,16 +1437,19 @@ private module MkStage { ) or // flow through a callable - exists(DataFlowCall call, ParameterPosition summaryCtx0, Ap argAp0 | - fwdFlowOutFromArg(call, node, state, summaryCtx0, argAp0, ap, apa, config) and - fwdFlowIsEntered(call, cc, summaryCtx, argAp, summaryCtx0, argAp0, config) + exists( + DataFlowCall call, CcCall ccc, RetNodeEx ret, boolean allowsFieldFlow, ApApprox innerArgApa + | + fwdFlowThrough(call, cc, state, ccc, summaryCtx, argAp, ap, apa, ret, innerArgApa, config) and + flowThroughOutOfCall(call, ccc, ret, node, allowsFieldFlow, innerArgApa, apa, config) and + if allowsFieldFlow = false then ap instanceof ApNil else any() ) } pragma[nomagic] private predicate fwdFlowStore( NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, FlowState state, Cc cc, - ParameterPositionOption summaryCtx, ApOption argAp, Configuration config + ParamNodeOption summaryCtx, ApOption argAp, Configuration config ) { exists(DataFlowType contentType, ApApprox apa1 | fwdFlow(node1, state, cc, summaryCtx, argAp, ap1, apa1, config) and @@ -1473,8 +1480,8 @@ private module MkStage { pragma[nomagic] private predicate fwdFlowRead0( - NodeEx node1, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - ApNonNil ap, Configuration config + NodeEx node1, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, ApNonNil ap, + Configuration config ) { fwdFlow(node1, state, cc, summaryCtx, argAp, ap, config) and PrevStage::readStepCand(node1, _, _, config) @@ -1483,7 +1490,7 @@ private module MkStage { pragma[nomagic] private predicate fwdFlowRead( Ap ap, Content c, NodeEx node1, NodeEx node2, FlowState state, Cc cc, - ParameterPositionOption summaryCtx, ApOption argAp, Configuration config + ParamNodeOption summaryCtx, ApOption argAp, Configuration config ) { fwdFlowRead0(node1, state, cc, summaryCtx, argAp, ap, config) and PrevStage::readStepCand(node1, c, node2, config) and @@ -1493,7 +1500,7 @@ private module MkStage { pragma[nomagic] private predicate fwdFlowIn( DataFlowCall call, ParamNodeEx p, FlowState state, Cc outercc, CcCall innercc, - ParameterPositionOption summaryCtx, ApOption argAp, Ap ap, ApApprox apa, Configuration config + ParamNodeOption summaryCtx, ApOption argAp, Ap ap, ApApprox apa, Configuration config ) { exists(ArgNodeEx arg, boolean allowsFieldFlow | fwdFlow(arg, state, outercc, summaryCtx, argAp, ap, apa, config) and @@ -1505,64 +1512,38 @@ private module MkStage { pragma[nomagic] private predicate fwdFlowRetFromArg( - RetNodeEx ret, FlowState state, CcCall ccc, ParameterPosition summaryCtx, ParamNodeEx p, - Ap argAp, ApApprox argApa, Ap ap, ApApprox apa, Configuration config + RetNodeEx ret, FlowState state, CcCall ccc, ParamNodeEx summaryCtx, Ap argAp, ApApprox argApa, + Ap ap, ApApprox apa, Configuration config ) { - exists(DataFlowCallable c, ReturnKindExt kind | + exists(ReturnKindExt kind | fwdFlow(pragma[only_bind_into](ret), state, ccc, - TParameterPositionSome(pragma[only_bind_into](summaryCtx)), apSome(argAp), ap, apa, config) and - getApprox(argAp) = argApa and - c = ret.getEnclosingCallable() and + TParamNodeSome(pragma[only_bind_into](summaryCtx.asNode())), + pragma[only_bind_into](apSome(argAp)), ap, pragma[only_bind_into](apa), + pragma[only_bind_into](config)) and kind = ret.getKind() and - p.isParameterOf(c, pragma[only_bind_into](summaryCtx)) and - parameterFlowThroughAllowed(p, kind) + parameterFlowThroughAllowed(summaryCtx, kind) and + argApa = getApprox(argAp) and + PrevStage::returnMayFlowThrough(ret, argApa, apa, kind, pragma[only_bind_into](config)) ) } pragma[inline] - private predicate fwdFlowInMayFlowThrough( - DataFlowCall call, Cc cc, CcCall innerCc, ParameterPositionOption summaryCtx, ApOption argAp, - ParamNodeEx param, Ap ap, ApApprox apa, Configuration config + private predicate fwdFlowThrough0( + DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, + ApOption argAp, Ap ap, ApApprox apa, RetNodeEx ret, ParamNodeEx innerSummaryCtx, + Ap innerArgAp, ApApprox innerArgApa, Configuration config ) { - fwdFlowIn(call, pragma[only_bind_into](param), _, cc, innerCc, summaryCtx, argAp, ap, - pragma[only_bind_into](apa), pragma[only_bind_into](config)) and - PrevStage::parameterMayFlowThrough(param, apa, config) - } - - // dedup before joining with `flowThroughOutOfCall` - pragma[nomagic] - private predicate fwdFlowInMayFlowThroughProj( - DataFlowCall call, CcCall innerCc, ApApprox apa, Configuration config - ) { - fwdFlowInMayFlowThrough(call, _, innerCc, _, _, _, _, apa, config) - } - - /** - * Same as `flowThroughOutOfCall`, but restricted to calls that are reached - * in the flow covered by `fwdFlow`, where data might flow through the target - * callable and back out at `call`. - */ - pragma[nomagic] - private predicate fwdFlowThroughOutOfCall( - DataFlowCall call, CcCall ccc, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow, - ApApprox argApa, ApApprox apa, Configuration config - ) { - fwdFlowInMayFlowThroughProj(call, ccc, argApa, config) and - flowThroughOutOfCall(call, ccc, ret, out, allowsFieldFlow, argApa, apa, config) + fwdFlowRetFromArg(ret, state, ccc, innerSummaryCtx, innerArgAp, innerArgApa, ap, apa, config) and + fwdFlowIsEntered(call, cc, ccc, summaryCtx, argAp, innerSummaryCtx, innerArgAp, config) } pragma[nomagic] - private predicate fwdFlowOutFromArg( - DataFlowCall call, NodeEx out, FlowState state, ParameterPosition summaryCtx, Ap argAp, Ap ap, - ApApprox apa, Configuration config + private predicate fwdFlowThrough( + DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, + ApOption argAp, Ap ap, ApApprox apa, RetNodeEx ret, ApApprox innerArgApa, Configuration config ) { - exists(RetNodeEx ret, boolean allowsFieldFlow, CcCall ccc, ApApprox argApa | - fwdFlowRetFromArg(pragma[only_bind_into](ret), state, pragma[only_bind_into](ccc), - summaryCtx, _, argAp, pragma[only_bind_into](argApa), ap, pragma[only_bind_into](apa), - config) and - fwdFlowThroughOutOfCall(call, ccc, ret, out, allowsFieldFlow, argApa, apa, config) and - (if allowsFieldFlow = false then ap instanceof ApNil else any()) - ) + fwdFlowThrough0(call, cc, state, ccc, summaryCtx, argAp, ap, apa, ret, _, _, innerArgApa, + config) } /** @@ -1571,12 +1552,14 @@ private module MkStage { */ pragma[nomagic] private predicate fwdFlowIsEntered( - DataFlowCall call, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - ParameterPosition pos, Ap ap, Configuration config + DataFlowCall call, Cc cc, CcCall innerCc, ParamNodeOption summaryCtx, ApOption argAp, + ParamNodeEx p, Ap ap, Configuration config ) { - exists(ParamNodeEx param | - fwdFlowInMayFlowThrough(call, cc, _, summaryCtx, argAp, param, ap, _, config) and - pos = param.getPosition() + exists(ApApprox apa | + fwdFlowIn(call, pragma[only_bind_into](p), _, cc, innerCc, summaryCtx, argAp, ap, + pragma[only_bind_into](apa), pragma[only_bind_into](config)) and + PrevStage::parameterMayFlowThrough(p, apa, config) and + PrevStage::callMayFlowThroughRev(call, pragma[only_bind_into](config)) ) } @@ -1596,23 +1579,31 @@ private module MkStage { fwdFlowConsCand(ap1, c, ap2, config) } + pragma[nomagic] + private predicate returnFlowsThrough0( + DataFlowCall call, FlowState state, CcCall ccc, Ap ap, ApApprox apa, RetNodeEx ret, + ParamNodeEx innerSummaryCtx, Ap innerArgAp, ApApprox innerArgApa, Configuration config + ) { + fwdFlowThrough0(call, _, state, ccc, _, _, ap, apa, ret, innerSummaryCtx, innerArgAp, + innerArgApa, config) + } + pragma[nomagic] private predicate returnFlowsThrough( - RetNodeEx ret, ReturnKindExt kind, FlowState state, CcCall ccc, ParamNodeEx p, Ap argAp, + RetNodeEx ret, ReturnPosition pos, FlowState state, CcCall ccc, ParamNodeEx p, Ap argAp, Ap ap, Configuration config ) { - exists(boolean allowsFieldFlow, ApApprox argApa, ApApprox apa | - fwdFlowRetFromArg(pragma[only_bind_into](ret), state, pragma[only_bind_into](ccc), _, p, - argAp, pragma[only_bind_into](argApa), ap, pragma[only_bind_into](apa), config) and - kind = ret.getKind() and - fwdFlowThroughOutOfCall(_, ccc, ret, _, allowsFieldFlow, argApa, apa, config) and - (if allowsFieldFlow = false then ap instanceof ApNil else any()) + exists(DataFlowCall call, ApApprox apa, boolean allowsFieldFlow, ApApprox innerArgApa | + returnFlowsThrough0(call, state, ccc, ap, apa, ret, p, argAp, innerArgApa, config) and + flowThroughOutOfCall(call, ccc, ret, _, allowsFieldFlow, innerArgApa, apa, config) and + pos = ret.getReturnPosition() and + if allowsFieldFlow = false then ap instanceof ApNil else any() ) } pragma[nomagic] private predicate flowThroughIntoCall( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap argAp, + DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap argAp, Ap ap, Configuration config ) { exists(ApApprox argApa | @@ -1620,7 +1611,7 @@ private module MkStage { allowsFieldFlow, argApa, pragma[only_bind_into](config)) and fwdFlow(arg, _, _, _, _, pragma[only_bind_into](argAp), argApa, pragma[only_bind_into](config)) and - returnFlowsThrough(_, _, _, _, p, pragma[only_bind_into](argAp), _, + returnFlowsThrough(_, _, _, _, p, pragma[only_bind_into](argAp), ap, pragma[only_bind_into](config)) and if allowsFieldFlow = false then argAp instanceof ApNil else any() ) @@ -1639,12 +1630,13 @@ private module MkStage { pragma[nomagic] private predicate flowOutOfCallAp( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, boolean allowsFieldFlow, + DataFlowCall call, RetNodeEx ret, ReturnPosition pos, NodeEx out, boolean allowsFieldFlow, Ap ap, Configuration config ) { exists(ApApprox apa | - flowOutOfCallApa(call, ret, kind, out, allowsFieldFlow, apa, config) and - fwdFlow(ret, _, _, _, _, ap, apa, config) + flowOutOfCallApa(call, ret, _, out, allowsFieldFlow, apa, config) and + fwdFlow(ret, _, _, _, _, ap, apa, config) and + pos = ret.getReturnPosition() ) } @@ -1739,17 +1731,17 @@ private module MkStage { ) or // flow through a callable - exists(DataFlowCall call, ReturnKindExt returnKind0, Ap returnAp0 | - revFlowInToReturn(call, node, state, returnKind0, returnAp0, ap, config) and - revFlowIsReturned(call, returnCtx, returnAp, returnKind0, returnAp0, config) + exists(DataFlowCall call, ParamNodeEx p, ReturnPosition pos, Ap innerReturnAp | + revFlowThrough(call, returnCtx, p, state, pos, returnAp, ap, innerReturnAp, config) and + flowThroughIntoCall(call, node, p, _, ap, innerReturnAp, config) ) or // flow out of a callable - exists(ReturnKindExt kind | - revFlowOut(_, node, kind, state, _, _, ap, config) and - if returnFlowsThrough(node, kind, state, _, _, _, ap, config) + exists(ReturnPosition pos | + revFlowOut(_, node, pos, state, _, _, ap, config) and + if returnFlowsThrough(node, pos, state, _, _, _, ap, config) then ( - returnCtx = TReturnCtxMaybeFlowThrough(kind) and + returnCtx = TReturnCtxMaybeFlowThrough(pos) and returnAp = apSome(ap) ) else ( returnCtx = TReturnCtxNoFlowThrough() and returnAp = apNone() @@ -1782,47 +1774,33 @@ private module MkStage { pragma[nomagic] private predicate revFlowOut( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, FlowState state, ReturnCtx returnCtx, + DataFlowCall call, RetNodeEx ret, ReturnPosition pos, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap, Configuration config ) { exists(NodeEx out, boolean allowsFieldFlow | revFlow(out, state, returnCtx, returnAp, ap, config) and - flowOutOfCallAp(call, ret, kind, out, allowsFieldFlow, ap, config) and + flowOutOfCallAp(call, ret, pos, out, allowsFieldFlow, ap, config) and if allowsFieldFlow = false then ap instanceof ApNil else any() ) } - /** - * Same as `flowThroughIntoCall`, but restricted to calls that are reached - * in the flow covered by `revFlow`, where data might flow through the target - * callable and back out at `call`. - */ - pragma[nomagic] - private predicate revFlowThroughIntoCall( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap argAp, - Configuration config - ) { - flowThroughIntoCall(call, arg, p, allowsFieldFlow, argAp, config) and - revFlowIsReturned(call, _, _, _, _, config) - } - pragma[nomagic] private predicate revFlowParamToReturn( - ParamNodeEx p, FlowState state, ReturnKindExt kind, Ap returnAp, Ap ap, Configuration config + ParamNodeEx p, FlowState state, ReturnPosition pos, Ap returnAp, Ap ap, Configuration config ) { - revFlow(p, state, TReturnCtxMaybeFlowThrough(kind), apSome(returnAp), ap, config) and - parameterFlowThroughAllowed(p, kind) + revFlow(pragma[only_bind_into](p), state, TReturnCtxMaybeFlowThrough(pos), apSome(returnAp), + pragma[only_bind_into](ap), pragma[only_bind_into](config)) and + parameterFlowThroughAllowed(p, pos.getKind()) and + PrevStage::parameterMayFlowThrough(p, getApprox(ap), config) } pragma[nomagic] - private predicate revFlowInToReturn( - DataFlowCall call, ArgNodeEx arg, FlowState state, ReturnKindExt kind, Ap returnAp, Ap ap, - Configuration config + private predicate revFlowThrough( + DataFlowCall call, ReturnCtx returnCtx, ParamNodeEx p, FlowState state, ReturnPosition pos, + ApOption returnAp, Ap ap, Ap innerReturnAp, Configuration config ) { - exists(ParamNodeEx p, boolean allowsFieldFlow | - revFlowParamToReturn(p, state, kind, returnAp, ap, config) and - revFlowThroughIntoCall(call, arg, p, allowsFieldFlow, ap, config) - ) + revFlowParamToReturn(p, state, pos, innerReturnAp, ap, config) and + revFlowIsReturned(call, returnCtx, returnAp, pos, innerReturnAp, config) } /** @@ -1832,12 +1810,12 @@ private module MkStage { */ pragma[nomagic] private predicate revFlowIsReturned( - DataFlowCall call, ReturnCtx returnCtx, ApOption returnAp, ReturnKindExt kind, Ap ap, + DataFlowCall call, ReturnCtx returnCtx, ApOption returnAp, ReturnPosition pos, Ap ap, Configuration config ) { exists(RetNodeEx ret, FlowState state, CcCall ccc | - revFlowOut(call, ret, kind, state, returnCtx, returnAp, ap, config) and - returnFlowsThrough(ret, kind, state, ccc, _, _, ap, config) and + revFlowOut(call, ret, pos, state, returnCtx, returnAp, ap, config) and + returnFlowsThrough(ret, pos, state, ccc, _, _, ap, config) and matchesCall(ccc, call) ) } @@ -1915,17 +1893,17 @@ private module MkStage { pragma[nomagic] private predicate parameterFlowsThroughRev( - ParamNodeEx p, Ap ap, ReturnKindExt kind, Ap returnAp, Configuration config + ParamNodeEx p, Ap ap, ReturnPosition pos, Ap returnAp, Configuration config ) { - revFlow(p, _, TReturnCtxMaybeFlowThrough(kind), apSome(returnAp), ap, config) and - parameterFlowThroughAllowed(p, kind) + revFlow(p, _, TReturnCtxMaybeFlowThrough(pos), apSome(returnAp), ap, config) and + parameterFlowThroughAllowed(p, pos.getKind()) } pragma[nomagic] predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap, Configuration config) { - exists(RetNodeEx ret, ReturnKindExt kind | - returnFlowsThrough(ret, kind, _, _, p, ap, _, config) and - parameterFlowsThroughRev(p, ap, kind, _, config) + exists(RetNodeEx ret, ReturnPosition pos | + returnFlowsThrough(ret, pos, _, _, p, ap, _, config) and + parameterFlowsThroughRev(p, ap, pos, _, config) ) } @@ -1933,20 +1911,21 @@ private module MkStage { predicate returnMayFlowThrough( RetNodeEx ret, Ap argAp, Ap ap, ReturnKindExt kind, Configuration config ) { - exists(ParamNodeEx p | - returnFlowsThrough(ret, kind, _, _, p, argAp, ap, config) and - parameterFlowsThroughRev(p, argAp, kind, ap, config) + exists(ParamNodeEx p, ReturnPosition pos | + returnFlowsThrough(ret, pos, _, _, p, argAp, ap, config) and + parameterFlowsThroughRev(p, argAp, pos, ap, config) and + kind = pos.getKind() ) } pragma[nomagic] - predicate revFlowInToReturnIsReturned( + private predicate revFlowThroughArg( DataFlowCall call, ArgNodeEx arg, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap, Configuration config ) { - exists(ReturnKindExt returnKind0, Ap returnAp0 | - revFlowInToReturn(call, arg, state, returnKind0, returnAp0, ap, config) and - revFlowIsReturned(call, returnCtx, returnAp, returnKind0, returnAp0, config) + exists(ParamNodeEx p, ReturnPosition pos, Ap innerReturnAp | + revFlowThrough(call, returnCtx, p, state, pos, returnAp, ap, innerReturnAp, config) and + flowThroughIntoCall(call, arg, p, _, ap, innerReturnAp, config) ) } @@ -1954,7 +1933,7 @@ private module MkStage { predicate callMayFlowThroughRev(DataFlowCall call, Configuration config) { exists(ArgNodeEx arg, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap | revFlow(arg, state, returnCtx, returnAp, ap, config) and - revFlowInToReturnIsReturned(call, arg, state, returnCtx, returnAp, ap, config) + revFlowThroughArg(call, arg, state, returnCtx, returnAp, ap, config) ) } @@ -1967,8 +1946,9 @@ private module MkStage { conscand = count(TypedContent f0, Ap ap | fwdConsCand(f0, ap, config)) and states = count(FlowState state | fwdFlow(_, state, _, _, _, _, config)) and tuples = - count(NodeEx n, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - Ap ap | fwdFlow(n, state, cc, summaryCtx, argAp, ap, config)) + count(NodeEx n, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap | + fwdFlow(n, state, cc, summaryCtx, argAp, ap, config) + ) or fwd = false and nodes = count(NodeEx node | revFlow(node, _, _, _, _, config)) and @@ -2823,13 +2803,12 @@ private Configuration unbindConf(Configuration conf) { pragma[nomagic] private predicate nodeMayUseSummary0( - NodeEx n, DataFlowCallable c, ParameterPosition pos, FlowState state, AccessPathApprox apa, - Configuration config + NodeEx n, ParamNodeEx p, FlowState state, AccessPathApprox apa, Configuration config ) { exists(AccessPathApprox apa0 | - c = n.getEnclosingCallable() and + Stage5::parameterMayFlowThrough(p, _, _) and Stage5::revFlow(n, state, TReturnCtxMaybeFlowThrough(_), _, apa0, config) and - Stage5::fwdFlow(n, state, any(CallContextCall ccc), TParameterPositionSome(pos), + Stage5::fwdFlow(n, state, any(CallContextCall ccc), TParamNodeSome(p.asNode()), TAccessPathApproxSome(apa), apa0, config) ) } @@ -2838,10 +2817,9 @@ pragma[nomagic] private predicate nodeMayUseSummary( NodeEx n, FlowState state, AccessPathApprox apa, Configuration config ) { - exists(DataFlowCallable c, ParameterPosition pos, ParamNodeEx p | + exists(ParamNodeEx p | Stage5::parameterMayFlowThrough(p, apa, config) and - nodeMayUseSummary0(n, c, pos, state, apa, config) and - p.isParameterOf(c, pos) + nodeMayUseSummary0(n, p, state, apa, config) ) } diff --git a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl4.qll b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl4.qll index 6741ccc2f06..1228d00b6ba 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl4.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl4.qll @@ -622,7 +622,11 @@ private predicate parameterFlowThroughAllowed(ParamNodeEx p, ReturnKindExt kind) } private module Stage1 implements StageSig { - class Ap = Unit; + class Ap extends int { + // workaround for bad functionality-induced joins (happens when using `Unit`) + pragma[nomagic] + Ap() { this in [0 .. 1] and this < 1 } + } private class Cc = boolean; @@ -1327,8 +1331,8 @@ private module MkStage { */ pragma[nomagic] additional predicate fwdFlow( - NodeEx node, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - Ap ap, ApApprox apa, Configuration config + NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, + ApApprox apa, Configuration config ) { fwdFlow0(node, state, cc, summaryCtx, argAp, ap, apa, config) and PrevStage::revFlow(node, state, apa, config) and @@ -1337,21 +1341,21 @@ private module MkStage { pragma[inline] additional predicate fwdFlow( - NodeEx node, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - Ap ap, Configuration config + NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, + Configuration config ) { fwdFlow(node, state, cc, summaryCtx, argAp, ap, _, config) } pragma[nomagic] private predicate fwdFlow0( - NodeEx node, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - Ap ap, ApApprox apa, Configuration config + NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, + ApApprox apa, Configuration config ) { sourceNode(node, state, config) and (if hasSourceCallCtx(config) then cc = ccSomeCall() else cc = ccNone()) and argAp = apNone() and - summaryCtx = TParameterPositionNone() and + summaryCtx = TParamNodeNone() and ap = getApNil(node) and apa = getApprox(ap) or @@ -1372,7 +1376,7 @@ private module MkStage { fwdFlow(mid, pragma[only_bind_into](state), _, _, _, ap, apa, pragma[only_bind_into](config)) and jumpStep(mid, node, config) and cc = ccNone() and - summaryCtx = TParameterPositionNone() and + summaryCtx = TParamNodeNone() and argAp = apNone() ) or @@ -1380,7 +1384,7 @@ private module MkStage { fwdFlow(mid, state, _, _, _, nil, pragma[only_bind_into](config)) and additionalJumpStep(mid, node, config) and cc = ccNone() and - summaryCtx = TParameterPositionNone() and + summaryCtx = TParamNodeNone() and argAp = apNone() and ap = getApNil(node) and apa = getApprox(ap) @@ -1390,7 +1394,7 @@ private module MkStage { fwdFlow(mid, state0, _, _, _, nil, pragma[only_bind_into](config)) and additionalJumpStateStep(mid, state0, node, state, config) and cc = ccNone() and - summaryCtx = TParameterPositionNone() and + summaryCtx = TParamNodeNone() and argAp = apNone() and ap = getApNil(node) and apa = getApprox(ap) @@ -1414,10 +1418,10 @@ private module MkStage { fwdFlowIn(_, node, state, _, cc, _, _, ap, apa, config) and if PrevStage::parameterMayFlowThrough(node, apa, config) then ( - summaryCtx = TParameterPositionSome(node.(ParamNodeEx).getPosition()) and + summaryCtx = TParamNodeSome(node.asNode()) and argAp = apSome(ap) ) else ( - summaryCtx = TParameterPositionNone() and argAp = apNone() + summaryCtx = TParamNodeNone() and argAp = apNone() ) or // flow out of a callable @@ -1433,16 +1437,19 @@ private module MkStage { ) or // flow through a callable - exists(DataFlowCall call, ParameterPosition summaryCtx0, Ap argAp0 | - fwdFlowOutFromArg(call, node, state, summaryCtx0, argAp0, ap, apa, config) and - fwdFlowIsEntered(call, cc, summaryCtx, argAp, summaryCtx0, argAp0, config) + exists( + DataFlowCall call, CcCall ccc, RetNodeEx ret, boolean allowsFieldFlow, ApApprox innerArgApa + | + fwdFlowThrough(call, cc, state, ccc, summaryCtx, argAp, ap, apa, ret, innerArgApa, config) and + flowThroughOutOfCall(call, ccc, ret, node, allowsFieldFlow, innerArgApa, apa, config) and + if allowsFieldFlow = false then ap instanceof ApNil else any() ) } pragma[nomagic] private predicate fwdFlowStore( NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, FlowState state, Cc cc, - ParameterPositionOption summaryCtx, ApOption argAp, Configuration config + ParamNodeOption summaryCtx, ApOption argAp, Configuration config ) { exists(DataFlowType contentType, ApApprox apa1 | fwdFlow(node1, state, cc, summaryCtx, argAp, ap1, apa1, config) and @@ -1473,8 +1480,8 @@ private module MkStage { pragma[nomagic] private predicate fwdFlowRead0( - NodeEx node1, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - ApNonNil ap, Configuration config + NodeEx node1, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, ApNonNil ap, + Configuration config ) { fwdFlow(node1, state, cc, summaryCtx, argAp, ap, config) and PrevStage::readStepCand(node1, _, _, config) @@ -1483,7 +1490,7 @@ private module MkStage { pragma[nomagic] private predicate fwdFlowRead( Ap ap, Content c, NodeEx node1, NodeEx node2, FlowState state, Cc cc, - ParameterPositionOption summaryCtx, ApOption argAp, Configuration config + ParamNodeOption summaryCtx, ApOption argAp, Configuration config ) { fwdFlowRead0(node1, state, cc, summaryCtx, argAp, ap, config) and PrevStage::readStepCand(node1, c, node2, config) and @@ -1493,7 +1500,7 @@ private module MkStage { pragma[nomagic] private predicate fwdFlowIn( DataFlowCall call, ParamNodeEx p, FlowState state, Cc outercc, CcCall innercc, - ParameterPositionOption summaryCtx, ApOption argAp, Ap ap, ApApprox apa, Configuration config + ParamNodeOption summaryCtx, ApOption argAp, Ap ap, ApApprox apa, Configuration config ) { exists(ArgNodeEx arg, boolean allowsFieldFlow | fwdFlow(arg, state, outercc, summaryCtx, argAp, ap, apa, config) and @@ -1505,64 +1512,38 @@ private module MkStage { pragma[nomagic] private predicate fwdFlowRetFromArg( - RetNodeEx ret, FlowState state, CcCall ccc, ParameterPosition summaryCtx, ParamNodeEx p, - Ap argAp, ApApprox argApa, Ap ap, ApApprox apa, Configuration config + RetNodeEx ret, FlowState state, CcCall ccc, ParamNodeEx summaryCtx, Ap argAp, ApApprox argApa, + Ap ap, ApApprox apa, Configuration config ) { - exists(DataFlowCallable c, ReturnKindExt kind | + exists(ReturnKindExt kind | fwdFlow(pragma[only_bind_into](ret), state, ccc, - TParameterPositionSome(pragma[only_bind_into](summaryCtx)), apSome(argAp), ap, apa, config) and - getApprox(argAp) = argApa and - c = ret.getEnclosingCallable() and + TParamNodeSome(pragma[only_bind_into](summaryCtx.asNode())), + pragma[only_bind_into](apSome(argAp)), ap, pragma[only_bind_into](apa), + pragma[only_bind_into](config)) and kind = ret.getKind() and - p.isParameterOf(c, pragma[only_bind_into](summaryCtx)) and - parameterFlowThroughAllowed(p, kind) + parameterFlowThroughAllowed(summaryCtx, kind) and + argApa = getApprox(argAp) and + PrevStage::returnMayFlowThrough(ret, argApa, apa, kind, pragma[only_bind_into](config)) ) } pragma[inline] - private predicate fwdFlowInMayFlowThrough( - DataFlowCall call, Cc cc, CcCall innerCc, ParameterPositionOption summaryCtx, ApOption argAp, - ParamNodeEx param, Ap ap, ApApprox apa, Configuration config + private predicate fwdFlowThrough0( + DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, + ApOption argAp, Ap ap, ApApprox apa, RetNodeEx ret, ParamNodeEx innerSummaryCtx, + Ap innerArgAp, ApApprox innerArgApa, Configuration config ) { - fwdFlowIn(call, pragma[only_bind_into](param), _, cc, innerCc, summaryCtx, argAp, ap, - pragma[only_bind_into](apa), pragma[only_bind_into](config)) and - PrevStage::parameterMayFlowThrough(param, apa, config) - } - - // dedup before joining with `flowThroughOutOfCall` - pragma[nomagic] - private predicate fwdFlowInMayFlowThroughProj( - DataFlowCall call, CcCall innerCc, ApApprox apa, Configuration config - ) { - fwdFlowInMayFlowThrough(call, _, innerCc, _, _, _, _, apa, config) - } - - /** - * Same as `flowThroughOutOfCall`, but restricted to calls that are reached - * in the flow covered by `fwdFlow`, where data might flow through the target - * callable and back out at `call`. - */ - pragma[nomagic] - private predicate fwdFlowThroughOutOfCall( - DataFlowCall call, CcCall ccc, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow, - ApApprox argApa, ApApprox apa, Configuration config - ) { - fwdFlowInMayFlowThroughProj(call, ccc, argApa, config) and - flowThroughOutOfCall(call, ccc, ret, out, allowsFieldFlow, argApa, apa, config) + fwdFlowRetFromArg(ret, state, ccc, innerSummaryCtx, innerArgAp, innerArgApa, ap, apa, config) and + fwdFlowIsEntered(call, cc, ccc, summaryCtx, argAp, innerSummaryCtx, innerArgAp, config) } pragma[nomagic] - private predicate fwdFlowOutFromArg( - DataFlowCall call, NodeEx out, FlowState state, ParameterPosition summaryCtx, Ap argAp, Ap ap, - ApApprox apa, Configuration config + private predicate fwdFlowThrough( + DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, + ApOption argAp, Ap ap, ApApprox apa, RetNodeEx ret, ApApprox innerArgApa, Configuration config ) { - exists(RetNodeEx ret, boolean allowsFieldFlow, CcCall ccc, ApApprox argApa | - fwdFlowRetFromArg(pragma[only_bind_into](ret), state, pragma[only_bind_into](ccc), - summaryCtx, _, argAp, pragma[only_bind_into](argApa), ap, pragma[only_bind_into](apa), - config) and - fwdFlowThroughOutOfCall(call, ccc, ret, out, allowsFieldFlow, argApa, apa, config) and - (if allowsFieldFlow = false then ap instanceof ApNil else any()) - ) + fwdFlowThrough0(call, cc, state, ccc, summaryCtx, argAp, ap, apa, ret, _, _, innerArgApa, + config) } /** @@ -1571,12 +1552,14 @@ private module MkStage { */ pragma[nomagic] private predicate fwdFlowIsEntered( - DataFlowCall call, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - ParameterPosition pos, Ap ap, Configuration config + DataFlowCall call, Cc cc, CcCall innerCc, ParamNodeOption summaryCtx, ApOption argAp, + ParamNodeEx p, Ap ap, Configuration config ) { - exists(ParamNodeEx param | - fwdFlowInMayFlowThrough(call, cc, _, summaryCtx, argAp, param, ap, _, config) and - pos = param.getPosition() + exists(ApApprox apa | + fwdFlowIn(call, pragma[only_bind_into](p), _, cc, innerCc, summaryCtx, argAp, ap, + pragma[only_bind_into](apa), pragma[only_bind_into](config)) and + PrevStage::parameterMayFlowThrough(p, apa, config) and + PrevStage::callMayFlowThroughRev(call, pragma[only_bind_into](config)) ) } @@ -1596,23 +1579,31 @@ private module MkStage { fwdFlowConsCand(ap1, c, ap2, config) } + pragma[nomagic] + private predicate returnFlowsThrough0( + DataFlowCall call, FlowState state, CcCall ccc, Ap ap, ApApprox apa, RetNodeEx ret, + ParamNodeEx innerSummaryCtx, Ap innerArgAp, ApApprox innerArgApa, Configuration config + ) { + fwdFlowThrough0(call, _, state, ccc, _, _, ap, apa, ret, innerSummaryCtx, innerArgAp, + innerArgApa, config) + } + pragma[nomagic] private predicate returnFlowsThrough( - RetNodeEx ret, ReturnKindExt kind, FlowState state, CcCall ccc, ParamNodeEx p, Ap argAp, + RetNodeEx ret, ReturnPosition pos, FlowState state, CcCall ccc, ParamNodeEx p, Ap argAp, Ap ap, Configuration config ) { - exists(boolean allowsFieldFlow, ApApprox argApa, ApApprox apa | - fwdFlowRetFromArg(pragma[only_bind_into](ret), state, pragma[only_bind_into](ccc), _, p, - argAp, pragma[only_bind_into](argApa), ap, pragma[only_bind_into](apa), config) and - kind = ret.getKind() and - fwdFlowThroughOutOfCall(_, ccc, ret, _, allowsFieldFlow, argApa, apa, config) and - (if allowsFieldFlow = false then ap instanceof ApNil else any()) + exists(DataFlowCall call, ApApprox apa, boolean allowsFieldFlow, ApApprox innerArgApa | + returnFlowsThrough0(call, state, ccc, ap, apa, ret, p, argAp, innerArgApa, config) and + flowThroughOutOfCall(call, ccc, ret, _, allowsFieldFlow, innerArgApa, apa, config) and + pos = ret.getReturnPosition() and + if allowsFieldFlow = false then ap instanceof ApNil else any() ) } pragma[nomagic] private predicate flowThroughIntoCall( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap argAp, + DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap argAp, Ap ap, Configuration config ) { exists(ApApprox argApa | @@ -1620,7 +1611,7 @@ private module MkStage { allowsFieldFlow, argApa, pragma[only_bind_into](config)) and fwdFlow(arg, _, _, _, _, pragma[only_bind_into](argAp), argApa, pragma[only_bind_into](config)) and - returnFlowsThrough(_, _, _, _, p, pragma[only_bind_into](argAp), _, + returnFlowsThrough(_, _, _, _, p, pragma[only_bind_into](argAp), ap, pragma[only_bind_into](config)) and if allowsFieldFlow = false then argAp instanceof ApNil else any() ) @@ -1639,12 +1630,13 @@ private module MkStage { pragma[nomagic] private predicate flowOutOfCallAp( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, boolean allowsFieldFlow, + DataFlowCall call, RetNodeEx ret, ReturnPosition pos, NodeEx out, boolean allowsFieldFlow, Ap ap, Configuration config ) { exists(ApApprox apa | - flowOutOfCallApa(call, ret, kind, out, allowsFieldFlow, apa, config) and - fwdFlow(ret, _, _, _, _, ap, apa, config) + flowOutOfCallApa(call, ret, _, out, allowsFieldFlow, apa, config) and + fwdFlow(ret, _, _, _, _, ap, apa, config) and + pos = ret.getReturnPosition() ) } @@ -1739,17 +1731,17 @@ private module MkStage { ) or // flow through a callable - exists(DataFlowCall call, ReturnKindExt returnKind0, Ap returnAp0 | - revFlowInToReturn(call, node, state, returnKind0, returnAp0, ap, config) and - revFlowIsReturned(call, returnCtx, returnAp, returnKind0, returnAp0, config) + exists(DataFlowCall call, ParamNodeEx p, ReturnPosition pos, Ap innerReturnAp | + revFlowThrough(call, returnCtx, p, state, pos, returnAp, ap, innerReturnAp, config) and + flowThroughIntoCall(call, node, p, _, ap, innerReturnAp, config) ) or // flow out of a callable - exists(ReturnKindExt kind | - revFlowOut(_, node, kind, state, _, _, ap, config) and - if returnFlowsThrough(node, kind, state, _, _, _, ap, config) + exists(ReturnPosition pos | + revFlowOut(_, node, pos, state, _, _, ap, config) and + if returnFlowsThrough(node, pos, state, _, _, _, ap, config) then ( - returnCtx = TReturnCtxMaybeFlowThrough(kind) and + returnCtx = TReturnCtxMaybeFlowThrough(pos) and returnAp = apSome(ap) ) else ( returnCtx = TReturnCtxNoFlowThrough() and returnAp = apNone() @@ -1782,47 +1774,33 @@ private module MkStage { pragma[nomagic] private predicate revFlowOut( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, FlowState state, ReturnCtx returnCtx, + DataFlowCall call, RetNodeEx ret, ReturnPosition pos, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap, Configuration config ) { exists(NodeEx out, boolean allowsFieldFlow | revFlow(out, state, returnCtx, returnAp, ap, config) and - flowOutOfCallAp(call, ret, kind, out, allowsFieldFlow, ap, config) and + flowOutOfCallAp(call, ret, pos, out, allowsFieldFlow, ap, config) and if allowsFieldFlow = false then ap instanceof ApNil else any() ) } - /** - * Same as `flowThroughIntoCall`, but restricted to calls that are reached - * in the flow covered by `revFlow`, where data might flow through the target - * callable and back out at `call`. - */ - pragma[nomagic] - private predicate revFlowThroughIntoCall( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap argAp, - Configuration config - ) { - flowThroughIntoCall(call, arg, p, allowsFieldFlow, argAp, config) and - revFlowIsReturned(call, _, _, _, _, config) - } - pragma[nomagic] private predicate revFlowParamToReturn( - ParamNodeEx p, FlowState state, ReturnKindExt kind, Ap returnAp, Ap ap, Configuration config + ParamNodeEx p, FlowState state, ReturnPosition pos, Ap returnAp, Ap ap, Configuration config ) { - revFlow(p, state, TReturnCtxMaybeFlowThrough(kind), apSome(returnAp), ap, config) and - parameterFlowThroughAllowed(p, kind) + revFlow(pragma[only_bind_into](p), state, TReturnCtxMaybeFlowThrough(pos), apSome(returnAp), + pragma[only_bind_into](ap), pragma[only_bind_into](config)) and + parameterFlowThroughAllowed(p, pos.getKind()) and + PrevStage::parameterMayFlowThrough(p, getApprox(ap), config) } pragma[nomagic] - private predicate revFlowInToReturn( - DataFlowCall call, ArgNodeEx arg, FlowState state, ReturnKindExt kind, Ap returnAp, Ap ap, - Configuration config + private predicate revFlowThrough( + DataFlowCall call, ReturnCtx returnCtx, ParamNodeEx p, FlowState state, ReturnPosition pos, + ApOption returnAp, Ap ap, Ap innerReturnAp, Configuration config ) { - exists(ParamNodeEx p, boolean allowsFieldFlow | - revFlowParamToReturn(p, state, kind, returnAp, ap, config) and - revFlowThroughIntoCall(call, arg, p, allowsFieldFlow, ap, config) - ) + revFlowParamToReturn(p, state, pos, innerReturnAp, ap, config) and + revFlowIsReturned(call, returnCtx, returnAp, pos, innerReturnAp, config) } /** @@ -1832,12 +1810,12 @@ private module MkStage { */ pragma[nomagic] private predicate revFlowIsReturned( - DataFlowCall call, ReturnCtx returnCtx, ApOption returnAp, ReturnKindExt kind, Ap ap, + DataFlowCall call, ReturnCtx returnCtx, ApOption returnAp, ReturnPosition pos, Ap ap, Configuration config ) { exists(RetNodeEx ret, FlowState state, CcCall ccc | - revFlowOut(call, ret, kind, state, returnCtx, returnAp, ap, config) and - returnFlowsThrough(ret, kind, state, ccc, _, _, ap, config) and + revFlowOut(call, ret, pos, state, returnCtx, returnAp, ap, config) and + returnFlowsThrough(ret, pos, state, ccc, _, _, ap, config) and matchesCall(ccc, call) ) } @@ -1915,17 +1893,17 @@ private module MkStage { pragma[nomagic] private predicate parameterFlowsThroughRev( - ParamNodeEx p, Ap ap, ReturnKindExt kind, Ap returnAp, Configuration config + ParamNodeEx p, Ap ap, ReturnPosition pos, Ap returnAp, Configuration config ) { - revFlow(p, _, TReturnCtxMaybeFlowThrough(kind), apSome(returnAp), ap, config) and - parameterFlowThroughAllowed(p, kind) + revFlow(p, _, TReturnCtxMaybeFlowThrough(pos), apSome(returnAp), ap, config) and + parameterFlowThroughAllowed(p, pos.getKind()) } pragma[nomagic] predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap, Configuration config) { - exists(RetNodeEx ret, ReturnKindExt kind | - returnFlowsThrough(ret, kind, _, _, p, ap, _, config) and - parameterFlowsThroughRev(p, ap, kind, _, config) + exists(RetNodeEx ret, ReturnPosition pos | + returnFlowsThrough(ret, pos, _, _, p, ap, _, config) and + parameterFlowsThroughRev(p, ap, pos, _, config) ) } @@ -1933,20 +1911,21 @@ private module MkStage { predicate returnMayFlowThrough( RetNodeEx ret, Ap argAp, Ap ap, ReturnKindExt kind, Configuration config ) { - exists(ParamNodeEx p | - returnFlowsThrough(ret, kind, _, _, p, argAp, ap, config) and - parameterFlowsThroughRev(p, argAp, kind, ap, config) + exists(ParamNodeEx p, ReturnPosition pos | + returnFlowsThrough(ret, pos, _, _, p, argAp, ap, config) and + parameterFlowsThroughRev(p, argAp, pos, ap, config) and + kind = pos.getKind() ) } pragma[nomagic] - predicate revFlowInToReturnIsReturned( + private predicate revFlowThroughArg( DataFlowCall call, ArgNodeEx arg, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap, Configuration config ) { - exists(ReturnKindExt returnKind0, Ap returnAp0 | - revFlowInToReturn(call, arg, state, returnKind0, returnAp0, ap, config) and - revFlowIsReturned(call, returnCtx, returnAp, returnKind0, returnAp0, config) + exists(ParamNodeEx p, ReturnPosition pos, Ap innerReturnAp | + revFlowThrough(call, returnCtx, p, state, pos, returnAp, ap, innerReturnAp, config) and + flowThroughIntoCall(call, arg, p, _, ap, innerReturnAp, config) ) } @@ -1954,7 +1933,7 @@ private module MkStage { predicate callMayFlowThroughRev(DataFlowCall call, Configuration config) { exists(ArgNodeEx arg, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap | revFlow(arg, state, returnCtx, returnAp, ap, config) and - revFlowInToReturnIsReturned(call, arg, state, returnCtx, returnAp, ap, config) + revFlowThroughArg(call, arg, state, returnCtx, returnAp, ap, config) ) } @@ -1967,8 +1946,9 @@ private module MkStage { conscand = count(TypedContent f0, Ap ap | fwdConsCand(f0, ap, config)) and states = count(FlowState state | fwdFlow(_, state, _, _, _, _, config)) and tuples = - count(NodeEx n, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - Ap ap | fwdFlow(n, state, cc, summaryCtx, argAp, ap, config)) + count(NodeEx n, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap | + fwdFlow(n, state, cc, summaryCtx, argAp, ap, config) + ) or fwd = false and nodes = count(NodeEx node | revFlow(node, _, _, _, _, config)) and @@ -2823,13 +2803,12 @@ private Configuration unbindConf(Configuration conf) { pragma[nomagic] private predicate nodeMayUseSummary0( - NodeEx n, DataFlowCallable c, ParameterPosition pos, FlowState state, AccessPathApprox apa, - Configuration config + NodeEx n, ParamNodeEx p, FlowState state, AccessPathApprox apa, Configuration config ) { exists(AccessPathApprox apa0 | - c = n.getEnclosingCallable() and + Stage5::parameterMayFlowThrough(p, _, _) and Stage5::revFlow(n, state, TReturnCtxMaybeFlowThrough(_), _, apa0, config) and - Stage5::fwdFlow(n, state, any(CallContextCall ccc), TParameterPositionSome(pos), + Stage5::fwdFlow(n, state, any(CallContextCall ccc), TParamNodeSome(p.asNode()), TAccessPathApproxSome(apa), apa0, config) ) } @@ -2838,10 +2817,9 @@ pragma[nomagic] private predicate nodeMayUseSummary( NodeEx n, FlowState state, AccessPathApprox apa, Configuration config ) { - exists(DataFlowCallable c, ParameterPosition pos, ParamNodeEx p | + exists(ParamNodeEx p | Stage5::parameterMayFlowThrough(p, apa, config) and - nodeMayUseSummary0(n, c, pos, state, apa, config) and - p.isParameterOf(c, pos) + nodeMayUseSummary0(n, p, state, apa, config) ) } diff --git a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImplCommon.qll b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImplCommon.qll index c66aefced8d..9aa6a529a5b 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImplCommon.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImplCommon.qll @@ -916,15 +916,15 @@ private module Cached { TDataFlowCallSome(DataFlowCall call) cached - newtype TParameterPositionOption = - TParameterPositionNone() or - TParameterPositionSome(ParameterPosition pos) + newtype TParamNodeOption = + TParamNodeNone() or + TParamNodeSome(ParamNode p) cached newtype TReturnCtx = TReturnCtxNone() or TReturnCtxNoFlowThrough() or - TReturnCtxMaybeFlowThrough(ReturnKindExt kind) + TReturnCtxMaybeFlowThrough(ReturnPosition pos) cached newtype TTypedContentApprox = @@ -1343,15 +1343,15 @@ class DataFlowCallOption extends TDataFlowCallOption { } } -/** An optional `ParameterPosition`. */ -class ParameterPositionOption extends TParameterPositionOption { +/** An optional `ParamNode`. */ +class ParamNodeOption extends TParamNodeOption { string toString() { - this = TParameterPositionNone() and + this = TParamNodeNone() and result = "(none)" or - exists(ParameterPosition pos | - this = TParameterPositionSome(pos) and - result = pos.toString() + exists(ParamNode p | + this = TParamNodeSome(p) and + result = p.toString() ) } } @@ -1363,7 +1363,7 @@ class ParameterPositionOption extends TParameterPositionOption { * * - `TReturnCtxNone()`: no return flow. * - `TReturnCtxNoFlowThrough()`: return flow, but flow through is not possible. - * - `TReturnCtxMaybeFlowThrough(ReturnKindExt kind)`: return flow, of kind `kind`, and + * - `TReturnCtxMaybeFlowThrough(ReturnPosition pos)`: return flow, of kind `pos`, and * flow through may be possible. */ class ReturnCtx extends TReturnCtx { @@ -1374,9 +1374,9 @@ class ReturnCtx extends TReturnCtx { this = TReturnCtxNoFlowThrough() and result = "(no flow through)" or - exists(ReturnKindExt kind | - this = TReturnCtxMaybeFlowThrough(kind) and - result = kind.toString() + exists(ReturnPosition pos | + this = TReturnCtxMaybeFlowThrough(pos) and + result = pos.toString() ) } } diff --git a/cpp/ql/lib/semmle/code/cpp/models/interfaces/Allocation.qll b/cpp/ql/lib/semmle/code/cpp/models/interfaces/Allocation.qll index 00281f0f756..38a3ce235fb 100644 --- a/cpp/ql/lib/semmle/code/cpp/models/interfaces/Allocation.qll +++ b/cpp/ql/lib/semmle/code/cpp/models/interfaces/Allocation.qll @@ -11,38 +11,6 @@ import semmle.code.cpp.Function import semmle.code.cpp.models.Models -/** - * An allocation function such as `malloc`. - */ -abstract class AllocationFunction extends Function { - /** - * Gets the index of the argument for the allocation size, if any. The actual - * allocation size is the value of this argument multiplied by the result of - * `getSizeMult()`, in bytes. - */ - int getSizeArg() { none() } - - /** - * Gets the index of an argument that multiplies the allocation size given by - * `getSizeArg`, if any. - */ - int getSizeMult() { none() } - - /** - * Gets the index of the input pointer argument to be reallocated, if this - * is a `realloc` function. - */ - int getReallocPtrArg() { none() } - - /** - * Whether or not this allocation requires a corresponding deallocation of - * some sort (most do, but `alloca` for example does not). If it is unclear, - * we default to no (for example a placement `new` allocation may or may not - * require a corresponding `delete`). - */ - predicate requiresDealloc() { any() } -} - /** * An allocation expression such as call to `malloc` or a `new` expression. */ @@ -86,6 +54,41 @@ abstract class AllocationExpr extends Expr { predicate requiresDealloc() { any() } } +/** + * An allocation function such as `malloc`. + * + * Note: `AllocationExpr` includes calls to allocation functions, so prefer + * to use that class unless you specifically need to reason about functions. + */ +abstract class AllocationFunction extends Function { + /** + * Gets the index of the argument for the allocation size, if any. The actual + * allocation size is the value of this argument multiplied by the result of + * `getSizeMult()`, in bytes. + */ + int getSizeArg() { none() } + + /** + * Gets the index of an argument that multiplies the allocation size given by + * `getSizeArg`, if any. + */ + int getSizeMult() { none() } + + /** + * Gets the index of the input pointer argument to be reallocated, if this + * is a `realloc` function. + */ + int getReallocPtrArg() { none() } + + /** + * Whether or not this allocation requires a corresponding deallocation of + * some sort (most do, but `alloca` for example does not). If it is unclear, + * we default to no (for example a placement `new` allocation may or may not + * require a corresponding `delete`). + */ + predicate requiresDealloc() { any() } +} + /** * An `operator new` or `operator new[]` function that may be associated with * `new` or `new[]` expressions. Note that `new` and `new[]` are not function diff --git a/cpp/ql/lib/semmle/code/cpp/models/interfaces/Deallocation.qll b/cpp/ql/lib/semmle/code/cpp/models/interfaces/Deallocation.qll index 9c74102e99c..569caebe36f 100644 --- a/cpp/ql/lib/semmle/code/cpp/models/interfaces/Deallocation.qll +++ b/cpp/ql/lib/semmle/code/cpp/models/interfaces/Deallocation.qll @@ -11,16 +11,6 @@ import semmle.code.cpp.Function import semmle.code.cpp.models.Models -/** - * A deallocation function such as `free`. - */ -abstract class DeallocationFunction extends Function { - /** - * Gets the index of the argument that is freed by this function. - */ - int getFreedArg() { none() } -} - /** * An deallocation expression such as call to `free` or a `delete` expression. */ @@ -31,6 +21,19 @@ abstract class DeallocationExpr extends Expr { Expr getFreedExpr() { none() } } +/** + * A deallocation function such as `free`. + * + * Note: `DeallocationExpr` includes calls to deallocation functions, so prefer + * to use that class unless you specifically need to reason about functions. + */ +abstract class DeallocationFunction extends Function { + /** + * Gets the index of the argument that is freed by this function. + */ + int getFreedArg() { none() } +} + /** * An `operator delete` or `operator delete[]` function that may be associated * with `delete` or `delete[]` expressions. Note that `delete` and `delete[]` diff --git a/cpp/ql/src/Best Practices/Likely Errors/OffsetUseBeforeRangeCheck.ql b/cpp/ql/src/Best Practices/Likely Errors/OffsetUseBeforeRangeCheck.ql index c8bf3842773..b0ce7fcce6d 100644 --- a/cpp/ql/src/Best Practices/Likely Errors/OffsetUseBeforeRangeCheck.ql +++ b/cpp/ql/src/Best Practices/Likely Errors/OffsetUseBeforeRangeCheck.ql @@ -15,6 +15,7 @@ import cpp +pragma[nomagic] predicate beforeArrayAccess(Variable v, ArrayExpr access, Expr before) { exists(LogicalAndExpr andexpr | access.getArrayOffset() = v.getAnAccess() and @@ -23,6 +24,7 @@ predicate beforeArrayAccess(Variable v, ArrayExpr access, Expr before) { ) } +pragma[nomagic] predicate afterArrayAccess(Variable v, ArrayExpr access, Expr after) { exists(LogicalAndExpr andexpr | access.getArrayOffset() = v.getAnAccess() and diff --git a/cpp/ql/src/Critical/MissingCheckScanf.ql b/cpp/ql/src/Critical/MissingCheckScanf.ql index cdb48099818..29f1c2b07ad 100644 --- a/cpp/ql/src/Critical/MissingCheckScanf.ql +++ b/cpp/ql/src/Critical/MissingCheckScanf.ql @@ -115,7 +115,8 @@ BasicBlock blockGuardedBy(int value, string op, ScanfFunctionCall call) { from ScanfOutput output, ScanfFunctionCall call, Access access where output.getCall() = call and - output.hasGuardedAccess(access, false) + output.hasGuardedAccess(access, false) and + not exists(DeallocationExpr dealloc | dealloc.getFreedExpr() = access) select access, "This variable is read, but may not have been written. " + "It should be guarded by a check that the $@ returns at least " + diff --git a/cpp/ql/src/change-notes/2022-12-15-no-scanf-buffer-allocation-warnings.md b/cpp/ql/src/change-notes/2022-12-15-no-scanf-buffer-allocation-warnings.md new file mode 100644 index 00000000000..fc02f7cbf3a --- /dev/null +++ b/cpp/ql/src/change-notes/2022-12-15-no-scanf-buffer-allocation-warnings.md @@ -0,0 +1,4 @@ +--- +category: minorAnalysis +--- +* The `cpp/missing-check-scanf` query no longer reports the free'ing of `scanf` output variables as potential reads. \ No newline at end of file diff --git a/cpp/ql/test/library-tests/floats/float128/errors.expected b/cpp/ql/test/library-tests/floats/float128/errors.expected index d7891f3e9b6..2f163e66cb0 100644 --- a/cpp/ql/test/library-tests/floats/float128/errors.expected +++ b/cpp/ql/test/library-tests/floats/float128/errors.expected @@ -1,4 +1,3 @@ | file://:0:0:0:0 | There was an error during this compilation | | float128.cpp:1:39:1:39 | 128-bit floating-point types are not supported in this configuration | -| float128.cpp:2:30:2:30 | an attribute specifies a mode incompatible with '' | -| float128.cpp:2:41:2:41 | invalid combination of type specifiers | +| float128.cpp:2:30:2:30 | 128-bit floating-point types are not supported in this configuration | diff --git a/cpp/ql/test/library-tests/floats/float128/usertypes.expected b/cpp/ql/test/library-tests/floats/float128/usertypes.expected index 84a38d93967..42b6612aff9 100644 --- a/cpp/ql/test/library-tests/floats/float128/usertypes.expected +++ b/cpp/ql/test/library-tests/floats/float128/usertypes.expected @@ -1,4 +1,5 @@ | float128.cpp:1:50:1:60 | _Complex128 | file://:0:0:0:0 | | +| float128.cpp:2:41:2:49 | _Float128 | file://:0:0:0:0 | | | float128.cpp:13:29:13:54 | __is_floating_point_helper | float128.cpp:10:8:10:17 | false_type | | float128.cpp:14:19:14:51 | __is_floating_point_helper | float128.cpp:11:8:11:16 | true_type | | float128.cpp:15:19:15:52 | __is_floating_point_helper | float128.cpp:11:8:11:16 | true_type | diff --git a/cpp/ql/test/query-tests/Critical/MissingCheckScanf/MissingCheckScanf.expected b/cpp/ql/test/query-tests/Critical/MissingCheckScanf/MissingCheckScanf.expected index ce11cb53c58..bbedf4ecc3f 100644 --- a/cpp/ql/test/query-tests/Critical/MissingCheckScanf/MissingCheckScanf.expected +++ b/cpp/ql/test/query-tests/Critical/MissingCheckScanf/MissingCheckScanf.expected @@ -1,19 +1,21 @@ -| test.cpp:30:7:30:7 | i | This variable is read, but may not have been written. It should be guarded by a check that the $@ returns at least 1. | test.cpp:29:3:29:7 | call to scanf | call to scanf | -| test.cpp:46:7:46:7 | i | This variable is read, but may not have been written. It should be guarded by a check that the $@ returns at least 1. | test.cpp:45:3:45:7 | call to scanf | call to scanf | -| test.cpp:63:7:63:7 | i | This variable is read, but may not have been written. It should be guarded by a check that the $@ returns at least 1. | test.cpp:62:3:62:7 | call to scanf | call to scanf | -| test.cpp:75:7:75:7 | i | This variable is read, but may not have been written. It should be guarded by a check that the $@ returns at least 1. | test.cpp:74:3:74:7 | call to scanf | call to scanf | -| test.cpp:87:7:87:7 | i | This variable is read, but may not have been written. It should be guarded by a check that the $@ returns at least 1. | test.cpp:86:3:86:8 | call to fscanf | call to fscanf | -| test.cpp:94:7:94:7 | i | This variable is read, but may not have been written. It should be guarded by a check that the $@ returns at least 1. | test.cpp:93:3:93:8 | call to sscanf | call to sscanf | -| test.cpp:143:8:143:8 | i | This variable is read, but may not have been written. It should be guarded by a check that the $@ returns at least 1. | test.cpp:141:7:141:11 | call to scanf | call to scanf | -| test.cpp:152:8:152:8 | i | This variable is read, but may not have been written. It should be guarded by a check that the $@ returns at least 1. | test.cpp:150:7:150:11 | call to scanf | call to scanf | -| test.cpp:184:8:184:8 | i | This variable is read, but may not have been written. It should be guarded by a check that the $@ returns at least 1. | test.cpp:183:7:183:11 | call to scanf | call to scanf | -| test.cpp:203:8:203:8 | j | This variable is read, but may not have been written. It should be guarded by a check that the $@ returns at least 2. | test.cpp:200:7:200:11 | call to scanf | call to scanf | -| test.cpp:227:9:227:9 | d | This variable is read, but may not have been written. It should be guarded by a check that the $@ returns at least 2. | test.cpp:225:25:225:29 | call to scanf | call to scanf | -| test.cpp:231:9:231:9 | d | This variable is read, but may not have been written. It should be guarded by a check that the $@ returns at least 2. | test.cpp:229:14:229:18 | call to scanf | call to scanf | -| test.cpp:243:7:243:7 | i | This variable is read, but may not have been written. It should be guarded by a check that the $@ returns at least 1. | test.cpp:242:3:242:7 | call to scanf | call to scanf | -| test.cpp:251:7:251:7 | i | This variable is read, but may not have been written. It should be guarded by a check that the $@ returns at least 1. | test.cpp:250:3:250:7 | call to scanf | call to scanf | -| test.cpp:259:7:259:7 | i | This variable is read, but may not have been written. It should be guarded by a check that the $@ returns at least 1. | test.cpp:258:3:258:7 | call to scanf | call to scanf | -| test.cpp:271:7:271:7 | i | This variable is read, but may not have been written. It should be guarded by a check that the $@ returns at least 1. | test.cpp:270:3:270:7 | call to scanf | call to scanf | -| test.cpp:281:8:281:12 | ptr_i | This variable is read, but may not have been written. It should be guarded by a check that the $@ returns at least 1. | test.cpp:280:3:280:7 | call to scanf | call to scanf | -| test.cpp:289:7:289:7 | i | This variable is read, but may not have been written. It should be guarded by a check that the $@ returns at least 1. | test.cpp:288:3:288:7 | call to scanf | call to scanf | -| test.cpp:383:25:383:25 | u | This variable is read, but may not have been written. It should be guarded by a check that the $@ returns at least 1. | test.cpp:382:6:382:11 | call to sscanf | call to sscanf | +| test.cpp:35:7:35:7 | i | This variable is read, but may not have been written. It should be guarded by a check that the $@ returns at least 1. | test.cpp:34:3:34:7 | call to scanf | call to scanf | +| test.cpp:51:7:51:7 | i | This variable is read, but may not have been written. It should be guarded by a check that the $@ returns at least 1. | test.cpp:50:3:50:7 | call to scanf | call to scanf | +| test.cpp:68:7:68:7 | i | This variable is read, but may not have been written. It should be guarded by a check that the $@ returns at least 1. | test.cpp:67:3:67:7 | call to scanf | call to scanf | +| test.cpp:80:7:80:7 | i | This variable is read, but may not have been written. It should be guarded by a check that the $@ returns at least 1. | test.cpp:79:3:79:7 | call to scanf | call to scanf | +| test.cpp:90:8:90:8 | i | This variable is read, but may not have been written. It should be guarded by a check that the $@ returns at least 1. | test.cpp:89:3:89:7 | call to scanf | call to scanf | +| test.cpp:98:8:98:8 | i | This variable is read, but may not have been written. It should be guarded by a check that the $@ returns at least 1. | test.cpp:97:3:97:7 | call to scanf | call to scanf | +| test.cpp:108:7:108:7 | i | This variable is read, but may not have been written. It should be guarded by a check that the $@ returns at least 1. | test.cpp:107:3:107:8 | call to fscanf | call to fscanf | +| test.cpp:115:7:115:7 | i | This variable is read, but may not have been written. It should be guarded by a check that the $@ returns at least 1. | test.cpp:114:3:114:8 | call to sscanf | call to sscanf | +| test.cpp:164:8:164:8 | i | This variable is read, but may not have been written. It should be guarded by a check that the $@ returns at least 1. | test.cpp:162:7:162:11 | call to scanf | call to scanf | +| test.cpp:173:8:173:8 | i | This variable is read, but may not have been written. It should be guarded by a check that the $@ returns at least 1. | test.cpp:171:7:171:11 | call to scanf | call to scanf | +| test.cpp:205:8:205:8 | i | This variable is read, but may not have been written. It should be guarded by a check that the $@ returns at least 1. | test.cpp:204:7:204:11 | call to scanf | call to scanf | +| test.cpp:224:8:224:8 | j | This variable is read, but may not have been written. It should be guarded by a check that the $@ returns at least 2. | test.cpp:221:7:221:11 | call to scanf | call to scanf | +| test.cpp:248:9:248:9 | d | This variable is read, but may not have been written. It should be guarded by a check that the $@ returns at least 2. | test.cpp:246:25:246:29 | call to scanf | call to scanf | +| test.cpp:252:9:252:9 | d | This variable is read, but may not have been written. It should be guarded by a check that the $@ returns at least 2. | test.cpp:250:14:250:18 | call to scanf | call to scanf | +| test.cpp:264:7:264:7 | i | This variable is read, but may not have been written. It should be guarded by a check that the $@ returns at least 1. | test.cpp:263:3:263:7 | call to scanf | call to scanf | +| test.cpp:272:7:272:7 | i | This variable is read, but may not have been written. It should be guarded by a check that the $@ returns at least 1. | test.cpp:271:3:271:7 | call to scanf | call to scanf | +| test.cpp:280:7:280:7 | i | This variable is read, but may not have been written. It should be guarded by a check that the $@ returns at least 1. | test.cpp:279:3:279:7 | call to scanf | call to scanf | +| test.cpp:292:7:292:7 | i | This variable is read, but may not have been written. It should be guarded by a check that the $@ returns at least 1. | test.cpp:291:3:291:7 | call to scanf | call to scanf | +| test.cpp:302:8:302:12 | ptr_i | This variable is read, but may not have been written. It should be guarded by a check that the $@ returns at least 1. | test.cpp:301:3:301:7 | call to scanf | call to scanf | +| test.cpp:310:7:310:7 | i | This variable is read, but may not have been written. It should be guarded by a check that the $@ returns at least 1. | test.cpp:309:3:309:7 | call to scanf | call to scanf | +| test.cpp:404:25:404:25 | u | This variable is read, but may not have been written. It should be guarded by a check that the $@ returns at least 1. | test.cpp:403:6:403:11 | call to sscanf | call to sscanf | diff --git a/cpp/ql/test/query-tests/Critical/MissingCheckScanf/test.cpp b/cpp/ql/test/query-tests/Critical/MissingCheckScanf/test.cpp index e621936dc33..38af4d7efcd 100644 --- a/cpp/ql/test/query-tests/Critical/MissingCheckScanf/test.cpp +++ b/cpp/ql/test/query-tests/Critical/MissingCheckScanf/test.cpp @@ -19,6 +19,11 @@ FILE *get_a_stream(); const char *get_a_string(); extern locale_t get_a_locale(); +typedef long size_t; + +void *malloc(size_t size); +void free(void *ptr); + int main() { // --- simple cases --- @@ -78,6 +83,22 @@ int main() use(i); // GOOD } + { + int *i = (int*)malloc(sizeof(int)); // Allocated variable + + scanf("%d", i); + use(*i); // BAD + free(i); // GOOD + } + + { + int *i = new int; // Allocated variable + + scanf("%d", i); + use(*i); // BAD + delete i; // GOOD + } + // --- different scanf functions --- { diff --git a/csharp/downgrades/83aca6b3e4fa38dd2b97b9b51dfc199a2ba9c7f2/expressions.ql b/csharp/downgrades/83aca6b3e4fa38dd2b97b9b51dfc199a2ba9c7f2/expressions.ql new file mode 100644 index 00000000000..05b9e374f10 --- /dev/null +++ b/csharp/downgrades/83aca6b3e4fa38dd2b97b9b51dfc199a2ba9c7f2/expressions.ql @@ -0,0 +1,13 @@ +class Expression extends @expr { + string toString() { none() } +} + +class TypeOrRef extends @type_or_ref { + string toString() { none() } +} + +from Expression e, int k, int kind, TypeOrRef t +where + expressions(e, k, t) and + if k = [131, 132] then kind = 106 else kind = k +select e, kind, t diff --git a/csharp/downgrades/83aca6b3e4fa38dd2b97b9b51dfc199a2ba9c7f2/old.dbscheme b/csharp/downgrades/83aca6b3e4fa38dd2b97b9b51dfc199a2ba9c7f2/old.dbscheme new file mode 100644 index 00000000000..83aca6b3e4f --- /dev/null +++ b/csharp/downgrades/83aca6b3e4fa38dd2b97b9b51dfc199a2ba9c7f2/old.dbscheme @@ -0,0 +1,2067 @@ +/* This is a dummy line to alter the dbscheme, so we can make a database upgrade + * without actually changing any of the dbscheme predicates. It contains a date + * to allow for such updates in the future as well. + * + * 2021-07-14 + * + * DO NOT remove this comment carelessly, since it can revert the dbscheme back to a + * previously seen state (matching a previously seen SHA), which would make the upgrade + * mechanism not work properly. + */ + +/** + * An invocation of the compiler. Note that more than one file may be + * compiled per invocation. For example, this command compiles three + * source files: + * + * csc f1.cs f2.cs f3.cs + * + * The `id` simply identifies the invocation, while `cwd` is the working + * directory from which the compiler was invoked. + */ +compilations( + unique int id : @compilation, + string cwd : string ref +); + +/** + * The arguments that were passed to the extractor for a compiler + * invocation. If `id` is for the compiler invocation + * + * csc f1.cs f2.cs f3.cs + * + * then typically there will be rows for + * + * num | arg + * --- | --- + * 0 | --compiler + * 1 | *path to compiler* + * 2 | f1.cs + * 3 | f2.cs + * 4 | f3.cs + */ +#keyset[id, num] +compilation_args( + int id : @compilation ref, + int num : int ref, + string arg : string ref +); + +/** + * The source files that are compiled by a compiler invocation. + * If `id` is for the compiler invocation + * + * csc f1.cs f2.cs f3.cs + * + * then there will be rows for + * + * num | arg + * --- | --- + * 0 | f1.cs + * 1 | f2.cs + * 2 | f3.cs + */ +#keyset[id, num] +compilation_compiling_files( + int id : @compilation ref, + int num : int ref, + int file : @file ref +); + +/** + * The references used by a compiler invocation. + * If `id` is for the compiler invocation + * + * csc f1.cs f2.cs f3.cs /r:ref1.dll /r:ref2.dll /r:ref3.dll + * + * then there will be rows for + * + * num | arg + * --- | --- + * 0 | ref1.dll + * 1 | ref2.dll + * 2 | ref3.dll + */ +#keyset[id, num] +compilation_referencing_files( + int id : @compilation ref, + int num : int ref, + int file : @file ref +); + +/** + * The time taken by the extractor for a compiler invocation. + * + * For each file `num`, there will be rows for + * + * kind | seconds + * ---- | --- + * 1 | CPU seconds used by the extractor frontend + * 2 | Elapsed seconds during the extractor frontend + * 3 | CPU seconds used by the extractor backend + * 4 | Elapsed seconds during the extractor backend + */ +#keyset[id, num, kind] +compilation_time( + int id : @compilation ref, + int num : int ref, + /* kind: + 1 = frontend_cpu_seconds + 2 = frontend_elapsed_seconds + 3 = extractor_cpu_seconds + 4 = extractor_elapsed_seconds + */ + int kind : int ref, + float seconds : float ref +); + +/** + * An error or warning generated by the extractor. + * The diagnostic message `diagnostic` was generated during compiler + * invocation `compilation`, and is the `file_number_diagnostic_number`th + * message generated while extracting the `file_number`th file of that + * invocation. + */ +#keyset[compilation, file_number, file_number_diagnostic_number] +diagnostic_for( + unique int diagnostic : @diagnostic ref, + int compilation : @compilation ref, + int file_number : int ref, + int file_number_diagnostic_number : int ref +); + +diagnostics( + unique int id: @diagnostic, + int severity: int ref, + string error_tag: string ref, + string error_message: string ref, + string full_error_message: string ref, + int location: @location_default ref +); + +extractor_messages( + unique int id: @extractor_message, + int severity: int ref, + string origin : string ref, + string text : string ref, + string entity : string ref, + int location: @location_default ref, + string stack_trace : string ref +); + +/** + * If extraction was successful, then `cpu_seconds` and + * `elapsed_seconds` are the CPU time and elapsed time (respectively) + * that extraction took for compiler invocation `id`. + */ +compilation_finished( + unique int id : @compilation ref, + float cpu_seconds : float ref, + float elapsed_seconds : float ref +); + +compilation_assembly( + unique int id : @compilation ref, + int assembly: @assembly ref +) + +// Populated by the CSV extractor +externalData( + int id: @externalDataElement, + string path: string ref, + int column: int ref, + string value: string ref); + +sourceLocationPrefix( + string prefix: string ref); + +/* + * C# dbscheme + */ + +/** ELEMENTS **/ + +@element = @declaration | @stmt | @expr | @modifier | @attribute | @namespace_declaration + | @using_directive | @type_parameter_constraints | @externalDataElement + | @xmllocatable | @asp_element | @namespace | @preprocessor_directive; + +@declaration = @callable | @generic | @assignable | @namespace; + +@named_element = @namespace | @declaration; + +@declaration_with_accessors = @property | @indexer | @event; + +@assignable = @variable | @assignable_with_accessors | @event; + +@assignable_with_accessors = @property | @indexer; + +@attributable = @assembly | @field | @parameter | @operator | @method | @constructor + | @destructor | @callable_accessor | @value_or_ref_type | @declaration_with_accessors + | @local_function | @lambda_expr; + +/** LOCATIONS, ASEMMBLIES, MODULES, FILES and FOLDERS **/ + +@location = @location_default | @assembly; + +locations_default( + unique int id: @location_default, + int file: @file ref, + int beginLine: int ref, + int beginColumn: int ref, + int endLine: int ref, + int endColumn: int ref); + +locations_mapped( + unique int id: @location_default ref, + int mapped_to: @location_default ref); + +@sourceline = @file | @callable | @xmllocatable; + +numlines( + int element_id: @sourceline ref, + int num_lines: int ref, + int num_code: int ref, + int num_comment: int ref); + +assemblies( + unique int id: @assembly, + int file: @file ref, + string fullname: string ref, + string name: string ref, + string version: string ref); + +files( + unique int id: @file, + string name: string ref); + +folders( + unique int id: @folder, + string name: string ref); + +@container = @folder | @file ; + +containerparent( + int parent: @container ref, + unique int child: @container ref); + +file_extraction_mode( + unique int file: @file ref, + int mode: int ref + /* 0 = normal, 1 = standalone extractor */ + ); + +/** NAMESPACES **/ + +@type_container = @namespace | @type; + +namespaces( + unique int id: @namespace, + string name: string ref); + +namespace_declarations( + unique int id: @namespace_declaration, + int namespace_id: @namespace ref); + +namespace_declaration_location( + unique int id: @namespace_declaration ref, + int loc: @location ref); + +parent_namespace( + unique int child_id: @type_container ref, + int namespace_id: @namespace ref); + +@declaration_or_directive = @namespace_declaration | @type | @using_directive; + +parent_namespace_declaration( + int child_id: @declaration_or_directive ref, // cannot be unique because of partial classes + int namespace_id: @namespace_declaration ref); + +@using_directive = @using_namespace_directive | @using_static_directive; + +using_global( + unique int id: @using_directive ref +); + +using_namespace_directives( + unique int id: @using_namespace_directive, + int namespace_id: @namespace ref); + +using_static_directives( + unique int id: @using_static_directive, + int type_id: @type_or_ref ref); + +using_directive_location( + unique int id: @using_directive ref, + int loc: @location ref); + +@preprocessor_directive = @pragma_warning | @pragma_checksum | @directive_define | @directive_undefine | @directive_warning + | @directive_error | @directive_nullable | @directive_line | @directive_region | @directive_endregion | @directive_if + | @directive_elif | @directive_else | @directive_endif; + +@conditional_directive = @directive_if | @directive_elif; +@branch_directive = @directive_if | @directive_elif | @directive_else; + +directive_ifs( + unique int id: @directive_if, + int branchTaken: int ref, /* 0: false, 1: true */ + int conditionValue: int ref); /* 0: false, 1: true */ + +directive_elifs( + unique int id: @directive_elif, + int branchTaken: int ref, /* 0: false, 1: true */ + int conditionValue: int ref, /* 0: false, 1: true */ + int parent: @directive_if ref, + int index: int ref); + +directive_elses( + unique int id: @directive_else, + int branchTaken: int ref, /* 0: false, 1: true */ + int parent: @directive_if ref, + int index: int ref); + +#keyset[id, start] +directive_endifs( + unique int id: @directive_endif, + unique int start: @directive_if ref); + +directive_define_symbols( + unique int id: @define_symbol_expr ref, + string name: string ref); + +directive_regions( + unique int id: @directive_region, + string name: string ref); + +#keyset[id, start] +directive_endregions( + unique int id: @directive_endregion, + unique int start: @directive_region ref); + +directive_lines( + unique int id: @directive_line, + int kind: int ref); /* 0: default, 1: hidden, 2: numeric, 3: span */ + +directive_line_value( + unique int id: @directive_line ref, + int line: int ref); + +directive_line_file( + unique int id: @directive_line ref, + int file: @file ref); + +directive_line_offset( + unique int id: @directive_line ref, + int offset: int ref); + +directive_line_span( + unique int id: @directive_line ref, + int startLine: int ref, + int startColumn: int ref, + int endLine: int ref, + int endColumn: int ref); + +directive_nullables( + unique int id: @directive_nullable, + int setting: int ref, /* 0: disable, 1: enable, 2: restore */ + int target: int ref); /* 0: none, 1: annotations, 2: warnings */ + +directive_warnings( + unique int id: @directive_warning, + string message: string ref); + +directive_errors( + unique int id: @directive_error, + string message: string ref); + +directive_undefines( + unique int id: @directive_undefine, + string name: string ref); + +directive_defines( + unique int id: @directive_define, + string name: string ref); + +pragma_checksums( + unique int id: @pragma_checksum, + int file: @file ref, + string guid: string ref, + string bytes: string ref); + +pragma_warnings( + unique int id: @pragma_warning, + int kind: int ref /* 0 = disable, 1 = restore */); + +#keyset[id, index] +pragma_warning_error_codes( + int id: @pragma_warning ref, + string errorCode: string ref, + int index: int ref); + +preprocessor_directive_location( + unique int id: @preprocessor_directive ref, + int loc: @location ref); + +preprocessor_directive_compilation( + unique int id: @preprocessor_directive ref, + int compilation: @compilation ref); + +preprocessor_directive_active( + unique int id: @preprocessor_directive ref, + int active: int ref); /* 0: false, 1: true */ + +/** TYPES **/ + +types( + unique int id: @type, + int kind: int ref, + string name: string ref); + +case @type.kind of + 1 = @bool_type +| 2 = @char_type +| 3 = @decimal_type +| 4 = @sbyte_type +| 5 = @short_type +| 6 = @int_type +| 7 = @long_type +| 8 = @byte_type +| 9 = @ushort_type +| 10 = @uint_type +| 11 = @ulong_type +| 12 = @float_type +| 13 = @double_type +| 14 = @enum_type +| 15 = @struct_type +| 17 = @class_type +| 19 = @interface_type +| 20 = @delegate_type +| 21 = @null_type +| 22 = @type_parameter +| 23 = @pointer_type +| 24 = @nullable_type +| 25 = @array_type +| 26 = @void_type +| 27 = @int_ptr_type +| 28 = @uint_ptr_type +| 29 = @dynamic_type +| 30 = @arglist_type +| 31 = @unknown_type +| 32 = @tuple_type +| 33 = @function_pointer_type + ; + +@simple_type = @bool_type | @char_type | @integral_type | @floating_point_type | @decimal_type; +@integral_type = @signed_integral_type | @unsigned_integral_type; +@signed_integral_type = @sbyte_type | @short_type | @int_type | @long_type; +@unsigned_integral_type = @byte_type | @ushort_type | @uint_type | @ulong_type; +@floating_point_type = @float_type | @double_type; +@value_type = @simple_type | @enum_type | @struct_type | @nullable_type | @int_ptr_type + | @uint_ptr_type | @tuple_type; +@ref_type = @class_type | @interface_type | @array_type | @delegate_type | @null_type + | @dynamic_type; +@value_or_ref_type = @value_type | @ref_type; + +typerefs( + unique int id: @typeref, + string name: string ref); + +typeref_type( + int id: @typeref ref, + unique int typeId: @type ref); + +@type_or_ref = @type | @typeref; + +array_element_type( + unique int array: @array_type ref, + int dimension: int ref, + int rank: int ref, + int element: @type_or_ref ref); + +nullable_underlying_type( + unique int nullable: @nullable_type ref, + int underlying: @type_or_ref ref); + +pointer_referent_type( + unique int pointer: @pointer_type ref, + int referent: @type_or_ref ref); + +enum_underlying_type( + unique int enum_id: @enum_type ref, + int underlying_type_id: @type_or_ref ref); + +delegate_return_type( + unique int delegate_id: @delegate_type ref, + int return_type_id: @type_or_ref ref); + +function_pointer_return_type( + unique int function_pointer_id: @function_pointer_type ref, + int return_type_id: @type_or_ref ref); + +extend( + int sub: @type ref, + int super: @type_or_ref ref); + +anonymous_types( + unique int id: @type ref); + +@interface_or_ref = @interface_type | @typeref; + +implement( + int sub: @type ref, + int super: @type_or_ref ref); + +type_location( + int id: @type ref, + int loc: @location ref); + +tuple_underlying_type( + unique int tuple: @tuple_type ref, + int struct: @type_or_ref ref); + +#keyset[tuple, index] +tuple_element( + int tuple: @tuple_type ref, + int index: int ref, + unique int field: @field ref); + +attributes( + unique int id: @attribute, + int kind: int ref, + int type_id: @type_or_ref ref, + int target: @attributable ref); + +case @attribute.kind of + 0 = @attribute_default +| 1 = @attribute_return +| 2 = @attribute_assembly +| 3 = @attribute_module +; + +attribute_location( + int id: @attribute ref, + int loc: @location ref); + +@type_mention_parent = @element | @type_mention; + +type_mention( + unique int id: @type_mention, + int type_id: @type_or_ref ref, + int parent: @type_mention_parent ref); + +type_mention_location( + unique int id: @type_mention ref, + int loc: @location ref); + +@has_type_annotation = @assignable | @type_parameter | @callable | @expr | @delegate_type | @generic | @function_pointer_type; + +/** + * A direct annotation on an entity, for example `string? x;`. + * + * Annotations: + * 2 = reftype is not annotated "!" + * 3 = reftype is annotated "?" + * 4 = readonly ref type / in parameter + * 5 = ref type parameter, return or local variable + * 6 = out parameter + * + * Note that the annotation depends on the element it annotates. + * @assignable: The annotation is on the type of the assignable, for example the variable type. + * @type_parameter: The annotation is on the reftype constraint + * @callable: The annotation is on the return type + * @array_type: The annotation is on the element type + */ +type_annotation(int id: @has_type_annotation ref, int annotation: int ref); + +nullability(unique int nullability: @nullability, int kind: int ref); + +case @nullability.kind of + 0 = @oblivious +| 1 = @not_annotated +| 2 = @annotated +; + +#keyset[parent, index] +nullability_parent(int nullability: @nullability ref, int index: int ref, int parent: @nullability ref) + +type_nullability(int id: @has_type_annotation ref, int nullability: @nullability ref); + +/** + * The nullable flow state of an expression, as determined by Roslyn. + * 0 = none (default, not populated) + * 1 = not null + * 2 = maybe null + */ +expr_flowstate(unique int id: @expr ref, int state: int ref); + +/** GENERICS **/ + +@generic = @type | @method | @local_function; + +type_parameters( + unique int id: @type_parameter ref, + int index: int ref, + int generic_id: @generic ref, + int variance: int ref /* none = 0, out = 1, in = 2 */); + +#keyset[constructed_id, index] +type_arguments( + int id: @type_or_ref ref, + int index: int ref, + int constructed_id: @generic_or_ref ref); + +@generic_or_ref = @generic | @typeref; + +constructed_generic( + unique int constructed: @generic ref, + int generic: @generic_or_ref ref); + +type_parameter_constraints( + unique int id: @type_parameter_constraints, + int param_id: @type_parameter ref); + +type_parameter_constraints_location( + int id: @type_parameter_constraints ref, + int loc: @location ref); + +general_type_parameter_constraints( + int id: @type_parameter_constraints ref, + int kind: int ref /* class = 1, struct = 2, new = 3 */); + +specific_type_parameter_constraints( + int id: @type_parameter_constraints ref, + int base_id: @type_or_ref ref); + +specific_type_parameter_nullability( + int id: @type_parameter_constraints ref, + int base_id: @type_or_ref ref, + int nullability: @nullability ref); + +/** FUNCTION POINTERS */ + +function_pointer_calling_conventions( + int id: @function_pointer_type ref, + int kind: int ref); + +#keyset[id, index] +has_unmanaged_calling_conventions( + int id: @function_pointer_type ref, + int index: int ref, + int conv_id: @type_or_ref ref); + +/** MODIFIERS */ + +@modifiable = @modifiable_direct | @event_accessor; + +@modifiable_direct = @member | @accessor | @local_function | @anonymous_function_expr; + +modifiers( + unique int id: @modifier, + string name: string ref); + +has_modifiers( + int id: @modifiable_direct ref, + int mod_id: @modifier ref); + +compiler_generated(unique int id: @modifiable ref); + +/** MEMBERS **/ + +@member = @method | @constructor | @destructor | @field | @property | @event | @operator | @indexer | @type; + +@named_exprorstmt = @goto_stmt | @labeled_stmt | @expr; + +@virtualizable = @method | @property | @indexer | @event; + +exprorstmt_name( + unique int parent_id: @named_exprorstmt ref, + string name: string ref); + +nested_types( + unique int id: @type ref, + int declaring_type_id: @type ref, + int unbound_id: @type ref); + +properties( + unique int id: @property, + string name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @property ref); + +property_location( + int id: @property ref, + int loc: @location ref); + +indexers( + unique int id: @indexer, + string name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @indexer ref); + +indexer_location( + int id: @indexer ref, + int loc: @location ref); + +accessors( + unique int id: @accessor, + int kind: int ref, + string name: string ref, + int declaring_member_id: @member ref, + int unbound_id: @accessor ref); + +case @accessor.kind of + 1 = @getter +| 2 = @setter + ; + +init_only_accessors( + unique int id: @accessor ref); + +accessor_location( + int id: @accessor ref, + int loc: @location ref); + +events( + unique int id: @event, + string name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @event ref); + +event_location( + int id: @event ref, + int loc: @location ref); + +event_accessors( + unique int id: @event_accessor, + int kind: int ref, + string name: string ref, + int declaring_event_id: @event ref, + int unbound_id: @event_accessor ref); + +case @event_accessor.kind of + 1 = @add_event_accessor +| 2 = @remove_event_accessor + ; + +event_accessor_location( + int id: @event_accessor ref, + int loc: @location ref); + +operators( + unique int id: @operator, + string name: string ref, + string symbol: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @operator ref); + +operator_location( + int id: @operator ref, + int loc: @location ref); + +constant_value( + int id: @variable ref, + string value: string ref); + +/** CALLABLES **/ + +@callable = @method | @constructor | @destructor | @operator | @callable_accessor | @anonymous_function_expr | @local_function; + +@callable_accessor = @accessor | @event_accessor; + +methods( + unique int id: @method, + string name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @method ref); + +method_location( + int id: @method ref, + int loc: @location ref); + +constructors( + unique int id: @constructor, + string name: string ref, + int declaring_type_id: @type ref, + int unbound_id: @constructor ref); + +constructor_location( + int id: @constructor ref, + int loc: @location ref); + +destructors( + unique int id: @destructor, + string name: string ref, + int declaring_type_id: @type ref, + int unbound_id: @destructor ref); + +destructor_location( + int id: @destructor ref, + int loc: @location ref); + +overrides( + int id: @callable ref, + int base_id: @callable ref); + +explicitly_implements( + int id: @member ref, + int interface_id: @interface_or_ref ref); + +local_functions( + unique int id: @local_function, + string name: string ref, + int return_type: @type ref, + int unbound_id: @local_function ref); + +local_function_stmts( + unique int fn: @local_function_stmt ref, + int stmt: @local_function ref); + +/** VARIABLES **/ + +@variable = @local_scope_variable | @field; + +@local_scope_variable = @local_variable | @parameter; + +fields( + unique int id: @field, + int kind: int ref, + string name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @field ref); + +case @field.kind of + 1 = @addressable_field +| 2 = @constant + ; + +field_location( + int id: @field ref, + int loc: @location ref); + +localvars( + unique int id: @local_variable, + int kind: int ref, + string name: string ref, + int implicitly_typed: int ref /* 0 = no, 1 = yes */, + int type_id: @type_or_ref ref, + int parent_id: @local_var_decl_expr ref); + +case @local_variable.kind of + 1 = @addressable_local_variable +| 2 = @local_constant +| 3 = @local_variable_ref + ; + +localvar_location( + unique int id: @local_variable ref, + int loc: @location ref); + +@parameterizable = @callable | @delegate_type | @indexer | @function_pointer_type; + +#keyset[name, parent_id] +#keyset[index, parent_id] +params( + unique int id: @parameter, + string name: string ref, + int type_id: @type_or_ref ref, + int index: int ref, + int mode: int ref, /* value = 0, ref = 1, out = 2, array = 3, this = 4 */ + int parent_id: @parameterizable ref, + int unbound_id: @parameter ref); + +param_location( + int id: @parameter ref, + int loc: @location ref); + +/** STATEMENTS **/ + +@exprorstmt_parent = @control_flow_element | @top_level_exprorstmt_parent; + +statements( + unique int id: @stmt, + int kind: int ref); + +#keyset[index, parent] +stmt_parent( + unique int stmt: @stmt ref, + int index: int ref, + int parent: @control_flow_element ref); + +@top_level_stmt_parent = @callable; + +// [index, parent] is not a keyset because the same parent may be compiled multiple times +stmt_parent_top_level( + unique int stmt: @stmt ref, + int index: int ref, + int parent: @top_level_stmt_parent ref); + +case @stmt.kind of + 1 = @block_stmt +| 2 = @expr_stmt +| 3 = @if_stmt +| 4 = @switch_stmt +| 5 = @while_stmt +| 6 = @do_stmt +| 7 = @for_stmt +| 8 = @foreach_stmt +| 9 = @break_stmt +| 10 = @continue_stmt +| 11 = @goto_stmt +| 12 = @goto_case_stmt +| 13 = @goto_default_stmt +| 14 = @throw_stmt +| 15 = @return_stmt +| 16 = @yield_stmt +| 17 = @try_stmt +| 18 = @checked_stmt +| 19 = @unchecked_stmt +| 20 = @lock_stmt +| 21 = @using_block_stmt +| 22 = @var_decl_stmt +| 23 = @const_decl_stmt +| 24 = @empty_stmt +| 25 = @unsafe_stmt +| 26 = @fixed_stmt +| 27 = @label_stmt +| 28 = @catch +| 29 = @case_stmt +| 30 = @local_function_stmt +| 31 = @using_decl_stmt + ; + +@using_stmt = @using_block_stmt | @using_decl_stmt; + +@labeled_stmt = @label_stmt | @case; + +@decl_stmt = @var_decl_stmt | @const_decl_stmt | @using_decl_stmt; + +@cond_stmt = @if_stmt | @switch_stmt; + +@loop_stmt = @while_stmt | @do_stmt | @for_stmt | @foreach_stmt; + +@jump_stmt = @break_stmt | @goto_any_stmt | @continue_stmt | @throw_stmt | @return_stmt + | @yield_stmt; + +@goto_any_stmt = @goto_default_stmt | @goto_case_stmt | @goto_stmt; + + +stmt_location( + unique int id: @stmt ref, + int loc: @location ref); + +catch_type( + unique int catch_id: @catch ref, + int type_id: @type_or_ref ref, + int kind: int ref /* explicit = 1, implicit = 2 */); + +foreach_stmt_info( + unique int id: @foreach_stmt ref, + int kind: int ref /* non-async = 1, async = 2 */); + +@foreach_symbol = @method | @property | @type_or_ref; + +#keyset[id, kind] +foreach_stmt_desugar( + int id: @foreach_stmt ref, + int symbol: @foreach_symbol ref, + int kind: int ref /* GetEnumeratorMethod = 1, CurrentProperty = 2, MoveNextMethod = 3, DisposeMethod = 4, ElementType = 5 */); + +/** EXPRESSIONS **/ + +expressions( + unique int id: @expr, + int kind: int ref, + int type_id: @type_or_ref ref); + +#keyset[index, parent] +expr_parent( + unique int expr: @expr ref, + int index: int ref, + int parent: @control_flow_element ref); + +@top_level_expr_parent = @attribute | @field | @property | @indexer | @parameter | @directive_if | @directive_elif; + +@top_level_exprorstmt_parent = @top_level_expr_parent | @top_level_stmt_parent; + +// [index, parent] is not a keyset because the same parent may be compiled multiple times +expr_parent_top_level( + unique int expr: @expr ref, + int index: int ref, + int parent: @top_level_exprorstmt_parent ref); + +case @expr.kind of +/* literal */ + 1 = @bool_literal_expr +| 2 = @char_literal_expr +| 3 = @decimal_literal_expr +| 4 = @int_literal_expr +| 5 = @long_literal_expr +| 6 = @uint_literal_expr +| 7 = @ulong_literal_expr +| 8 = @float_literal_expr +| 9 = @double_literal_expr +| 10 = @string_literal_expr +| 11 = @null_literal_expr +/* primary & unary */ +| 12 = @this_access_expr +| 13 = @base_access_expr +| 14 = @local_variable_access_expr +| 15 = @parameter_access_expr +| 16 = @field_access_expr +| 17 = @property_access_expr +| 18 = @method_access_expr +| 19 = @event_access_expr +| 20 = @indexer_access_expr +| 21 = @array_access_expr +| 22 = @type_access_expr +| 23 = @typeof_expr +| 24 = @method_invocation_expr +| 25 = @delegate_invocation_expr +| 26 = @operator_invocation_expr +| 27 = @cast_expr +| 28 = @object_creation_expr +| 29 = @explicit_delegate_creation_expr +| 30 = @implicit_delegate_creation_expr +| 31 = @array_creation_expr +| 32 = @default_expr +| 33 = @plus_expr +| 34 = @minus_expr +| 35 = @bit_not_expr +| 36 = @log_not_expr +| 37 = @post_incr_expr +| 38 = @post_decr_expr +| 39 = @pre_incr_expr +| 40 = @pre_decr_expr +/* multiplicative */ +| 41 = @mul_expr +| 42 = @div_expr +| 43 = @rem_expr +/* additive */ +| 44 = @add_expr +| 45 = @sub_expr +/* shift */ +| 46 = @lshift_expr +| 47 = @rshift_expr +/* relational */ +| 48 = @lt_expr +| 49 = @gt_expr +| 50 = @le_expr +| 51 = @ge_expr +/* equality */ +| 52 = @eq_expr +| 53 = @ne_expr +/* logical */ +| 54 = @bit_and_expr +| 55 = @bit_xor_expr +| 56 = @bit_or_expr +| 57 = @log_and_expr +| 58 = @log_or_expr +/* type testing */ +| 59 = @is_expr +| 60 = @as_expr +/* null coalescing */ +| 61 = @null_coalescing_expr +/* conditional */ +| 62 = @conditional_expr +/* assignment */ +| 63 = @simple_assign_expr +| 64 = @assign_add_expr +| 65 = @assign_sub_expr +| 66 = @assign_mul_expr +| 67 = @assign_div_expr +| 68 = @assign_rem_expr +| 69 = @assign_and_expr +| 70 = @assign_xor_expr +| 71 = @assign_or_expr +| 72 = @assign_lshift_expr +| 73 = @assign_rshift_expr +/* more */ +| 74 = @object_init_expr +| 75 = @collection_init_expr +| 76 = @array_init_expr +| 77 = @checked_expr +| 78 = @unchecked_expr +| 79 = @constructor_init_expr +| 80 = @add_event_expr +| 81 = @remove_event_expr +| 82 = @par_expr +| 83 = @local_var_decl_expr +| 84 = @lambda_expr +| 85 = @anonymous_method_expr +| 86 = @namespace_expr +/* dynamic */ +| 92 = @dynamic_element_access_expr +| 93 = @dynamic_member_access_expr +/* unsafe */ +| 100 = @pointer_indirection_expr +| 101 = @address_of_expr +| 102 = @sizeof_expr +/* async */ +| 103 = @await_expr +/* C# 6.0 */ +| 104 = @nameof_expr +| 105 = @interpolated_string_expr +| 106 = @unknown_expr +/* C# 7.0 */ +| 107 = @throw_expr +| 108 = @tuple_expr +| 109 = @local_function_invocation_expr +| 110 = @ref_expr +| 111 = @discard_expr +/* C# 8.0 */ +| 112 = @range_expr +| 113 = @index_expr +| 114 = @switch_expr +| 115 = @recursive_pattern_expr +| 116 = @property_pattern_expr +| 117 = @positional_pattern_expr +| 118 = @switch_case_expr +| 119 = @assign_coalesce_expr +| 120 = @suppress_nullable_warning_expr +| 121 = @namespace_access_expr +/* C# 9.0 */ +| 122 = @lt_pattern_expr +| 123 = @gt_pattern_expr +| 124 = @le_pattern_expr +| 125 = @ge_pattern_expr +| 126 = @not_pattern_expr +| 127 = @and_pattern_expr +| 128 = @or_pattern_expr +| 129 = @function_pointer_invocation_expr +| 130 = @with_expr +/* C# 11.0 */ +| 131 = @list_pattern_expr +| 132 = @slice_pattern_expr +/* Preprocessor */ +| 999 = @define_symbol_expr +; + +@switch = @switch_stmt | @switch_expr; +@case = @case_stmt | @switch_case_expr; +@pattern_match = @case | @is_expr; +@unary_pattern_expr = @not_pattern_expr; +@relational_pattern_expr = @gt_pattern_expr | @lt_pattern_expr | @ge_pattern_expr | @le_pattern_expr; +@binary_pattern_expr = @and_pattern_expr | @or_pattern_expr; + +@integer_literal_expr = @int_literal_expr | @long_literal_expr | @uint_literal_expr | @ulong_literal_expr; +@real_literal_expr = @float_literal_expr | @double_literal_expr | @decimal_literal_expr; +@literal_expr = @bool_literal_expr | @char_literal_expr | @integer_literal_expr | @real_literal_expr + | @string_literal_expr | @null_literal_expr; + +@assign_expr = @simple_assign_expr | @assign_op_expr | @local_var_decl_expr; +@assign_op_expr = @assign_arith_expr | @assign_bitwise_expr | @assign_event_expr | @assign_coalesce_expr; +@assign_event_expr = @add_event_expr | @remove_event_expr; + +@assign_arith_expr = @assign_add_expr | @assign_sub_expr | @assign_mul_expr | @assign_div_expr + | @assign_rem_expr +@assign_bitwise_expr = @assign_and_expr | @assign_or_expr | @assign_xor_expr + | @assign_lshift_expr | @assign_rshift_expr; + +@member_access_expr = @field_access_expr | @property_access_expr | @indexer_access_expr | @event_access_expr + | @method_access_expr | @type_access_expr | @dynamic_member_access_expr; +@access_expr = @member_access_expr | @this_access_expr | @base_access_expr | @assignable_access_expr | @namespace_access_expr; +@element_access_expr = @indexer_access_expr | @array_access_expr | @dynamic_element_access_expr; + +@local_variable_access = @local_variable_access_expr | @local_var_decl_expr; +@local_scope_variable_access_expr = @parameter_access_expr | @local_variable_access; +@variable_access_expr = @local_scope_variable_access_expr | @field_access_expr; + +@assignable_access_expr = @variable_access_expr | @property_access_expr | @element_access_expr + | @event_access_expr | @dynamic_member_access_expr; + +@objectorcollection_init_expr = @object_init_expr | @collection_init_expr; + +@delegate_creation_expr = @explicit_delegate_creation_expr | @implicit_delegate_creation_expr; + +@bin_arith_op_expr = @mul_expr | @div_expr | @rem_expr | @add_expr | @sub_expr; +@incr_op_expr = @pre_incr_expr | @post_incr_expr; +@decr_op_expr = @pre_decr_expr | @post_decr_expr; +@mut_op_expr = @incr_op_expr | @decr_op_expr; +@un_arith_op_expr = @plus_expr | @minus_expr | @mut_op_expr; +@arith_op_expr = @bin_arith_op_expr | @un_arith_op_expr; + +@ternary_log_op_expr = @conditional_expr; +@bin_log_op_expr = @log_and_expr | @log_or_expr | @null_coalescing_expr; +@un_log_op_expr = @log_not_expr; +@log_expr = @un_log_op_expr | @bin_log_op_expr | @ternary_log_op_expr; + +@bin_bit_op_expr = @bit_and_expr | @bit_or_expr | @bit_xor_expr | @lshift_expr + | @rshift_expr; +@un_bit_op_expr = @bit_not_expr; +@bit_expr = @un_bit_op_expr | @bin_bit_op_expr; + +@equality_op_expr = @eq_expr | @ne_expr; +@rel_op_expr = @gt_expr | @lt_expr| @ge_expr | @le_expr; +@comp_expr = @equality_op_expr | @rel_op_expr; + +@op_expr = @assign_expr | @un_op | @bin_op | @ternary_op; + +@ternary_op = @ternary_log_op_expr; +@bin_op = @bin_arith_op_expr | @bin_log_op_expr | @bin_bit_op_expr | @comp_expr; +@un_op = @un_arith_op_expr | @un_log_op_expr | @un_bit_op_expr | @sizeof_expr + | @pointer_indirection_expr | @address_of_expr; + +@anonymous_function_expr = @lambda_expr | @anonymous_method_expr; + +@call = @method_invocation_expr | @constructor_init_expr | @operator_invocation_expr + | @delegate_invocation_expr | @object_creation_expr | @call_access_expr + | @local_function_invocation_expr | @function_pointer_invocation_expr; + +@call_access_expr = @property_access_expr | @event_access_expr | @indexer_access_expr; + +@late_bindable_expr = @dynamic_element_access_expr | @dynamic_member_access_expr + | @object_creation_expr | @method_invocation_expr | @operator_invocation_expr; + +@throw_element = @throw_expr | @throw_stmt; + +@implicitly_typeable_object_creation_expr = @object_creation_expr | @explicit_delegate_creation_expr; + +implicitly_typed_array_creation( + unique int id: @array_creation_expr ref); + +explicitly_sized_array_creation( + unique int id: @array_creation_expr ref); + +stackalloc_array_creation( + unique int id: @array_creation_expr ref); + +implicitly_typed_object_creation( + unique int id: @implicitly_typeable_object_creation_expr ref); + +mutator_invocation_mode( + unique int id: @operator_invocation_expr ref, + int mode: int ref /* prefix = 1, postfix = 2*/); + +expr_compiler_generated( + unique int id: @expr ref); + +expr_value( + unique int id: @expr ref, + string value: string ref); + +expr_call( + unique int caller_id: @expr ref, + int target_id: @callable ref); + +expr_access( + unique int accesser_id: @access_expr ref, + int target_id: @accessible ref); + +@accessible = @method | @assignable | @local_function | @namespace; + +expr_location( + unique int id: @expr ref, + int loc: @location ref); + +dynamic_member_name( + unique int id: @late_bindable_expr ref, + string name: string ref); + +@qualifiable_expr = @member_access_expr + | @method_invocation_expr + | @element_access_expr; + +conditional_access( + unique int id: @qualifiable_expr ref); + +expr_argument( + unique int id: @expr ref, + int mode: int ref); + /* mode is the same as params: value = 0, ref = 1, out = 2 */ + +expr_argument_name( + unique int id: @expr ref, + string name: string ref); + +lambda_expr_return_type( + unique int id: @lambda_expr ref, + int type_id: @type_or_ref ref); + +/** CONTROL/DATA FLOW **/ + +@control_flow_element = @stmt | @expr; + +/* XML Files */ + +xmlEncoding ( + unique int id: @file ref, + string encoding: string ref); + +xmlDTDs( + unique int id: @xmldtd, + string root: string ref, + string publicId: string ref, + string systemId: string ref, + int fileid: @file ref); + +xmlElements( + unique int id: @xmlelement, + string name: string ref, + int parentid: @xmlparent ref, + int idx: int ref, + int fileid: @file ref); + +xmlAttrs( + unique int id: @xmlattribute, + int elementid: @xmlelement ref, + string name: string ref, + string value: string ref, + int idx: int ref, + int fileid: @file ref); + +xmlNs( + int id: @xmlnamespace, + string prefixName: string ref, + string URI: string ref, + int fileid: @file ref); + +xmlHasNs( + int elementId: @xmlnamespaceable ref, + int nsId: @xmlnamespace ref, + int fileid: @file ref); + +xmlComments( + unique int id: @xmlcomment, + string text: string ref, + int parentid: @xmlparent ref, + int fileid: @file ref); + +xmlChars( + unique int id: @xmlcharacters, + string text: string ref, + int parentid: @xmlparent ref, + int idx: int ref, + int isCDATA: int ref, + int fileid: @file ref); + +@xmlparent = @file | @xmlelement; +@xmlnamespaceable = @xmlelement | @xmlattribute; + +xmllocations( + int xmlElement: @xmllocatable ref, + int location: @location_default ref); + +@xmllocatable = @xmlcharacters | @xmlelement | @xmlcomment | @xmlattribute | @xmldtd | @file | @xmlnamespace; + +/* Comments */ + +commentline( + unique int id: @commentline, + int kind: int ref, + string text: string ref, + string rawtext: string ref); + +case @commentline.kind of + 0 = @singlelinecomment +| 1 = @xmldoccomment +| 2 = @multilinecomment; + +commentline_location( + unique int id: @commentline ref, + int loc: @location ref); + +commentblock( + unique int id : @commentblock); + +commentblock_location( + unique int id: @commentblock ref, + int loc: @location ref); + +commentblock_binding( + int id: @commentblock ref, + int entity: @element ref, + int bindtype: int ref); /* 0: Parent, 1: Best, 2: Before, 3: After */ + +commentblock_child( + int id: @commentblock ref, + int commentline: @commentline ref, + int index: int ref); + +/* ASP.NET */ + +case @asp_element.kind of + 0=@asp_close_tag +| 1=@asp_code +| 2=@asp_comment +| 3=@asp_data_binding +| 4=@asp_directive +| 5=@asp_open_tag +| 6=@asp_quoted_string +| 7=@asp_text +| 8=@asp_xml_directive; + +@asp_attribute = @asp_code | @asp_data_binding | @asp_quoted_string; + +asp_elements( + unique int id: @asp_element, + int kind: int ref, + int loc: @location ref); + +asp_comment_server(unique int comment: @asp_comment ref); +asp_code_inline(unique int code: @asp_code ref); +asp_directive_attribute( + int directive: @asp_directive ref, + int index: int ref, + string name: string ref, + int value: @asp_quoted_string ref); +asp_directive_name( + unique int directive: @asp_directive ref, + string name: string ref); +asp_element_body( + unique int element: @asp_element ref, + string body: string ref); +asp_tag_attribute( + int tag: @asp_open_tag ref, + int index: int ref, + string name: string ref, + int attribute: @asp_attribute ref); +asp_tag_name( + unique int tag: @asp_open_tag ref, + string name: string ref); +asp_tag_isempty(int tag: @asp_open_tag ref); + +/* Common Intermediate Language - CIL */ + +case @cil_instruction.opcode of + 0 = @cil_nop +| 1 = @cil_break +| 2 = @cil_ldarg_0 +| 3 = @cil_ldarg_1 +| 4 = @cil_ldarg_2 +| 5 = @cil_ldarg_3 +| 6 = @cil_ldloc_0 +| 7 = @cil_ldloc_1 +| 8 = @cil_ldloc_2 +| 9 = @cil_ldloc_3 +| 10 = @cil_stloc_0 +| 11 = @cil_stloc_1 +| 12 = @cil_stloc_2 +| 13 = @cil_stloc_3 +| 14 = @cil_ldarg_s +| 15 = @cil_ldarga_s +| 16 = @cil_starg_s +| 17 = @cil_ldloc_s +| 18 = @cil_ldloca_s +| 19 = @cil_stloc_s +| 20 = @cil_ldnull +| 21 = @cil_ldc_i4_m1 +| 22 = @cil_ldc_i4_0 +| 23 = @cil_ldc_i4_1 +| 24 = @cil_ldc_i4_2 +| 25 = @cil_ldc_i4_3 +| 26 = @cil_ldc_i4_4 +| 27 = @cil_ldc_i4_5 +| 28 = @cil_ldc_i4_6 +| 29 = @cil_ldc_i4_7 +| 30 = @cil_ldc_i4_8 +| 31 = @cil_ldc_i4_s +| 32 = @cil_ldc_i4 +| 33 = @cil_ldc_i8 +| 34 = @cil_ldc_r4 +| 35 = @cil_ldc_r8 +| 37 = @cil_dup +| 38 = @cil_pop +| 39 = @cil_jmp +| 40 = @cil_call +| 41 = @cil_calli +| 42 = @cil_ret +| 43 = @cil_br_s +| 44 = @cil_brfalse_s +| 45 = @cil_brtrue_s +| 46 = @cil_beq_s +| 47 = @cil_bge_s +| 48 = @cil_bgt_s +| 49 = @cil_ble_s +| 50 = @cil_blt_s +| 51 = @cil_bne_un_s +| 52 = @cil_bge_un_s +| 53 = @cil_bgt_un_s +| 54 = @cil_ble_un_s +| 55 = @cil_blt_un_s +| 56 = @cil_br +| 57 = @cil_brfalse +| 58 = @cil_brtrue +| 59 = @cil_beq +| 60 = @cil_bge +| 61 = @cil_bgt +| 62 = @cil_ble +| 63 = @cil_blt +| 64 = @cil_bne_un +| 65 = @cil_bge_un +| 66 = @cil_bgt_un +| 67 = @cil_ble_un +| 68 = @cil_blt_un +| 69 = @cil_switch +| 70 = @cil_ldind_i1 +| 71 = @cil_ldind_u1 +| 72 = @cil_ldind_i2 +| 73 = @cil_ldind_u2 +| 74 = @cil_ldind_i4 +| 75 = @cil_ldind_u4 +| 76 = @cil_ldind_i8 +| 77 = @cil_ldind_i +| 78 = @cil_ldind_r4 +| 79 = @cil_ldind_r8 +| 80 = @cil_ldind_ref +| 81 = @cil_stind_ref +| 82 = @cil_stind_i1 +| 83 = @cil_stind_i2 +| 84 = @cil_stind_i4 +| 85 = @cil_stind_i8 +| 86 = @cil_stind_r4 +| 87 = @cil_stind_r8 +| 88 = @cil_add +| 89 = @cil_sub +| 90 = @cil_mul +| 91 = @cil_div +| 92 = @cil_div_un +| 93 = @cil_rem +| 94 = @cil_rem_un +| 95 = @cil_and +| 96 = @cil_or +| 97 = @cil_xor +| 98 = @cil_shl +| 99 = @cil_shr +| 100 = @cil_shr_un +| 101 = @cil_neg +| 102 = @cil_not +| 103 = @cil_conv_i1 +| 104 = @cil_conv_i2 +| 105 = @cil_conv_i4 +| 106 = @cil_conv_i8 +| 107 = @cil_conv_r4 +| 108 = @cil_conv_r8 +| 109 = @cil_conv_u4 +| 110 = @cil_conv_u8 +| 111 = @cil_callvirt +| 112 = @cil_cpobj +| 113 = @cil_ldobj +| 114 = @cil_ldstr +| 115 = @cil_newobj +| 116 = @cil_castclass +| 117 = @cil_isinst +| 118 = @cil_conv_r_un +| 121 = @cil_unbox +| 122 = @cil_throw +| 123 = @cil_ldfld +| 124 = @cil_ldflda +| 125 = @cil_stfld +| 126 = @cil_ldsfld +| 127 = @cil_ldsflda +| 128 = @cil_stsfld +| 129 = @cil_stobj +| 130 = @cil_conv_ovf_i1_un +| 131 = @cil_conv_ovf_i2_un +| 132 = @cil_conv_ovf_i4_un +| 133 = @cil_conv_ovf_i8_un +| 134 = @cil_conv_ovf_u1_un +| 135 = @cil_conv_ovf_u2_un +| 136 = @cil_conv_ovf_u4_un +| 137 = @cil_conv_ovf_u8_un +| 138 = @cil_conv_ovf_i_un +| 139 = @cil_conv_ovf_u_un +| 140 = @cil_box +| 141 = @cil_newarr +| 142 = @cil_ldlen +| 143 = @cil_ldelema +| 144 = @cil_ldelem_i1 +| 145 = @cil_ldelem_u1 +| 146 = @cil_ldelem_i2 +| 147 = @cil_ldelem_u2 +| 148 = @cil_ldelem_i4 +| 149 = @cil_ldelem_u4 +| 150 = @cil_ldelem_i8 +| 151 = @cil_ldelem_i +| 152 = @cil_ldelem_r4 +| 153 = @cil_ldelem_r8 +| 154 = @cil_ldelem_ref +| 155 = @cil_stelem_i +| 156 = @cil_stelem_i1 +| 157 = @cil_stelem_i2 +| 158 = @cil_stelem_i4 +| 159 = @cil_stelem_i8 +| 160 = @cil_stelem_r4 +| 161 = @cil_stelem_r8 +| 162 = @cil_stelem_ref +| 163 = @cil_ldelem +| 164 = @cil_stelem +| 165 = @cil_unbox_any +| 179 = @cil_conv_ovf_i1 +| 180 = @cil_conv_ovf_u1 +| 181 = @cil_conv_ovf_i2 +| 182 = @cil_conv_ovf_u2 +| 183 = @cil_conv_ovf_i4 +| 184 = @cil_conv_ovf_u4 +| 185 = @cil_conv_ovf_i8 +| 186 = @cil_conv_ovf_u8 +| 194 = @cil_refanyval +| 195 = @cil_ckinfinite +| 198 = @cil_mkrefany +| 208 = @cil_ldtoken +| 209 = @cil_conv_u2 +| 210 = @cil_conv_u1 +| 211 = @cil_conv_i +| 212 = @cil_conv_ovf_i +| 213 = @cil_conv_ovf_u +| 214 = @cil_add_ovf +| 215 = @cil_add_ovf_un +| 216 = @cil_mul_ovf +| 217 = @cil_mul_ovf_un +| 218 = @cil_sub_ovf +| 219 = @cil_sub_ovf_un +| 220 = @cil_endfinally +| 221 = @cil_leave +| 222 = @cil_leave_s +| 223 = @cil_stind_i +| 224 = @cil_conv_u +| 65024 = @cil_arglist +| 65025 = @cil_ceq +| 65026 = @cil_cgt +| 65027 = @cil_cgt_un +| 65028 = @cil_clt +| 65029 = @cil_clt_un +| 65030 = @cil_ldftn +| 65031 = @cil_ldvirtftn +| 65033 = @cil_ldarg +| 65034 = @cil_ldarga +| 65035 = @cil_starg +| 65036 = @cil_ldloc +| 65037 = @cil_ldloca +| 65038 = @cil_stloc +| 65039 = @cil_localloc +| 65041 = @cil_endfilter +| 65042 = @cil_unaligned +| 65043 = @cil_volatile +| 65044 = @cil_tail +| 65045 = @cil_initobj +| 65046 = @cil_constrained +| 65047 = @cil_cpblk +| 65048 = @cil_initblk +| 65050 = @cil_rethrow +| 65052 = @cil_sizeof +| 65053 = @cil_refanytype +| 65054 = @cil_readonly +; + +// CIL ignored instructions + +@cil_ignore = @cil_nop | @cil_break | @cil_volatile | @cil_unaligned; + +// CIL local/parameter/field access + +@cil_ldarg_any = @cil_ldarg_0 | @cil_ldarg_1 | @cil_ldarg_2 | @cil_ldarg_3 | @cil_ldarg_s | @cil_ldarga_s | @cil_ldarg | @cil_ldarga; +@cil_starg_any = @cil_starg | @cil_starg_s; + +@cil_ldloc_any = @cil_ldloc_0 | @cil_ldloc_1 | @cil_ldloc_2 | @cil_ldloc_3 | @cil_ldloc_s | @cil_ldloca_s | @cil_ldloc | @cil_ldloca; +@cil_stloc_any = @cil_stloc_0 | @cil_stloc_1 | @cil_stloc_2 | @cil_stloc_3 | @cil_stloc_s | @cil_stloc; + +@cil_ldfld_any = @cil_ldfld | @cil_ldsfld | @cil_ldsflda | @cil_ldflda; +@cil_stfld_any = @cil_stfld | @cil_stsfld; + +@cil_local_access = @cil_stloc_any | @cil_ldloc_any; +@cil_arg_access = @cil_starg_any | @cil_ldarg_any; +@cil_read_access = @cil_ldloc_any | @cil_ldarg_any | @cil_ldfld_any; +@cil_write_access = @cil_stloc_any | @cil_starg_any | @cil_stfld_any; + +@cil_stack_access = @cil_local_access | @cil_arg_access; +@cil_field_access = @cil_ldfld_any | @cil_stfld_any; + +@cil_access = @cil_read_access | @cil_write_access; + +// CIL constant/literal instructions + +@cil_ldc_i = @cil_ldc_i4_any | @cil_ldc_i8; + +@cil_ldc_i4_any = @cil_ldc_i4_m1 | @cil_ldc_i4_0 | @cil_ldc_i4_1 | @cil_ldc_i4_2 | @cil_ldc_i4_3 | + @cil_ldc_i4_4 | @cil_ldc_i4_5 | @cil_ldc_i4_6 | @cil_ldc_i4_7 | @cil_ldc_i4_8 | @cil_ldc_i4_s | @cil_ldc_i4; + +@cil_ldc_r = @cil_ldc_r4 | @cil_ldc_r8; + +@cil_literal = @cil_ldnull | @cil_ldc_i | @cil_ldc_r | @cil_ldstr; + +// Control flow + +@cil_conditional_jump = @cil_binary_jump | @cil_unary_jump; +@cil_binary_jump = @cil_beq_s | @cil_bge_s | @cil_bgt_s | @cil_ble_s | @cil_blt_s | + @cil_bne_un_s | @cil_bge_un_s | @cil_bgt_un_s | @cil_ble_un_s | @cil_blt_un_s | + @cil_beq | @cil_bge | @cil_bgt | @cil_ble | @cil_blt | + @cil_bne_un | @cil_bge_un | @cil_bgt_un | @cil_ble_un | @cil_blt_un; +@cil_unary_jump = @cil_brfalse_s | @cil_brtrue_s | @cil_brfalse | @cil_brtrue | @cil_switch; +@cil_unconditional_jump = @cil_br | @cil_br_s | @cil_leave_any; +@cil_leave_any = @cil_leave | @cil_leave_s; +@cil_jump = @cil_unconditional_jump | @cil_conditional_jump; + +// CIL call instructions + +@cil_call_any = @cil_jmp | @cil_call | @cil_calli | @cil_tail | @cil_callvirt | @cil_newobj; + +// CIL expression instructions + +@cil_expr = @cil_literal | @cil_binary_expr | @cil_unary_expr | @cil_call_any | @cil_read_access | + @cil_newarr | @cil_ldtoken | @cil_sizeof | + @cil_ldftn | @cil_ldvirtftn | @cil_localloc | @cil_mkrefany | @cil_refanytype | @cil_arglist | @cil_dup; + +@cil_unary_expr = + @cil_conversion_operation | @cil_unary_arithmetic_operation | @cil_unary_bitwise_operation| + @cil_ldlen | @cil_isinst | @cil_box | @cil_ldobj | @cil_castclass | @cil_unbox_any | + @cil_ldind | @cil_unbox; + +@cil_conversion_operation = + @cil_conv_i1 | @cil_conv_i2 | @cil_conv_i4 | @cil_conv_i8 | + @cil_conv_u1 | @cil_conv_u2 | @cil_conv_u4 | @cil_conv_u8 | + @cil_conv_ovf_i | @cil_conv_ovf_i_un | @cil_conv_ovf_i1 | @cil_conv_ovf_i1_un | + @cil_conv_ovf_i2 | @cil_conv_ovf_i2_un | @cil_conv_ovf_i4 | @cil_conv_ovf_i4_un | + @cil_conv_ovf_i8 | @cil_conv_ovf_i8_un | @cil_conv_ovf_u | @cil_conv_ovf_u_un | + @cil_conv_ovf_u1 | @cil_conv_ovf_u1_un | @cil_conv_ovf_u2 | @cil_conv_ovf_u2_un | + @cil_conv_ovf_u4 | @cil_conv_ovf_u4_un | @cil_conv_ovf_u8 | @cil_conv_ovf_u8_un | + @cil_conv_r4 | @cil_conv_r8 | @cil_conv_ovf_u2 | @cil_conv_ovf_u2_un | + @cil_conv_i | @cil_conv_u | @cil_conv_r_un; + +@cil_ldind = @cil_ldind_i | @cil_ldind_i1 | @cil_ldind_i2 | @cil_ldind_i4 | @cil_ldind_i8 | + @cil_ldind_r4 | @cil_ldind_r8 | @cil_ldind_ref | @cil_ldind_u1 | @cil_ldind_u2 | @cil_ldind_u4; + +@cil_stind = @cil_stind_i | @cil_stind_i1 | @cil_stind_i2 | @cil_stind_i4 | @cil_stind_i8 | + @cil_stind_r4 | @cil_stind_r8 | @cil_stind_ref; + +@cil_bitwise_operation = @cil_binary_bitwise_operation | @cil_unary_bitwise_operation; + +@cil_binary_bitwise_operation = @cil_and | @cil_or | @cil_xor | @cil_shr | @cil_shr | @cil_shr_un | @cil_shl; + +@cil_binary_arithmetic_operation = @cil_add | @cil_sub | @cil_mul | @cil_div | @cil_div_un | + @cil_rem | @cil_rem_un | @cil_add_ovf | @cil_add_ovf_un | @cil_mul_ovf | @cil_mul_ovf_un | + @cil_sub_ovf | @cil_sub_ovf_un; + +@cil_unary_bitwise_operation = @cil_not; + +@cil_binary_expr = @cil_binary_arithmetic_operation | @cil_binary_bitwise_operation | @cil_read_array | @cil_comparison_operation; + +@cil_unary_arithmetic_operation = @cil_neg; + +@cil_comparison_operation = @cil_cgt_un | @cil_ceq | @cil_cgt | @cil_clt | @cil_clt_un; + +// Elements that retrieve an address of something +@cil_read_ref = @cil_ldloca_s | @cil_ldarga_s | @cil_ldflda | @cil_ldsflda | @cil_ldelema; + +// CIL array instructions + +@cil_read_array = + @cil_ldelem | @cil_ldelema | @cil_ldelem_i1 | @cil_ldelem_ref | @cil_ldelem_i | + @cil_ldelem_i1 | @cil_ldelem_i2 | @cil_ldelem_i4 | @cil_ldelem_i8 | @cil_ldelem_r4 | + @cil_ldelem_r8 | @cil_ldelem_u1 | @cil_ldelem_u2 | @cil_ldelem_u4; + +@cil_write_array = @cil_stelem | @cil_stelem_ref | + @cil_stelem_i | @cil_stelem_i1 | @cil_stelem_i2 | @cil_stelem_i4 | @cil_stelem_i8 | + @cil_stelem_r4 | @cil_stelem_r8; + +@cil_throw_any = @cil_throw | @cil_rethrow; + +#keyset[impl, index] +cil_instruction( + unique int id: @cil_instruction, + int opcode: int ref, + int index: int ref, + int impl: @cil_method_implementation ref); + +cil_jump( + unique int instruction: @cil_jump ref, + int target: @cil_instruction ref); + +cil_access( + unique int instruction: @cil_instruction ref, + int target: @cil_accessible ref); + +cil_value( + unique int instruction: @cil_literal ref, + string value: string ref); + +#keyset[instruction, index] +cil_switch( + int instruction: @cil_switch ref, + int index: int ref, + int target: @cil_instruction ref); + +cil_instruction_location( + unique int id: @cil_instruction ref, + int loc: @location ref); + +cil_type_location( + int id: @cil_type ref, + int loc: @location ref); + +cil_method_location( + int id: @cil_method ref, + int loc: @location ref); + +@cil_namespace = @namespace; + +@cil_type_container = @cil_type | @cil_namespace | @cil_method; + +case @cil_type.kind of + 0 = @cil_valueorreftype +| 1 = @cil_typeparameter +| 2 = @cil_array_type +| 3 = @cil_pointer_type +| 4 = @cil_function_pointer_type +; + +cil_type( + unique int id: @cil_type, + string name: string ref, + int kind: int ref, + int parent: @cil_type_container ref, + int sourceDecl: @cil_type ref); + +cil_pointer_type( + unique int id: @cil_pointer_type ref, + int pointee: @cil_type ref); + +cil_array_type( + unique int id: @cil_array_type ref, + int element_type: @cil_type ref, + int rank: int ref); + +cil_function_pointer_return_type( + unique int id: @cil_function_pointer_type ref, + int return_type: @cil_type ref); + +cil_method( + unique int id: @cil_method, + string name: string ref, + int parent: @cil_type ref, + int return_type: @cil_type ref); + +cil_method_source_declaration( + unique int method: @cil_method ref, + int source: @cil_method ref); + +cil_method_implementation( + unique int id: @cil_method_implementation, + int method: @cil_method ref, + int location: @assembly ref); + +cil_implements( + int id: @cil_method ref, + int decl: @cil_method ref); + +#keyset[parent, name] +cil_field( + unique int id: @cil_field, + int parent: @cil_type ref, + string name: string ref, + int field_type: @cil_type ref); + +@cil_element = @cil_instruction | @cil_declaration | @cil_handler | @cil_attribute | @cil_namespace; +@cil_named_element = @cil_declaration | @cil_namespace; +@cil_declaration = @cil_variable | @cil_method | @cil_type | @cil_member; +@cil_accessible = @cil_declaration; +@cil_variable = @cil_field | @cil_stack_variable; +@cil_stack_variable = @cil_local_variable | @cil_parameter; +@cil_member = @cil_method | @cil_type | @cil_field | @cil_property | @cil_event; +@cil_custom_modifier_receiver = @cil_method | @cil_property | @cil_parameter | @cil_field | @cil_function_pointer_type; +@cil_parameterizable = @cil_method | @cil_function_pointer_type; +@cil_has_type_annotation = @cil_stack_variable | @cil_property | @cil_method | @cil_function_pointer_type; + +#keyset[parameterizable, index] +cil_parameter( + unique int id: @cil_parameter, + int parameterizable: @cil_parameterizable ref, + int index: int ref, + int param_type: @cil_type ref); + +cil_parameter_in(unique int id: @cil_parameter ref); +cil_parameter_out(unique int id: @cil_parameter ref); + +cil_setter(unique int prop: @cil_property ref, + int method: @cil_method ref); + +#keyset[id, modifier] +cil_custom_modifiers( + int id: @cil_custom_modifier_receiver ref, + int modifier: @cil_type ref, + int kind: int ref); // modreq: 1, modopt: 0 + +cil_type_annotation( + int id: @cil_has_type_annotation ref, + int annotation: int ref); + +cil_getter(unique int prop: @cil_property ref, + int method: @cil_method ref); + +cil_adder(unique int event: @cil_event ref, + int method: @cil_method ref); + +cil_remover(unique int event: @cil_event ref, int method: @cil_method ref); + +cil_raiser(unique int event: @cil_event ref, int method: @cil_method ref); + +cil_property( + unique int id: @cil_property, + int parent: @cil_type ref, + string name: string ref, + int property_type: @cil_type ref); + +#keyset[parent, name] +cil_event(unique int id: @cil_event, + int parent: @cil_type ref, + string name: string ref, + int event_type: @cil_type ref); + +#keyset[impl, index] +cil_local_variable( + unique int id: @cil_local_variable, + int impl: @cil_method_implementation ref, + int index: int ref, + int var_type: @cil_type ref); + +cil_function_pointer_calling_conventions( + int id: @cil_function_pointer_type ref, + int kind: int ref); + +// CIL handlers (exception handlers etc). + +case @cil_handler.kind of + 0 = @cil_catch_handler +| 1 = @cil_filter_handler +| 2 = @cil_finally_handler +| 4 = @cil_fault_handler +; + +#keyset[impl, index] +cil_handler( + unique int id: @cil_handler, + int impl: @cil_method_implementation ref, + int index: int ref, + int kind: int ref, + int try_start: @cil_instruction ref, + int try_end: @cil_instruction ref, + int handler_start: @cil_instruction ref); + +cil_handler_filter( + unique int id: @cil_handler ref, + int filter_start: @cil_instruction ref); + +cil_handler_type( + unique int id: @cil_handler ref, + int catch_type: @cil_type ref); + +@cil_controlflow_node = @cil_entry_point | @cil_instruction; + +@cil_entry_point = @cil_method_implementation | @cil_handler; + +@cil_dataflow_node = @cil_instruction | @cil_variable | @cil_method; + +cil_method_stack_size( + unique int method: @cil_method_implementation ref, + int size: int ref); + +// CIL modifiers + +cil_public(int id: @cil_member ref); +cil_private(int id: @cil_member ref); +cil_protected(int id: @cil_member ref); +cil_internal(int id: @cil_member ref); +cil_static(int id: @cil_member ref); +cil_sealed(int id: @cil_member ref); +cil_virtual(int id: @cil_method ref); +cil_abstract(int id: @cil_member ref); +cil_class(int id: @cil_type ref); +cil_interface(int id: @cil_type ref); +cil_security(int id: @cil_member ref); +cil_requiresecobject(int id: @cil_method ref); +cil_specialname(int id: @cil_method ref); +cil_newslot(int id: @cil_method ref); + +cil_base_class(unique int id: @cil_type ref, int base: @cil_type ref); +cil_base_interface(int id: @cil_type ref, int base: @cil_type ref); +cil_enum_underlying_type(unique int id: @cil_type ref, int underlying: @cil_type ref); + +#keyset[unbound, index] +cil_type_parameter( + int unbound: @cil_member ref, + int index: int ref, + int param: @cil_typeparameter ref); + +#keyset[bound, index] +cil_type_argument( + int bound: @cil_member ref, + int index: int ref, + int t: @cil_type ref); + +// CIL type parameter constraints + +cil_typeparam_covariant(int tp: @cil_typeparameter ref); +cil_typeparam_contravariant(int tp: @cil_typeparameter ref); +cil_typeparam_class(int tp: @cil_typeparameter ref); +cil_typeparam_struct(int tp: @cil_typeparameter ref); +cil_typeparam_new(int tp: @cil_typeparameter ref); +cil_typeparam_constraint(int tp: @cil_typeparameter ref, int supertype: @cil_type ref); + +// CIL attributes + +cil_attribute( + unique int attributeid: @cil_attribute, + int element: @cil_declaration ref, + int constructor: @cil_method ref); + +#keyset[attribute_id, param] +cil_attribute_named_argument( + int attribute_id: @cil_attribute ref, + string param: string ref, + string value: string ref); + +#keyset[attribute_id, index] +cil_attribute_positional_argument( + int attribute_id: @cil_attribute ref, + int index: int ref, + string value: string ref); + + +// Common .Net data model covering both C# and CIL + +// Common elements +@dotnet_element = @element | @cil_element; +@dotnet_named_element = @named_element | @cil_named_element; +@dotnet_callable = @callable | @cil_method; +@dotnet_variable = @variable | @cil_variable; +@dotnet_field = @field | @cil_field; +@dotnet_parameter = @parameter | @cil_parameter; +@dotnet_declaration = @declaration | @cil_declaration; +@dotnet_member = @member | @cil_member; +@dotnet_event = @event | @cil_event; +@dotnet_property = @property | @cil_property | @indexer; +@dotnet_parameterizable = @parameterizable | @cil_parameterizable; + +// Common types +@dotnet_type = @type | @cil_type; +@dotnet_call = @call | @cil_call_any; +@dotnet_throw = @throw_element | @cil_throw_any; +@dotnet_valueorreftype = @cil_valueorreftype | @value_or_ref_type | @cil_array_type | @void_type; +@dotnet_typeparameter = @type_parameter | @cil_typeparameter; +@dotnet_array_type = @array_type | @cil_array_type; +@dotnet_pointer_type = @pointer_type | @cil_pointer_type; +@dotnet_type_parameter = @type_parameter | @cil_typeparameter; +@dotnet_generic = @dotnet_valueorreftype | @dotnet_callable; + +// Attributes +@dotnet_attribute = @attribute | @cil_attribute; + +// Expressions +@dotnet_expr = @expr | @cil_expr; + +// Literals +@dotnet_literal = @literal_expr | @cil_literal; +@dotnet_string_literal = @string_literal_expr | @cil_ldstr; +@dotnet_int_literal = @integer_literal_expr | @cil_ldc_i; +@dotnet_float_literal = @float_literal_expr | @cil_ldc_r; +@dotnet_null_literal = @null_literal_expr | @cil_ldnull; + +@metadata_entity = @cil_method | @cil_type | @cil_field | @cil_property | @field | @property | + @callable | @value_or_ref_type | @void_type; + +#keyset[entity, location] +metadata_handle(int entity : @metadata_entity ref, int location: @assembly ref, int handle: int ref) diff --git a/csharp/downgrades/83aca6b3e4fa38dd2b97b9b51dfc199a2ba9c7f2/semmlecode.csharp.dbscheme b/csharp/downgrades/83aca6b3e4fa38dd2b97b9b51dfc199a2ba9c7f2/semmlecode.csharp.dbscheme new file mode 100644 index 00000000000..4ac7d8bcac6 --- /dev/null +++ b/csharp/downgrades/83aca6b3e4fa38dd2b97b9b51dfc199a2ba9c7f2/semmlecode.csharp.dbscheme @@ -0,0 +1,2064 @@ +/* This is a dummy line to alter the dbscheme, so we can make a database upgrade + * without actually changing any of the dbscheme predicates. It contains a date + * to allow for such updates in the future as well. + * + * 2021-07-14 + * + * DO NOT remove this comment carelessly, since it can revert the dbscheme back to a + * previously seen state (matching a previously seen SHA), which would make the upgrade + * mechanism not work properly. + */ + +/** + * An invocation of the compiler. Note that more than one file may be + * compiled per invocation. For example, this command compiles three + * source files: + * + * csc f1.cs f2.cs f3.cs + * + * The `id` simply identifies the invocation, while `cwd` is the working + * directory from which the compiler was invoked. + */ +compilations( + unique int id : @compilation, + string cwd : string ref +); + +/** + * The arguments that were passed to the extractor for a compiler + * invocation. If `id` is for the compiler invocation + * + * csc f1.cs f2.cs f3.cs + * + * then typically there will be rows for + * + * num | arg + * --- | --- + * 0 | --compiler + * 1 | *path to compiler* + * 2 | f1.cs + * 3 | f2.cs + * 4 | f3.cs + */ +#keyset[id, num] +compilation_args( + int id : @compilation ref, + int num : int ref, + string arg : string ref +); + +/** + * The source files that are compiled by a compiler invocation. + * If `id` is for the compiler invocation + * + * csc f1.cs f2.cs f3.cs + * + * then there will be rows for + * + * num | arg + * --- | --- + * 0 | f1.cs + * 1 | f2.cs + * 2 | f3.cs + */ +#keyset[id, num] +compilation_compiling_files( + int id : @compilation ref, + int num : int ref, + int file : @file ref +); + +/** + * The references used by a compiler invocation. + * If `id` is for the compiler invocation + * + * csc f1.cs f2.cs f3.cs /r:ref1.dll /r:ref2.dll /r:ref3.dll + * + * then there will be rows for + * + * num | arg + * --- | --- + * 0 | ref1.dll + * 1 | ref2.dll + * 2 | ref3.dll + */ +#keyset[id, num] +compilation_referencing_files( + int id : @compilation ref, + int num : int ref, + int file : @file ref +); + +/** + * The time taken by the extractor for a compiler invocation. + * + * For each file `num`, there will be rows for + * + * kind | seconds + * ---- | --- + * 1 | CPU seconds used by the extractor frontend + * 2 | Elapsed seconds during the extractor frontend + * 3 | CPU seconds used by the extractor backend + * 4 | Elapsed seconds during the extractor backend + */ +#keyset[id, num, kind] +compilation_time( + int id : @compilation ref, + int num : int ref, + /* kind: + 1 = frontend_cpu_seconds + 2 = frontend_elapsed_seconds + 3 = extractor_cpu_seconds + 4 = extractor_elapsed_seconds + */ + int kind : int ref, + float seconds : float ref +); + +/** + * An error or warning generated by the extractor. + * The diagnostic message `diagnostic` was generated during compiler + * invocation `compilation`, and is the `file_number_diagnostic_number`th + * message generated while extracting the `file_number`th file of that + * invocation. + */ +#keyset[compilation, file_number, file_number_diagnostic_number] +diagnostic_for( + unique int diagnostic : @diagnostic ref, + int compilation : @compilation ref, + int file_number : int ref, + int file_number_diagnostic_number : int ref +); + +diagnostics( + unique int id: @diagnostic, + int severity: int ref, + string error_tag: string ref, + string error_message: string ref, + string full_error_message: string ref, + int location: @location_default ref +); + +extractor_messages( + unique int id: @extractor_message, + int severity: int ref, + string origin : string ref, + string text : string ref, + string entity : string ref, + int location: @location_default ref, + string stack_trace : string ref +); + +/** + * If extraction was successful, then `cpu_seconds` and + * `elapsed_seconds` are the CPU time and elapsed time (respectively) + * that extraction took for compiler invocation `id`. + */ +compilation_finished( + unique int id : @compilation ref, + float cpu_seconds : float ref, + float elapsed_seconds : float ref +); + +compilation_assembly( + unique int id : @compilation ref, + int assembly: @assembly ref +) + +// Populated by the CSV extractor +externalData( + int id: @externalDataElement, + string path: string ref, + int column: int ref, + string value: string ref); + +sourceLocationPrefix( + string prefix: string ref); + +/* + * C# dbscheme + */ + +/** ELEMENTS **/ + +@element = @declaration | @stmt | @expr | @modifier | @attribute | @namespace_declaration + | @using_directive | @type_parameter_constraints | @externalDataElement + | @xmllocatable | @asp_element | @namespace | @preprocessor_directive; + +@declaration = @callable | @generic | @assignable | @namespace; + +@named_element = @namespace | @declaration; + +@declaration_with_accessors = @property | @indexer | @event; + +@assignable = @variable | @assignable_with_accessors | @event; + +@assignable_with_accessors = @property | @indexer; + +@attributable = @assembly | @field | @parameter | @operator | @method | @constructor + | @destructor | @callable_accessor | @value_or_ref_type | @declaration_with_accessors + | @local_function | @lambda_expr; + +/** LOCATIONS, ASEMMBLIES, MODULES, FILES and FOLDERS **/ + +@location = @location_default | @assembly; + +locations_default( + unique int id: @location_default, + int file: @file ref, + int beginLine: int ref, + int beginColumn: int ref, + int endLine: int ref, + int endColumn: int ref); + +locations_mapped( + unique int id: @location_default ref, + int mapped_to: @location_default ref); + +@sourceline = @file | @callable | @xmllocatable; + +numlines( + int element_id: @sourceline ref, + int num_lines: int ref, + int num_code: int ref, + int num_comment: int ref); + +assemblies( + unique int id: @assembly, + int file: @file ref, + string fullname: string ref, + string name: string ref, + string version: string ref); + +files( + unique int id: @file, + string name: string ref); + +folders( + unique int id: @folder, + string name: string ref); + +@container = @folder | @file ; + +containerparent( + int parent: @container ref, + unique int child: @container ref); + +file_extraction_mode( + unique int file: @file ref, + int mode: int ref + /* 0 = normal, 1 = standalone extractor */ + ); + +/** NAMESPACES **/ + +@type_container = @namespace | @type; + +namespaces( + unique int id: @namespace, + string name: string ref); + +namespace_declarations( + unique int id: @namespace_declaration, + int namespace_id: @namespace ref); + +namespace_declaration_location( + unique int id: @namespace_declaration ref, + int loc: @location ref); + +parent_namespace( + unique int child_id: @type_container ref, + int namespace_id: @namespace ref); + +@declaration_or_directive = @namespace_declaration | @type | @using_directive; + +parent_namespace_declaration( + int child_id: @declaration_or_directive ref, // cannot be unique because of partial classes + int namespace_id: @namespace_declaration ref); + +@using_directive = @using_namespace_directive | @using_static_directive; + +using_global( + unique int id: @using_directive ref +); + +using_namespace_directives( + unique int id: @using_namespace_directive, + int namespace_id: @namespace ref); + +using_static_directives( + unique int id: @using_static_directive, + int type_id: @type_or_ref ref); + +using_directive_location( + unique int id: @using_directive ref, + int loc: @location ref); + +@preprocessor_directive = @pragma_warning | @pragma_checksum | @directive_define | @directive_undefine | @directive_warning + | @directive_error | @directive_nullable | @directive_line | @directive_region | @directive_endregion | @directive_if + | @directive_elif | @directive_else | @directive_endif; + +@conditional_directive = @directive_if | @directive_elif; +@branch_directive = @directive_if | @directive_elif | @directive_else; + +directive_ifs( + unique int id: @directive_if, + int branchTaken: int ref, /* 0: false, 1: true */ + int conditionValue: int ref); /* 0: false, 1: true */ + +directive_elifs( + unique int id: @directive_elif, + int branchTaken: int ref, /* 0: false, 1: true */ + int conditionValue: int ref, /* 0: false, 1: true */ + int parent: @directive_if ref, + int index: int ref); + +directive_elses( + unique int id: @directive_else, + int branchTaken: int ref, /* 0: false, 1: true */ + int parent: @directive_if ref, + int index: int ref); + +#keyset[id, start] +directive_endifs( + unique int id: @directive_endif, + unique int start: @directive_if ref); + +directive_define_symbols( + unique int id: @define_symbol_expr ref, + string name: string ref); + +directive_regions( + unique int id: @directive_region, + string name: string ref); + +#keyset[id, start] +directive_endregions( + unique int id: @directive_endregion, + unique int start: @directive_region ref); + +directive_lines( + unique int id: @directive_line, + int kind: int ref); /* 0: default, 1: hidden, 2: numeric, 3: span */ + +directive_line_value( + unique int id: @directive_line ref, + int line: int ref); + +directive_line_file( + unique int id: @directive_line ref, + int file: @file ref); + +directive_line_offset( + unique int id: @directive_line ref, + int offset: int ref); + +directive_line_span( + unique int id: @directive_line ref, + int startLine: int ref, + int startColumn: int ref, + int endLine: int ref, + int endColumn: int ref); + +directive_nullables( + unique int id: @directive_nullable, + int setting: int ref, /* 0: disable, 1: enable, 2: restore */ + int target: int ref); /* 0: none, 1: annotations, 2: warnings */ + +directive_warnings( + unique int id: @directive_warning, + string message: string ref); + +directive_errors( + unique int id: @directive_error, + string message: string ref); + +directive_undefines( + unique int id: @directive_undefine, + string name: string ref); + +directive_defines( + unique int id: @directive_define, + string name: string ref); + +pragma_checksums( + unique int id: @pragma_checksum, + int file: @file ref, + string guid: string ref, + string bytes: string ref); + +pragma_warnings( + unique int id: @pragma_warning, + int kind: int ref /* 0 = disable, 1 = restore */); + +#keyset[id, index] +pragma_warning_error_codes( + int id: @pragma_warning ref, + string errorCode: string ref, + int index: int ref); + +preprocessor_directive_location( + unique int id: @preprocessor_directive ref, + int loc: @location ref); + +preprocessor_directive_compilation( + unique int id: @preprocessor_directive ref, + int compilation: @compilation ref); + +preprocessor_directive_active( + unique int id: @preprocessor_directive ref, + int active: int ref); /* 0: false, 1: true */ + +/** TYPES **/ + +types( + unique int id: @type, + int kind: int ref, + string name: string ref); + +case @type.kind of + 1 = @bool_type +| 2 = @char_type +| 3 = @decimal_type +| 4 = @sbyte_type +| 5 = @short_type +| 6 = @int_type +| 7 = @long_type +| 8 = @byte_type +| 9 = @ushort_type +| 10 = @uint_type +| 11 = @ulong_type +| 12 = @float_type +| 13 = @double_type +| 14 = @enum_type +| 15 = @struct_type +| 17 = @class_type +| 19 = @interface_type +| 20 = @delegate_type +| 21 = @null_type +| 22 = @type_parameter +| 23 = @pointer_type +| 24 = @nullable_type +| 25 = @array_type +| 26 = @void_type +| 27 = @int_ptr_type +| 28 = @uint_ptr_type +| 29 = @dynamic_type +| 30 = @arglist_type +| 31 = @unknown_type +| 32 = @tuple_type +| 33 = @function_pointer_type + ; + +@simple_type = @bool_type | @char_type | @integral_type | @floating_point_type | @decimal_type; +@integral_type = @signed_integral_type | @unsigned_integral_type; +@signed_integral_type = @sbyte_type | @short_type | @int_type | @long_type; +@unsigned_integral_type = @byte_type | @ushort_type | @uint_type | @ulong_type; +@floating_point_type = @float_type | @double_type; +@value_type = @simple_type | @enum_type | @struct_type | @nullable_type | @int_ptr_type + | @uint_ptr_type | @tuple_type; +@ref_type = @class_type | @interface_type | @array_type | @delegate_type | @null_type + | @dynamic_type; +@value_or_ref_type = @value_type | @ref_type; + +typerefs( + unique int id: @typeref, + string name: string ref); + +typeref_type( + int id: @typeref ref, + unique int typeId: @type ref); + +@type_or_ref = @type | @typeref; + +array_element_type( + unique int array: @array_type ref, + int dimension: int ref, + int rank: int ref, + int element: @type_or_ref ref); + +nullable_underlying_type( + unique int nullable: @nullable_type ref, + int underlying: @type_or_ref ref); + +pointer_referent_type( + unique int pointer: @pointer_type ref, + int referent: @type_or_ref ref); + +enum_underlying_type( + unique int enum_id: @enum_type ref, + int underlying_type_id: @type_or_ref ref); + +delegate_return_type( + unique int delegate_id: @delegate_type ref, + int return_type_id: @type_or_ref ref); + +function_pointer_return_type( + unique int function_pointer_id: @function_pointer_type ref, + int return_type_id: @type_or_ref ref); + +extend( + int sub: @type ref, + int super: @type_or_ref ref); + +anonymous_types( + unique int id: @type ref); + +@interface_or_ref = @interface_type | @typeref; + +implement( + int sub: @type ref, + int super: @type_or_ref ref); + +type_location( + int id: @type ref, + int loc: @location ref); + +tuple_underlying_type( + unique int tuple: @tuple_type ref, + int struct: @type_or_ref ref); + +#keyset[tuple, index] +tuple_element( + int tuple: @tuple_type ref, + int index: int ref, + unique int field: @field ref); + +attributes( + unique int id: @attribute, + int kind: int ref, + int type_id: @type_or_ref ref, + int target: @attributable ref); + +case @attribute.kind of + 0 = @attribute_default +| 1 = @attribute_return +| 2 = @attribute_assembly +| 3 = @attribute_module +; + +attribute_location( + int id: @attribute ref, + int loc: @location ref); + +@type_mention_parent = @element | @type_mention; + +type_mention( + unique int id: @type_mention, + int type_id: @type_or_ref ref, + int parent: @type_mention_parent ref); + +type_mention_location( + unique int id: @type_mention ref, + int loc: @location ref); + +@has_type_annotation = @assignable | @type_parameter | @callable | @expr | @delegate_type | @generic | @function_pointer_type; + +/** + * A direct annotation on an entity, for example `string? x;`. + * + * Annotations: + * 2 = reftype is not annotated "!" + * 3 = reftype is annotated "?" + * 4 = readonly ref type / in parameter + * 5 = ref type parameter, return or local variable + * 6 = out parameter + * + * Note that the annotation depends on the element it annotates. + * @assignable: The annotation is on the type of the assignable, for example the variable type. + * @type_parameter: The annotation is on the reftype constraint + * @callable: The annotation is on the return type + * @array_type: The annotation is on the element type + */ +type_annotation(int id: @has_type_annotation ref, int annotation: int ref); + +nullability(unique int nullability: @nullability, int kind: int ref); + +case @nullability.kind of + 0 = @oblivious +| 1 = @not_annotated +| 2 = @annotated +; + +#keyset[parent, index] +nullability_parent(int nullability: @nullability ref, int index: int ref, int parent: @nullability ref) + +type_nullability(int id: @has_type_annotation ref, int nullability: @nullability ref); + +/** + * The nullable flow state of an expression, as determined by Roslyn. + * 0 = none (default, not populated) + * 1 = not null + * 2 = maybe null + */ +expr_flowstate(unique int id: @expr ref, int state: int ref); + +/** GENERICS **/ + +@generic = @type | @method | @local_function; + +type_parameters( + unique int id: @type_parameter ref, + int index: int ref, + int generic_id: @generic ref, + int variance: int ref /* none = 0, out = 1, in = 2 */); + +#keyset[constructed_id, index] +type_arguments( + int id: @type_or_ref ref, + int index: int ref, + int constructed_id: @generic_or_ref ref); + +@generic_or_ref = @generic | @typeref; + +constructed_generic( + unique int constructed: @generic ref, + int generic: @generic_or_ref ref); + +type_parameter_constraints( + unique int id: @type_parameter_constraints, + int param_id: @type_parameter ref); + +type_parameter_constraints_location( + int id: @type_parameter_constraints ref, + int loc: @location ref); + +general_type_parameter_constraints( + int id: @type_parameter_constraints ref, + int kind: int ref /* class = 1, struct = 2, new = 3 */); + +specific_type_parameter_constraints( + int id: @type_parameter_constraints ref, + int base_id: @type_or_ref ref); + +specific_type_parameter_nullability( + int id: @type_parameter_constraints ref, + int base_id: @type_or_ref ref, + int nullability: @nullability ref); + +/** FUNCTION POINTERS */ + +function_pointer_calling_conventions( + int id: @function_pointer_type ref, + int kind: int ref); + +#keyset[id, index] +has_unmanaged_calling_conventions( + int id: @function_pointer_type ref, + int index: int ref, + int conv_id: @type_or_ref ref); + +/** MODIFIERS */ + +@modifiable = @modifiable_direct | @event_accessor; + +@modifiable_direct = @member | @accessor | @local_function | @anonymous_function_expr; + +modifiers( + unique int id: @modifier, + string name: string ref); + +has_modifiers( + int id: @modifiable_direct ref, + int mod_id: @modifier ref); + +compiler_generated(unique int id: @modifiable ref); + +/** MEMBERS **/ + +@member = @method | @constructor | @destructor | @field | @property | @event | @operator | @indexer | @type; + +@named_exprorstmt = @goto_stmt | @labeled_stmt | @expr; + +@virtualizable = @method | @property | @indexer | @event; + +exprorstmt_name( + unique int parent_id: @named_exprorstmt ref, + string name: string ref); + +nested_types( + unique int id: @type ref, + int declaring_type_id: @type ref, + int unbound_id: @type ref); + +properties( + unique int id: @property, + string name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @property ref); + +property_location( + int id: @property ref, + int loc: @location ref); + +indexers( + unique int id: @indexer, + string name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @indexer ref); + +indexer_location( + int id: @indexer ref, + int loc: @location ref); + +accessors( + unique int id: @accessor, + int kind: int ref, + string name: string ref, + int declaring_member_id: @member ref, + int unbound_id: @accessor ref); + +case @accessor.kind of + 1 = @getter +| 2 = @setter + ; + +init_only_accessors( + unique int id: @accessor ref); + +accessor_location( + int id: @accessor ref, + int loc: @location ref); + +events( + unique int id: @event, + string name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @event ref); + +event_location( + int id: @event ref, + int loc: @location ref); + +event_accessors( + unique int id: @event_accessor, + int kind: int ref, + string name: string ref, + int declaring_event_id: @event ref, + int unbound_id: @event_accessor ref); + +case @event_accessor.kind of + 1 = @add_event_accessor +| 2 = @remove_event_accessor + ; + +event_accessor_location( + int id: @event_accessor ref, + int loc: @location ref); + +operators( + unique int id: @operator, + string name: string ref, + string symbol: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @operator ref); + +operator_location( + int id: @operator ref, + int loc: @location ref); + +constant_value( + int id: @variable ref, + string value: string ref); + +/** CALLABLES **/ + +@callable = @method | @constructor | @destructor | @operator | @callable_accessor | @anonymous_function_expr | @local_function; + +@callable_accessor = @accessor | @event_accessor; + +methods( + unique int id: @method, + string name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @method ref); + +method_location( + int id: @method ref, + int loc: @location ref); + +constructors( + unique int id: @constructor, + string name: string ref, + int declaring_type_id: @type ref, + int unbound_id: @constructor ref); + +constructor_location( + int id: @constructor ref, + int loc: @location ref); + +destructors( + unique int id: @destructor, + string name: string ref, + int declaring_type_id: @type ref, + int unbound_id: @destructor ref); + +destructor_location( + int id: @destructor ref, + int loc: @location ref); + +overrides( + int id: @callable ref, + int base_id: @callable ref); + +explicitly_implements( + int id: @member ref, + int interface_id: @interface_or_ref ref); + +local_functions( + unique int id: @local_function, + string name: string ref, + int return_type: @type ref, + int unbound_id: @local_function ref); + +local_function_stmts( + unique int fn: @local_function_stmt ref, + int stmt: @local_function ref); + +/** VARIABLES **/ + +@variable = @local_scope_variable | @field; + +@local_scope_variable = @local_variable | @parameter; + +fields( + unique int id: @field, + int kind: int ref, + string name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @field ref); + +case @field.kind of + 1 = @addressable_field +| 2 = @constant + ; + +field_location( + int id: @field ref, + int loc: @location ref); + +localvars( + unique int id: @local_variable, + int kind: int ref, + string name: string ref, + int implicitly_typed: int ref /* 0 = no, 1 = yes */, + int type_id: @type_or_ref ref, + int parent_id: @local_var_decl_expr ref); + +case @local_variable.kind of + 1 = @addressable_local_variable +| 2 = @local_constant +| 3 = @local_variable_ref + ; + +localvar_location( + unique int id: @local_variable ref, + int loc: @location ref); + +@parameterizable = @callable | @delegate_type | @indexer | @function_pointer_type; + +#keyset[name, parent_id] +#keyset[index, parent_id] +params( + unique int id: @parameter, + string name: string ref, + int type_id: @type_or_ref ref, + int index: int ref, + int mode: int ref, /* value = 0, ref = 1, out = 2, array = 3, this = 4 */ + int parent_id: @parameterizable ref, + int unbound_id: @parameter ref); + +param_location( + int id: @parameter ref, + int loc: @location ref); + +/** STATEMENTS **/ + +@exprorstmt_parent = @control_flow_element | @top_level_exprorstmt_parent; + +statements( + unique int id: @stmt, + int kind: int ref); + +#keyset[index, parent] +stmt_parent( + unique int stmt: @stmt ref, + int index: int ref, + int parent: @control_flow_element ref); + +@top_level_stmt_parent = @callable; + +// [index, parent] is not a keyset because the same parent may be compiled multiple times +stmt_parent_top_level( + unique int stmt: @stmt ref, + int index: int ref, + int parent: @top_level_stmt_parent ref); + +case @stmt.kind of + 1 = @block_stmt +| 2 = @expr_stmt +| 3 = @if_stmt +| 4 = @switch_stmt +| 5 = @while_stmt +| 6 = @do_stmt +| 7 = @for_stmt +| 8 = @foreach_stmt +| 9 = @break_stmt +| 10 = @continue_stmt +| 11 = @goto_stmt +| 12 = @goto_case_stmt +| 13 = @goto_default_stmt +| 14 = @throw_stmt +| 15 = @return_stmt +| 16 = @yield_stmt +| 17 = @try_stmt +| 18 = @checked_stmt +| 19 = @unchecked_stmt +| 20 = @lock_stmt +| 21 = @using_block_stmt +| 22 = @var_decl_stmt +| 23 = @const_decl_stmt +| 24 = @empty_stmt +| 25 = @unsafe_stmt +| 26 = @fixed_stmt +| 27 = @label_stmt +| 28 = @catch +| 29 = @case_stmt +| 30 = @local_function_stmt +| 31 = @using_decl_stmt + ; + +@using_stmt = @using_block_stmt | @using_decl_stmt; + +@labeled_stmt = @label_stmt | @case; + +@decl_stmt = @var_decl_stmt | @const_decl_stmt | @using_decl_stmt; + +@cond_stmt = @if_stmt | @switch_stmt; + +@loop_stmt = @while_stmt | @do_stmt | @for_stmt | @foreach_stmt; + +@jump_stmt = @break_stmt | @goto_any_stmt | @continue_stmt | @throw_stmt | @return_stmt + | @yield_stmt; + +@goto_any_stmt = @goto_default_stmt | @goto_case_stmt | @goto_stmt; + + +stmt_location( + unique int id: @stmt ref, + int loc: @location ref); + +catch_type( + unique int catch_id: @catch ref, + int type_id: @type_or_ref ref, + int kind: int ref /* explicit = 1, implicit = 2 */); + +foreach_stmt_info( + unique int id: @foreach_stmt ref, + int kind: int ref /* non-async = 1, async = 2 */); + +@foreach_symbol = @method | @property | @type_or_ref; + +#keyset[id, kind] +foreach_stmt_desugar( + int id: @foreach_stmt ref, + int symbol: @foreach_symbol ref, + int kind: int ref /* GetEnumeratorMethod = 1, CurrentProperty = 2, MoveNextMethod = 3, DisposeMethod = 4, ElementType = 5 */); + +/** EXPRESSIONS **/ + +expressions( + unique int id: @expr, + int kind: int ref, + int type_id: @type_or_ref ref); + +#keyset[index, parent] +expr_parent( + unique int expr: @expr ref, + int index: int ref, + int parent: @control_flow_element ref); + +@top_level_expr_parent = @attribute | @field | @property | @indexer | @parameter | @directive_if | @directive_elif; + +@top_level_exprorstmt_parent = @top_level_expr_parent | @top_level_stmt_parent; + +// [index, parent] is not a keyset because the same parent may be compiled multiple times +expr_parent_top_level( + unique int expr: @expr ref, + int index: int ref, + int parent: @top_level_exprorstmt_parent ref); + +case @expr.kind of +/* literal */ + 1 = @bool_literal_expr +| 2 = @char_literal_expr +| 3 = @decimal_literal_expr +| 4 = @int_literal_expr +| 5 = @long_literal_expr +| 6 = @uint_literal_expr +| 7 = @ulong_literal_expr +| 8 = @float_literal_expr +| 9 = @double_literal_expr +| 10 = @string_literal_expr +| 11 = @null_literal_expr +/* primary & unary */ +| 12 = @this_access_expr +| 13 = @base_access_expr +| 14 = @local_variable_access_expr +| 15 = @parameter_access_expr +| 16 = @field_access_expr +| 17 = @property_access_expr +| 18 = @method_access_expr +| 19 = @event_access_expr +| 20 = @indexer_access_expr +| 21 = @array_access_expr +| 22 = @type_access_expr +| 23 = @typeof_expr +| 24 = @method_invocation_expr +| 25 = @delegate_invocation_expr +| 26 = @operator_invocation_expr +| 27 = @cast_expr +| 28 = @object_creation_expr +| 29 = @explicit_delegate_creation_expr +| 30 = @implicit_delegate_creation_expr +| 31 = @array_creation_expr +| 32 = @default_expr +| 33 = @plus_expr +| 34 = @minus_expr +| 35 = @bit_not_expr +| 36 = @log_not_expr +| 37 = @post_incr_expr +| 38 = @post_decr_expr +| 39 = @pre_incr_expr +| 40 = @pre_decr_expr +/* multiplicative */ +| 41 = @mul_expr +| 42 = @div_expr +| 43 = @rem_expr +/* additive */ +| 44 = @add_expr +| 45 = @sub_expr +/* shift */ +| 46 = @lshift_expr +| 47 = @rshift_expr +/* relational */ +| 48 = @lt_expr +| 49 = @gt_expr +| 50 = @le_expr +| 51 = @ge_expr +/* equality */ +| 52 = @eq_expr +| 53 = @ne_expr +/* logical */ +| 54 = @bit_and_expr +| 55 = @bit_xor_expr +| 56 = @bit_or_expr +| 57 = @log_and_expr +| 58 = @log_or_expr +/* type testing */ +| 59 = @is_expr +| 60 = @as_expr +/* null coalescing */ +| 61 = @null_coalescing_expr +/* conditional */ +| 62 = @conditional_expr +/* assignment */ +| 63 = @simple_assign_expr +| 64 = @assign_add_expr +| 65 = @assign_sub_expr +| 66 = @assign_mul_expr +| 67 = @assign_div_expr +| 68 = @assign_rem_expr +| 69 = @assign_and_expr +| 70 = @assign_xor_expr +| 71 = @assign_or_expr +| 72 = @assign_lshift_expr +| 73 = @assign_rshift_expr +/* more */ +| 74 = @object_init_expr +| 75 = @collection_init_expr +| 76 = @array_init_expr +| 77 = @checked_expr +| 78 = @unchecked_expr +| 79 = @constructor_init_expr +| 80 = @add_event_expr +| 81 = @remove_event_expr +| 82 = @par_expr +| 83 = @local_var_decl_expr +| 84 = @lambda_expr +| 85 = @anonymous_method_expr +| 86 = @namespace_expr +/* dynamic */ +| 92 = @dynamic_element_access_expr +| 93 = @dynamic_member_access_expr +/* unsafe */ +| 100 = @pointer_indirection_expr +| 101 = @address_of_expr +| 102 = @sizeof_expr +/* async */ +| 103 = @await_expr +/* C# 6.0 */ +| 104 = @nameof_expr +| 105 = @interpolated_string_expr +| 106 = @unknown_expr +/* C# 7.0 */ +| 107 = @throw_expr +| 108 = @tuple_expr +| 109 = @local_function_invocation_expr +| 110 = @ref_expr +| 111 = @discard_expr +/* C# 8.0 */ +| 112 = @range_expr +| 113 = @index_expr +| 114 = @switch_expr +| 115 = @recursive_pattern_expr +| 116 = @property_pattern_expr +| 117 = @positional_pattern_expr +| 118 = @switch_case_expr +| 119 = @assign_coalesce_expr +| 120 = @suppress_nullable_warning_expr +| 121 = @namespace_access_expr +/* C# 9.0 */ +| 122 = @lt_pattern_expr +| 123 = @gt_pattern_expr +| 124 = @le_pattern_expr +| 125 = @ge_pattern_expr +| 126 = @not_pattern_expr +| 127 = @and_pattern_expr +| 128 = @or_pattern_expr +| 129 = @function_pointer_invocation_expr +| 130 = @with_expr +/* Preprocessor */ +| 999 = @define_symbol_expr +; + +@switch = @switch_stmt | @switch_expr; +@case = @case_stmt | @switch_case_expr; +@pattern_match = @case | @is_expr; +@unary_pattern_expr = @not_pattern_expr; +@relational_pattern_expr = @gt_pattern_expr | @lt_pattern_expr | @ge_pattern_expr | @le_pattern_expr; +@binary_pattern_expr = @and_pattern_expr | @or_pattern_expr; + +@integer_literal_expr = @int_literal_expr | @long_literal_expr | @uint_literal_expr | @ulong_literal_expr; +@real_literal_expr = @float_literal_expr | @double_literal_expr | @decimal_literal_expr; +@literal_expr = @bool_literal_expr | @char_literal_expr | @integer_literal_expr | @real_literal_expr + | @string_literal_expr | @null_literal_expr; + +@assign_expr = @simple_assign_expr | @assign_op_expr | @local_var_decl_expr; +@assign_op_expr = @assign_arith_expr | @assign_bitwise_expr | @assign_event_expr | @assign_coalesce_expr; +@assign_event_expr = @add_event_expr | @remove_event_expr; + +@assign_arith_expr = @assign_add_expr | @assign_sub_expr | @assign_mul_expr | @assign_div_expr + | @assign_rem_expr +@assign_bitwise_expr = @assign_and_expr | @assign_or_expr | @assign_xor_expr + | @assign_lshift_expr | @assign_rshift_expr; + +@member_access_expr = @field_access_expr | @property_access_expr | @indexer_access_expr | @event_access_expr + | @method_access_expr | @type_access_expr | @dynamic_member_access_expr; +@access_expr = @member_access_expr | @this_access_expr | @base_access_expr | @assignable_access_expr | @namespace_access_expr; +@element_access_expr = @indexer_access_expr | @array_access_expr | @dynamic_element_access_expr; + +@local_variable_access = @local_variable_access_expr | @local_var_decl_expr; +@local_scope_variable_access_expr = @parameter_access_expr | @local_variable_access; +@variable_access_expr = @local_scope_variable_access_expr | @field_access_expr; + +@assignable_access_expr = @variable_access_expr | @property_access_expr | @element_access_expr + | @event_access_expr | @dynamic_member_access_expr; + +@objectorcollection_init_expr = @object_init_expr | @collection_init_expr; + +@delegate_creation_expr = @explicit_delegate_creation_expr | @implicit_delegate_creation_expr; + +@bin_arith_op_expr = @mul_expr | @div_expr | @rem_expr | @add_expr | @sub_expr; +@incr_op_expr = @pre_incr_expr | @post_incr_expr; +@decr_op_expr = @pre_decr_expr | @post_decr_expr; +@mut_op_expr = @incr_op_expr | @decr_op_expr; +@un_arith_op_expr = @plus_expr | @minus_expr | @mut_op_expr; +@arith_op_expr = @bin_arith_op_expr | @un_arith_op_expr; + +@ternary_log_op_expr = @conditional_expr; +@bin_log_op_expr = @log_and_expr | @log_or_expr | @null_coalescing_expr; +@un_log_op_expr = @log_not_expr; +@log_expr = @un_log_op_expr | @bin_log_op_expr | @ternary_log_op_expr; + +@bin_bit_op_expr = @bit_and_expr | @bit_or_expr | @bit_xor_expr | @lshift_expr + | @rshift_expr; +@un_bit_op_expr = @bit_not_expr; +@bit_expr = @un_bit_op_expr | @bin_bit_op_expr; + +@equality_op_expr = @eq_expr | @ne_expr; +@rel_op_expr = @gt_expr | @lt_expr| @ge_expr | @le_expr; +@comp_expr = @equality_op_expr | @rel_op_expr; + +@op_expr = @assign_expr | @un_op | @bin_op | @ternary_op; + +@ternary_op = @ternary_log_op_expr; +@bin_op = @bin_arith_op_expr | @bin_log_op_expr | @bin_bit_op_expr | @comp_expr; +@un_op = @un_arith_op_expr | @un_log_op_expr | @un_bit_op_expr | @sizeof_expr + | @pointer_indirection_expr | @address_of_expr; + +@anonymous_function_expr = @lambda_expr | @anonymous_method_expr; + +@call = @method_invocation_expr | @constructor_init_expr | @operator_invocation_expr + | @delegate_invocation_expr | @object_creation_expr | @call_access_expr + | @local_function_invocation_expr | @function_pointer_invocation_expr; + +@call_access_expr = @property_access_expr | @event_access_expr | @indexer_access_expr; + +@late_bindable_expr = @dynamic_element_access_expr | @dynamic_member_access_expr + | @object_creation_expr | @method_invocation_expr | @operator_invocation_expr; + +@throw_element = @throw_expr | @throw_stmt; + +@implicitly_typeable_object_creation_expr = @object_creation_expr | @explicit_delegate_creation_expr; + +implicitly_typed_array_creation( + unique int id: @array_creation_expr ref); + +explicitly_sized_array_creation( + unique int id: @array_creation_expr ref); + +stackalloc_array_creation( + unique int id: @array_creation_expr ref); + +implicitly_typed_object_creation( + unique int id: @implicitly_typeable_object_creation_expr ref); + +mutator_invocation_mode( + unique int id: @operator_invocation_expr ref, + int mode: int ref /* prefix = 1, postfix = 2*/); + +expr_compiler_generated( + unique int id: @expr ref); + +expr_value( + unique int id: @expr ref, + string value: string ref); + +expr_call( + unique int caller_id: @expr ref, + int target_id: @callable ref); + +expr_access( + unique int accesser_id: @access_expr ref, + int target_id: @accessible ref); + +@accessible = @method | @assignable | @local_function | @namespace; + +expr_location( + unique int id: @expr ref, + int loc: @location ref); + +dynamic_member_name( + unique int id: @late_bindable_expr ref, + string name: string ref); + +@qualifiable_expr = @member_access_expr + | @method_invocation_expr + | @element_access_expr; + +conditional_access( + unique int id: @qualifiable_expr ref); + +expr_argument( + unique int id: @expr ref, + int mode: int ref); + /* mode is the same as params: value = 0, ref = 1, out = 2 */ + +expr_argument_name( + unique int id: @expr ref, + string name: string ref); + +lambda_expr_return_type( + unique int id: @lambda_expr ref, + int type_id: @type_or_ref ref); + +/** CONTROL/DATA FLOW **/ + +@control_flow_element = @stmt | @expr; + +/* XML Files */ + +xmlEncoding ( + unique int id: @file ref, + string encoding: string ref); + +xmlDTDs( + unique int id: @xmldtd, + string root: string ref, + string publicId: string ref, + string systemId: string ref, + int fileid: @file ref); + +xmlElements( + unique int id: @xmlelement, + string name: string ref, + int parentid: @xmlparent ref, + int idx: int ref, + int fileid: @file ref); + +xmlAttrs( + unique int id: @xmlattribute, + int elementid: @xmlelement ref, + string name: string ref, + string value: string ref, + int idx: int ref, + int fileid: @file ref); + +xmlNs( + int id: @xmlnamespace, + string prefixName: string ref, + string URI: string ref, + int fileid: @file ref); + +xmlHasNs( + int elementId: @xmlnamespaceable ref, + int nsId: @xmlnamespace ref, + int fileid: @file ref); + +xmlComments( + unique int id: @xmlcomment, + string text: string ref, + int parentid: @xmlparent ref, + int fileid: @file ref); + +xmlChars( + unique int id: @xmlcharacters, + string text: string ref, + int parentid: @xmlparent ref, + int idx: int ref, + int isCDATA: int ref, + int fileid: @file ref); + +@xmlparent = @file | @xmlelement; +@xmlnamespaceable = @xmlelement | @xmlattribute; + +xmllocations( + int xmlElement: @xmllocatable ref, + int location: @location_default ref); + +@xmllocatable = @xmlcharacters | @xmlelement | @xmlcomment | @xmlattribute | @xmldtd | @file | @xmlnamespace; + +/* Comments */ + +commentline( + unique int id: @commentline, + int kind: int ref, + string text: string ref, + string rawtext: string ref); + +case @commentline.kind of + 0 = @singlelinecomment +| 1 = @xmldoccomment +| 2 = @multilinecomment; + +commentline_location( + unique int id: @commentline ref, + int loc: @location ref); + +commentblock( + unique int id : @commentblock); + +commentblock_location( + unique int id: @commentblock ref, + int loc: @location ref); + +commentblock_binding( + int id: @commentblock ref, + int entity: @element ref, + int bindtype: int ref); /* 0: Parent, 1: Best, 2: Before, 3: After */ + +commentblock_child( + int id: @commentblock ref, + int commentline: @commentline ref, + int index: int ref); + +/* ASP.NET */ + +case @asp_element.kind of + 0=@asp_close_tag +| 1=@asp_code +| 2=@asp_comment +| 3=@asp_data_binding +| 4=@asp_directive +| 5=@asp_open_tag +| 6=@asp_quoted_string +| 7=@asp_text +| 8=@asp_xml_directive; + +@asp_attribute = @asp_code | @asp_data_binding | @asp_quoted_string; + +asp_elements( + unique int id: @asp_element, + int kind: int ref, + int loc: @location ref); + +asp_comment_server(unique int comment: @asp_comment ref); +asp_code_inline(unique int code: @asp_code ref); +asp_directive_attribute( + int directive: @asp_directive ref, + int index: int ref, + string name: string ref, + int value: @asp_quoted_string ref); +asp_directive_name( + unique int directive: @asp_directive ref, + string name: string ref); +asp_element_body( + unique int element: @asp_element ref, + string body: string ref); +asp_tag_attribute( + int tag: @asp_open_tag ref, + int index: int ref, + string name: string ref, + int attribute: @asp_attribute ref); +asp_tag_name( + unique int tag: @asp_open_tag ref, + string name: string ref); +asp_tag_isempty(int tag: @asp_open_tag ref); + +/* Common Intermediate Language - CIL */ + +case @cil_instruction.opcode of + 0 = @cil_nop +| 1 = @cil_break +| 2 = @cil_ldarg_0 +| 3 = @cil_ldarg_1 +| 4 = @cil_ldarg_2 +| 5 = @cil_ldarg_3 +| 6 = @cil_ldloc_0 +| 7 = @cil_ldloc_1 +| 8 = @cil_ldloc_2 +| 9 = @cil_ldloc_3 +| 10 = @cil_stloc_0 +| 11 = @cil_stloc_1 +| 12 = @cil_stloc_2 +| 13 = @cil_stloc_3 +| 14 = @cil_ldarg_s +| 15 = @cil_ldarga_s +| 16 = @cil_starg_s +| 17 = @cil_ldloc_s +| 18 = @cil_ldloca_s +| 19 = @cil_stloc_s +| 20 = @cil_ldnull +| 21 = @cil_ldc_i4_m1 +| 22 = @cil_ldc_i4_0 +| 23 = @cil_ldc_i4_1 +| 24 = @cil_ldc_i4_2 +| 25 = @cil_ldc_i4_3 +| 26 = @cil_ldc_i4_4 +| 27 = @cil_ldc_i4_5 +| 28 = @cil_ldc_i4_6 +| 29 = @cil_ldc_i4_7 +| 30 = @cil_ldc_i4_8 +| 31 = @cil_ldc_i4_s +| 32 = @cil_ldc_i4 +| 33 = @cil_ldc_i8 +| 34 = @cil_ldc_r4 +| 35 = @cil_ldc_r8 +| 37 = @cil_dup +| 38 = @cil_pop +| 39 = @cil_jmp +| 40 = @cil_call +| 41 = @cil_calli +| 42 = @cil_ret +| 43 = @cil_br_s +| 44 = @cil_brfalse_s +| 45 = @cil_brtrue_s +| 46 = @cil_beq_s +| 47 = @cil_bge_s +| 48 = @cil_bgt_s +| 49 = @cil_ble_s +| 50 = @cil_blt_s +| 51 = @cil_bne_un_s +| 52 = @cil_bge_un_s +| 53 = @cil_bgt_un_s +| 54 = @cil_ble_un_s +| 55 = @cil_blt_un_s +| 56 = @cil_br +| 57 = @cil_brfalse +| 58 = @cil_brtrue +| 59 = @cil_beq +| 60 = @cil_bge +| 61 = @cil_bgt +| 62 = @cil_ble +| 63 = @cil_blt +| 64 = @cil_bne_un +| 65 = @cil_bge_un +| 66 = @cil_bgt_un +| 67 = @cil_ble_un +| 68 = @cil_blt_un +| 69 = @cil_switch +| 70 = @cil_ldind_i1 +| 71 = @cil_ldind_u1 +| 72 = @cil_ldind_i2 +| 73 = @cil_ldind_u2 +| 74 = @cil_ldind_i4 +| 75 = @cil_ldind_u4 +| 76 = @cil_ldind_i8 +| 77 = @cil_ldind_i +| 78 = @cil_ldind_r4 +| 79 = @cil_ldind_r8 +| 80 = @cil_ldind_ref +| 81 = @cil_stind_ref +| 82 = @cil_stind_i1 +| 83 = @cil_stind_i2 +| 84 = @cil_stind_i4 +| 85 = @cil_stind_i8 +| 86 = @cil_stind_r4 +| 87 = @cil_stind_r8 +| 88 = @cil_add +| 89 = @cil_sub +| 90 = @cil_mul +| 91 = @cil_div +| 92 = @cil_div_un +| 93 = @cil_rem +| 94 = @cil_rem_un +| 95 = @cil_and +| 96 = @cil_or +| 97 = @cil_xor +| 98 = @cil_shl +| 99 = @cil_shr +| 100 = @cil_shr_un +| 101 = @cil_neg +| 102 = @cil_not +| 103 = @cil_conv_i1 +| 104 = @cil_conv_i2 +| 105 = @cil_conv_i4 +| 106 = @cil_conv_i8 +| 107 = @cil_conv_r4 +| 108 = @cil_conv_r8 +| 109 = @cil_conv_u4 +| 110 = @cil_conv_u8 +| 111 = @cil_callvirt +| 112 = @cil_cpobj +| 113 = @cil_ldobj +| 114 = @cil_ldstr +| 115 = @cil_newobj +| 116 = @cil_castclass +| 117 = @cil_isinst +| 118 = @cil_conv_r_un +| 121 = @cil_unbox +| 122 = @cil_throw +| 123 = @cil_ldfld +| 124 = @cil_ldflda +| 125 = @cil_stfld +| 126 = @cil_ldsfld +| 127 = @cil_ldsflda +| 128 = @cil_stsfld +| 129 = @cil_stobj +| 130 = @cil_conv_ovf_i1_un +| 131 = @cil_conv_ovf_i2_un +| 132 = @cil_conv_ovf_i4_un +| 133 = @cil_conv_ovf_i8_un +| 134 = @cil_conv_ovf_u1_un +| 135 = @cil_conv_ovf_u2_un +| 136 = @cil_conv_ovf_u4_un +| 137 = @cil_conv_ovf_u8_un +| 138 = @cil_conv_ovf_i_un +| 139 = @cil_conv_ovf_u_un +| 140 = @cil_box +| 141 = @cil_newarr +| 142 = @cil_ldlen +| 143 = @cil_ldelema +| 144 = @cil_ldelem_i1 +| 145 = @cil_ldelem_u1 +| 146 = @cil_ldelem_i2 +| 147 = @cil_ldelem_u2 +| 148 = @cil_ldelem_i4 +| 149 = @cil_ldelem_u4 +| 150 = @cil_ldelem_i8 +| 151 = @cil_ldelem_i +| 152 = @cil_ldelem_r4 +| 153 = @cil_ldelem_r8 +| 154 = @cil_ldelem_ref +| 155 = @cil_stelem_i +| 156 = @cil_stelem_i1 +| 157 = @cil_stelem_i2 +| 158 = @cil_stelem_i4 +| 159 = @cil_stelem_i8 +| 160 = @cil_stelem_r4 +| 161 = @cil_stelem_r8 +| 162 = @cil_stelem_ref +| 163 = @cil_ldelem +| 164 = @cil_stelem +| 165 = @cil_unbox_any +| 179 = @cil_conv_ovf_i1 +| 180 = @cil_conv_ovf_u1 +| 181 = @cil_conv_ovf_i2 +| 182 = @cil_conv_ovf_u2 +| 183 = @cil_conv_ovf_i4 +| 184 = @cil_conv_ovf_u4 +| 185 = @cil_conv_ovf_i8 +| 186 = @cil_conv_ovf_u8 +| 194 = @cil_refanyval +| 195 = @cil_ckinfinite +| 198 = @cil_mkrefany +| 208 = @cil_ldtoken +| 209 = @cil_conv_u2 +| 210 = @cil_conv_u1 +| 211 = @cil_conv_i +| 212 = @cil_conv_ovf_i +| 213 = @cil_conv_ovf_u +| 214 = @cil_add_ovf +| 215 = @cil_add_ovf_un +| 216 = @cil_mul_ovf +| 217 = @cil_mul_ovf_un +| 218 = @cil_sub_ovf +| 219 = @cil_sub_ovf_un +| 220 = @cil_endfinally +| 221 = @cil_leave +| 222 = @cil_leave_s +| 223 = @cil_stind_i +| 224 = @cil_conv_u +| 65024 = @cil_arglist +| 65025 = @cil_ceq +| 65026 = @cil_cgt +| 65027 = @cil_cgt_un +| 65028 = @cil_clt +| 65029 = @cil_clt_un +| 65030 = @cil_ldftn +| 65031 = @cil_ldvirtftn +| 65033 = @cil_ldarg +| 65034 = @cil_ldarga +| 65035 = @cil_starg +| 65036 = @cil_ldloc +| 65037 = @cil_ldloca +| 65038 = @cil_stloc +| 65039 = @cil_localloc +| 65041 = @cil_endfilter +| 65042 = @cil_unaligned +| 65043 = @cil_volatile +| 65044 = @cil_tail +| 65045 = @cil_initobj +| 65046 = @cil_constrained +| 65047 = @cil_cpblk +| 65048 = @cil_initblk +| 65050 = @cil_rethrow +| 65052 = @cil_sizeof +| 65053 = @cil_refanytype +| 65054 = @cil_readonly +; + +// CIL ignored instructions + +@cil_ignore = @cil_nop | @cil_break | @cil_volatile | @cil_unaligned; + +// CIL local/parameter/field access + +@cil_ldarg_any = @cil_ldarg_0 | @cil_ldarg_1 | @cil_ldarg_2 | @cil_ldarg_3 | @cil_ldarg_s | @cil_ldarga_s | @cil_ldarg | @cil_ldarga; +@cil_starg_any = @cil_starg | @cil_starg_s; + +@cil_ldloc_any = @cil_ldloc_0 | @cil_ldloc_1 | @cil_ldloc_2 | @cil_ldloc_3 | @cil_ldloc_s | @cil_ldloca_s | @cil_ldloc | @cil_ldloca; +@cil_stloc_any = @cil_stloc_0 | @cil_stloc_1 | @cil_stloc_2 | @cil_stloc_3 | @cil_stloc_s | @cil_stloc; + +@cil_ldfld_any = @cil_ldfld | @cil_ldsfld | @cil_ldsflda | @cil_ldflda; +@cil_stfld_any = @cil_stfld | @cil_stsfld; + +@cil_local_access = @cil_stloc_any | @cil_ldloc_any; +@cil_arg_access = @cil_starg_any | @cil_ldarg_any; +@cil_read_access = @cil_ldloc_any | @cil_ldarg_any | @cil_ldfld_any; +@cil_write_access = @cil_stloc_any | @cil_starg_any | @cil_stfld_any; + +@cil_stack_access = @cil_local_access | @cil_arg_access; +@cil_field_access = @cil_ldfld_any | @cil_stfld_any; + +@cil_access = @cil_read_access | @cil_write_access; + +// CIL constant/literal instructions + +@cil_ldc_i = @cil_ldc_i4_any | @cil_ldc_i8; + +@cil_ldc_i4_any = @cil_ldc_i4_m1 | @cil_ldc_i4_0 | @cil_ldc_i4_1 | @cil_ldc_i4_2 | @cil_ldc_i4_3 | + @cil_ldc_i4_4 | @cil_ldc_i4_5 | @cil_ldc_i4_6 | @cil_ldc_i4_7 | @cil_ldc_i4_8 | @cil_ldc_i4_s | @cil_ldc_i4; + +@cil_ldc_r = @cil_ldc_r4 | @cil_ldc_r8; + +@cil_literal = @cil_ldnull | @cil_ldc_i | @cil_ldc_r | @cil_ldstr; + +// Control flow + +@cil_conditional_jump = @cil_binary_jump | @cil_unary_jump; +@cil_binary_jump = @cil_beq_s | @cil_bge_s | @cil_bgt_s | @cil_ble_s | @cil_blt_s | + @cil_bne_un_s | @cil_bge_un_s | @cil_bgt_un_s | @cil_ble_un_s | @cil_blt_un_s | + @cil_beq | @cil_bge | @cil_bgt | @cil_ble | @cil_blt | + @cil_bne_un | @cil_bge_un | @cil_bgt_un | @cil_ble_un | @cil_blt_un; +@cil_unary_jump = @cil_brfalse_s | @cil_brtrue_s | @cil_brfalse | @cil_brtrue | @cil_switch; +@cil_unconditional_jump = @cil_br | @cil_br_s | @cil_leave_any; +@cil_leave_any = @cil_leave | @cil_leave_s; +@cil_jump = @cil_unconditional_jump | @cil_conditional_jump; + +// CIL call instructions + +@cil_call_any = @cil_jmp | @cil_call | @cil_calli | @cil_tail | @cil_callvirt | @cil_newobj; + +// CIL expression instructions + +@cil_expr = @cil_literal | @cil_binary_expr | @cil_unary_expr | @cil_call_any | @cil_read_access | + @cil_newarr | @cil_ldtoken | @cil_sizeof | + @cil_ldftn | @cil_ldvirtftn | @cil_localloc | @cil_mkrefany | @cil_refanytype | @cil_arglist | @cil_dup; + +@cil_unary_expr = + @cil_conversion_operation | @cil_unary_arithmetic_operation | @cil_unary_bitwise_operation| + @cil_ldlen | @cil_isinst | @cil_box | @cil_ldobj | @cil_castclass | @cil_unbox_any | + @cil_ldind | @cil_unbox; + +@cil_conversion_operation = + @cil_conv_i1 | @cil_conv_i2 | @cil_conv_i4 | @cil_conv_i8 | + @cil_conv_u1 | @cil_conv_u2 | @cil_conv_u4 | @cil_conv_u8 | + @cil_conv_ovf_i | @cil_conv_ovf_i_un | @cil_conv_ovf_i1 | @cil_conv_ovf_i1_un | + @cil_conv_ovf_i2 | @cil_conv_ovf_i2_un | @cil_conv_ovf_i4 | @cil_conv_ovf_i4_un | + @cil_conv_ovf_i8 | @cil_conv_ovf_i8_un | @cil_conv_ovf_u | @cil_conv_ovf_u_un | + @cil_conv_ovf_u1 | @cil_conv_ovf_u1_un | @cil_conv_ovf_u2 | @cil_conv_ovf_u2_un | + @cil_conv_ovf_u4 | @cil_conv_ovf_u4_un | @cil_conv_ovf_u8 | @cil_conv_ovf_u8_un | + @cil_conv_r4 | @cil_conv_r8 | @cil_conv_ovf_u2 | @cil_conv_ovf_u2_un | + @cil_conv_i | @cil_conv_u | @cil_conv_r_un; + +@cil_ldind = @cil_ldind_i | @cil_ldind_i1 | @cil_ldind_i2 | @cil_ldind_i4 | @cil_ldind_i8 | + @cil_ldind_r4 | @cil_ldind_r8 | @cil_ldind_ref | @cil_ldind_u1 | @cil_ldind_u2 | @cil_ldind_u4; + +@cil_stind = @cil_stind_i | @cil_stind_i1 | @cil_stind_i2 | @cil_stind_i4 | @cil_stind_i8 | + @cil_stind_r4 | @cil_stind_r8 | @cil_stind_ref; + +@cil_bitwise_operation = @cil_binary_bitwise_operation | @cil_unary_bitwise_operation; + +@cil_binary_bitwise_operation = @cil_and | @cil_or | @cil_xor | @cil_shr | @cil_shr | @cil_shr_un | @cil_shl; + +@cil_binary_arithmetic_operation = @cil_add | @cil_sub | @cil_mul | @cil_div | @cil_div_un | + @cil_rem | @cil_rem_un | @cil_add_ovf | @cil_add_ovf_un | @cil_mul_ovf | @cil_mul_ovf_un | + @cil_sub_ovf | @cil_sub_ovf_un; + +@cil_unary_bitwise_operation = @cil_not; + +@cil_binary_expr = @cil_binary_arithmetic_operation | @cil_binary_bitwise_operation | @cil_read_array | @cil_comparison_operation; + +@cil_unary_arithmetic_operation = @cil_neg; + +@cil_comparison_operation = @cil_cgt_un | @cil_ceq | @cil_cgt | @cil_clt | @cil_clt_un; + +// Elements that retrieve an address of something +@cil_read_ref = @cil_ldloca_s | @cil_ldarga_s | @cil_ldflda | @cil_ldsflda | @cil_ldelema; + +// CIL array instructions + +@cil_read_array = + @cil_ldelem | @cil_ldelema | @cil_ldelem_i1 | @cil_ldelem_ref | @cil_ldelem_i | + @cil_ldelem_i1 | @cil_ldelem_i2 | @cil_ldelem_i4 | @cil_ldelem_i8 | @cil_ldelem_r4 | + @cil_ldelem_r8 | @cil_ldelem_u1 | @cil_ldelem_u2 | @cil_ldelem_u4; + +@cil_write_array = @cil_stelem | @cil_stelem_ref | + @cil_stelem_i | @cil_stelem_i1 | @cil_stelem_i2 | @cil_stelem_i4 | @cil_stelem_i8 | + @cil_stelem_r4 | @cil_stelem_r8; + +@cil_throw_any = @cil_throw | @cil_rethrow; + +#keyset[impl, index] +cil_instruction( + unique int id: @cil_instruction, + int opcode: int ref, + int index: int ref, + int impl: @cil_method_implementation ref); + +cil_jump( + unique int instruction: @cil_jump ref, + int target: @cil_instruction ref); + +cil_access( + unique int instruction: @cil_instruction ref, + int target: @cil_accessible ref); + +cil_value( + unique int instruction: @cil_literal ref, + string value: string ref); + +#keyset[instruction, index] +cil_switch( + int instruction: @cil_switch ref, + int index: int ref, + int target: @cil_instruction ref); + +cil_instruction_location( + unique int id: @cil_instruction ref, + int loc: @location ref); + +cil_type_location( + int id: @cil_type ref, + int loc: @location ref); + +cil_method_location( + int id: @cil_method ref, + int loc: @location ref); + +@cil_namespace = @namespace; + +@cil_type_container = @cil_type | @cil_namespace | @cil_method; + +case @cil_type.kind of + 0 = @cil_valueorreftype +| 1 = @cil_typeparameter +| 2 = @cil_array_type +| 3 = @cil_pointer_type +| 4 = @cil_function_pointer_type +; + +cil_type( + unique int id: @cil_type, + string name: string ref, + int kind: int ref, + int parent: @cil_type_container ref, + int sourceDecl: @cil_type ref); + +cil_pointer_type( + unique int id: @cil_pointer_type ref, + int pointee: @cil_type ref); + +cil_array_type( + unique int id: @cil_array_type ref, + int element_type: @cil_type ref, + int rank: int ref); + +cil_function_pointer_return_type( + unique int id: @cil_function_pointer_type ref, + int return_type: @cil_type ref); + +cil_method( + unique int id: @cil_method, + string name: string ref, + int parent: @cil_type ref, + int return_type: @cil_type ref); + +cil_method_source_declaration( + unique int method: @cil_method ref, + int source: @cil_method ref); + +cil_method_implementation( + unique int id: @cil_method_implementation, + int method: @cil_method ref, + int location: @assembly ref); + +cil_implements( + int id: @cil_method ref, + int decl: @cil_method ref); + +#keyset[parent, name] +cil_field( + unique int id: @cil_field, + int parent: @cil_type ref, + string name: string ref, + int field_type: @cil_type ref); + +@cil_element = @cil_instruction | @cil_declaration | @cil_handler | @cil_attribute | @cil_namespace; +@cil_named_element = @cil_declaration | @cil_namespace; +@cil_declaration = @cil_variable | @cil_method | @cil_type | @cil_member; +@cil_accessible = @cil_declaration; +@cil_variable = @cil_field | @cil_stack_variable; +@cil_stack_variable = @cil_local_variable | @cil_parameter; +@cil_member = @cil_method | @cil_type | @cil_field | @cil_property | @cil_event; +@cil_custom_modifier_receiver = @cil_method | @cil_property | @cil_parameter | @cil_field | @cil_function_pointer_type; +@cil_parameterizable = @cil_method | @cil_function_pointer_type; +@cil_has_type_annotation = @cil_stack_variable | @cil_property | @cil_method | @cil_function_pointer_type; + +#keyset[parameterizable, index] +cil_parameter( + unique int id: @cil_parameter, + int parameterizable: @cil_parameterizable ref, + int index: int ref, + int param_type: @cil_type ref); + +cil_parameter_in(unique int id: @cil_parameter ref); +cil_parameter_out(unique int id: @cil_parameter ref); + +cil_setter(unique int prop: @cil_property ref, + int method: @cil_method ref); + +#keyset[id, modifier] +cil_custom_modifiers( + int id: @cil_custom_modifier_receiver ref, + int modifier: @cil_type ref, + int kind: int ref); // modreq: 1, modopt: 0 + +cil_type_annotation( + int id: @cil_has_type_annotation ref, + int annotation: int ref); + +cil_getter(unique int prop: @cil_property ref, + int method: @cil_method ref); + +cil_adder(unique int event: @cil_event ref, + int method: @cil_method ref); + +cil_remover(unique int event: @cil_event ref, int method: @cil_method ref); + +cil_raiser(unique int event: @cil_event ref, int method: @cil_method ref); + +cil_property( + unique int id: @cil_property, + int parent: @cil_type ref, + string name: string ref, + int property_type: @cil_type ref); + +#keyset[parent, name] +cil_event(unique int id: @cil_event, + int parent: @cil_type ref, + string name: string ref, + int event_type: @cil_type ref); + +#keyset[impl, index] +cil_local_variable( + unique int id: @cil_local_variable, + int impl: @cil_method_implementation ref, + int index: int ref, + int var_type: @cil_type ref); + +cil_function_pointer_calling_conventions( + int id: @cil_function_pointer_type ref, + int kind: int ref); + +// CIL handlers (exception handlers etc). + +case @cil_handler.kind of + 0 = @cil_catch_handler +| 1 = @cil_filter_handler +| 2 = @cil_finally_handler +| 4 = @cil_fault_handler +; + +#keyset[impl, index] +cil_handler( + unique int id: @cil_handler, + int impl: @cil_method_implementation ref, + int index: int ref, + int kind: int ref, + int try_start: @cil_instruction ref, + int try_end: @cil_instruction ref, + int handler_start: @cil_instruction ref); + +cil_handler_filter( + unique int id: @cil_handler ref, + int filter_start: @cil_instruction ref); + +cil_handler_type( + unique int id: @cil_handler ref, + int catch_type: @cil_type ref); + +@cil_controlflow_node = @cil_entry_point | @cil_instruction; + +@cil_entry_point = @cil_method_implementation | @cil_handler; + +@cil_dataflow_node = @cil_instruction | @cil_variable | @cil_method; + +cil_method_stack_size( + unique int method: @cil_method_implementation ref, + int size: int ref); + +// CIL modifiers + +cil_public(int id: @cil_member ref); +cil_private(int id: @cil_member ref); +cil_protected(int id: @cil_member ref); +cil_internal(int id: @cil_member ref); +cil_static(int id: @cil_member ref); +cil_sealed(int id: @cil_member ref); +cil_virtual(int id: @cil_method ref); +cil_abstract(int id: @cil_member ref); +cil_class(int id: @cil_type ref); +cil_interface(int id: @cil_type ref); +cil_security(int id: @cil_member ref); +cil_requiresecobject(int id: @cil_method ref); +cil_specialname(int id: @cil_method ref); +cil_newslot(int id: @cil_method ref); + +cil_base_class(unique int id: @cil_type ref, int base: @cil_type ref); +cil_base_interface(int id: @cil_type ref, int base: @cil_type ref); +cil_enum_underlying_type(unique int id: @cil_type ref, int underlying: @cil_type ref); + +#keyset[unbound, index] +cil_type_parameter( + int unbound: @cil_member ref, + int index: int ref, + int param: @cil_typeparameter ref); + +#keyset[bound, index] +cil_type_argument( + int bound: @cil_member ref, + int index: int ref, + int t: @cil_type ref); + +// CIL type parameter constraints + +cil_typeparam_covariant(int tp: @cil_typeparameter ref); +cil_typeparam_contravariant(int tp: @cil_typeparameter ref); +cil_typeparam_class(int tp: @cil_typeparameter ref); +cil_typeparam_struct(int tp: @cil_typeparameter ref); +cil_typeparam_new(int tp: @cil_typeparameter ref); +cil_typeparam_constraint(int tp: @cil_typeparameter ref, int supertype: @cil_type ref); + +// CIL attributes + +cil_attribute( + unique int attributeid: @cil_attribute, + int element: @cil_declaration ref, + int constructor: @cil_method ref); + +#keyset[attribute_id, param] +cil_attribute_named_argument( + int attribute_id: @cil_attribute ref, + string param: string ref, + string value: string ref); + +#keyset[attribute_id, index] +cil_attribute_positional_argument( + int attribute_id: @cil_attribute ref, + int index: int ref, + string value: string ref); + + +// Common .Net data model covering both C# and CIL + +// Common elements +@dotnet_element = @element | @cil_element; +@dotnet_named_element = @named_element | @cil_named_element; +@dotnet_callable = @callable | @cil_method; +@dotnet_variable = @variable | @cil_variable; +@dotnet_field = @field | @cil_field; +@dotnet_parameter = @parameter | @cil_parameter; +@dotnet_declaration = @declaration | @cil_declaration; +@dotnet_member = @member | @cil_member; +@dotnet_event = @event | @cil_event; +@dotnet_property = @property | @cil_property | @indexer; +@dotnet_parameterizable = @parameterizable | @cil_parameterizable; + +// Common types +@dotnet_type = @type | @cil_type; +@dotnet_call = @call | @cil_call_any; +@dotnet_throw = @throw_element | @cil_throw_any; +@dotnet_valueorreftype = @cil_valueorreftype | @value_or_ref_type | @cil_array_type | @void_type; +@dotnet_typeparameter = @type_parameter | @cil_typeparameter; +@dotnet_array_type = @array_type | @cil_array_type; +@dotnet_pointer_type = @pointer_type | @cil_pointer_type; +@dotnet_type_parameter = @type_parameter | @cil_typeparameter; +@dotnet_generic = @dotnet_valueorreftype | @dotnet_callable; + +// Attributes +@dotnet_attribute = @attribute | @cil_attribute; + +// Expressions +@dotnet_expr = @expr | @cil_expr; + +// Literals +@dotnet_literal = @literal_expr | @cil_literal; +@dotnet_string_literal = @string_literal_expr | @cil_ldstr; +@dotnet_int_literal = @integer_literal_expr | @cil_ldc_i; +@dotnet_float_literal = @float_literal_expr | @cil_ldc_r; +@dotnet_null_literal = @null_literal_expr | @cil_ldnull; + +@metadata_entity = @cil_method | @cil_type | @cil_field | @cil_property | @field | @property | + @callable | @value_or_ref_type | @void_type; + +#keyset[entity, location] +metadata_handle(int entity : @metadata_entity ref, int location: @assembly ref, int handle: int ref) diff --git a/csharp/downgrades/83aca6b3e4fa38dd2b97b9b51dfc199a2ba9c7f2/upgrade.properties b/csharp/downgrades/83aca6b3e4fa38dd2b97b9b51dfc199a2ba9c7f2/upgrade.properties new file mode 100644 index 00000000000..f6ae8c489a2 --- /dev/null +++ b/csharp/downgrades/83aca6b3e4fa38dd2b97b9b51dfc199a2ba9c7f2/upgrade.properties @@ -0,0 +1,3 @@ +description: Remove list- and slice pattern expression kinds. +compatibility: backwards +expressions.rel: run expressions.qlo \ No newline at end of file diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/CommentBlock.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/CommentBlock.cs index a564d3e7f16..3c4cdcffc0e 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/CommentBlock.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/CommentBlock.cs @@ -1,5 +1,5 @@ -using Semmle.Extraction.Entities; using System.IO; +using Semmle.Util; namespace Semmle.Extraction.CSharp.Entities { @@ -11,12 +11,8 @@ namespace Semmle.Extraction.CSharp.Entities public override void Populate(TextWriter trapFile) { trapFile.commentblock(this); - var child = 0; trapFile.commentblock_location(this, Context.CreateLocation(Symbol.Location)); - foreach (var l in Symbol.CommentLines) - { - trapFile.commentblock_child(this, (CommentLine)l, child++); - } + Symbol.CommentLines.ForEach((l, child) => trapFile.commentblock_child(this, l, child)); } public override bool NeedsPopulation => true; diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Compilations/Compilation.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Compilations/Compilation.cs index 75614d3ad1e..8dd6cd1ee22 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Compilations/Compilation.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Compilations/Compilation.cs @@ -39,45 +39,29 @@ namespace Semmle.Extraction.CSharp.Entities trapFile.compilation_assembly(this, assembly); // Arguments - var index = 0; - foreach (var arg in Compilation.Settings.Args) - { - trapFile.compilation_args(this, index++, arg); - } + Compilation.Settings.Args.ForEach((arg, index) => trapFile.compilation_args(this, index, arg)); // Files - index = 0; - foreach (var file in Context.Compilation.SyntaxTrees.Select(tree => File.Create(Context, tree.FilePath))) - { - trapFile.compilation_compiling_files(this, index++, file); - } + Context.Compilation.SyntaxTrees.Select(tree => File.Create(Context, tree.FilePath)).ForEach((file, index) => trapFile.compilation_compiling_files(this, index, file)); // References - index = 0; - foreach (var file in Context.Compilation.References + Context.Compilation.References .OfType() .Where(r => r.FilePath is not null) - .Select(r => File.Create(Context, r.FilePath!))) - { - trapFile.compilation_referencing_files(this, index++, file); - } + .Select(r => File.Create(Context, r.FilePath!)) + .ForEach((file, index) => trapFile.compilation_referencing_files(this, index, file)); // Diagnostics - index = 0; - foreach (var diag in Context.Compilation.GetDiagnostics().Select(d => new Diagnostic(Context, d))) - { - trapFile.diagnostic_for(diag, this, 0, index++); - } + Context.Compilation + .GetDiagnostics() + .Select(d => new Diagnostic(Context, d)) + .ForEach((diag, index) => trapFile.diagnostic_for(diag, this, 0, index)); } public void PopulatePerformance(PerformanceMetrics p) { var trapFile = Context.TrapWriter.Writer; - var index = 0; - foreach (var metric in p.Metrics) - { - trapFile.compilation_time(this, -1, index++, metric); - } + p.Metrics.ForEach((metric, index) => trapFile.compilation_time(this, -1, index, metric)); trapFile.compilation_finished(this, (float)p.Total.Cpu.TotalSeconds, (float)p.Total.Elapsed.TotalSeconds); } diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/ArrayCreation.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/ArrayCreation.cs index c7860d2ad93..345fdd612b3 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/ArrayCreation.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/ArrayCreation.cs @@ -2,6 +2,7 @@ using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; using Semmle.Extraction.Kinds; +using Semmle.Util; using System.Collections.Generic; using System.IO; using System.Linq; @@ -108,11 +109,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions if (length > 0) { var arrayInit = ArrayInitializer.CreateGenerated(cx, arrayCreation, InitializerIndex, location); - var child = 0; - foreach (var item in items) - { - Expression.CreateGenerated(cx, item, arrayInit, child++, location); - } + items.ForEach((item, child) => Expression.CreateGenerated(cx, item, arrayInit, child, location)); } return arrayCreation; diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Initializer.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Initializer.cs index 7124929a37c..266c820f68d 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Initializer.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Initializer.cs @@ -1,8 +1,8 @@ using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; -using Semmle.Extraction.Entities; using Semmle.Extraction.Kinds; +using Semmle.Util; using System.IO; namespace Semmle.Extraction.CSharp.Entities.Expressions @@ -146,11 +146,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions var init = (InitializerExpressionSyntax)i; - var addChild = 0; - foreach (var arg in init.Expressions) - { - Create(Context, arg, invocation, addChild++); - } + init.Expressions.ForEach((arg, child) => Create(Context, arg, invocation, child)); } else { diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Patterns/BinaryPattern.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Patterns/BinaryPattern.cs index 2d0292ae720..ec5177c8ce6 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Patterns/BinaryPattern.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Patterns/BinaryPattern.cs @@ -1,7 +1,6 @@ using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; -using Semmle.Extraction.Entities; using Semmle.Extraction.Kinds; namespace Semmle.Extraction.CSharp.Entities.Expressions diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Patterns/ListPattern.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Patterns/ListPattern.cs new file mode 100644 index 00000000000..37e19b41aa7 --- /dev/null +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Patterns/ListPattern.cs @@ -0,0 +1,15 @@ +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Semmle.Extraction.Kinds; +using Semmle.Util; + +namespace Semmle.Extraction.CSharp.Entities.Expressions +{ + internal class ListPattern : Expression + { + internal ListPattern(Context cx, ListPatternSyntax syntax, IExpressionParentEntity parent, int child) : + base(new ExpressionInfo(cx, null, cx.CreateLocation(syntax.GetLocation()), ExprKind.LIST_PATTERN, parent, child, false, null)) + { + syntax.Patterns.ForEach((p, i) => Pattern.Create(cx, p, this, i)); + } + } +} \ No newline at end of file diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Patterns/Pattern.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Patterns/Pattern.cs index d883995d062..500154b654d 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Patterns/Pattern.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Patterns/Pattern.cs @@ -1,7 +1,6 @@ using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.CSharp; -using Semmle.Extraction.Entities; namespace Semmle.Extraction.CSharp.Entities.Expressions { @@ -74,6 +73,12 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions case DiscardPatternSyntax dp: return new Discard(cx, dp, parent, child); + case ListPatternSyntax listPattern: + return new ListPattern(cx, listPattern, parent, child); + + case SlicePatternSyntax slicePattern: + return new SlicePattern(cx, slicePattern, parent, child); + default: throw new InternalError(syntax, "Pattern not handled"); } diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Patterns/PositionalPattern.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Patterns/PositionalPattern.cs index f0ae03ae9dc..53e3dbbacd9 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Patterns/PositionalPattern.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Patterns/PositionalPattern.cs @@ -1,6 +1,6 @@ using Microsoft.CodeAnalysis.CSharp.Syntax; using Semmle.Extraction.Kinds; -using Semmle.Extraction.Entities; +using Semmle.Util; namespace Semmle.Extraction.CSharp.Entities.Expressions { @@ -9,11 +9,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions internal PositionalPattern(Context cx, PositionalPatternClauseSyntax posPc, IExpressionParentEntity parent, int child) : base(new ExpressionInfo(cx, null, cx.CreateLocation(posPc.GetLocation()), ExprKind.POSITIONAL_PATTERN, parent, child, false, null)) { - child = 0; - foreach (var sub in posPc.Subpatterns) - { - Expressions.Pattern.Create(cx, sub.Pattern, this, child++); - } + posPc.Subpatterns.ForEach((p, i) => Pattern.Create(cx, p.Pattern, this, i)); } } } diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Patterns/PropertyPattern.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Patterns/PropertyPattern.cs index 1aa515eca2a..30a020702e5 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Patterns/PropertyPattern.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Patterns/PropertyPattern.cs @@ -1,8 +1,6 @@ -using System; using System.Collections.Generic; using Microsoft.CodeAnalysis.CSharp.Syntax; using Semmle.Extraction.Kinds; -using Semmle.Extraction.Entities; namespace Semmle.Extraction.CSharp.Entities.Expressions { @@ -27,7 +25,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions private class AccessStepPack { - public readonly List Prefix = new List(); + public readonly List Prefix = new(); public AccessStep Last { get; private set; } public AccessStepPack Add(string identifier, Microsoft.CodeAnalysis.Location location) diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Patterns/RecursivePattern.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Patterns/RecursivePattern.cs index d29292b3073..8fa3e8f5f23 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Patterns/RecursivePattern.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Patterns/RecursivePattern.cs @@ -2,7 +2,6 @@ using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.CSharp; using Semmle.Extraction.Kinds; -using Semmle.Extraction.Entities; namespace Semmle.Extraction.CSharp.Entities.Expressions { diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Patterns/RelationalPattern.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Patterns/RelationalPattern.cs index 471ab5ca48f..e062692cf8f 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Patterns/RelationalPattern.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Patterns/RelationalPattern.cs @@ -2,7 +2,6 @@ using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.CSharp; using Semmle.Extraction.Kinds; -using Semmle.Extraction.Entities; namespace Semmle.Extraction.CSharp.Entities.Expressions { diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Patterns/SlicePattern.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Patterns/SlicePattern.cs new file mode 100644 index 00000000000..d52af4f54f4 --- /dev/null +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Patterns/SlicePattern.cs @@ -0,0 +1,17 @@ +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Semmle.Extraction.Kinds; + +namespace Semmle.Extraction.CSharp.Entities.Expressions +{ + internal class SlicePattern : Expression + { + public SlicePattern(Context cx, SlicePatternSyntax syntax, IExpressionParentEntity parent, int child) : + base(new ExpressionInfo(cx, null, cx.CreateLocation(syntax.GetLocation()), ExprKind.SLICE_PATTERN, parent, child, false, null)) + { + if (syntax.Pattern is not null) + { + Pattern.Create(cx, syntax.Pattern, this, 0); + } + } + } +} \ No newline at end of file diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Patterns/UnaryPattern.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Patterns/UnaryPattern.cs index ce2cf773a92..1703211fb3d 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Patterns/UnaryPattern.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Patterns/UnaryPattern.cs @@ -1,5 +1,4 @@ using Microsoft.CodeAnalysis.CSharp.Syntax; -using Semmle.Extraction.Entities; using Semmle.Extraction.Kinds; namespace Semmle.Extraction.CSharp.Entities.Expressions diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/PreprocessorDirectives/PragmaWarningDirective.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/PreprocessorDirectives/PragmaWarningDirective.cs index 0e4ca37a49f..81444206fd7 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/PreprocessorDirectives/PragmaWarningDirective.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/PreprocessorDirectives/PragmaWarningDirective.cs @@ -1,6 +1,7 @@ using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; +using Semmle.Util; using System.IO; namespace Semmle.Extraction.CSharp.Entities @@ -15,12 +16,7 @@ namespace Semmle.Extraction.CSharp.Entities protected override void PopulatePreprocessor(TextWriter trapFile) { trapFile.pragma_warnings(this, Symbol.DisableOrRestoreKeyword.IsKind(SyntaxKind.DisableKeyword) ? 0 : 1); - - var childIndex = 0; - foreach (var code in Symbol.ErrorCodes) - { - trapFile.pragma_warning_error_codes(this, code.ToString(), childIndex++); - } + Symbol.ErrorCodes.ForEach((code, child) => trapFile.pragma_warning_error_codes(this, code.ToString(), child)); } public static PragmaWarningDirective Create(Context cx, PragmaWarningDirectiveTriviaSyntax p) => diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Kinds/ExprKind.cs b/csharp/extractor/Semmle.Extraction.CSharp/Kinds/ExprKind.cs index de48df1dc71..a56ccf4c746 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Kinds/ExprKind.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Kinds/ExprKind.cs @@ -125,6 +125,8 @@ namespace Semmle.Extraction.Kinds OR_PATTERN = 128, FUNCTION_POINTER_INVOCATION = 129, WITH = 130, - DEFINE_SYMBOL = 999 + LIST_PATTERN = 131, + SLICE_PATTERN = 132, + DEFINE_SYMBOL = 999, } } diff --git a/csharp/extractor/Semmle.Util/IEnumerableExtensions.cs b/csharp/extractor/Semmle.Util/IEnumerableExtensions.cs index 06be296d255..4e40288d88c 100644 --- a/csharp/extractor/Semmle.Util/IEnumerableExtensions.cs +++ b/csharp/extractor/Semmle.Util/IEnumerableExtensions.cs @@ -79,6 +79,19 @@ namespace Semmle.Util a(item); } + /// + /// Applies the action to each item and its index in this collection. + /// + public static void ForEach(this IEnumerable items, Action a) + { + var i = 0; + foreach (var item in items) + { + a(item, i); + i++; + } + } + /// /// Forces enumeration of this collection and discards the result. /// diff --git a/csharp/ql/lib/change-notes/2022-12-08-listpatterns.md b/csharp/ql/lib/change-notes/2022-12-08-listpatterns.md new file mode 100644 index 00000000000..5f11d1bed81 --- /dev/null +++ b/csharp/ql/lib/change-notes/2022-12-08-listpatterns.md @@ -0,0 +1,4 @@ +--- +category: minorAnalysis +--- +* C# 11: Added support for list- and slice patterns in the extractor. \ No newline at end of file diff --git a/csharp/ql/lib/ext/Dapper.model.yml b/csharp/ql/lib/ext/Dapper.model.yml index 949bc007574..e72f3b076a6 100644 --- a/csharp/ql/lib/ext/Dapper.model.yml +++ b/csharp/ql/lib/ext/Dapper.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/csharp-all - extensible: extSinkModel + extensible: sinkModel data: - ["Dapper", "SqlMapper", False, "Execute", "(System.Data.IDbConnection,System.String,System.Object,System.Data.IDbTransaction,System.Nullable,System.Nullable)", "", "Argument[1]", "sql", "manual"] - ["Dapper", "SqlMapper", False, "ExecuteAsync", "(System.Data.IDbConnection,System.String,System.Object,System.Data.IDbTransaction,System.Nullable,System.Nullable)", "", "Argument[1]", "sql", "manual"] diff --git a/csharp/ql/lib/ext/Microsoft.ApplicationBlocks.Data.model.yml b/csharp/ql/lib/ext/Microsoft.ApplicationBlocks.Data.model.yml index 6a8b6031825..5b5e2657bfd 100644 --- a/csharp/ql/lib/ext/Microsoft.ApplicationBlocks.Data.model.yml +++ b/csharp/ql/lib/ext/Microsoft.ApplicationBlocks.Data.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/csharp-all - extensible: extSinkModel + extensible: sinkModel data: - ["Microsoft.ApplicationBlocks.Data", "SqlHelper", False, "ExecuteDataset", "(System.Data.SqlClient.SqlConnection,System.Data.CommandType,System.String)", "", "Argument[2]", "sql", "manual"] - ["Microsoft.ApplicationBlocks.Data", "SqlHelper", False, "ExecuteDataset", "(System.Data.SqlClient.SqlConnection,System.Data.CommandType,System.String,System.Data.SqlClient.SqlParameter[])", "", "Argument[2]", "sql", "manual"] diff --git a/csharp/ql/lib/ext/Microsoft.EntityFrameworkCore.model.yml b/csharp/ql/lib/ext/Microsoft.EntityFrameworkCore.model.yml index 51ae12fe6fa..3928adf0624 100644 --- a/csharp/ql/lib/ext/Microsoft.EntityFrameworkCore.model.yml +++ b/csharp/ql/lib/ext/Microsoft.EntityFrameworkCore.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/csharp-all - extensible: extSinkModel + extensible: sinkModel data: - ["Microsoft.EntityFrameworkCore", "RelationalDatabaseFacadeExtensions", False, "ExecuteSqlRaw", "(Microsoft.EntityFrameworkCore.Infrastructure.DatabaseFacade,System.String,System.Collections.Generic.IEnumerable)", "", "Argument[1]", "sql", "manual"] - ["Microsoft.EntityFrameworkCore", "RelationalDatabaseFacadeExtensions", False, "ExecuteSqlRaw", "(Microsoft.EntityFrameworkCore.Infrastructure.DatabaseFacade,System.String,System.Object[])", "", "Argument[1]", "sql", "manual"] diff --git a/csharp/ql/lib/ext/Microsoft.Extensions.Primitives.model.yml b/csharp/ql/lib/ext/Microsoft.Extensions.Primitives.model.yml index a6d867fae01..07e50792787 100644 --- a/csharp/ql/lib/ext/Microsoft.Extensions.Primitives.model.yml +++ b/csharp/ql/lib/ext/Microsoft.Extensions.Primitives.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/csharp-all - extensible: extSummaryModel + extensible: summaryModel data: - ["Microsoft.Extensions.Primitives", "StringValues", False, "Add", "(System.String)", "", "Argument[0]", "ReturnValue", "taint", "manual"] - ["Microsoft.Extensions.Primitives", "StringValues", False, "Add", "(System.String)", "", "Argument[this]", "ReturnValue", "taint", "manual"] diff --git a/csharp/ql/lib/ext/Microsoft.VisualBasic.model.yml b/csharp/ql/lib/ext/Microsoft.VisualBasic.model.yml index 3546e3092b3..708f103fdfd 100644 --- a/csharp/ql/lib/ext/Microsoft.VisualBasic.model.yml +++ b/csharp/ql/lib/ext/Microsoft.VisualBasic.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/csharp-all - extensible: extSummaryModel + extensible: summaryModel data: - ["Microsoft.VisualBasic", "Collection", False, "Clear", "()", "", "Argument[this].WithoutElement", "Argument[this]", "value", "manual"] - ["Microsoft.VisualBasic", "Collection", False, "GetEnumerator", "()", "", "Argument[this].Element", "ReturnValue.Property[System.Collections.IEnumerator.Current]", "value", "manual"] diff --git a/csharp/ql/lib/ext/MySql.Data.MySqlClient.model.yml b/csharp/ql/lib/ext/MySql.Data.MySqlClient.model.yml index 7f504e87ace..70d849e122a 100644 --- a/csharp/ql/lib/ext/MySql.Data.MySqlClient.model.yml +++ b/csharp/ql/lib/ext/MySql.Data.MySqlClient.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/csharp-all - extensible: extSinkModel + extensible: sinkModel data: - ["MySql.Data.MySqlClient", "MySqlHelper", False, "ExecuteDataRow", "(System.String,System.String,MySql.Data.MySqlClient.MySqlParameter[])", "", "Argument[1]", "sql", "manual"] - ["MySql.Data.MySqlClient", "MySqlHelper", False, "ExecuteDataRowAsync", "(System.String,System.String,MySql.Data.MySqlClient.MySqlParameter[])", "", "Argument[1]", "sql", "manual"] diff --git a/csharp/ql/lib/ext/Newtonsoft.Json.Linq.model.yml b/csharp/ql/lib/ext/Newtonsoft.Json.Linq.model.yml index adeafdce6a3..ae26fd24c43 100644 --- a/csharp/ql/lib/ext/Newtonsoft.Json.Linq.model.yml +++ b/csharp/ql/lib/ext/Newtonsoft.Json.Linq.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/csharp-all - extensible: extSummaryModel + extensible: summaryModel data: - ["Newtonsoft.Json.Linq", "JArray", False, "get_Item", "(System.Object)", "", "Argument[this].Element", "ReturnValue", "value", "manual"] - ["Newtonsoft.Json.Linq", "JArray", False, "set_Item", "(System.Object,Newtonsoft.Json.Linq.JToken)", "", "Argument[1]", "Argument[this].Element", "value", "manual"] diff --git a/csharp/ql/lib/ext/Newtonsoft.Json.model.yml b/csharp/ql/lib/ext/Newtonsoft.Json.model.yml index 8ac9b9c3383..ce7783b5205 100644 --- a/csharp/ql/lib/ext/Newtonsoft.Json.model.yml +++ b/csharp/ql/lib/ext/Newtonsoft.Json.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/csharp-all - extensible: extSummaryModel + extensible: summaryModel data: - ["Newtonsoft.Json", "JsonConvert", False, "DeserializeAnonymousType<>", "(System.String,T)", "", "Argument[0]", "ReturnValue", "taint", "manual"] - ["Newtonsoft.Json", "JsonConvert", False, "DeserializeAnonymousType<>", "(System.String,T,Newtonsoft.Json.JsonSerializerSettings)", "", "Argument[0]", "ReturnValue", "taint", "manual"] diff --git a/csharp/ql/lib/ext/ServiceStack.OrmLite.model.yml b/csharp/ql/lib/ext/ServiceStack.OrmLite.model.yml index ee6d27168c4..ea7634bc244 100644 --- a/csharp/ql/lib/ext/ServiceStack.OrmLite.model.yml +++ b/csharp/ql/lib/ext/ServiceStack.OrmLite.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/csharp-all - extensible: extSinkModel + extensible: sinkModel data: - ["ServiceStack.OrmLite", "IUntypedSqlExpression", True, "UnsafeAnd", "(System.String,System.Object[])", "", "Argument[0]", "sql", "manual"] - ["ServiceStack.OrmLite", "IUntypedSqlExpression", True, "UnsafeFrom", "(System.String)", "", "Argument[0]", "sql", "manual"] diff --git a/csharp/ql/lib/ext/ServiceStack.Redis.model.yml b/csharp/ql/lib/ext/ServiceStack.Redis.model.yml index a48f736d20a..46415828318 100644 --- a/csharp/ql/lib/ext/ServiceStack.Redis.model.yml +++ b/csharp/ql/lib/ext/ServiceStack.Redis.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/csharp-all - extensible: extSinkModel + extensible: sinkModel data: - ["ServiceStack.Redis", "IRedisClient", True, "Custom", "(System.Object[])", "", "Argument[0]", "code", "manual"] - ["ServiceStack.Redis", "IRedisClient", True, "ExecCachedLua", "(System.String,System.Func)", "", "Argument[0]", "code", "manual"] diff --git a/csharp/ql/lib/ext/ServiceStack.model.yml b/csharp/ql/lib/ext/ServiceStack.model.yml index 814e97f7792..988c7f3b8f9 100644 --- a/csharp/ql/lib/ext/ServiceStack.model.yml +++ b/csharp/ql/lib/ext/ServiceStack.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/csharp-all - extensible: extSinkModel + extensible: sinkModel data: - ["ServiceStack", "IOneWayClient", True, "SendAllOneWay", "(System.Collections.Generic.IEnumerable)", "", "Argument[1].Element", "remote", "manual"] - ["ServiceStack", "IOneWayClient", True, "SendOneWay", "(System.Object)", "", "Argument[0]", "remote", "manual"] @@ -80,7 +80,7 @@ extensions: - ["ServiceStack", "ServiceClientBase", True, "Put", "(System.Object)", "", "Argument[0]", "remote", "manual"] - addsTo: pack: codeql/csharp-all - extensible: extSummaryModel + extensible: summaryModel data: - ["ServiceStack", "HttpResult", False, "HttpResult", "(System.Byte[],System.String)", "", "Argument[0]", "Argument[this]", "taint", "manual"] - ["ServiceStack", "HttpResult", False, "HttpResult", "(System.IO.Stream,System.String)", "", "Argument[0]", "Argument[this]", "taint", "manual"] diff --git a/csharp/ql/lib/ext/System.CodeDom.model.yml b/csharp/ql/lib/ext/System.CodeDom.model.yml index a078b085a33..281812fc6bc 100644 --- a/csharp/ql/lib/ext/System.CodeDom.model.yml +++ b/csharp/ql/lib/ext/System.CodeDom.model.yml @@ -1,6 +1,6 @@ extensions: - addsTo: pack: codeql/csharp-all - extensible: extSummaryModel + extensible: summaryModel data: - ["System.CodeDom", "CodeNamespaceImportCollection", False, "Clear", "()", "", "Argument[this].WithoutElement", "Argument[this]", "value", "manual"] diff --git a/csharp/ql/lib/ext/System.Collections.Concurrent.model.yml b/csharp/ql/lib/ext/System.Collections.Concurrent.model.yml index d009ec9d122..1de81de635c 100644 --- a/csharp/ql/lib/ext/System.Collections.Concurrent.model.yml +++ b/csharp/ql/lib/ext/System.Collections.Concurrent.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/csharp-all - extensible: extSummaryModel + extensible: summaryModel data: - ["System.Collections.Concurrent", "BlockingCollection<>", False, "Add", "(T)", "", "Argument[0]", "Argument[this].Element", "value", "manual"] - ["System.Collections.Concurrent", "BlockingCollection<>", False, "CopyTo", "(T[],System.Int32)", "", "Argument[this].Element", "Argument[0].Element", "value", "manual"] diff --git a/csharp/ql/lib/ext/System.Collections.Generic.model.yml b/csharp/ql/lib/ext/System.Collections.Generic.model.yml index 5f87d13015a..3029690b03f 100644 --- a/csharp/ql/lib/ext/System.Collections.Generic.model.yml +++ b/csharp/ql/lib/ext/System.Collections.Generic.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/csharp-all - extensible: extSummaryModel + extensible: summaryModel data: - ["System.Collections.Generic", "Dictionary<,>", False, "Add", "(System.Collections.Generic.KeyValuePair)", "", "Argument[0].Property[System.Collections.Generic.KeyValuePair<,>.Key]", "Argument[this].Element.Property[System.Collections.Generic.KeyValuePair<,>.Key]", "value", "manual"] - ["System.Collections.Generic", "Dictionary<,>", False, "Add", "(System.Collections.Generic.KeyValuePair)", "", "Argument[0].Property[System.Collections.Generic.KeyValuePair<,>.Value]", "Argument[this].Element.Property[System.Collections.Generic.KeyValuePair<,>.Value]", "value", "manual"] diff --git a/csharp/ql/lib/ext/System.Collections.Immutable.model.yml b/csharp/ql/lib/ext/System.Collections.Immutable.model.yml index 5bafea13557..b2bd1b6a774 100644 --- a/csharp/ql/lib/ext/System.Collections.Immutable.model.yml +++ b/csharp/ql/lib/ext/System.Collections.Immutable.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/csharp-all - extensible: extSummaryModel + extensible: summaryModel data: - ["System.Collections.Immutable", "IImmutableDictionary<,>", True, "AddRange", "(System.Collections.Generic.IEnumerable>)", "", "Argument[0].Element", "Argument[this].Element", "value", "manual"] - ["System.Collections.Immutable", "IImmutableDictionary<,>", True, "Clear", "()", "", "Argument[this].WithoutElement", "ReturnValue", "value", "manual"] diff --git a/csharp/ql/lib/ext/System.Collections.ObjectModel.model.yml b/csharp/ql/lib/ext/System.Collections.ObjectModel.model.yml index 93b88af59bf..b504b034830 100644 --- a/csharp/ql/lib/ext/System.Collections.ObjectModel.model.yml +++ b/csharp/ql/lib/ext/System.Collections.ObjectModel.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/csharp-all - extensible: extSummaryModel + extensible: summaryModel data: - ["System.Collections.ObjectModel", "KeyedCollection<,>", False, "get_Item", "(TKey)", "", "Argument[this].Element", "ReturnValue", "value", "manual"] - ["System.Collections.ObjectModel", "ReadOnlyCollection<>", False, "get_Item", "(System.Int32)", "", "Argument[this].Element", "ReturnValue", "value", "manual"] diff --git a/csharp/ql/lib/ext/System.Collections.Specialized.model.yml b/csharp/ql/lib/ext/System.Collections.Specialized.model.yml index 00a09505fca..8456af24f14 100644 --- a/csharp/ql/lib/ext/System.Collections.Specialized.model.yml +++ b/csharp/ql/lib/ext/System.Collections.Specialized.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/csharp-all - extensible: extSummaryModel + extensible: summaryModel data: - ["System.Collections.Specialized", "IOrderedDictionary", True, "get_Item", "(System.Int32)", "", "Argument[this].Element.Property[System.Collections.Generic.KeyValuePair<,>.Value]", "ReturnValue", "value", "manual"] - ["System.Collections.Specialized", "IOrderedDictionary", True, "set_Item", "(System.Int32,System.Object)", "", "Argument[0]", "Argument[this].Element.Property[System.Collections.Generic.KeyValuePair<,>.Key]", "value", "manual"] diff --git a/csharp/ql/lib/ext/System.Collections.model.yml b/csharp/ql/lib/ext/System.Collections.model.yml index 8a364ee5357..9aa2c2489c9 100644 --- a/csharp/ql/lib/ext/System.Collections.model.yml +++ b/csharp/ql/lib/ext/System.Collections.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/csharp-all - extensible: extSummaryModel + extensible: summaryModel data: - ["System.Collections", "ArrayList", False, "AddRange", "(System.Collections.ICollection)", "", "Argument[0].Element", "Argument[this].Element", "value", "manual"] - ["System.Collections", "ArrayList", False, "Clone", "()", "", "Argument[0].Element", "ReturnValue.Element", "value", "manual"] diff --git a/csharp/ql/lib/ext/System.ComponentModel.Design.model.yml b/csharp/ql/lib/ext/System.ComponentModel.Design.model.yml index 38a6cd47520..465a7595f60 100644 --- a/csharp/ql/lib/ext/System.ComponentModel.Design.model.yml +++ b/csharp/ql/lib/ext/System.ComponentModel.Design.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/csharp-all - extensible: extSummaryModel + extensible: summaryModel data: - ["System.ComponentModel.Design", "DesignerCollection", False, "GetEnumerator", "()", "", "Argument[this].Element", "ReturnValue.Property[System.Collections.IEnumerator.Current]", "value", "manual"] - ["System.ComponentModel.Design", "DesignerOptionService+DesignerOptionCollection", False, "get_Item", "(System.Int32)", "", "Argument[this].Element", "ReturnValue", "value", "manual"] diff --git a/csharp/ql/lib/ext/System.ComponentModel.model.yml b/csharp/ql/lib/ext/System.ComponentModel.model.yml index b20eaa0a871..cdb5ee29993 100644 --- a/csharp/ql/lib/ext/System.ComponentModel.model.yml +++ b/csharp/ql/lib/ext/System.ComponentModel.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/csharp-all - extensible: extSummaryModel + extensible: summaryModel data: - ["System.ComponentModel", "AttributeCollection", False, "GetEnumerator", "()", "", "Argument[this].Element", "ReturnValue.Property[System.Collections.IEnumerator.Current]", "value", "manual"] - ["System.ComponentModel", "ComponentCollection", False, "CopyTo", "(System.ComponentModel.IComponent[],System.Int32)", "", "Argument[this].Element", "Argument[0].Element", "value", "manual"] diff --git a/csharp/ql/lib/ext/System.Configuration.Provider.model.yml b/csharp/ql/lib/ext/System.Configuration.Provider.model.yml index 5c5e60f2f88..b532f8cd95a 100644 --- a/csharp/ql/lib/ext/System.Configuration.Provider.model.yml +++ b/csharp/ql/lib/ext/System.Configuration.Provider.model.yml @@ -1,6 +1,6 @@ extensions: - addsTo: pack: codeql/csharp-all - extensible: extSummaryModel + extensible: summaryModel data: - ["System.Configuration.Provider", "ProviderCollection", False, "Clear", "()", "", "Argument[this].WithoutElement", "Argument[this]", "value", "manual"] diff --git a/csharp/ql/lib/ext/System.Configuration.model.yml b/csharp/ql/lib/ext/System.Configuration.model.yml index 457642ab238..cf367cdcaa8 100644 --- a/csharp/ql/lib/ext/System.Configuration.model.yml +++ b/csharp/ql/lib/ext/System.Configuration.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/csharp-all - extensible: extSummaryModel + extensible: summaryModel data: - ["System.Configuration", "CommaDelimitedStringCollection", False, "Clear", "()", "", "Argument[this].WithoutElement", "Argument[this]", "value", "manual"] - ["System.Configuration", "ConfigurationLockCollection", False, "Clear", "()", "", "Argument[this].WithoutElement", "Argument[this]", "value", "manual"] diff --git a/csharp/ql/lib/ext/System.Data.Common.model.yml b/csharp/ql/lib/ext/System.Data.Common.model.yml index f85c4aa6712..bc3864d2813 100644 --- a/csharp/ql/lib/ext/System.Data.Common.model.yml +++ b/csharp/ql/lib/ext/System.Data.Common.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/csharp-all - extensible: extSummaryModel + extensible: summaryModel data: - ["System.Data.Common", "DataColumnMappingCollection", False, "AddRange", "(System.Array)", "", "Argument[0].Element", "Argument[this].Element", "value", "manual"] - ["System.Data.Common", "DataColumnMappingCollection", False, "AddRange", "(System.Data.Common.DataColumnMapping[])", "", "Argument[0].Element", "Argument[this].Element", "value", "manual"] diff --git a/csharp/ql/lib/ext/System.Data.Entity.model.yml b/csharp/ql/lib/ext/System.Data.Entity.model.yml index 9df471d3489..36eccd9b38d 100644 --- a/csharp/ql/lib/ext/System.Data.Entity.model.yml +++ b/csharp/ql/lib/ext/System.Data.Entity.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/csharp-all - extensible: extSinkModel + extensible: sinkModel data: - ["System.Data.Entity", "Database", False, "ExecuteSqlCommand", "(System.Data.Entity.TransactionalBehavior,System.String,System.Object[])", "", "Argument[1]", "sql", "manual"] - ["System.Data.Entity", "Database", False, "ExecuteSqlCommand", "(System.String,System.Object[])", "", "Argument[0]", "sql", "manual"] diff --git a/csharp/ql/lib/ext/System.Data.EntityClient.model.yml b/csharp/ql/lib/ext/System.Data.EntityClient.model.yml index 692c35d352a..16a24580647 100644 --- a/csharp/ql/lib/ext/System.Data.EntityClient.model.yml +++ b/csharp/ql/lib/ext/System.Data.EntityClient.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/csharp-all - extensible: extSinkModel + extensible: sinkModel data: - ["System.Data.EntityClient", "EntityCommand", False, "EntityCommand", "(System.String)", "", "Argument[0]", "sql", "manual"] - ["System.Data.EntityClient", "EntityCommand", False, "EntityCommand", "(System.String,System.Data.EntityClient.EntityConnection)", "", "Argument[0]", "sql", "manual"] diff --git a/csharp/ql/lib/ext/System.Data.Odbc.model.yml b/csharp/ql/lib/ext/System.Data.Odbc.model.yml index 3bb650739a2..d1f6a24d5fc 100644 --- a/csharp/ql/lib/ext/System.Data.Odbc.model.yml +++ b/csharp/ql/lib/ext/System.Data.Odbc.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/csharp-all - extensible: extSinkModel + extensible: sinkModel data: - ["System.Data.Odbc", "OdbcCommand", False, "OdbcCommand", "(System.String)", "", "Argument[0]", "sql", "manual"] - ["System.Data.Odbc", "OdbcCommand", False, "OdbcCommand", "(System.String,System.Data.Odbc.OdbcConnection)", "", "Argument[0]", "sql", "manual"] diff --git a/csharp/ql/lib/ext/System.Data.OleDb.model.yml b/csharp/ql/lib/ext/System.Data.OleDb.model.yml index 5acb38217fc..ebe3cc8b157 100644 --- a/csharp/ql/lib/ext/System.Data.OleDb.model.yml +++ b/csharp/ql/lib/ext/System.Data.OleDb.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/csharp-all - extensible: extSinkModel + extensible: sinkModel data: - ["System.Data.OleDb", "OleDbCommand", False, "OleDbCommand", "(System.String)", "", "Argument[0]", "sql", "manual"] - ["System.Data.OleDb", "OleDbCommand", False, "OleDbCommand", "(System.String,System.Data.OleDb.OleDbConnection)", "", "Argument[0]", "sql", "manual"] diff --git a/csharp/ql/lib/ext/System.Data.SQLite.model.yml b/csharp/ql/lib/ext/System.Data.SQLite.model.yml index cba3abb6d81..d6d1d70e608 100644 --- a/csharp/ql/lib/ext/System.Data.SQLite.model.yml +++ b/csharp/ql/lib/ext/System.Data.SQLite.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/csharp-all - extensible: extSinkModel + extensible: sinkModel data: - ["System.Data.SQLite", "SQLiteCommand", False, "SQLiteCommand", "(System.String)", "", "Argument[0]", "sql", "manual"] - ["System.Data.SQLite", "SQLiteCommand", False, "SQLiteCommand", "(System.String,System.Data.SQLite.SQLiteConnection)", "", "Argument[0]", "sql", "manual"] @@ -12,7 +12,7 @@ extensions: - ["System.Data.SQLite", "SQLiteDataAdapter", False, "SQLiteDataAdapter", "(System.String,System.String,System.Boolean)", "", "Argument[0]", "sql", "manual"] - addsTo: pack: codeql/csharp-all - extensible: extSummaryModel + extensible: summaryModel data: - ["System.Data.SQLite", "SQLiteCommand", False, "SQLiteCommand", "(System.String)", "", "Argument[0]", "Argument[this]", "taint", "manual"] - ["System.Data.SQLite", "SQLiteCommand", False, "SQLiteCommand", "(System.String,System.Data.SQLite.SQLiteConnection)", "", "Argument[0]", "Argument[this]", "taint", "manual"] diff --git a/csharp/ql/lib/ext/System.Data.SqlClient.model.yml b/csharp/ql/lib/ext/System.Data.SqlClient.model.yml index 54e0aec4a53..2040e0f9798 100644 --- a/csharp/ql/lib/ext/System.Data.SqlClient.model.yml +++ b/csharp/ql/lib/ext/System.Data.SqlClient.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/csharp-all - extensible: extSinkModel + extensible: sinkModel data: - ["System.Data.SqlClient", "SqlCommand", False, "SqlCommand", "(System.String)", "", "Argument[0]", "sql", "manual"] - ["System.Data.SqlClient", "SqlCommand", False, "SqlCommand", "(System.String,System.Data.SqlClient.SqlConnection)", "", "Argument[0]", "sql", "manual"] @@ -11,7 +11,7 @@ extensions: - ["System.Data.SqlClient", "SqlDataAdapter", False, "SqlDataAdapter", "(System.String,System.String)", "", "Argument[0]", "sql", "manual"] - addsTo: pack: codeql/csharp-all - extensible: extSummaryModel + extensible: summaryModel data: - ["System.Data.SqlClient", "SqlCommand", False, "SqlCommand", "(System.String)", "", "Argument[0]", "Argument[this]", "taint", "manual"] - ["System.Data.SqlClient", "SqlCommand", False, "SqlCommand", "(System.String,System.Data.SqlClient.SqlConnection)", "", "Argument[0]", "Argument[this]", "taint", "manual"] diff --git a/csharp/ql/lib/ext/System.Data.model.yml b/csharp/ql/lib/ext/System.Data.model.yml index 158811616f4..26f650c96a5 100644 --- a/csharp/ql/lib/ext/System.Data.model.yml +++ b/csharp/ql/lib/ext/System.Data.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/csharp-all - extensible: extSummaryModel + extensible: summaryModel data: - ["System.Data", "ConstraintCollection", False, "Add", "(System.Data.Constraint)", "", "Argument[0]", "Argument[this].Element", "value", "manual"] - ["System.Data", "ConstraintCollection", False, "AddRange", "(System.Data.Constraint[])", "", "Argument[0].Element", "Argument[this].Element", "value", "manual"] diff --git a/csharp/ql/lib/ext/System.Diagnostics.model.yml b/csharp/ql/lib/ext/System.Diagnostics.model.yml index 7d3a862cd91..7085f740265 100644 --- a/csharp/ql/lib/ext/System.Diagnostics.model.yml +++ b/csharp/ql/lib/ext/System.Diagnostics.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/csharp-all - extensible: extSummaryModel + extensible: summaryModel data: - ["System.Diagnostics", "ActivityTagsCollection", False, "ActivityTagsCollection", "(System.Collections.Generic.IEnumerable>)", "", "Argument[0].Element.Property[System.Collections.Generic.KeyValuePair<,>.Key]", "Argument[this].Element.Property[System.Collections.Generic.KeyValuePair<,>.Key]", "value", "manual"] - ["System.Diagnostics", "ActivityTagsCollection", False, "ActivityTagsCollection", "(System.Collections.Generic.IEnumerable>)", "", "Argument[0].Element.Property[System.Collections.Generic.KeyValuePair<,>.Value]", "Argument[this].Element.Property[System.Collections.Generic.KeyValuePair<,>.Value]", "value", "manual"] diff --git a/csharp/ql/lib/ext/System.Dynamic.model.yml b/csharp/ql/lib/ext/System.Dynamic.model.yml index a79b7538213..19e0c6552a9 100644 --- a/csharp/ql/lib/ext/System.Dynamic.model.yml +++ b/csharp/ql/lib/ext/System.Dynamic.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/csharp-all - extensible: extSummaryModel + extensible: summaryModel data: - ["System.Dynamic", "ExpandoObject", False, "Add", "(System.Collections.Generic.KeyValuePair)", "", "Argument[0].Property[System.Collections.Generic.KeyValuePair<,>.Key]", "Argument[this].Element.Property[System.Collections.Generic.KeyValuePair<,>.Key]", "value", "manual"] - ["System.Dynamic", "ExpandoObject", False, "Add", "(System.Collections.Generic.KeyValuePair)", "", "Argument[0].Property[System.Collections.Generic.KeyValuePair<,>.Value]", "Argument[this].Element.Property[System.Collections.Generic.KeyValuePair<,>.Value]", "value", "manual"] diff --git a/csharp/ql/lib/ext/System.IO.Compression.model.yml b/csharp/ql/lib/ext/System.IO.Compression.model.yml index 57d93bab865..592b2748a0a 100644 --- a/csharp/ql/lib/ext/System.IO.Compression.model.yml +++ b/csharp/ql/lib/ext/System.IO.Compression.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/csharp-all - extensible: extSummaryModel + extensible: summaryModel data: - ["System.IO.Compression", "DeflateStream", False, "DeflateStream", "(System.IO.Stream,System.IO.Compression.CompressionLevel)", "", "Argument[0]", "Argument[this]", "taint", "manual"] - ["System.IO.Compression", "DeflateStream", False, "DeflateStream", "(System.IO.Stream,System.IO.Compression.CompressionLevel,System.Boolean)", "", "Argument[0]", "Argument[this]", "taint", "manual"] diff --git a/csharp/ql/lib/ext/System.IO.model.yml b/csharp/ql/lib/ext/System.IO.model.yml index c66cd6286b2..49b0818ef5f 100644 --- a/csharp/ql/lib/ext/System.IO.model.yml +++ b/csharp/ql/lib/ext/System.IO.model.yml @@ -1,12 +1,12 @@ extensions: - addsTo: pack: codeql/csharp-all - extensible: extSourceModel + extensible: sourceModel data: - ["System.IO", "FileStream", False, "FileStream", "", "", "Argument[this]", "file", "manual"] - addsTo: pack: codeql/csharp-all - extensible: extSummaryModel + extensible: summaryModel data: - ["System.IO", "FileStream", False, "FileStream", "(System.String,System.IO.FileMode)", "", "Argument[0]", "Argument[this]", "taint", "manual"] - ["System.IO", "FileStream", False, "FileStream", "(System.String,System.IO.FileMode,System.IO.FileAccess)", "", "Argument[0]", "Argument[this]", "taint", "manual"] @@ -58,18 +58,18 @@ extensions: - ["System.IO", "Stream", False, "WriteAsync", "(System.Byte[],System.Int32,System.Int32)", "", "Argument[0].Element", "Argument[this]", "taint", "manual"] - ["System.IO", "Stream", True, "WriteAsync", "(System.Byte[],System.Int32,System.Int32,System.Threading.CancellationToken)", "", "Argument[0].Element", "Argument[this]", "taint", "manual"] - ["System.IO", "StreamReader", False, "StreamReader", "(System.IO.Stream)", "", "Argument[0]", "Argument[this]", "taint", "manual"] - - ["System.IO", "StreamReader", False, "StreamReader", "(System.String,System.Text.Encoding,System.Boolean,System.IO.FileStreamOptions)", "", "Argument[0]", "Argument[this]", "taint", "manual"] - - ["System.IO", "StreamReader", False, "StreamReader", "(System.String,System.Text.Encoding,System.Boolean,System.Int32)", "", "Argument[0]", "Argument[this]", "taint", "manual"] + - ["System.IO", "StreamReader", False, "StreamReader", "(System.IO.Stream,System.Boolean)", "", "Argument[0]", "Argument[this]", "taint", "manual"] + - ["System.IO", "StreamReader", False, "StreamReader", "(System.IO.Stream,System.Text.Encoding)", "", "Argument[0]", "Argument[this]", "taint", "manual"] + - ["System.IO", "StreamReader", False, "StreamReader", "(System.IO.Stream,System.Text.Encoding,System.Boolean)", "", "Argument[0]", "Argument[this]", "taint", "manual"] - ["System.IO", "StreamReader", False, "StreamReader", "(System.IO.Stream,System.Text.Encoding,System.Boolean,System.Int32)", "", "Argument[0]", "Argument[this]", "taint", "manual"] - ["System.IO", "StreamReader", False, "StreamReader", "(System.IO.Stream,System.Text.Encoding,System.Boolean,System.Int32,System.Boolean)", "", "Argument[0]", "Argument[this]", "taint", "manual"] - - ["System.IO", "StreamReader", False, "StreamReader", "(System.IO.Stream,System.Text.Encoding,System.Boolean)", "", "Argument[0]", "Argument[this]", "taint", "manual"] - - ["System.IO", "StreamReader", False, "StreamReader", "(System.String,System.Text.Encoding,System.Boolean)", "", "Argument[0]", "Argument[this]", "taint", "manual"] - - ["System.IO", "StreamReader", False, "StreamReader", "(System.String,System.IO.FileStreamOptions)", "", "Argument[0]", "Argument[this]", "taint", "manual"] - - ["System.IO", "StreamReader", False, "StreamReader", "(System.String,System.Boolean)", "", "Argument[0]", "Argument[this]", "taint", "manual"] - - ["System.IO", "StreamReader", False, "StreamReader", "(System.IO.Stream,System.Text.Encoding)", "", "Argument[0]", "Argument[this]", "taint", "manual"] - - ["System.IO", "StreamReader", False, "StreamReader", "(System.IO.Stream,System.Boolean)", "", "Argument[0]", "Argument[this]", "taint", "manual"] - ["System.IO", "StreamReader", False, "StreamReader", "(System.String)", "", "Argument[0]", "Argument[this]", "taint", "manual"] + - ["System.IO", "StreamReader", False, "StreamReader", "(System.String,System.Boolean)", "", "Argument[0]", "Argument[this]", "taint", "manual"] + - ["System.IO", "StreamReader", False, "StreamReader", "(System.String,System.IO.FileStreamOptions)", "", "Argument[0]", "Argument[this]", "taint", "manual"] - ["System.IO", "StreamReader", False, "StreamReader", "(System.String,System.Text.Encoding)", "", "Argument[0]", "Argument[this]", "taint", "manual"] + - ["System.IO", "StreamReader", False, "StreamReader", "(System.String,System.Text.Encoding,System.Boolean)", "", "Argument[0]", "Argument[this]", "taint", "manual"] + - ["System.IO", "StreamReader", False, "StreamReader", "(System.String,System.Text.Encoding,System.Boolean,System.IO.FileStreamOptions)", "", "Argument[0]", "Argument[this]", "taint", "manual"] + - ["System.IO", "StreamReader", False, "StreamReader", "(System.String,System.Text.Encoding,System.Boolean,System.Int32)", "", "Argument[0]", "Argument[this]", "taint", "manual"] - ["System.IO", "StringReader", False, "StringReader", "(System.String)", "", "Argument[0]", "Argument[this]", "taint", "manual"] - ["System.IO", "TextReader", True, "Read", "()", "", "Argument[this]", "ReturnValue", "taint", "manual"] - ["System.IO", "TextReader", True, "Read", "(System.Char[],System.Int32,System.Int32)", "", "Argument[this]", "ReturnValue", "taint", "manual"] diff --git a/csharp/ql/lib/ext/System.Linq.model.yml b/csharp/ql/lib/ext/System.Linq.model.yml index df5fc4d349f..8dd3c81327c 100644 --- a/csharp/ql/lib/ext/System.Linq.model.yml +++ b/csharp/ql/lib/ext/System.Linq.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/csharp-all - extensible: extSummaryModel + extensible: summaryModel data: - ["System.Linq", "Enumerable", False, "Aggregate<,,>", "(System.Collections.Generic.IEnumerable,TAccumulate,System.Func,System.Func)", "", "Argument[0].Element", "Argument[2].Parameter[1]", "value", "manual"] - ["System.Linq", "Enumerable", False, "Aggregate<,,>", "(System.Collections.Generic.IEnumerable,TAccumulate,System.Func,System.Func)", "", "Argument[1]", "Argument[2].Parameter[0]", "value", "manual"] diff --git a/csharp/ql/lib/ext/System.Net.Http.Headers.model.yml b/csharp/ql/lib/ext/System.Net.Http.Headers.model.yml index 6a6a44fb18a..79b6b8cf40c 100644 --- a/csharp/ql/lib/ext/System.Net.Http.Headers.model.yml +++ b/csharp/ql/lib/ext/System.Net.Http.Headers.model.yml @@ -1,6 +1,6 @@ extensions: - addsTo: pack: codeql/csharp-all - extensible: extSummaryModel + extensible: summaryModel data: - ["System.Net.Http.Headers", "HttpHeaders", False, "Clear", "()", "", "Argument[this].WithoutElement", "Argument[this]", "value", "manual"] diff --git a/csharp/ql/lib/ext/System.Net.Http.model.yml b/csharp/ql/lib/ext/System.Net.Http.model.yml index d0ecdd4fb6c..0eafc30988a 100644 --- a/csharp/ql/lib/ext/System.Net.Http.model.yml +++ b/csharp/ql/lib/ext/System.Net.Http.model.yml @@ -1,12 +1,12 @@ extensions: - addsTo: pack: codeql/csharp-all - extensible: extSinkModel + extensible: sinkModel data: - ["System.Net.Http", "StringContent", False, "StringContent", "", "", "Argument[0]", "xss", "manual"] - addsTo: pack: codeql/csharp-all - extensible: extSummaryModel + extensible: summaryModel data: - ["System.Net.Http", "HttpRequestOptions", False, "Add", "(System.Collections.Generic.KeyValuePair)", "", "Argument[0].Property[System.Collections.Generic.KeyValuePair<,>.Key]", "Argument[this].Element.Property[System.Collections.Generic.KeyValuePair<,>.Key]", "value", "manual"] - ["System.Net.Http", "HttpRequestOptions", False, "Add", "(System.Collections.Generic.KeyValuePair)", "", "Argument[0].Property[System.Collections.Generic.KeyValuePair<,>.Value]", "Argument[this].Element.Property[System.Collections.Generic.KeyValuePair<,>.Value]", "value", "manual"] diff --git a/csharp/ql/lib/ext/System.Net.Mail.model.yml b/csharp/ql/lib/ext/System.Net.Mail.model.yml index 92cf36da3b0..5694b634560 100644 --- a/csharp/ql/lib/ext/System.Net.Mail.model.yml +++ b/csharp/ql/lib/ext/System.Net.Mail.model.yml @@ -1,6 +1,6 @@ extensions: - addsTo: pack: codeql/csharp-all - extensible: extSummaryModel + extensible: summaryModel data: - ["System.Net.Mail", "MailAddressCollection", False, "Add", "(System.String)", "", "Argument[0]", "Argument[this].Element", "value", "manual"] diff --git a/csharp/ql/lib/ext/System.Net.Sockets.model.yml b/csharp/ql/lib/ext/System.Net.Sockets.model.yml new file mode 100644 index 00000000000..950a818e2d8 --- /dev/null +++ b/csharp/ql/lib/ext/System.Net.Sockets.model.yml @@ -0,0 +1,9 @@ +extensions: + - addsTo: + pack: codeql/csharp-all + extensible: sourceModel + data: + - ["System.Net.Sockets", "TcpClient", False, "GetStream", "", "", "ReturnValue", "remote", "manual"] + - ["System.Net.Sockets", "UpdClient", False, "EndReceive", "", "", "ReturnValue", "remote", "manual"] + - ["System.Net.Sockets", "UpdClient", False, "Receive", "", "", "ReturnValue", "remote", "manual"] + - ["System.Net.Sockets", "UpdClient", False, "ReceiveAsync", "", "", "ReturnValue", "remote", "manual"] diff --git a/csharp/ql/lib/ext/System.Net.model.yml b/csharp/ql/lib/ext/System.Net.model.yml index f59feb7c3cd..8e225805c93 100644 --- a/csharp/ql/lib/ext/System.Net.model.yml +++ b/csharp/ql/lib/ext/System.Net.model.yml @@ -1,15 +1,7 @@ extensions: - addsTo: pack: codeql/csharp-all - extensible: extSourceModel - data: - - ["System.Net.Sockets", "TcpClient", False, "GetStream", "", "", "ReturnValue", "remote", "manual"] - - ["System.Net.Sockets", "UpdClient", False, "EndReceive", "", "", "ReturnValue", "remote", "manual"] - - ["System.Net.Sockets", "UpdClient", False, "Receive", "", "", "ReturnValue", "remote", "manual"] - - ["System.Net.Sockets", "UpdClient", False, "ReceiveAsync", "", "", "ReturnValue", "remote", "manual"] - - addsTo: - pack: codeql/csharp-all - extensible: extSummaryModel + extensible: summaryModel data: - ["System.Net", "Cookie", False, "get_Value", "()", "", "Argument[this]", "ReturnValue", "taint", "manual"] - ["System.Net", "CookieCollection", False, "Add", "(System.Net.CookieCollection)", "", "Argument[0]", "Argument[this].Element", "value", "manual"] diff --git a/csharp/ql/lib/ext/System.Runtime.CompilerServices.model.yml b/csharp/ql/lib/ext/System.Runtime.CompilerServices.model.yml index 6ccf3138f02..bd28d9168fd 100644 --- a/csharp/ql/lib/ext/System.Runtime.CompilerServices.model.yml +++ b/csharp/ql/lib/ext/System.Runtime.CompilerServices.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/csharp-all - extensible: extSummaryModel + extensible: summaryModel data: - ["System.Runtime.CompilerServices", "ConditionalWeakTable<,>", False, "Clear", "()", "", "Argument[this].WithoutElement", "Argument[this]", "value", "manual"] - ["System.Runtime.CompilerServices", "ConfiguredTaskAwaitable<>", False, "GetAwaiter", "()", "", "Argument[this].SyntheticField[m_configuredTaskAwaiter]", "ReturnValue", "value", "manual"] diff --git a/csharp/ql/lib/ext/System.Security.Cryptography.X509Certificates.model.yml b/csharp/ql/lib/ext/System.Security.Cryptography.X509Certificates.model.yml index 04c27e61279..d15a5b94713 100644 --- a/csharp/ql/lib/ext/System.Security.Cryptography.X509Certificates.model.yml +++ b/csharp/ql/lib/ext/System.Security.Cryptography.X509Certificates.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/csharp-all - extensible: extSummaryModel + extensible: summaryModel data: - ["System.Security.Cryptography.X509Certificates", "X509Certificate2Collection", False, "Add", "(System.Security.Cryptography.X509Certificates.X509Certificate2)", "", "Argument[0]", "Argument[this].Element", "value", "manual"] - ["System.Security.Cryptography.X509Certificates", "X509Certificate2Collection", False, "AddRange", "(System.Security.Cryptography.X509Certificates.X509Certificate2Collection)", "", "Argument[0].Element", "Argument[this].Element", "value", "manual"] diff --git a/csharp/ql/lib/ext/System.Security.Cryptography.model.yml b/csharp/ql/lib/ext/System.Security.Cryptography.model.yml index 99027d1559b..1a3392074cf 100644 --- a/csharp/ql/lib/ext/System.Security.Cryptography.model.yml +++ b/csharp/ql/lib/ext/System.Security.Cryptography.model.yml @@ -1,14 +1,14 @@ extensions: - addsTo: pack: codeql/csharp-all - extensible: extSinkModel + extensible: sinkModel data: - ["System.Security.Cryptography", "SymmetricAlgorithm", True, "CreateDecryptor", "(System.Byte[],System.Byte[])", "", "Argument[0]", "encryption-decryptor", "manual"] - ["System.Security.Cryptography", "SymmetricAlgorithm", True, "CreateEncryptor", "(System.Byte[],System.Byte[])", "", "Argument[0]", "encryption-encryptor", "manual"] - ["System.Security.Cryptography", "SymmetricAlgorithm", True, "set_Key", "(System.Byte[])", "", "Argument[0]", "encryption-keyprop", "manual"] - addsTo: pack: codeql/csharp-all - extensible: extSummaryModel + extensible: summaryModel data: - ["System.Security.Cryptography", "AsnEncodedDataCollection", False, "Add", "(System.Security.Cryptography.AsnEncodedData)", "", "Argument[0]", "Argument[this].Element", "value", "manual"] - ["System.Security.Cryptography", "AsnEncodedDataCollection", False, "CopyTo", "(System.Security.Cryptography.AsnEncodedData[],System.Int32)", "", "Argument[this].Element", "Argument[0].Element", "value", "manual"] diff --git a/csharp/ql/lib/ext/System.Security.Permissions.model.yml b/csharp/ql/lib/ext/System.Security.Permissions.model.yml index 742901782b7..d5b9d6436db 100644 --- a/csharp/ql/lib/ext/System.Security.Permissions.model.yml +++ b/csharp/ql/lib/ext/System.Security.Permissions.model.yml @@ -1,6 +1,6 @@ extensions: - addsTo: pack: codeql/csharp-all - extensible: extSummaryModel + extensible: summaryModel data: - ["System.Security.Permissions", "KeyContainerPermissionAccessEntryCollection", False, "Clear", "()", "", "Argument[this].WithoutElement", "Argument[this]", "value", "manual"] diff --git a/csharp/ql/lib/ext/System.Security.Policy.model.yml b/csharp/ql/lib/ext/System.Security.Policy.model.yml index 4d93d0269a3..751aab19877 100644 --- a/csharp/ql/lib/ext/System.Security.Policy.model.yml +++ b/csharp/ql/lib/ext/System.Security.Policy.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/csharp-all - extensible: extSummaryModel + extensible: summaryModel data: - ["System.Security.Policy", "ApplicationTrustCollection", False, "Clear", "()", "", "Argument[this].WithoutElement", "Argument[this]", "value", "manual"] - ["System.Security.Policy", "Evidence", False, "Clear", "()", "", "Argument[this].WithoutElement", "Argument[this]", "value", "manual"] diff --git a/csharp/ql/lib/ext/System.Text.RegularExpressions.model.yml b/csharp/ql/lib/ext/System.Text.RegularExpressions.model.yml index 131bed81625..e3890031f9e 100644 --- a/csharp/ql/lib/ext/System.Text.RegularExpressions.model.yml +++ b/csharp/ql/lib/ext/System.Text.RegularExpressions.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/csharp-all - extensible: extSummaryModel + extensible: summaryModel data: - ["System.Text.RegularExpressions", "CaptureCollection", False, "get_Item", "(System.Int32)", "", "Argument[this].Element", "ReturnValue", "value", "manual"] - ["System.Text.RegularExpressions", "GroupCollection", False, "get_Item", "(System.Int32)", "", "Argument[this].Element", "ReturnValue", "value", "manual"] diff --git a/csharp/ql/lib/ext/System.Text.model.yml b/csharp/ql/lib/ext/System.Text.model.yml index 3aab1e14484..f21a34132bd 100644 --- a/csharp/ql/lib/ext/System.Text.model.yml +++ b/csharp/ql/lib/ext/System.Text.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/csharp-all - extensible: extSummaryModel + extensible: summaryModel data: - ["System.Text", "Encoding", True, "GetBytes", "(System.Char*,System.Int32,System.Byte*,System.Int32)", "", "Argument[0]", "ReturnValue", "taint", "manual"] - ["System.Text", "Encoding", True, "GetBytes", "(System.Char[])", "", "Argument[0].Element", "ReturnValue", "taint", "manual"] diff --git a/csharp/ql/lib/ext/System.Threading.Tasks.model.yml b/csharp/ql/lib/ext/System.Threading.Tasks.model.yml index 73fc8d1c149..efdd211ea21 100644 --- a/csharp/ql/lib/ext/System.Threading.Tasks.model.yml +++ b/csharp/ql/lib/ext/System.Threading.Tasks.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/csharp-all - extensible: extSummaryModel + extensible: summaryModel data: - ["System.Threading.Tasks", "Task", False, "ContinueWith", "(System.Action,System.Object)", "", "Argument[1]", "Argument[0].Parameter[1]", "value", "manual"] - ["System.Threading.Tasks", "Task", False, "ContinueWith", "(System.Action,System.Object,System.Threading.CancellationToken)", "", "Argument[1]", "Argument[0].Parameter[1]", "value", "manual"] diff --git a/csharp/ql/lib/ext/System.Web.UI.WebControls.model.yml b/csharp/ql/lib/ext/System.Web.UI.WebControls.model.yml index e73e563f31a..1c50d56d5cc 100644 --- a/csharp/ql/lib/ext/System.Web.UI.WebControls.model.yml +++ b/csharp/ql/lib/ext/System.Web.UI.WebControls.model.yml @@ -1,6 +1,6 @@ extensions: - addsTo: pack: codeql/csharp-all - extensible: extSummaryModel + extensible: summaryModel data: - ["System.Web.UI.WebControls", "TextBox", False, "get_Text", "()", "", "Argument[this]", "ReturnValue", "taint", "manual"] diff --git a/csharp/ql/lib/ext/System.Web.model.yml b/csharp/ql/lib/ext/System.Web.model.yml index 998070a6c64..5cf065ec6dd 100644 --- a/csharp/ql/lib/ext/System.Web.model.yml +++ b/csharp/ql/lib/ext/System.Web.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/csharp-all - extensible: extSinkModel + extensible: sinkModel data: - ["System.Web", "HttpResponse", False, "BinaryWrite", "", "", "Argument[0]", "html", "manual"] - ["System.Web", "HttpResponse", False, "TransmitFile", "", "", "Argument[0]", "html", "manual"] @@ -9,7 +9,7 @@ extensions: - ["System.Web", "HttpResponse", False, "WriteFile", "", "", "Argument[0]", "html", "manual"] - addsTo: pack: codeql/csharp-all - extensible: extSummaryModel + extensible: summaryModel data: - ["System.Web", "HttpCookie", False, "get_Value", "()", "", "Argument[this]", "ReturnValue", "taint", "manual"] - ["System.Web", "HttpCookie", False, "get_Values", "()", "", "Argument[this]", "ReturnValue", "taint", "manual"] diff --git a/csharp/ql/lib/ext/System.Xml.Schema.model.yml b/csharp/ql/lib/ext/System.Xml.Schema.model.yml index 6c2c62f8b35..6666d4bf24c 100644 --- a/csharp/ql/lib/ext/System.Xml.Schema.model.yml +++ b/csharp/ql/lib/ext/System.Xml.Schema.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/csharp-all - extensible: extSummaryModel + extensible: summaryModel data: - ["System.Xml.Schema", "XmlSchemaCollection", False, "Add", "(System.Xml.Schema.XmlSchema)", "", "Argument[0]", "Argument[this].Element", "value", "manual"] - ["System.Xml.Schema", "XmlSchemaCollection", False, "Add", "(System.Xml.Schema.XmlSchemaCollection)", "", "Argument[0]", "Argument[this].Element", "value", "manual"] diff --git a/csharp/ql/lib/ext/System.Xml.Serialization.model.yml b/csharp/ql/lib/ext/System.Xml.Serialization.model.yml index 7dfad76ea35..c506aa4c665 100644 --- a/csharp/ql/lib/ext/System.Xml.Serialization.model.yml +++ b/csharp/ql/lib/ext/System.Xml.Serialization.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/csharp-all - extensible: extSummaryModel + extensible: summaryModel data: - ["System.Xml.Serialization", "XmlAnyElementAttributes", False, "Add", "(System.Xml.Serialization.XmlAnyElementAttribute)", "", "Argument[0]", "Argument[this].Element", "value", "manual"] - ["System.Xml.Serialization", "XmlAnyElementAttributes", False, "CopyTo", "(System.Xml.Serialization.XmlAnyElementAttribute[],System.Int32)", "", "Argument[this].Element", "Argument[0].Element", "value", "manual"] diff --git a/csharp/ql/lib/ext/System.Xml.model.yml b/csharp/ql/lib/ext/System.Xml.model.yml index c2c6ab13517..55825304a14 100644 --- a/csharp/ql/lib/ext/System.Xml.model.yml +++ b/csharp/ql/lib/ext/System.Xml.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/csharp-all - extensible: extSummaryModel + extensible: summaryModel data: - ["System.Xml", "XmlAttributeCollection", False, "CopyTo", "(System.Xml.XmlAttribute[],System.Int32)", "", "Argument[this].Element", "Argument[0].Element", "value", "manual"] - ["System.Xml", "XmlDocument", False, "Load", "(System.IO.Stream)", "", "Argument[0]", "Argument[this]", "taint", "manual"] diff --git a/csharp/ql/lib/ext/System.model.yml b/csharp/ql/lib/ext/System.model.yml index 8693948d3de..b0f74507b87 100644 --- a/csharp/ql/lib/ext/System.model.yml +++ b/csharp/ql/lib/ext/System.model.yml @@ -1,14 +1,14 @@ extensions: - addsTo: pack: codeql/csharp-all - extensible: extSourceModel + extensible: sourceModel data: - ["System", "Console", False, "Read", "", "", "ReturnValue", "local", "manual"] - ["System", "Console", False, "ReadKey", "", "", "ReturnValue", "local", "manual"] - ["System", "Console", False, "ReadLine", "", "", "ReturnValue", "local", "manual"] - addsTo: pack: codeql/csharp-all - extensible: extSummaryModel + extensible: summaryModel data: - ["System", "Array", False, "AsReadOnly<>", "(T[])", "", "Argument[0].Element", "ReturnValue.Element", "value", "manual"] - ["System", "Array", False, "Clear", "(System.Array)", "", "Argument[0].WithoutElement", "Argument[0]", "value", "manual"] diff --git a/csharp/ql/lib/ext/Windows.Security.Cryptography.Core.model.yml b/csharp/ql/lib/ext/Windows.Security.Cryptography.Core.model.yml index de9953ea8ef..094826380b4 100644 --- a/csharp/ql/lib/ext/Windows.Security.Cryptography.Core.model.yml +++ b/csharp/ql/lib/ext/Windows.Security.Cryptography.Core.model.yml @@ -1,6 +1,6 @@ extensions: - addsTo: pack: codeql/csharp-all - extensible: extSinkModel + extensible: sinkModel data: - ["Windows.Security.Cryptography.Core", "SymmetricKeyAlgorithmProvider", False, "CreateSymmetricKey", "(Windows.Storage.Streams.IBuffer)", "", "Argument[0]", "encryption-symmetrickey", "manual"] diff --git a/csharp/ql/lib/ext/generated/dotnet_runtime.model.yml b/csharp/ql/lib/ext/generated/dotnet_runtime.model.yml index 1bf56eecf70..f2c4ea2cb29 100644 --- a/csharp/ql/lib/ext/generated/dotnet_runtime.model.yml +++ b/csharp/ql/lib/ext/generated/dotnet_runtime.model.yml @@ -5,7 +5,7 @@ extensions: - addsTo: pack: codeql/csharp-all - extensible: extSinkModel + extensible: sinkModel data: - ["System.Data.Odbc", "OdbcDataAdapter", false, "OdbcDataAdapter", "(System.String,System.Data.Odbc.OdbcConnection)", "", "Argument[0]", "sql", "generated"] - ["System.Data.Odbc", "OdbcDataAdapter", false, "OdbcDataAdapter", "(System.String,System.String)", "", "Argument[0]", "sql", "generated"] @@ -39,7 +39,7 @@ extensions: - addsTo: pack: codeql/csharp-all - extensible: extSummaryModel + extensible: summaryModel data: - ["JsonToItemsTaskFactory", "JsonToItemsTaskFactory+CaseInsensitiveDictionaryConverter", false, "Read", "(System.Text.Json.Utf8JsonReader,System.Type,System.Text.Json.JsonSerializerOptions)", "", "Argument[0]", "ReturnValue", "taint", "generated"] - ["JsonToItemsTaskFactory", "JsonToItemsTaskFactory+JsonModelItemConverter", false, "Read", "(System.Text.Json.Utf8JsonReader,System.Type,System.Text.Json.JsonSerializerOptions)", "", "Argument[0]", "ReturnValue", "taint", "generated"] @@ -10195,7 +10195,7 @@ extensions: - addsTo: pack: codeql/csharp-all - extensible: extNeutralModel + extensible: neutralModel data: - ["AssemblyStripper", "AssemblyStripper", "StripAssembly", "(System.String,System.String)", "generated"] - ["Generators", "EventSourceGenerator", "Execute", "(Microsoft.CodeAnalysis.GeneratorExecutionContext)", "generated"] diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/ExternalFlow.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/ExternalFlow.qll index 38517cc21da..dda86ebcd91 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/ExternalFlow.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/ExternalFlow.qll @@ -82,6 +82,7 @@ */ import csharp +private import ExternalFlowExtensions as Extensions private import internal.AccessPathSyntax private import internal.DataFlowDispatch private import internal.DataFlowPrivate @@ -138,14 +139,6 @@ private predicate summaryModelInternal(string row) { any(SummaryModelCsvInternal private predicate sinkModelInternal(string row) { any(SinkModelCsvInternal s).row(row) } -/** - * Holds if a source model exists for the given parameters. - */ -extensible predicate extSourceModel( - string namespace, string type, boolean subtypes, string name, string signature, string ext, - string output, string kind, string provenance -); - /** Holds if a source model exists for the given parameters. */ predicate sourceModel( string namespace, string type, boolean subtypes, string name, string signature, string ext, @@ -165,15 +158,9 @@ predicate sourceModel( row.splitAt(";", 8) = provenance ) or - extSourceModel(namespace, type, subtypes, name, signature, ext, output, kind, provenance) + Extensions::sourceModel(namespace, type, subtypes, name, signature, ext, output, kind, provenance) } -/** Holds if a sink model exists for the given parameters. */ -extensible predicate extSinkModel( - string namespace, string type, boolean subtypes, string name, string signature, string ext, - string input, string kind, string provenance -); - /** Holds if a sink model exists for the given parameters. */ predicate sinkModel( string namespace, string type, boolean subtypes, string name, string signature, string ext, @@ -193,15 +180,9 @@ predicate sinkModel( row.splitAt(";", 8) = provenance ) or - extSinkModel(namespace, type, subtypes, name, signature, ext, input, kind, provenance) + Extensions::sinkModel(namespace, type, subtypes, name, signature, ext, input, kind, provenance) } -/** Holds if a summary model exists for the given parameters. */ -extensible predicate extSummaryModel( - string namespace, string type, boolean subtypes, string name, string signature, string ext, - string input, string output, string kind, string provenance -); - /** Holds if a summary model exists for the given parameters. */ predicate summaryModel( string namespace, string type, boolean subtypes, string name, string signature, string ext, @@ -222,20 +203,12 @@ predicate summaryModel( row.splitAt(";", 9) = provenance ) or - extSummaryModel(namespace, type, subtypes, name, signature, ext, input, output, kind, provenance) + Extensions::summaryModel(namespace, type, subtypes, name, signature, ext, input, output, kind, + provenance) } /** Holds if a model exists indicating there is no flow for the given parameters. */ -extensible predicate extNeutralModel( - string namespace, string type, string name, string signature, string provenance -); - -/** Holds if a model exists indicating there is no flow for the given parameters. */ -predicate neutralModel( - string namespace, string type, string name, string signature, string provenance -) { - extNeutralModel(namespace, type, name, signature, provenance) -} +predicate neutralModel = Extensions::neutralModel/5; private predicate relevantNamespace(string namespace) { sourceModel(namespace, _, _, _, _, _, _, _, _) or diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/ExternalFlowExtensions.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/ExternalFlowExtensions.qll new file mode 100644 index 00000000000..aab3d67e620 --- /dev/null +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/ExternalFlowExtensions.qll @@ -0,0 +1,34 @@ +/** + * This module provides extensible predicates for defining MaD models. + */ + +/** + * Holds if a source model exists for the given parameters. + */ +extensible predicate sourceModel( + string namespace, string type, boolean subtypes, string name, string signature, string ext, + string output, string kind, string provenance +); + +/** + * Holds if a sink model exists for the given parameters. + */ +extensible predicate sinkModel( + string namespace, string type, boolean subtypes, string name, string signature, string ext, + string input, string kind, string provenance +); + +/** + * Holds if a summary model exists for the given parameters. + */ +extensible predicate summaryModel( + string namespace, string type, boolean subtypes, string name, string signature, string ext, + string input, string output, string kind, string provenance +); + +/** + * Holds if a model exists indicating there is no flow for the given parameters. + */ +extensible predicate neutralModel( + string namespace, string type, string name, string signature, string provenance +); 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 6741ccc2f06..1228d00b6ba 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl.qll @@ -622,7 +622,11 @@ private predicate parameterFlowThroughAllowed(ParamNodeEx p, ReturnKindExt kind) } private module Stage1 implements StageSig { - class Ap = Unit; + class Ap extends int { + // workaround for bad functionality-induced joins (happens when using `Unit`) + pragma[nomagic] + Ap() { this in [0 .. 1] and this < 1 } + } private class Cc = boolean; @@ -1327,8 +1331,8 @@ private module MkStage { */ pragma[nomagic] additional predicate fwdFlow( - NodeEx node, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - Ap ap, ApApprox apa, Configuration config + NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, + ApApprox apa, Configuration config ) { fwdFlow0(node, state, cc, summaryCtx, argAp, ap, apa, config) and PrevStage::revFlow(node, state, apa, config) and @@ -1337,21 +1341,21 @@ private module MkStage { pragma[inline] additional predicate fwdFlow( - NodeEx node, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - Ap ap, Configuration config + NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, + Configuration config ) { fwdFlow(node, state, cc, summaryCtx, argAp, ap, _, config) } pragma[nomagic] private predicate fwdFlow0( - NodeEx node, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - Ap ap, ApApprox apa, Configuration config + NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, + ApApprox apa, Configuration config ) { sourceNode(node, state, config) and (if hasSourceCallCtx(config) then cc = ccSomeCall() else cc = ccNone()) and argAp = apNone() and - summaryCtx = TParameterPositionNone() and + summaryCtx = TParamNodeNone() and ap = getApNil(node) and apa = getApprox(ap) or @@ -1372,7 +1376,7 @@ private module MkStage { fwdFlow(mid, pragma[only_bind_into](state), _, _, _, ap, apa, pragma[only_bind_into](config)) and jumpStep(mid, node, config) and cc = ccNone() and - summaryCtx = TParameterPositionNone() and + summaryCtx = TParamNodeNone() and argAp = apNone() ) or @@ -1380,7 +1384,7 @@ private module MkStage { fwdFlow(mid, state, _, _, _, nil, pragma[only_bind_into](config)) and additionalJumpStep(mid, node, config) and cc = ccNone() and - summaryCtx = TParameterPositionNone() and + summaryCtx = TParamNodeNone() and argAp = apNone() and ap = getApNil(node) and apa = getApprox(ap) @@ -1390,7 +1394,7 @@ private module MkStage { fwdFlow(mid, state0, _, _, _, nil, pragma[only_bind_into](config)) and additionalJumpStateStep(mid, state0, node, state, config) and cc = ccNone() and - summaryCtx = TParameterPositionNone() and + summaryCtx = TParamNodeNone() and argAp = apNone() and ap = getApNil(node) and apa = getApprox(ap) @@ -1414,10 +1418,10 @@ private module MkStage { fwdFlowIn(_, node, state, _, cc, _, _, ap, apa, config) and if PrevStage::parameterMayFlowThrough(node, apa, config) then ( - summaryCtx = TParameterPositionSome(node.(ParamNodeEx).getPosition()) and + summaryCtx = TParamNodeSome(node.asNode()) and argAp = apSome(ap) ) else ( - summaryCtx = TParameterPositionNone() and argAp = apNone() + summaryCtx = TParamNodeNone() and argAp = apNone() ) or // flow out of a callable @@ -1433,16 +1437,19 @@ private module MkStage { ) or // flow through a callable - exists(DataFlowCall call, ParameterPosition summaryCtx0, Ap argAp0 | - fwdFlowOutFromArg(call, node, state, summaryCtx0, argAp0, ap, apa, config) and - fwdFlowIsEntered(call, cc, summaryCtx, argAp, summaryCtx0, argAp0, config) + exists( + DataFlowCall call, CcCall ccc, RetNodeEx ret, boolean allowsFieldFlow, ApApprox innerArgApa + | + fwdFlowThrough(call, cc, state, ccc, summaryCtx, argAp, ap, apa, ret, innerArgApa, config) and + flowThroughOutOfCall(call, ccc, ret, node, allowsFieldFlow, innerArgApa, apa, config) and + if allowsFieldFlow = false then ap instanceof ApNil else any() ) } pragma[nomagic] private predicate fwdFlowStore( NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, FlowState state, Cc cc, - ParameterPositionOption summaryCtx, ApOption argAp, Configuration config + ParamNodeOption summaryCtx, ApOption argAp, Configuration config ) { exists(DataFlowType contentType, ApApprox apa1 | fwdFlow(node1, state, cc, summaryCtx, argAp, ap1, apa1, config) and @@ -1473,8 +1480,8 @@ private module MkStage { pragma[nomagic] private predicate fwdFlowRead0( - NodeEx node1, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - ApNonNil ap, Configuration config + NodeEx node1, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, ApNonNil ap, + Configuration config ) { fwdFlow(node1, state, cc, summaryCtx, argAp, ap, config) and PrevStage::readStepCand(node1, _, _, config) @@ -1483,7 +1490,7 @@ private module MkStage { pragma[nomagic] private predicate fwdFlowRead( Ap ap, Content c, NodeEx node1, NodeEx node2, FlowState state, Cc cc, - ParameterPositionOption summaryCtx, ApOption argAp, Configuration config + ParamNodeOption summaryCtx, ApOption argAp, Configuration config ) { fwdFlowRead0(node1, state, cc, summaryCtx, argAp, ap, config) and PrevStage::readStepCand(node1, c, node2, config) and @@ -1493,7 +1500,7 @@ private module MkStage { pragma[nomagic] private predicate fwdFlowIn( DataFlowCall call, ParamNodeEx p, FlowState state, Cc outercc, CcCall innercc, - ParameterPositionOption summaryCtx, ApOption argAp, Ap ap, ApApprox apa, Configuration config + ParamNodeOption summaryCtx, ApOption argAp, Ap ap, ApApprox apa, Configuration config ) { exists(ArgNodeEx arg, boolean allowsFieldFlow | fwdFlow(arg, state, outercc, summaryCtx, argAp, ap, apa, config) and @@ -1505,64 +1512,38 @@ private module MkStage { pragma[nomagic] private predicate fwdFlowRetFromArg( - RetNodeEx ret, FlowState state, CcCall ccc, ParameterPosition summaryCtx, ParamNodeEx p, - Ap argAp, ApApprox argApa, Ap ap, ApApprox apa, Configuration config + RetNodeEx ret, FlowState state, CcCall ccc, ParamNodeEx summaryCtx, Ap argAp, ApApprox argApa, + Ap ap, ApApprox apa, Configuration config ) { - exists(DataFlowCallable c, ReturnKindExt kind | + exists(ReturnKindExt kind | fwdFlow(pragma[only_bind_into](ret), state, ccc, - TParameterPositionSome(pragma[only_bind_into](summaryCtx)), apSome(argAp), ap, apa, config) and - getApprox(argAp) = argApa and - c = ret.getEnclosingCallable() and + TParamNodeSome(pragma[only_bind_into](summaryCtx.asNode())), + pragma[only_bind_into](apSome(argAp)), ap, pragma[only_bind_into](apa), + pragma[only_bind_into](config)) and kind = ret.getKind() and - p.isParameterOf(c, pragma[only_bind_into](summaryCtx)) and - parameterFlowThroughAllowed(p, kind) + parameterFlowThroughAllowed(summaryCtx, kind) and + argApa = getApprox(argAp) and + PrevStage::returnMayFlowThrough(ret, argApa, apa, kind, pragma[only_bind_into](config)) ) } pragma[inline] - private predicate fwdFlowInMayFlowThrough( - DataFlowCall call, Cc cc, CcCall innerCc, ParameterPositionOption summaryCtx, ApOption argAp, - ParamNodeEx param, Ap ap, ApApprox apa, Configuration config + private predicate fwdFlowThrough0( + DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, + ApOption argAp, Ap ap, ApApprox apa, RetNodeEx ret, ParamNodeEx innerSummaryCtx, + Ap innerArgAp, ApApprox innerArgApa, Configuration config ) { - fwdFlowIn(call, pragma[only_bind_into](param), _, cc, innerCc, summaryCtx, argAp, ap, - pragma[only_bind_into](apa), pragma[only_bind_into](config)) and - PrevStage::parameterMayFlowThrough(param, apa, config) - } - - // dedup before joining with `flowThroughOutOfCall` - pragma[nomagic] - private predicate fwdFlowInMayFlowThroughProj( - DataFlowCall call, CcCall innerCc, ApApprox apa, Configuration config - ) { - fwdFlowInMayFlowThrough(call, _, innerCc, _, _, _, _, apa, config) - } - - /** - * Same as `flowThroughOutOfCall`, but restricted to calls that are reached - * in the flow covered by `fwdFlow`, where data might flow through the target - * callable and back out at `call`. - */ - pragma[nomagic] - private predicate fwdFlowThroughOutOfCall( - DataFlowCall call, CcCall ccc, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow, - ApApprox argApa, ApApprox apa, Configuration config - ) { - fwdFlowInMayFlowThroughProj(call, ccc, argApa, config) and - flowThroughOutOfCall(call, ccc, ret, out, allowsFieldFlow, argApa, apa, config) + fwdFlowRetFromArg(ret, state, ccc, innerSummaryCtx, innerArgAp, innerArgApa, ap, apa, config) and + fwdFlowIsEntered(call, cc, ccc, summaryCtx, argAp, innerSummaryCtx, innerArgAp, config) } pragma[nomagic] - private predicate fwdFlowOutFromArg( - DataFlowCall call, NodeEx out, FlowState state, ParameterPosition summaryCtx, Ap argAp, Ap ap, - ApApprox apa, Configuration config + private predicate fwdFlowThrough( + DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, + ApOption argAp, Ap ap, ApApprox apa, RetNodeEx ret, ApApprox innerArgApa, Configuration config ) { - exists(RetNodeEx ret, boolean allowsFieldFlow, CcCall ccc, ApApprox argApa | - fwdFlowRetFromArg(pragma[only_bind_into](ret), state, pragma[only_bind_into](ccc), - summaryCtx, _, argAp, pragma[only_bind_into](argApa), ap, pragma[only_bind_into](apa), - config) and - fwdFlowThroughOutOfCall(call, ccc, ret, out, allowsFieldFlow, argApa, apa, config) and - (if allowsFieldFlow = false then ap instanceof ApNil else any()) - ) + fwdFlowThrough0(call, cc, state, ccc, summaryCtx, argAp, ap, apa, ret, _, _, innerArgApa, + config) } /** @@ -1571,12 +1552,14 @@ private module MkStage { */ pragma[nomagic] private predicate fwdFlowIsEntered( - DataFlowCall call, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - ParameterPosition pos, Ap ap, Configuration config + DataFlowCall call, Cc cc, CcCall innerCc, ParamNodeOption summaryCtx, ApOption argAp, + ParamNodeEx p, Ap ap, Configuration config ) { - exists(ParamNodeEx param | - fwdFlowInMayFlowThrough(call, cc, _, summaryCtx, argAp, param, ap, _, config) and - pos = param.getPosition() + exists(ApApprox apa | + fwdFlowIn(call, pragma[only_bind_into](p), _, cc, innerCc, summaryCtx, argAp, ap, + pragma[only_bind_into](apa), pragma[only_bind_into](config)) and + PrevStage::parameterMayFlowThrough(p, apa, config) and + PrevStage::callMayFlowThroughRev(call, pragma[only_bind_into](config)) ) } @@ -1596,23 +1579,31 @@ private module MkStage { fwdFlowConsCand(ap1, c, ap2, config) } + pragma[nomagic] + private predicate returnFlowsThrough0( + DataFlowCall call, FlowState state, CcCall ccc, Ap ap, ApApprox apa, RetNodeEx ret, + ParamNodeEx innerSummaryCtx, Ap innerArgAp, ApApprox innerArgApa, Configuration config + ) { + fwdFlowThrough0(call, _, state, ccc, _, _, ap, apa, ret, innerSummaryCtx, innerArgAp, + innerArgApa, config) + } + pragma[nomagic] private predicate returnFlowsThrough( - RetNodeEx ret, ReturnKindExt kind, FlowState state, CcCall ccc, ParamNodeEx p, Ap argAp, + RetNodeEx ret, ReturnPosition pos, FlowState state, CcCall ccc, ParamNodeEx p, Ap argAp, Ap ap, Configuration config ) { - exists(boolean allowsFieldFlow, ApApprox argApa, ApApprox apa | - fwdFlowRetFromArg(pragma[only_bind_into](ret), state, pragma[only_bind_into](ccc), _, p, - argAp, pragma[only_bind_into](argApa), ap, pragma[only_bind_into](apa), config) and - kind = ret.getKind() and - fwdFlowThroughOutOfCall(_, ccc, ret, _, allowsFieldFlow, argApa, apa, config) and - (if allowsFieldFlow = false then ap instanceof ApNil else any()) + exists(DataFlowCall call, ApApprox apa, boolean allowsFieldFlow, ApApprox innerArgApa | + returnFlowsThrough0(call, state, ccc, ap, apa, ret, p, argAp, innerArgApa, config) and + flowThroughOutOfCall(call, ccc, ret, _, allowsFieldFlow, innerArgApa, apa, config) and + pos = ret.getReturnPosition() and + if allowsFieldFlow = false then ap instanceof ApNil else any() ) } pragma[nomagic] private predicate flowThroughIntoCall( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap argAp, + DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap argAp, Ap ap, Configuration config ) { exists(ApApprox argApa | @@ -1620,7 +1611,7 @@ private module MkStage { allowsFieldFlow, argApa, pragma[only_bind_into](config)) and fwdFlow(arg, _, _, _, _, pragma[only_bind_into](argAp), argApa, pragma[only_bind_into](config)) and - returnFlowsThrough(_, _, _, _, p, pragma[only_bind_into](argAp), _, + returnFlowsThrough(_, _, _, _, p, pragma[only_bind_into](argAp), ap, pragma[only_bind_into](config)) and if allowsFieldFlow = false then argAp instanceof ApNil else any() ) @@ -1639,12 +1630,13 @@ private module MkStage { pragma[nomagic] private predicate flowOutOfCallAp( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, boolean allowsFieldFlow, + DataFlowCall call, RetNodeEx ret, ReturnPosition pos, NodeEx out, boolean allowsFieldFlow, Ap ap, Configuration config ) { exists(ApApprox apa | - flowOutOfCallApa(call, ret, kind, out, allowsFieldFlow, apa, config) and - fwdFlow(ret, _, _, _, _, ap, apa, config) + flowOutOfCallApa(call, ret, _, out, allowsFieldFlow, apa, config) and + fwdFlow(ret, _, _, _, _, ap, apa, config) and + pos = ret.getReturnPosition() ) } @@ -1739,17 +1731,17 @@ private module MkStage { ) or // flow through a callable - exists(DataFlowCall call, ReturnKindExt returnKind0, Ap returnAp0 | - revFlowInToReturn(call, node, state, returnKind0, returnAp0, ap, config) and - revFlowIsReturned(call, returnCtx, returnAp, returnKind0, returnAp0, config) + exists(DataFlowCall call, ParamNodeEx p, ReturnPosition pos, Ap innerReturnAp | + revFlowThrough(call, returnCtx, p, state, pos, returnAp, ap, innerReturnAp, config) and + flowThroughIntoCall(call, node, p, _, ap, innerReturnAp, config) ) or // flow out of a callable - exists(ReturnKindExt kind | - revFlowOut(_, node, kind, state, _, _, ap, config) and - if returnFlowsThrough(node, kind, state, _, _, _, ap, config) + exists(ReturnPosition pos | + revFlowOut(_, node, pos, state, _, _, ap, config) and + if returnFlowsThrough(node, pos, state, _, _, _, ap, config) then ( - returnCtx = TReturnCtxMaybeFlowThrough(kind) and + returnCtx = TReturnCtxMaybeFlowThrough(pos) and returnAp = apSome(ap) ) else ( returnCtx = TReturnCtxNoFlowThrough() and returnAp = apNone() @@ -1782,47 +1774,33 @@ private module MkStage { pragma[nomagic] private predicate revFlowOut( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, FlowState state, ReturnCtx returnCtx, + DataFlowCall call, RetNodeEx ret, ReturnPosition pos, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap, Configuration config ) { exists(NodeEx out, boolean allowsFieldFlow | revFlow(out, state, returnCtx, returnAp, ap, config) and - flowOutOfCallAp(call, ret, kind, out, allowsFieldFlow, ap, config) and + flowOutOfCallAp(call, ret, pos, out, allowsFieldFlow, ap, config) and if allowsFieldFlow = false then ap instanceof ApNil else any() ) } - /** - * Same as `flowThroughIntoCall`, but restricted to calls that are reached - * in the flow covered by `revFlow`, where data might flow through the target - * callable and back out at `call`. - */ - pragma[nomagic] - private predicate revFlowThroughIntoCall( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap argAp, - Configuration config - ) { - flowThroughIntoCall(call, arg, p, allowsFieldFlow, argAp, config) and - revFlowIsReturned(call, _, _, _, _, config) - } - pragma[nomagic] private predicate revFlowParamToReturn( - ParamNodeEx p, FlowState state, ReturnKindExt kind, Ap returnAp, Ap ap, Configuration config + ParamNodeEx p, FlowState state, ReturnPosition pos, Ap returnAp, Ap ap, Configuration config ) { - revFlow(p, state, TReturnCtxMaybeFlowThrough(kind), apSome(returnAp), ap, config) and - parameterFlowThroughAllowed(p, kind) + revFlow(pragma[only_bind_into](p), state, TReturnCtxMaybeFlowThrough(pos), apSome(returnAp), + pragma[only_bind_into](ap), pragma[only_bind_into](config)) and + parameterFlowThroughAllowed(p, pos.getKind()) and + PrevStage::parameterMayFlowThrough(p, getApprox(ap), config) } pragma[nomagic] - private predicate revFlowInToReturn( - DataFlowCall call, ArgNodeEx arg, FlowState state, ReturnKindExt kind, Ap returnAp, Ap ap, - Configuration config + private predicate revFlowThrough( + DataFlowCall call, ReturnCtx returnCtx, ParamNodeEx p, FlowState state, ReturnPosition pos, + ApOption returnAp, Ap ap, Ap innerReturnAp, Configuration config ) { - exists(ParamNodeEx p, boolean allowsFieldFlow | - revFlowParamToReturn(p, state, kind, returnAp, ap, config) and - revFlowThroughIntoCall(call, arg, p, allowsFieldFlow, ap, config) - ) + revFlowParamToReturn(p, state, pos, innerReturnAp, ap, config) and + revFlowIsReturned(call, returnCtx, returnAp, pos, innerReturnAp, config) } /** @@ -1832,12 +1810,12 @@ private module MkStage { */ pragma[nomagic] private predicate revFlowIsReturned( - DataFlowCall call, ReturnCtx returnCtx, ApOption returnAp, ReturnKindExt kind, Ap ap, + DataFlowCall call, ReturnCtx returnCtx, ApOption returnAp, ReturnPosition pos, Ap ap, Configuration config ) { exists(RetNodeEx ret, FlowState state, CcCall ccc | - revFlowOut(call, ret, kind, state, returnCtx, returnAp, ap, config) and - returnFlowsThrough(ret, kind, state, ccc, _, _, ap, config) and + revFlowOut(call, ret, pos, state, returnCtx, returnAp, ap, config) and + returnFlowsThrough(ret, pos, state, ccc, _, _, ap, config) and matchesCall(ccc, call) ) } @@ -1915,17 +1893,17 @@ private module MkStage { pragma[nomagic] private predicate parameterFlowsThroughRev( - ParamNodeEx p, Ap ap, ReturnKindExt kind, Ap returnAp, Configuration config + ParamNodeEx p, Ap ap, ReturnPosition pos, Ap returnAp, Configuration config ) { - revFlow(p, _, TReturnCtxMaybeFlowThrough(kind), apSome(returnAp), ap, config) and - parameterFlowThroughAllowed(p, kind) + revFlow(p, _, TReturnCtxMaybeFlowThrough(pos), apSome(returnAp), ap, config) and + parameterFlowThroughAllowed(p, pos.getKind()) } pragma[nomagic] predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap, Configuration config) { - exists(RetNodeEx ret, ReturnKindExt kind | - returnFlowsThrough(ret, kind, _, _, p, ap, _, config) and - parameterFlowsThroughRev(p, ap, kind, _, config) + exists(RetNodeEx ret, ReturnPosition pos | + returnFlowsThrough(ret, pos, _, _, p, ap, _, config) and + parameterFlowsThroughRev(p, ap, pos, _, config) ) } @@ -1933,20 +1911,21 @@ private module MkStage { predicate returnMayFlowThrough( RetNodeEx ret, Ap argAp, Ap ap, ReturnKindExt kind, Configuration config ) { - exists(ParamNodeEx p | - returnFlowsThrough(ret, kind, _, _, p, argAp, ap, config) and - parameterFlowsThroughRev(p, argAp, kind, ap, config) + exists(ParamNodeEx p, ReturnPosition pos | + returnFlowsThrough(ret, pos, _, _, p, argAp, ap, config) and + parameterFlowsThroughRev(p, argAp, pos, ap, config) and + kind = pos.getKind() ) } pragma[nomagic] - predicate revFlowInToReturnIsReturned( + private predicate revFlowThroughArg( DataFlowCall call, ArgNodeEx arg, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap, Configuration config ) { - exists(ReturnKindExt returnKind0, Ap returnAp0 | - revFlowInToReturn(call, arg, state, returnKind0, returnAp0, ap, config) and - revFlowIsReturned(call, returnCtx, returnAp, returnKind0, returnAp0, config) + exists(ParamNodeEx p, ReturnPosition pos, Ap innerReturnAp | + revFlowThrough(call, returnCtx, p, state, pos, returnAp, ap, innerReturnAp, config) and + flowThroughIntoCall(call, arg, p, _, ap, innerReturnAp, config) ) } @@ -1954,7 +1933,7 @@ private module MkStage { predicate callMayFlowThroughRev(DataFlowCall call, Configuration config) { exists(ArgNodeEx arg, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap | revFlow(arg, state, returnCtx, returnAp, ap, config) and - revFlowInToReturnIsReturned(call, arg, state, returnCtx, returnAp, ap, config) + revFlowThroughArg(call, arg, state, returnCtx, returnAp, ap, config) ) } @@ -1967,8 +1946,9 @@ private module MkStage { conscand = count(TypedContent f0, Ap ap | fwdConsCand(f0, ap, config)) and states = count(FlowState state | fwdFlow(_, state, _, _, _, _, config)) and tuples = - count(NodeEx n, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - Ap ap | fwdFlow(n, state, cc, summaryCtx, argAp, ap, config)) + count(NodeEx n, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap | + fwdFlow(n, state, cc, summaryCtx, argAp, ap, config) + ) or fwd = false and nodes = count(NodeEx node | revFlow(node, _, _, _, _, config)) and @@ -2823,13 +2803,12 @@ private Configuration unbindConf(Configuration conf) { pragma[nomagic] private predicate nodeMayUseSummary0( - NodeEx n, DataFlowCallable c, ParameterPosition pos, FlowState state, AccessPathApprox apa, - Configuration config + NodeEx n, ParamNodeEx p, FlowState state, AccessPathApprox apa, Configuration config ) { exists(AccessPathApprox apa0 | - c = n.getEnclosingCallable() and + Stage5::parameterMayFlowThrough(p, _, _) and Stage5::revFlow(n, state, TReturnCtxMaybeFlowThrough(_), _, apa0, config) and - Stage5::fwdFlow(n, state, any(CallContextCall ccc), TParameterPositionSome(pos), + Stage5::fwdFlow(n, state, any(CallContextCall ccc), TParamNodeSome(p.asNode()), TAccessPathApproxSome(apa), apa0, config) ) } @@ -2838,10 +2817,9 @@ pragma[nomagic] private predicate nodeMayUseSummary( NodeEx n, FlowState state, AccessPathApprox apa, Configuration config ) { - exists(DataFlowCallable c, ParameterPosition pos, ParamNodeEx p | + exists(ParamNodeEx p | Stage5::parameterMayFlowThrough(p, apa, config) and - nodeMayUseSummary0(n, c, pos, state, apa, config) and - p.isParameterOf(c, pos) + nodeMayUseSummary0(n, p, state, apa, config) ) } diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl2.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl2.qll index 6741ccc2f06..1228d00b6ba 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl2.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl2.qll @@ -622,7 +622,11 @@ private predicate parameterFlowThroughAllowed(ParamNodeEx p, ReturnKindExt kind) } private module Stage1 implements StageSig { - class Ap = Unit; + class Ap extends int { + // workaround for bad functionality-induced joins (happens when using `Unit`) + pragma[nomagic] + Ap() { this in [0 .. 1] and this < 1 } + } private class Cc = boolean; @@ -1327,8 +1331,8 @@ private module MkStage { */ pragma[nomagic] additional predicate fwdFlow( - NodeEx node, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - Ap ap, ApApprox apa, Configuration config + NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, + ApApprox apa, Configuration config ) { fwdFlow0(node, state, cc, summaryCtx, argAp, ap, apa, config) and PrevStage::revFlow(node, state, apa, config) and @@ -1337,21 +1341,21 @@ private module MkStage { pragma[inline] additional predicate fwdFlow( - NodeEx node, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - Ap ap, Configuration config + NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, + Configuration config ) { fwdFlow(node, state, cc, summaryCtx, argAp, ap, _, config) } pragma[nomagic] private predicate fwdFlow0( - NodeEx node, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - Ap ap, ApApprox apa, Configuration config + NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, + ApApprox apa, Configuration config ) { sourceNode(node, state, config) and (if hasSourceCallCtx(config) then cc = ccSomeCall() else cc = ccNone()) and argAp = apNone() and - summaryCtx = TParameterPositionNone() and + summaryCtx = TParamNodeNone() and ap = getApNil(node) and apa = getApprox(ap) or @@ -1372,7 +1376,7 @@ private module MkStage { fwdFlow(mid, pragma[only_bind_into](state), _, _, _, ap, apa, pragma[only_bind_into](config)) and jumpStep(mid, node, config) and cc = ccNone() and - summaryCtx = TParameterPositionNone() and + summaryCtx = TParamNodeNone() and argAp = apNone() ) or @@ -1380,7 +1384,7 @@ private module MkStage { fwdFlow(mid, state, _, _, _, nil, pragma[only_bind_into](config)) and additionalJumpStep(mid, node, config) and cc = ccNone() and - summaryCtx = TParameterPositionNone() and + summaryCtx = TParamNodeNone() and argAp = apNone() and ap = getApNil(node) and apa = getApprox(ap) @@ -1390,7 +1394,7 @@ private module MkStage { fwdFlow(mid, state0, _, _, _, nil, pragma[only_bind_into](config)) and additionalJumpStateStep(mid, state0, node, state, config) and cc = ccNone() and - summaryCtx = TParameterPositionNone() and + summaryCtx = TParamNodeNone() and argAp = apNone() and ap = getApNil(node) and apa = getApprox(ap) @@ -1414,10 +1418,10 @@ private module MkStage { fwdFlowIn(_, node, state, _, cc, _, _, ap, apa, config) and if PrevStage::parameterMayFlowThrough(node, apa, config) then ( - summaryCtx = TParameterPositionSome(node.(ParamNodeEx).getPosition()) and + summaryCtx = TParamNodeSome(node.asNode()) and argAp = apSome(ap) ) else ( - summaryCtx = TParameterPositionNone() and argAp = apNone() + summaryCtx = TParamNodeNone() and argAp = apNone() ) or // flow out of a callable @@ -1433,16 +1437,19 @@ private module MkStage { ) or // flow through a callable - exists(DataFlowCall call, ParameterPosition summaryCtx0, Ap argAp0 | - fwdFlowOutFromArg(call, node, state, summaryCtx0, argAp0, ap, apa, config) and - fwdFlowIsEntered(call, cc, summaryCtx, argAp, summaryCtx0, argAp0, config) + exists( + DataFlowCall call, CcCall ccc, RetNodeEx ret, boolean allowsFieldFlow, ApApprox innerArgApa + | + fwdFlowThrough(call, cc, state, ccc, summaryCtx, argAp, ap, apa, ret, innerArgApa, config) and + flowThroughOutOfCall(call, ccc, ret, node, allowsFieldFlow, innerArgApa, apa, config) and + if allowsFieldFlow = false then ap instanceof ApNil else any() ) } pragma[nomagic] private predicate fwdFlowStore( NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, FlowState state, Cc cc, - ParameterPositionOption summaryCtx, ApOption argAp, Configuration config + ParamNodeOption summaryCtx, ApOption argAp, Configuration config ) { exists(DataFlowType contentType, ApApprox apa1 | fwdFlow(node1, state, cc, summaryCtx, argAp, ap1, apa1, config) and @@ -1473,8 +1480,8 @@ private module MkStage { pragma[nomagic] private predicate fwdFlowRead0( - NodeEx node1, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - ApNonNil ap, Configuration config + NodeEx node1, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, ApNonNil ap, + Configuration config ) { fwdFlow(node1, state, cc, summaryCtx, argAp, ap, config) and PrevStage::readStepCand(node1, _, _, config) @@ -1483,7 +1490,7 @@ private module MkStage { pragma[nomagic] private predicate fwdFlowRead( Ap ap, Content c, NodeEx node1, NodeEx node2, FlowState state, Cc cc, - ParameterPositionOption summaryCtx, ApOption argAp, Configuration config + ParamNodeOption summaryCtx, ApOption argAp, Configuration config ) { fwdFlowRead0(node1, state, cc, summaryCtx, argAp, ap, config) and PrevStage::readStepCand(node1, c, node2, config) and @@ -1493,7 +1500,7 @@ private module MkStage { pragma[nomagic] private predicate fwdFlowIn( DataFlowCall call, ParamNodeEx p, FlowState state, Cc outercc, CcCall innercc, - ParameterPositionOption summaryCtx, ApOption argAp, Ap ap, ApApprox apa, Configuration config + ParamNodeOption summaryCtx, ApOption argAp, Ap ap, ApApprox apa, Configuration config ) { exists(ArgNodeEx arg, boolean allowsFieldFlow | fwdFlow(arg, state, outercc, summaryCtx, argAp, ap, apa, config) and @@ -1505,64 +1512,38 @@ private module MkStage { pragma[nomagic] private predicate fwdFlowRetFromArg( - RetNodeEx ret, FlowState state, CcCall ccc, ParameterPosition summaryCtx, ParamNodeEx p, - Ap argAp, ApApprox argApa, Ap ap, ApApprox apa, Configuration config + RetNodeEx ret, FlowState state, CcCall ccc, ParamNodeEx summaryCtx, Ap argAp, ApApprox argApa, + Ap ap, ApApprox apa, Configuration config ) { - exists(DataFlowCallable c, ReturnKindExt kind | + exists(ReturnKindExt kind | fwdFlow(pragma[only_bind_into](ret), state, ccc, - TParameterPositionSome(pragma[only_bind_into](summaryCtx)), apSome(argAp), ap, apa, config) and - getApprox(argAp) = argApa and - c = ret.getEnclosingCallable() and + TParamNodeSome(pragma[only_bind_into](summaryCtx.asNode())), + pragma[only_bind_into](apSome(argAp)), ap, pragma[only_bind_into](apa), + pragma[only_bind_into](config)) and kind = ret.getKind() and - p.isParameterOf(c, pragma[only_bind_into](summaryCtx)) and - parameterFlowThroughAllowed(p, kind) + parameterFlowThroughAllowed(summaryCtx, kind) and + argApa = getApprox(argAp) and + PrevStage::returnMayFlowThrough(ret, argApa, apa, kind, pragma[only_bind_into](config)) ) } pragma[inline] - private predicate fwdFlowInMayFlowThrough( - DataFlowCall call, Cc cc, CcCall innerCc, ParameterPositionOption summaryCtx, ApOption argAp, - ParamNodeEx param, Ap ap, ApApprox apa, Configuration config + private predicate fwdFlowThrough0( + DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, + ApOption argAp, Ap ap, ApApprox apa, RetNodeEx ret, ParamNodeEx innerSummaryCtx, + Ap innerArgAp, ApApprox innerArgApa, Configuration config ) { - fwdFlowIn(call, pragma[only_bind_into](param), _, cc, innerCc, summaryCtx, argAp, ap, - pragma[only_bind_into](apa), pragma[only_bind_into](config)) and - PrevStage::parameterMayFlowThrough(param, apa, config) - } - - // dedup before joining with `flowThroughOutOfCall` - pragma[nomagic] - private predicate fwdFlowInMayFlowThroughProj( - DataFlowCall call, CcCall innerCc, ApApprox apa, Configuration config - ) { - fwdFlowInMayFlowThrough(call, _, innerCc, _, _, _, _, apa, config) - } - - /** - * Same as `flowThroughOutOfCall`, but restricted to calls that are reached - * in the flow covered by `fwdFlow`, where data might flow through the target - * callable and back out at `call`. - */ - pragma[nomagic] - private predicate fwdFlowThroughOutOfCall( - DataFlowCall call, CcCall ccc, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow, - ApApprox argApa, ApApprox apa, Configuration config - ) { - fwdFlowInMayFlowThroughProj(call, ccc, argApa, config) and - flowThroughOutOfCall(call, ccc, ret, out, allowsFieldFlow, argApa, apa, config) + fwdFlowRetFromArg(ret, state, ccc, innerSummaryCtx, innerArgAp, innerArgApa, ap, apa, config) and + fwdFlowIsEntered(call, cc, ccc, summaryCtx, argAp, innerSummaryCtx, innerArgAp, config) } pragma[nomagic] - private predicate fwdFlowOutFromArg( - DataFlowCall call, NodeEx out, FlowState state, ParameterPosition summaryCtx, Ap argAp, Ap ap, - ApApprox apa, Configuration config + private predicate fwdFlowThrough( + DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, + ApOption argAp, Ap ap, ApApprox apa, RetNodeEx ret, ApApprox innerArgApa, Configuration config ) { - exists(RetNodeEx ret, boolean allowsFieldFlow, CcCall ccc, ApApprox argApa | - fwdFlowRetFromArg(pragma[only_bind_into](ret), state, pragma[only_bind_into](ccc), - summaryCtx, _, argAp, pragma[only_bind_into](argApa), ap, pragma[only_bind_into](apa), - config) and - fwdFlowThroughOutOfCall(call, ccc, ret, out, allowsFieldFlow, argApa, apa, config) and - (if allowsFieldFlow = false then ap instanceof ApNil else any()) - ) + fwdFlowThrough0(call, cc, state, ccc, summaryCtx, argAp, ap, apa, ret, _, _, innerArgApa, + config) } /** @@ -1571,12 +1552,14 @@ private module MkStage { */ pragma[nomagic] private predicate fwdFlowIsEntered( - DataFlowCall call, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - ParameterPosition pos, Ap ap, Configuration config + DataFlowCall call, Cc cc, CcCall innerCc, ParamNodeOption summaryCtx, ApOption argAp, + ParamNodeEx p, Ap ap, Configuration config ) { - exists(ParamNodeEx param | - fwdFlowInMayFlowThrough(call, cc, _, summaryCtx, argAp, param, ap, _, config) and - pos = param.getPosition() + exists(ApApprox apa | + fwdFlowIn(call, pragma[only_bind_into](p), _, cc, innerCc, summaryCtx, argAp, ap, + pragma[only_bind_into](apa), pragma[only_bind_into](config)) and + PrevStage::parameterMayFlowThrough(p, apa, config) and + PrevStage::callMayFlowThroughRev(call, pragma[only_bind_into](config)) ) } @@ -1596,23 +1579,31 @@ private module MkStage { fwdFlowConsCand(ap1, c, ap2, config) } + pragma[nomagic] + private predicate returnFlowsThrough0( + DataFlowCall call, FlowState state, CcCall ccc, Ap ap, ApApprox apa, RetNodeEx ret, + ParamNodeEx innerSummaryCtx, Ap innerArgAp, ApApprox innerArgApa, Configuration config + ) { + fwdFlowThrough0(call, _, state, ccc, _, _, ap, apa, ret, innerSummaryCtx, innerArgAp, + innerArgApa, config) + } + pragma[nomagic] private predicate returnFlowsThrough( - RetNodeEx ret, ReturnKindExt kind, FlowState state, CcCall ccc, ParamNodeEx p, Ap argAp, + RetNodeEx ret, ReturnPosition pos, FlowState state, CcCall ccc, ParamNodeEx p, Ap argAp, Ap ap, Configuration config ) { - exists(boolean allowsFieldFlow, ApApprox argApa, ApApprox apa | - fwdFlowRetFromArg(pragma[only_bind_into](ret), state, pragma[only_bind_into](ccc), _, p, - argAp, pragma[only_bind_into](argApa), ap, pragma[only_bind_into](apa), config) and - kind = ret.getKind() and - fwdFlowThroughOutOfCall(_, ccc, ret, _, allowsFieldFlow, argApa, apa, config) and - (if allowsFieldFlow = false then ap instanceof ApNil else any()) + exists(DataFlowCall call, ApApprox apa, boolean allowsFieldFlow, ApApprox innerArgApa | + returnFlowsThrough0(call, state, ccc, ap, apa, ret, p, argAp, innerArgApa, config) and + flowThroughOutOfCall(call, ccc, ret, _, allowsFieldFlow, innerArgApa, apa, config) and + pos = ret.getReturnPosition() and + if allowsFieldFlow = false then ap instanceof ApNil else any() ) } pragma[nomagic] private predicate flowThroughIntoCall( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap argAp, + DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap argAp, Ap ap, Configuration config ) { exists(ApApprox argApa | @@ -1620,7 +1611,7 @@ private module MkStage { allowsFieldFlow, argApa, pragma[only_bind_into](config)) and fwdFlow(arg, _, _, _, _, pragma[only_bind_into](argAp), argApa, pragma[only_bind_into](config)) and - returnFlowsThrough(_, _, _, _, p, pragma[only_bind_into](argAp), _, + returnFlowsThrough(_, _, _, _, p, pragma[only_bind_into](argAp), ap, pragma[only_bind_into](config)) and if allowsFieldFlow = false then argAp instanceof ApNil else any() ) @@ -1639,12 +1630,13 @@ private module MkStage { pragma[nomagic] private predicate flowOutOfCallAp( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, boolean allowsFieldFlow, + DataFlowCall call, RetNodeEx ret, ReturnPosition pos, NodeEx out, boolean allowsFieldFlow, Ap ap, Configuration config ) { exists(ApApprox apa | - flowOutOfCallApa(call, ret, kind, out, allowsFieldFlow, apa, config) and - fwdFlow(ret, _, _, _, _, ap, apa, config) + flowOutOfCallApa(call, ret, _, out, allowsFieldFlow, apa, config) and + fwdFlow(ret, _, _, _, _, ap, apa, config) and + pos = ret.getReturnPosition() ) } @@ -1739,17 +1731,17 @@ private module MkStage { ) or // flow through a callable - exists(DataFlowCall call, ReturnKindExt returnKind0, Ap returnAp0 | - revFlowInToReturn(call, node, state, returnKind0, returnAp0, ap, config) and - revFlowIsReturned(call, returnCtx, returnAp, returnKind0, returnAp0, config) + exists(DataFlowCall call, ParamNodeEx p, ReturnPosition pos, Ap innerReturnAp | + revFlowThrough(call, returnCtx, p, state, pos, returnAp, ap, innerReturnAp, config) and + flowThroughIntoCall(call, node, p, _, ap, innerReturnAp, config) ) or // flow out of a callable - exists(ReturnKindExt kind | - revFlowOut(_, node, kind, state, _, _, ap, config) and - if returnFlowsThrough(node, kind, state, _, _, _, ap, config) + exists(ReturnPosition pos | + revFlowOut(_, node, pos, state, _, _, ap, config) and + if returnFlowsThrough(node, pos, state, _, _, _, ap, config) then ( - returnCtx = TReturnCtxMaybeFlowThrough(kind) and + returnCtx = TReturnCtxMaybeFlowThrough(pos) and returnAp = apSome(ap) ) else ( returnCtx = TReturnCtxNoFlowThrough() and returnAp = apNone() @@ -1782,47 +1774,33 @@ private module MkStage { pragma[nomagic] private predicate revFlowOut( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, FlowState state, ReturnCtx returnCtx, + DataFlowCall call, RetNodeEx ret, ReturnPosition pos, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap, Configuration config ) { exists(NodeEx out, boolean allowsFieldFlow | revFlow(out, state, returnCtx, returnAp, ap, config) and - flowOutOfCallAp(call, ret, kind, out, allowsFieldFlow, ap, config) and + flowOutOfCallAp(call, ret, pos, out, allowsFieldFlow, ap, config) and if allowsFieldFlow = false then ap instanceof ApNil else any() ) } - /** - * Same as `flowThroughIntoCall`, but restricted to calls that are reached - * in the flow covered by `revFlow`, where data might flow through the target - * callable and back out at `call`. - */ - pragma[nomagic] - private predicate revFlowThroughIntoCall( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap argAp, - Configuration config - ) { - flowThroughIntoCall(call, arg, p, allowsFieldFlow, argAp, config) and - revFlowIsReturned(call, _, _, _, _, config) - } - pragma[nomagic] private predicate revFlowParamToReturn( - ParamNodeEx p, FlowState state, ReturnKindExt kind, Ap returnAp, Ap ap, Configuration config + ParamNodeEx p, FlowState state, ReturnPosition pos, Ap returnAp, Ap ap, Configuration config ) { - revFlow(p, state, TReturnCtxMaybeFlowThrough(kind), apSome(returnAp), ap, config) and - parameterFlowThroughAllowed(p, kind) + revFlow(pragma[only_bind_into](p), state, TReturnCtxMaybeFlowThrough(pos), apSome(returnAp), + pragma[only_bind_into](ap), pragma[only_bind_into](config)) and + parameterFlowThroughAllowed(p, pos.getKind()) and + PrevStage::parameterMayFlowThrough(p, getApprox(ap), config) } pragma[nomagic] - private predicate revFlowInToReturn( - DataFlowCall call, ArgNodeEx arg, FlowState state, ReturnKindExt kind, Ap returnAp, Ap ap, - Configuration config + private predicate revFlowThrough( + DataFlowCall call, ReturnCtx returnCtx, ParamNodeEx p, FlowState state, ReturnPosition pos, + ApOption returnAp, Ap ap, Ap innerReturnAp, Configuration config ) { - exists(ParamNodeEx p, boolean allowsFieldFlow | - revFlowParamToReturn(p, state, kind, returnAp, ap, config) and - revFlowThroughIntoCall(call, arg, p, allowsFieldFlow, ap, config) - ) + revFlowParamToReturn(p, state, pos, innerReturnAp, ap, config) and + revFlowIsReturned(call, returnCtx, returnAp, pos, innerReturnAp, config) } /** @@ -1832,12 +1810,12 @@ private module MkStage { */ pragma[nomagic] private predicate revFlowIsReturned( - DataFlowCall call, ReturnCtx returnCtx, ApOption returnAp, ReturnKindExt kind, Ap ap, + DataFlowCall call, ReturnCtx returnCtx, ApOption returnAp, ReturnPosition pos, Ap ap, Configuration config ) { exists(RetNodeEx ret, FlowState state, CcCall ccc | - revFlowOut(call, ret, kind, state, returnCtx, returnAp, ap, config) and - returnFlowsThrough(ret, kind, state, ccc, _, _, ap, config) and + revFlowOut(call, ret, pos, state, returnCtx, returnAp, ap, config) and + returnFlowsThrough(ret, pos, state, ccc, _, _, ap, config) and matchesCall(ccc, call) ) } @@ -1915,17 +1893,17 @@ private module MkStage { pragma[nomagic] private predicate parameterFlowsThroughRev( - ParamNodeEx p, Ap ap, ReturnKindExt kind, Ap returnAp, Configuration config + ParamNodeEx p, Ap ap, ReturnPosition pos, Ap returnAp, Configuration config ) { - revFlow(p, _, TReturnCtxMaybeFlowThrough(kind), apSome(returnAp), ap, config) and - parameterFlowThroughAllowed(p, kind) + revFlow(p, _, TReturnCtxMaybeFlowThrough(pos), apSome(returnAp), ap, config) and + parameterFlowThroughAllowed(p, pos.getKind()) } pragma[nomagic] predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap, Configuration config) { - exists(RetNodeEx ret, ReturnKindExt kind | - returnFlowsThrough(ret, kind, _, _, p, ap, _, config) and - parameterFlowsThroughRev(p, ap, kind, _, config) + exists(RetNodeEx ret, ReturnPosition pos | + returnFlowsThrough(ret, pos, _, _, p, ap, _, config) and + parameterFlowsThroughRev(p, ap, pos, _, config) ) } @@ -1933,20 +1911,21 @@ private module MkStage { predicate returnMayFlowThrough( RetNodeEx ret, Ap argAp, Ap ap, ReturnKindExt kind, Configuration config ) { - exists(ParamNodeEx p | - returnFlowsThrough(ret, kind, _, _, p, argAp, ap, config) and - parameterFlowsThroughRev(p, argAp, kind, ap, config) + exists(ParamNodeEx p, ReturnPosition pos | + returnFlowsThrough(ret, pos, _, _, p, argAp, ap, config) and + parameterFlowsThroughRev(p, argAp, pos, ap, config) and + kind = pos.getKind() ) } pragma[nomagic] - predicate revFlowInToReturnIsReturned( + private predicate revFlowThroughArg( DataFlowCall call, ArgNodeEx arg, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap, Configuration config ) { - exists(ReturnKindExt returnKind0, Ap returnAp0 | - revFlowInToReturn(call, arg, state, returnKind0, returnAp0, ap, config) and - revFlowIsReturned(call, returnCtx, returnAp, returnKind0, returnAp0, config) + exists(ParamNodeEx p, ReturnPosition pos, Ap innerReturnAp | + revFlowThrough(call, returnCtx, p, state, pos, returnAp, ap, innerReturnAp, config) and + flowThroughIntoCall(call, arg, p, _, ap, innerReturnAp, config) ) } @@ -1954,7 +1933,7 @@ private module MkStage { predicate callMayFlowThroughRev(DataFlowCall call, Configuration config) { exists(ArgNodeEx arg, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap | revFlow(arg, state, returnCtx, returnAp, ap, config) and - revFlowInToReturnIsReturned(call, arg, state, returnCtx, returnAp, ap, config) + revFlowThroughArg(call, arg, state, returnCtx, returnAp, ap, config) ) } @@ -1967,8 +1946,9 @@ private module MkStage { conscand = count(TypedContent f0, Ap ap | fwdConsCand(f0, ap, config)) and states = count(FlowState state | fwdFlow(_, state, _, _, _, _, config)) and tuples = - count(NodeEx n, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - Ap ap | fwdFlow(n, state, cc, summaryCtx, argAp, ap, config)) + count(NodeEx n, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap | + fwdFlow(n, state, cc, summaryCtx, argAp, ap, config) + ) or fwd = false and nodes = count(NodeEx node | revFlow(node, _, _, _, _, config)) and @@ -2823,13 +2803,12 @@ private Configuration unbindConf(Configuration conf) { pragma[nomagic] private predicate nodeMayUseSummary0( - NodeEx n, DataFlowCallable c, ParameterPosition pos, FlowState state, AccessPathApprox apa, - Configuration config + NodeEx n, ParamNodeEx p, FlowState state, AccessPathApprox apa, Configuration config ) { exists(AccessPathApprox apa0 | - c = n.getEnclosingCallable() and + Stage5::parameterMayFlowThrough(p, _, _) and Stage5::revFlow(n, state, TReturnCtxMaybeFlowThrough(_), _, apa0, config) and - Stage5::fwdFlow(n, state, any(CallContextCall ccc), TParameterPositionSome(pos), + Stage5::fwdFlow(n, state, any(CallContextCall ccc), TParamNodeSome(p.asNode()), TAccessPathApproxSome(apa), apa0, config) ) } @@ -2838,10 +2817,9 @@ pragma[nomagic] private predicate nodeMayUseSummary( NodeEx n, FlowState state, AccessPathApprox apa, Configuration config ) { - exists(DataFlowCallable c, ParameterPosition pos, ParamNodeEx p | + exists(ParamNodeEx p | Stage5::parameterMayFlowThrough(p, apa, config) and - nodeMayUseSummary0(n, c, pos, state, apa, config) and - p.isParameterOf(c, pos) + nodeMayUseSummary0(n, p, state, apa, config) ) } diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl3.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl3.qll index 6741ccc2f06..1228d00b6ba 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl3.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl3.qll @@ -622,7 +622,11 @@ private predicate parameterFlowThroughAllowed(ParamNodeEx p, ReturnKindExt kind) } private module Stage1 implements StageSig { - class Ap = Unit; + class Ap extends int { + // workaround for bad functionality-induced joins (happens when using `Unit`) + pragma[nomagic] + Ap() { this in [0 .. 1] and this < 1 } + } private class Cc = boolean; @@ -1327,8 +1331,8 @@ private module MkStage { */ pragma[nomagic] additional predicate fwdFlow( - NodeEx node, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - Ap ap, ApApprox apa, Configuration config + NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, + ApApprox apa, Configuration config ) { fwdFlow0(node, state, cc, summaryCtx, argAp, ap, apa, config) and PrevStage::revFlow(node, state, apa, config) and @@ -1337,21 +1341,21 @@ private module MkStage { pragma[inline] additional predicate fwdFlow( - NodeEx node, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - Ap ap, Configuration config + NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, + Configuration config ) { fwdFlow(node, state, cc, summaryCtx, argAp, ap, _, config) } pragma[nomagic] private predicate fwdFlow0( - NodeEx node, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - Ap ap, ApApprox apa, Configuration config + NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, + ApApprox apa, Configuration config ) { sourceNode(node, state, config) and (if hasSourceCallCtx(config) then cc = ccSomeCall() else cc = ccNone()) and argAp = apNone() and - summaryCtx = TParameterPositionNone() and + summaryCtx = TParamNodeNone() and ap = getApNil(node) and apa = getApprox(ap) or @@ -1372,7 +1376,7 @@ private module MkStage { fwdFlow(mid, pragma[only_bind_into](state), _, _, _, ap, apa, pragma[only_bind_into](config)) and jumpStep(mid, node, config) and cc = ccNone() and - summaryCtx = TParameterPositionNone() and + summaryCtx = TParamNodeNone() and argAp = apNone() ) or @@ -1380,7 +1384,7 @@ private module MkStage { fwdFlow(mid, state, _, _, _, nil, pragma[only_bind_into](config)) and additionalJumpStep(mid, node, config) and cc = ccNone() and - summaryCtx = TParameterPositionNone() and + summaryCtx = TParamNodeNone() and argAp = apNone() and ap = getApNil(node) and apa = getApprox(ap) @@ -1390,7 +1394,7 @@ private module MkStage { fwdFlow(mid, state0, _, _, _, nil, pragma[only_bind_into](config)) and additionalJumpStateStep(mid, state0, node, state, config) and cc = ccNone() and - summaryCtx = TParameterPositionNone() and + summaryCtx = TParamNodeNone() and argAp = apNone() and ap = getApNil(node) and apa = getApprox(ap) @@ -1414,10 +1418,10 @@ private module MkStage { fwdFlowIn(_, node, state, _, cc, _, _, ap, apa, config) and if PrevStage::parameterMayFlowThrough(node, apa, config) then ( - summaryCtx = TParameterPositionSome(node.(ParamNodeEx).getPosition()) and + summaryCtx = TParamNodeSome(node.asNode()) and argAp = apSome(ap) ) else ( - summaryCtx = TParameterPositionNone() and argAp = apNone() + summaryCtx = TParamNodeNone() and argAp = apNone() ) or // flow out of a callable @@ -1433,16 +1437,19 @@ private module MkStage { ) or // flow through a callable - exists(DataFlowCall call, ParameterPosition summaryCtx0, Ap argAp0 | - fwdFlowOutFromArg(call, node, state, summaryCtx0, argAp0, ap, apa, config) and - fwdFlowIsEntered(call, cc, summaryCtx, argAp, summaryCtx0, argAp0, config) + exists( + DataFlowCall call, CcCall ccc, RetNodeEx ret, boolean allowsFieldFlow, ApApprox innerArgApa + | + fwdFlowThrough(call, cc, state, ccc, summaryCtx, argAp, ap, apa, ret, innerArgApa, config) and + flowThroughOutOfCall(call, ccc, ret, node, allowsFieldFlow, innerArgApa, apa, config) and + if allowsFieldFlow = false then ap instanceof ApNil else any() ) } pragma[nomagic] private predicate fwdFlowStore( NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, FlowState state, Cc cc, - ParameterPositionOption summaryCtx, ApOption argAp, Configuration config + ParamNodeOption summaryCtx, ApOption argAp, Configuration config ) { exists(DataFlowType contentType, ApApprox apa1 | fwdFlow(node1, state, cc, summaryCtx, argAp, ap1, apa1, config) and @@ -1473,8 +1480,8 @@ private module MkStage { pragma[nomagic] private predicate fwdFlowRead0( - NodeEx node1, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - ApNonNil ap, Configuration config + NodeEx node1, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, ApNonNil ap, + Configuration config ) { fwdFlow(node1, state, cc, summaryCtx, argAp, ap, config) and PrevStage::readStepCand(node1, _, _, config) @@ -1483,7 +1490,7 @@ private module MkStage { pragma[nomagic] private predicate fwdFlowRead( Ap ap, Content c, NodeEx node1, NodeEx node2, FlowState state, Cc cc, - ParameterPositionOption summaryCtx, ApOption argAp, Configuration config + ParamNodeOption summaryCtx, ApOption argAp, Configuration config ) { fwdFlowRead0(node1, state, cc, summaryCtx, argAp, ap, config) and PrevStage::readStepCand(node1, c, node2, config) and @@ -1493,7 +1500,7 @@ private module MkStage { pragma[nomagic] private predicate fwdFlowIn( DataFlowCall call, ParamNodeEx p, FlowState state, Cc outercc, CcCall innercc, - ParameterPositionOption summaryCtx, ApOption argAp, Ap ap, ApApprox apa, Configuration config + ParamNodeOption summaryCtx, ApOption argAp, Ap ap, ApApprox apa, Configuration config ) { exists(ArgNodeEx arg, boolean allowsFieldFlow | fwdFlow(arg, state, outercc, summaryCtx, argAp, ap, apa, config) and @@ -1505,64 +1512,38 @@ private module MkStage { pragma[nomagic] private predicate fwdFlowRetFromArg( - RetNodeEx ret, FlowState state, CcCall ccc, ParameterPosition summaryCtx, ParamNodeEx p, - Ap argAp, ApApprox argApa, Ap ap, ApApprox apa, Configuration config + RetNodeEx ret, FlowState state, CcCall ccc, ParamNodeEx summaryCtx, Ap argAp, ApApprox argApa, + Ap ap, ApApprox apa, Configuration config ) { - exists(DataFlowCallable c, ReturnKindExt kind | + exists(ReturnKindExt kind | fwdFlow(pragma[only_bind_into](ret), state, ccc, - TParameterPositionSome(pragma[only_bind_into](summaryCtx)), apSome(argAp), ap, apa, config) and - getApprox(argAp) = argApa and - c = ret.getEnclosingCallable() and + TParamNodeSome(pragma[only_bind_into](summaryCtx.asNode())), + pragma[only_bind_into](apSome(argAp)), ap, pragma[only_bind_into](apa), + pragma[only_bind_into](config)) and kind = ret.getKind() and - p.isParameterOf(c, pragma[only_bind_into](summaryCtx)) and - parameterFlowThroughAllowed(p, kind) + parameterFlowThroughAllowed(summaryCtx, kind) and + argApa = getApprox(argAp) and + PrevStage::returnMayFlowThrough(ret, argApa, apa, kind, pragma[only_bind_into](config)) ) } pragma[inline] - private predicate fwdFlowInMayFlowThrough( - DataFlowCall call, Cc cc, CcCall innerCc, ParameterPositionOption summaryCtx, ApOption argAp, - ParamNodeEx param, Ap ap, ApApprox apa, Configuration config + private predicate fwdFlowThrough0( + DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, + ApOption argAp, Ap ap, ApApprox apa, RetNodeEx ret, ParamNodeEx innerSummaryCtx, + Ap innerArgAp, ApApprox innerArgApa, Configuration config ) { - fwdFlowIn(call, pragma[only_bind_into](param), _, cc, innerCc, summaryCtx, argAp, ap, - pragma[only_bind_into](apa), pragma[only_bind_into](config)) and - PrevStage::parameterMayFlowThrough(param, apa, config) - } - - // dedup before joining with `flowThroughOutOfCall` - pragma[nomagic] - private predicate fwdFlowInMayFlowThroughProj( - DataFlowCall call, CcCall innerCc, ApApprox apa, Configuration config - ) { - fwdFlowInMayFlowThrough(call, _, innerCc, _, _, _, _, apa, config) - } - - /** - * Same as `flowThroughOutOfCall`, but restricted to calls that are reached - * in the flow covered by `fwdFlow`, where data might flow through the target - * callable and back out at `call`. - */ - pragma[nomagic] - private predicate fwdFlowThroughOutOfCall( - DataFlowCall call, CcCall ccc, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow, - ApApprox argApa, ApApprox apa, Configuration config - ) { - fwdFlowInMayFlowThroughProj(call, ccc, argApa, config) and - flowThroughOutOfCall(call, ccc, ret, out, allowsFieldFlow, argApa, apa, config) + fwdFlowRetFromArg(ret, state, ccc, innerSummaryCtx, innerArgAp, innerArgApa, ap, apa, config) and + fwdFlowIsEntered(call, cc, ccc, summaryCtx, argAp, innerSummaryCtx, innerArgAp, config) } pragma[nomagic] - private predicate fwdFlowOutFromArg( - DataFlowCall call, NodeEx out, FlowState state, ParameterPosition summaryCtx, Ap argAp, Ap ap, - ApApprox apa, Configuration config + private predicate fwdFlowThrough( + DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, + ApOption argAp, Ap ap, ApApprox apa, RetNodeEx ret, ApApprox innerArgApa, Configuration config ) { - exists(RetNodeEx ret, boolean allowsFieldFlow, CcCall ccc, ApApprox argApa | - fwdFlowRetFromArg(pragma[only_bind_into](ret), state, pragma[only_bind_into](ccc), - summaryCtx, _, argAp, pragma[only_bind_into](argApa), ap, pragma[only_bind_into](apa), - config) and - fwdFlowThroughOutOfCall(call, ccc, ret, out, allowsFieldFlow, argApa, apa, config) and - (if allowsFieldFlow = false then ap instanceof ApNil else any()) - ) + fwdFlowThrough0(call, cc, state, ccc, summaryCtx, argAp, ap, apa, ret, _, _, innerArgApa, + config) } /** @@ -1571,12 +1552,14 @@ private module MkStage { */ pragma[nomagic] private predicate fwdFlowIsEntered( - DataFlowCall call, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - ParameterPosition pos, Ap ap, Configuration config + DataFlowCall call, Cc cc, CcCall innerCc, ParamNodeOption summaryCtx, ApOption argAp, + ParamNodeEx p, Ap ap, Configuration config ) { - exists(ParamNodeEx param | - fwdFlowInMayFlowThrough(call, cc, _, summaryCtx, argAp, param, ap, _, config) and - pos = param.getPosition() + exists(ApApprox apa | + fwdFlowIn(call, pragma[only_bind_into](p), _, cc, innerCc, summaryCtx, argAp, ap, + pragma[only_bind_into](apa), pragma[only_bind_into](config)) and + PrevStage::parameterMayFlowThrough(p, apa, config) and + PrevStage::callMayFlowThroughRev(call, pragma[only_bind_into](config)) ) } @@ -1596,23 +1579,31 @@ private module MkStage { fwdFlowConsCand(ap1, c, ap2, config) } + pragma[nomagic] + private predicate returnFlowsThrough0( + DataFlowCall call, FlowState state, CcCall ccc, Ap ap, ApApprox apa, RetNodeEx ret, + ParamNodeEx innerSummaryCtx, Ap innerArgAp, ApApprox innerArgApa, Configuration config + ) { + fwdFlowThrough0(call, _, state, ccc, _, _, ap, apa, ret, innerSummaryCtx, innerArgAp, + innerArgApa, config) + } + pragma[nomagic] private predicate returnFlowsThrough( - RetNodeEx ret, ReturnKindExt kind, FlowState state, CcCall ccc, ParamNodeEx p, Ap argAp, + RetNodeEx ret, ReturnPosition pos, FlowState state, CcCall ccc, ParamNodeEx p, Ap argAp, Ap ap, Configuration config ) { - exists(boolean allowsFieldFlow, ApApprox argApa, ApApprox apa | - fwdFlowRetFromArg(pragma[only_bind_into](ret), state, pragma[only_bind_into](ccc), _, p, - argAp, pragma[only_bind_into](argApa), ap, pragma[only_bind_into](apa), config) and - kind = ret.getKind() and - fwdFlowThroughOutOfCall(_, ccc, ret, _, allowsFieldFlow, argApa, apa, config) and - (if allowsFieldFlow = false then ap instanceof ApNil else any()) + exists(DataFlowCall call, ApApprox apa, boolean allowsFieldFlow, ApApprox innerArgApa | + returnFlowsThrough0(call, state, ccc, ap, apa, ret, p, argAp, innerArgApa, config) and + flowThroughOutOfCall(call, ccc, ret, _, allowsFieldFlow, innerArgApa, apa, config) and + pos = ret.getReturnPosition() and + if allowsFieldFlow = false then ap instanceof ApNil else any() ) } pragma[nomagic] private predicate flowThroughIntoCall( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap argAp, + DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap argAp, Ap ap, Configuration config ) { exists(ApApprox argApa | @@ -1620,7 +1611,7 @@ private module MkStage { allowsFieldFlow, argApa, pragma[only_bind_into](config)) and fwdFlow(arg, _, _, _, _, pragma[only_bind_into](argAp), argApa, pragma[only_bind_into](config)) and - returnFlowsThrough(_, _, _, _, p, pragma[only_bind_into](argAp), _, + returnFlowsThrough(_, _, _, _, p, pragma[only_bind_into](argAp), ap, pragma[only_bind_into](config)) and if allowsFieldFlow = false then argAp instanceof ApNil else any() ) @@ -1639,12 +1630,13 @@ private module MkStage { pragma[nomagic] private predicate flowOutOfCallAp( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, boolean allowsFieldFlow, + DataFlowCall call, RetNodeEx ret, ReturnPosition pos, NodeEx out, boolean allowsFieldFlow, Ap ap, Configuration config ) { exists(ApApprox apa | - flowOutOfCallApa(call, ret, kind, out, allowsFieldFlow, apa, config) and - fwdFlow(ret, _, _, _, _, ap, apa, config) + flowOutOfCallApa(call, ret, _, out, allowsFieldFlow, apa, config) and + fwdFlow(ret, _, _, _, _, ap, apa, config) and + pos = ret.getReturnPosition() ) } @@ -1739,17 +1731,17 @@ private module MkStage { ) or // flow through a callable - exists(DataFlowCall call, ReturnKindExt returnKind0, Ap returnAp0 | - revFlowInToReturn(call, node, state, returnKind0, returnAp0, ap, config) and - revFlowIsReturned(call, returnCtx, returnAp, returnKind0, returnAp0, config) + exists(DataFlowCall call, ParamNodeEx p, ReturnPosition pos, Ap innerReturnAp | + revFlowThrough(call, returnCtx, p, state, pos, returnAp, ap, innerReturnAp, config) and + flowThroughIntoCall(call, node, p, _, ap, innerReturnAp, config) ) or // flow out of a callable - exists(ReturnKindExt kind | - revFlowOut(_, node, kind, state, _, _, ap, config) and - if returnFlowsThrough(node, kind, state, _, _, _, ap, config) + exists(ReturnPosition pos | + revFlowOut(_, node, pos, state, _, _, ap, config) and + if returnFlowsThrough(node, pos, state, _, _, _, ap, config) then ( - returnCtx = TReturnCtxMaybeFlowThrough(kind) and + returnCtx = TReturnCtxMaybeFlowThrough(pos) and returnAp = apSome(ap) ) else ( returnCtx = TReturnCtxNoFlowThrough() and returnAp = apNone() @@ -1782,47 +1774,33 @@ private module MkStage { pragma[nomagic] private predicate revFlowOut( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, FlowState state, ReturnCtx returnCtx, + DataFlowCall call, RetNodeEx ret, ReturnPosition pos, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap, Configuration config ) { exists(NodeEx out, boolean allowsFieldFlow | revFlow(out, state, returnCtx, returnAp, ap, config) and - flowOutOfCallAp(call, ret, kind, out, allowsFieldFlow, ap, config) and + flowOutOfCallAp(call, ret, pos, out, allowsFieldFlow, ap, config) and if allowsFieldFlow = false then ap instanceof ApNil else any() ) } - /** - * Same as `flowThroughIntoCall`, but restricted to calls that are reached - * in the flow covered by `revFlow`, where data might flow through the target - * callable and back out at `call`. - */ - pragma[nomagic] - private predicate revFlowThroughIntoCall( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap argAp, - Configuration config - ) { - flowThroughIntoCall(call, arg, p, allowsFieldFlow, argAp, config) and - revFlowIsReturned(call, _, _, _, _, config) - } - pragma[nomagic] private predicate revFlowParamToReturn( - ParamNodeEx p, FlowState state, ReturnKindExt kind, Ap returnAp, Ap ap, Configuration config + ParamNodeEx p, FlowState state, ReturnPosition pos, Ap returnAp, Ap ap, Configuration config ) { - revFlow(p, state, TReturnCtxMaybeFlowThrough(kind), apSome(returnAp), ap, config) and - parameterFlowThroughAllowed(p, kind) + revFlow(pragma[only_bind_into](p), state, TReturnCtxMaybeFlowThrough(pos), apSome(returnAp), + pragma[only_bind_into](ap), pragma[only_bind_into](config)) and + parameterFlowThroughAllowed(p, pos.getKind()) and + PrevStage::parameterMayFlowThrough(p, getApprox(ap), config) } pragma[nomagic] - private predicate revFlowInToReturn( - DataFlowCall call, ArgNodeEx arg, FlowState state, ReturnKindExt kind, Ap returnAp, Ap ap, - Configuration config + private predicate revFlowThrough( + DataFlowCall call, ReturnCtx returnCtx, ParamNodeEx p, FlowState state, ReturnPosition pos, + ApOption returnAp, Ap ap, Ap innerReturnAp, Configuration config ) { - exists(ParamNodeEx p, boolean allowsFieldFlow | - revFlowParamToReturn(p, state, kind, returnAp, ap, config) and - revFlowThroughIntoCall(call, arg, p, allowsFieldFlow, ap, config) - ) + revFlowParamToReturn(p, state, pos, innerReturnAp, ap, config) and + revFlowIsReturned(call, returnCtx, returnAp, pos, innerReturnAp, config) } /** @@ -1832,12 +1810,12 @@ private module MkStage { */ pragma[nomagic] private predicate revFlowIsReturned( - DataFlowCall call, ReturnCtx returnCtx, ApOption returnAp, ReturnKindExt kind, Ap ap, + DataFlowCall call, ReturnCtx returnCtx, ApOption returnAp, ReturnPosition pos, Ap ap, Configuration config ) { exists(RetNodeEx ret, FlowState state, CcCall ccc | - revFlowOut(call, ret, kind, state, returnCtx, returnAp, ap, config) and - returnFlowsThrough(ret, kind, state, ccc, _, _, ap, config) and + revFlowOut(call, ret, pos, state, returnCtx, returnAp, ap, config) and + returnFlowsThrough(ret, pos, state, ccc, _, _, ap, config) and matchesCall(ccc, call) ) } @@ -1915,17 +1893,17 @@ private module MkStage { pragma[nomagic] private predicate parameterFlowsThroughRev( - ParamNodeEx p, Ap ap, ReturnKindExt kind, Ap returnAp, Configuration config + ParamNodeEx p, Ap ap, ReturnPosition pos, Ap returnAp, Configuration config ) { - revFlow(p, _, TReturnCtxMaybeFlowThrough(kind), apSome(returnAp), ap, config) and - parameterFlowThroughAllowed(p, kind) + revFlow(p, _, TReturnCtxMaybeFlowThrough(pos), apSome(returnAp), ap, config) and + parameterFlowThroughAllowed(p, pos.getKind()) } pragma[nomagic] predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap, Configuration config) { - exists(RetNodeEx ret, ReturnKindExt kind | - returnFlowsThrough(ret, kind, _, _, p, ap, _, config) and - parameterFlowsThroughRev(p, ap, kind, _, config) + exists(RetNodeEx ret, ReturnPosition pos | + returnFlowsThrough(ret, pos, _, _, p, ap, _, config) and + parameterFlowsThroughRev(p, ap, pos, _, config) ) } @@ -1933,20 +1911,21 @@ private module MkStage { predicate returnMayFlowThrough( RetNodeEx ret, Ap argAp, Ap ap, ReturnKindExt kind, Configuration config ) { - exists(ParamNodeEx p | - returnFlowsThrough(ret, kind, _, _, p, argAp, ap, config) and - parameterFlowsThroughRev(p, argAp, kind, ap, config) + exists(ParamNodeEx p, ReturnPosition pos | + returnFlowsThrough(ret, pos, _, _, p, argAp, ap, config) and + parameterFlowsThroughRev(p, argAp, pos, ap, config) and + kind = pos.getKind() ) } pragma[nomagic] - predicate revFlowInToReturnIsReturned( + private predicate revFlowThroughArg( DataFlowCall call, ArgNodeEx arg, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap, Configuration config ) { - exists(ReturnKindExt returnKind0, Ap returnAp0 | - revFlowInToReturn(call, arg, state, returnKind0, returnAp0, ap, config) and - revFlowIsReturned(call, returnCtx, returnAp, returnKind0, returnAp0, config) + exists(ParamNodeEx p, ReturnPosition pos, Ap innerReturnAp | + revFlowThrough(call, returnCtx, p, state, pos, returnAp, ap, innerReturnAp, config) and + flowThroughIntoCall(call, arg, p, _, ap, innerReturnAp, config) ) } @@ -1954,7 +1933,7 @@ private module MkStage { predicate callMayFlowThroughRev(DataFlowCall call, Configuration config) { exists(ArgNodeEx arg, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap | revFlow(arg, state, returnCtx, returnAp, ap, config) and - revFlowInToReturnIsReturned(call, arg, state, returnCtx, returnAp, ap, config) + revFlowThroughArg(call, arg, state, returnCtx, returnAp, ap, config) ) } @@ -1967,8 +1946,9 @@ private module MkStage { conscand = count(TypedContent f0, Ap ap | fwdConsCand(f0, ap, config)) and states = count(FlowState state | fwdFlow(_, state, _, _, _, _, config)) and tuples = - count(NodeEx n, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - Ap ap | fwdFlow(n, state, cc, summaryCtx, argAp, ap, config)) + count(NodeEx n, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap | + fwdFlow(n, state, cc, summaryCtx, argAp, ap, config) + ) or fwd = false and nodes = count(NodeEx node | revFlow(node, _, _, _, _, config)) and @@ -2823,13 +2803,12 @@ private Configuration unbindConf(Configuration conf) { pragma[nomagic] private predicate nodeMayUseSummary0( - NodeEx n, DataFlowCallable c, ParameterPosition pos, FlowState state, AccessPathApprox apa, - Configuration config + NodeEx n, ParamNodeEx p, FlowState state, AccessPathApprox apa, Configuration config ) { exists(AccessPathApprox apa0 | - c = n.getEnclosingCallable() and + Stage5::parameterMayFlowThrough(p, _, _) and Stage5::revFlow(n, state, TReturnCtxMaybeFlowThrough(_), _, apa0, config) and - Stage5::fwdFlow(n, state, any(CallContextCall ccc), TParameterPositionSome(pos), + Stage5::fwdFlow(n, state, any(CallContextCall ccc), TParamNodeSome(p.asNode()), TAccessPathApproxSome(apa), apa0, config) ) } @@ -2838,10 +2817,9 @@ pragma[nomagic] private predicate nodeMayUseSummary( NodeEx n, FlowState state, AccessPathApprox apa, Configuration config ) { - exists(DataFlowCallable c, ParameterPosition pos, ParamNodeEx p | + exists(ParamNodeEx p | Stage5::parameterMayFlowThrough(p, apa, config) and - nodeMayUseSummary0(n, c, pos, state, apa, config) and - p.isParameterOf(c, pos) + nodeMayUseSummary0(n, p, state, apa, config) ) } diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl4.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl4.qll index 6741ccc2f06..1228d00b6ba 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl4.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl4.qll @@ -622,7 +622,11 @@ private predicate parameterFlowThroughAllowed(ParamNodeEx p, ReturnKindExt kind) } private module Stage1 implements StageSig { - class Ap = Unit; + class Ap extends int { + // workaround for bad functionality-induced joins (happens when using `Unit`) + pragma[nomagic] + Ap() { this in [0 .. 1] and this < 1 } + } private class Cc = boolean; @@ -1327,8 +1331,8 @@ private module MkStage { */ pragma[nomagic] additional predicate fwdFlow( - NodeEx node, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - Ap ap, ApApprox apa, Configuration config + NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, + ApApprox apa, Configuration config ) { fwdFlow0(node, state, cc, summaryCtx, argAp, ap, apa, config) and PrevStage::revFlow(node, state, apa, config) and @@ -1337,21 +1341,21 @@ private module MkStage { pragma[inline] additional predicate fwdFlow( - NodeEx node, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - Ap ap, Configuration config + NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, + Configuration config ) { fwdFlow(node, state, cc, summaryCtx, argAp, ap, _, config) } pragma[nomagic] private predicate fwdFlow0( - NodeEx node, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - Ap ap, ApApprox apa, Configuration config + NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, + ApApprox apa, Configuration config ) { sourceNode(node, state, config) and (if hasSourceCallCtx(config) then cc = ccSomeCall() else cc = ccNone()) and argAp = apNone() and - summaryCtx = TParameterPositionNone() and + summaryCtx = TParamNodeNone() and ap = getApNil(node) and apa = getApprox(ap) or @@ -1372,7 +1376,7 @@ private module MkStage { fwdFlow(mid, pragma[only_bind_into](state), _, _, _, ap, apa, pragma[only_bind_into](config)) and jumpStep(mid, node, config) and cc = ccNone() and - summaryCtx = TParameterPositionNone() and + summaryCtx = TParamNodeNone() and argAp = apNone() ) or @@ -1380,7 +1384,7 @@ private module MkStage { fwdFlow(mid, state, _, _, _, nil, pragma[only_bind_into](config)) and additionalJumpStep(mid, node, config) and cc = ccNone() and - summaryCtx = TParameterPositionNone() and + summaryCtx = TParamNodeNone() and argAp = apNone() and ap = getApNil(node) and apa = getApprox(ap) @@ -1390,7 +1394,7 @@ private module MkStage { fwdFlow(mid, state0, _, _, _, nil, pragma[only_bind_into](config)) and additionalJumpStateStep(mid, state0, node, state, config) and cc = ccNone() and - summaryCtx = TParameterPositionNone() and + summaryCtx = TParamNodeNone() and argAp = apNone() and ap = getApNil(node) and apa = getApprox(ap) @@ -1414,10 +1418,10 @@ private module MkStage { fwdFlowIn(_, node, state, _, cc, _, _, ap, apa, config) and if PrevStage::parameterMayFlowThrough(node, apa, config) then ( - summaryCtx = TParameterPositionSome(node.(ParamNodeEx).getPosition()) and + summaryCtx = TParamNodeSome(node.asNode()) and argAp = apSome(ap) ) else ( - summaryCtx = TParameterPositionNone() and argAp = apNone() + summaryCtx = TParamNodeNone() and argAp = apNone() ) or // flow out of a callable @@ -1433,16 +1437,19 @@ private module MkStage { ) or // flow through a callable - exists(DataFlowCall call, ParameterPosition summaryCtx0, Ap argAp0 | - fwdFlowOutFromArg(call, node, state, summaryCtx0, argAp0, ap, apa, config) and - fwdFlowIsEntered(call, cc, summaryCtx, argAp, summaryCtx0, argAp0, config) + exists( + DataFlowCall call, CcCall ccc, RetNodeEx ret, boolean allowsFieldFlow, ApApprox innerArgApa + | + fwdFlowThrough(call, cc, state, ccc, summaryCtx, argAp, ap, apa, ret, innerArgApa, config) and + flowThroughOutOfCall(call, ccc, ret, node, allowsFieldFlow, innerArgApa, apa, config) and + if allowsFieldFlow = false then ap instanceof ApNil else any() ) } pragma[nomagic] private predicate fwdFlowStore( NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, FlowState state, Cc cc, - ParameterPositionOption summaryCtx, ApOption argAp, Configuration config + ParamNodeOption summaryCtx, ApOption argAp, Configuration config ) { exists(DataFlowType contentType, ApApprox apa1 | fwdFlow(node1, state, cc, summaryCtx, argAp, ap1, apa1, config) and @@ -1473,8 +1480,8 @@ private module MkStage { pragma[nomagic] private predicate fwdFlowRead0( - NodeEx node1, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - ApNonNil ap, Configuration config + NodeEx node1, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, ApNonNil ap, + Configuration config ) { fwdFlow(node1, state, cc, summaryCtx, argAp, ap, config) and PrevStage::readStepCand(node1, _, _, config) @@ -1483,7 +1490,7 @@ private module MkStage { pragma[nomagic] private predicate fwdFlowRead( Ap ap, Content c, NodeEx node1, NodeEx node2, FlowState state, Cc cc, - ParameterPositionOption summaryCtx, ApOption argAp, Configuration config + ParamNodeOption summaryCtx, ApOption argAp, Configuration config ) { fwdFlowRead0(node1, state, cc, summaryCtx, argAp, ap, config) and PrevStage::readStepCand(node1, c, node2, config) and @@ -1493,7 +1500,7 @@ private module MkStage { pragma[nomagic] private predicate fwdFlowIn( DataFlowCall call, ParamNodeEx p, FlowState state, Cc outercc, CcCall innercc, - ParameterPositionOption summaryCtx, ApOption argAp, Ap ap, ApApprox apa, Configuration config + ParamNodeOption summaryCtx, ApOption argAp, Ap ap, ApApprox apa, Configuration config ) { exists(ArgNodeEx arg, boolean allowsFieldFlow | fwdFlow(arg, state, outercc, summaryCtx, argAp, ap, apa, config) and @@ -1505,64 +1512,38 @@ private module MkStage { pragma[nomagic] private predicate fwdFlowRetFromArg( - RetNodeEx ret, FlowState state, CcCall ccc, ParameterPosition summaryCtx, ParamNodeEx p, - Ap argAp, ApApprox argApa, Ap ap, ApApprox apa, Configuration config + RetNodeEx ret, FlowState state, CcCall ccc, ParamNodeEx summaryCtx, Ap argAp, ApApprox argApa, + Ap ap, ApApprox apa, Configuration config ) { - exists(DataFlowCallable c, ReturnKindExt kind | + exists(ReturnKindExt kind | fwdFlow(pragma[only_bind_into](ret), state, ccc, - TParameterPositionSome(pragma[only_bind_into](summaryCtx)), apSome(argAp), ap, apa, config) and - getApprox(argAp) = argApa and - c = ret.getEnclosingCallable() and + TParamNodeSome(pragma[only_bind_into](summaryCtx.asNode())), + pragma[only_bind_into](apSome(argAp)), ap, pragma[only_bind_into](apa), + pragma[only_bind_into](config)) and kind = ret.getKind() and - p.isParameterOf(c, pragma[only_bind_into](summaryCtx)) and - parameterFlowThroughAllowed(p, kind) + parameterFlowThroughAllowed(summaryCtx, kind) and + argApa = getApprox(argAp) and + PrevStage::returnMayFlowThrough(ret, argApa, apa, kind, pragma[only_bind_into](config)) ) } pragma[inline] - private predicate fwdFlowInMayFlowThrough( - DataFlowCall call, Cc cc, CcCall innerCc, ParameterPositionOption summaryCtx, ApOption argAp, - ParamNodeEx param, Ap ap, ApApprox apa, Configuration config + private predicate fwdFlowThrough0( + DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, + ApOption argAp, Ap ap, ApApprox apa, RetNodeEx ret, ParamNodeEx innerSummaryCtx, + Ap innerArgAp, ApApprox innerArgApa, Configuration config ) { - fwdFlowIn(call, pragma[only_bind_into](param), _, cc, innerCc, summaryCtx, argAp, ap, - pragma[only_bind_into](apa), pragma[only_bind_into](config)) and - PrevStage::parameterMayFlowThrough(param, apa, config) - } - - // dedup before joining with `flowThroughOutOfCall` - pragma[nomagic] - private predicate fwdFlowInMayFlowThroughProj( - DataFlowCall call, CcCall innerCc, ApApprox apa, Configuration config - ) { - fwdFlowInMayFlowThrough(call, _, innerCc, _, _, _, _, apa, config) - } - - /** - * Same as `flowThroughOutOfCall`, but restricted to calls that are reached - * in the flow covered by `fwdFlow`, where data might flow through the target - * callable and back out at `call`. - */ - pragma[nomagic] - private predicate fwdFlowThroughOutOfCall( - DataFlowCall call, CcCall ccc, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow, - ApApprox argApa, ApApprox apa, Configuration config - ) { - fwdFlowInMayFlowThroughProj(call, ccc, argApa, config) and - flowThroughOutOfCall(call, ccc, ret, out, allowsFieldFlow, argApa, apa, config) + fwdFlowRetFromArg(ret, state, ccc, innerSummaryCtx, innerArgAp, innerArgApa, ap, apa, config) and + fwdFlowIsEntered(call, cc, ccc, summaryCtx, argAp, innerSummaryCtx, innerArgAp, config) } pragma[nomagic] - private predicate fwdFlowOutFromArg( - DataFlowCall call, NodeEx out, FlowState state, ParameterPosition summaryCtx, Ap argAp, Ap ap, - ApApprox apa, Configuration config + private predicate fwdFlowThrough( + DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, + ApOption argAp, Ap ap, ApApprox apa, RetNodeEx ret, ApApprox innerArgApa, Configuration config ) { - exists(RetNodeEx ret, boolean allowsFieldFlow, CcCall ccc, ApApprox argApa | - fwdFlowRetFromArg(pragma[only_bind_into](ret), state, pragma[only_bind_into](ccc), - summaryCtx, _, argAp, pragma[only_bind_into](argApa), ap, pragma[only_bind_into](apa), - config) and - fwdFlowThroughOutOfCall(call, ccc, ret, out, allowsFieldFlow, argApa, apa, config) and - (if allowsFieldFlow = false then ap instanceof ApNil else any()) - ) + fwdFlowThrough0(call, cc, state, ccc, summaryCtx, argAp, ap, apa, ret, _, _, innerArgApa, + config) } /** @@ -1571,12 +1552,14 @@ private module MkStage { */ pragma[nomagic] private predicate fwdFlowIsEntered( - DataFlowCall call, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - ParameterPosition pos, Ap ap, Configuration config + DataFlowCall call, Cc cc, CcCall innerCc, ParamNodeOption summaryCtx, ApOption argAp, + ParamNodeEx p, Ap ap, Configuration config ) { - exists(ParamNodeEx param | - fwdFlowInMayFlowThrough(call, cc, _, summaryCtx, argAp, param, ap, _, config) and - pos = param.getPosition() + exists(ApApprox apa | + fwdFlowIn(call, pragma[only_bind_into](p), _, cc, innerCc, summaryCtx, argAp, ap, + pragma[only_bind_into](apa), pragma[only_bind_into](config)) and + PrevStage::parameterMayFlowThrough(p, apa, config) and + PrevStage::callMayFlowThroughRev(call, pragma[only_bind_into](config)) ) } @@ -1596,23 +1579,31 @@ private module MkStage { fwdFlowConsCand(ap1, c, ap2, config) } + pragma[nomagic] + private predicate returnFlowsThrough0( + DataFlowCall call, FlowState state, CcCall ccc, Ap ap, ApApprox apa, RetNodeEx ret, + ParamNodeEx innerSummaryCtx, Ap innerArgAp, ApApprox innerArgApa, Configuration config + ) { + fwdFlowThrough0(call, _, state, ccc, _, _, ap, apa, ret, innerSummaryCtx, innerArgAp, + innerArgApa, config) + } + pragma[nomagic] private predicate returnFlowsThrough( - RetNodeEx ret, ReturnKindExt kind, FlowState state, CcCall ccc, ParamNodeEx p, Ap argAp, + RetNodeEx ret, ReturnPosition pos, FlowState state, CcCall ccc, ParamNodeEx p, Ap argAp, Ap ap, Configuration config ) { - exists(boolean allowsFieldFlow, ApApprox argApa, ApApprox apa | - fwdFlowRetFromArg(pragma[only_bind_into](ret), state, pragma[only_bind_into](ccc), _, p, - argAp, pragma[only_bind_into](argApa), ap, pragma[only_bind_into](apa), config) and - kind = ret.getKind() and - fwdFlowThroughOutOfCall(_, ccc, ret, _, allowsFieldFlow, argApa, apa, config) and - (if allowsFieldFlow = false then ap instanceof ApNil else any()) + exists(DataFlowCall call, ApApprox apa, boolean allowsFieldFlow, ApApprox innerArgApa | + returnFlowsThrough0(call, state, ccc, ap, apa, ret, p, argAp, innerArgApa, config) and + flowThroughOutOfCall(call, ccc, ret, _, allowsFieldFlow, innerArgApa, apa, config) and + pos = ret.getReturnPosition() and + if allowsFieldFlow = false then ap instanceof ApNil else any() ) } pragma[nomagic] private predicate flowThroughIntoCall( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap argAp, + DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap argAp, Ap ap, Configuration config ) { exists(ApApprox argApa | @@ -1620,7 +1611,7 @@ private module MkStage { allowsFieldFlow, argApa, pragma[only_bind_into](config)) and fwdFlow(arg, _, _, _, _, pragma[only_bind_into](argAp), argApa, pragma[only_bind_into](config)) and - returnFlowsThrough(_, _, _, _, p, pragma[only_bind_into](argAp), _, + returnFlowsThrough(_, _, _, _, p, pragma[only_bind_into](argAp), ap, pragma[only_bind_into](config)) and if allowsFieldFlow = false then argAp instanceof ApNil else any() ) @@ -1639,12 +1630,13 @@ private module MkStage { pragma[nomagic] private predicate flowOutOfCallAp( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, boolean allowsFieldFlow, + DataFlowCall call, RetNodeEx ret, ReturnPosition pos, NodeEx out, boolean allowsFieldFlow, Ap ap, Configuration config ) { exists(ApApprox apa | - flowOutOfCallApa(call, ret, kind, out, allowsFieldFlow, apa, config) and - fwdFlow(ret, _, _, _, _, ap, apa, config) + flowOutOfCallApa(call, ret, _, out, allowsFieldFlow, apa, config) and + fwdFlow(ret, _, _, _, _, ap, apa, config) and + pos = ret.getReturnPosition() ) } @@ -1739,17 +1731,17 @@ private module MkStage { ) or // flow through a callable - exists(DataFlowCall call, ReturnKindExt returnKind0, Ap returnAp0 | - revFlowInToReturn(call, node, state, returnKind0, returnAp0, ap, config) and - revFlowIsReturned(call, returnCtx, returnAp, returnKind0, returnAp0, config) + exists(DataFlowCall call, ParamNodeEx p, ReturnPosition pos, Ap innerReturnAp | + revFlowThrough(call, returnCtx, p, state, pos, returnAp, ap, innerReturnAp, config) and + flowThroughIntoCall(call, node, p, _, ap, innerReturnAp, config) ) or // flow out of a callable - exists(ReturnKindExt kind | - revFlowOut(_, node, kind, state, _, _, ap, config) and - if returnFlowsThrough(node, kind, state, _, _, _, ap, config) + exists(ReturnPosition pos | + revFlowOut(_, node, pos, state, _, _, ap, config) and + if returnFlowsThrough(node, pos, state, _, _, _, ap, config) then ( - returnCtx = TReturnCtxMaybeFlowThrough(kind) and + returnCtx = TReturnCtxMaybeFlowThrough(pos) and returnAp = apSome(ap) ) else ( returnCtx = TReturnCtxNoFlowThrough() and returnAp = apNone() @@ -1782,47 +1774,33 @@ private module MkStage { pragma[nomagic] private predicate revFlowOut( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, FlowState state, ReturnCtx returnCtx, + DataFlowCall call, RetNodeEx ret, ReturnPosition pos, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap, Configuration config ) { exists(NodeEx out, boolean allowsFieldFlow | revFlow(out, state, returnCtx, returnAp, ap, config) and - flowOutOfCallAp(call, ret, kind, out, allowsFieldFlow, ap, config) and + flowOutOfCallAp(call, ret, pos, out, allowsFieldFlow, ap, config) and if allowsFieldFlow = false then ap instanceof ApNil else any() ) } - /** - * Same as `flowThroughIntoCall`, but restricted to calls that are reached - * in the flow covered by `revFlow`, where data might flow through the target - * callable and back out at `call`. - */ - pragma[nomagic] - private predicate revFlowThroughIntoCall( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap argAp, - Configuration config - ) { - flowThroughIntoCall(call, arg, p, allowsFieldFlow, argAp, config) and - revFlowIsReturned(call, _, _, _, _, config) - } - pragma[nomagic] private predicate revFlowParamToReturn( - ParamNodeEx p, FlowState state, ReturnKindExt kind, Ap returnAp, Ap ap, Configuration config + ParamNodeEx p, FlowState state, ReturnPosition pos, Ap returnAp, Ap ap, Configuration config ) { - revFlow(p, state, TReturnCtxMaybeFlowThrough(kind), apSome(returnAp), ap, config) and - parameterFlowThroughAllowed(p, kind) + revFlow(pragma[only_bind_into](p), state, TReturnCtxMaybeFlowThrough(pos), apSome(returnAp), + pragma[only_bind_into](ap), pragma[only_bind_into](config)) and + parameterFlowThroughAllowed(p, pos.getKind()) and + PrevStage::parameterMayFlowThrough(p, getApprox(ap), config) } pragma[nomagic] - private predicate revFlowInToReturn( - DataFlowCall call, ArgNodeEx arg, FlowState state, ReturnKindExt kind, Ap returnAp, Ap ap, - Configuration config + private predicate revFlowThrough( + DataFlowCall call, ReturnCtx returnCtx, ParamNodeEx p, FlowState state, ReturnPosition pos, + ApOption returnAp, Ap ap, Ap innerReturnAp, Configuration config ) { - exists(ParamNodeEx p, boolean allowsFieldFlow | - revFlowParamToReturn(p, state, kind, returnAp, ap, config) and - revFlowThroughIntoCall(call, arg, p, allowsFieldFlow, ap, config) - ) + revFlowParamToReturn(p, state, pos, innerReturnAp, ap, config) and + revFlowIsReturned(call, returnCtx, returnAp, pos, innerReturnAp, config) } /** @@ -1832,12 +1810,12 @@ private module MkStage { */ pragma[nomagic] private predicate revFlowIsReturned( - DataFlowCall call, ReturnCtx returnCtx, ApOption returnAp, ReturnKindExt kind, Ap ap, + DataFlowCall call, ReturnCtx returnCtx, ApOption returnAp, ReturnPosition pos, Ap ap, Configuration config ) { exists(RetNodeEx ret, FlowState state, CcCall ccc | - revFlowOut(call, ret, kind, state, returnCtx, returnAp, ap, config) and - returnFlowsThrough(ret, kind, state, ccc, _, _, ap, config) and + revFlowOut(call, ret, pos, state, returnCtx, returnAp, ap, config) and + returnFlowsThrough(ret, pos, state, ccc, _, _, ap, config) and matchesCall(ccc, call) ) } @@ -1915,17 +1893,17 @@ private module MkStage { pragma[nomagic] private predicate parameterFlowsThroughRev( - ParamNodeEx p, Ap ap, ReturnKindExt kind, Ap returnAp, Configuration config + ParamNodeEx p, Ap ap, ReturnPosition pos, Ap returnAp, Configuration config ) { - revFlow(p, _, TReturnCtxMaybeFlowThrough(kind), apSome(returnAp), ap, config) and - parameterFlowThroughAllowed(p, kind) + revFlow(p, _, TReturnCtxMaybeFlowThrough(pos), apSome(returnAp), ap, config) and + parameterFlowThroughAllowed(p, pos.getKind()) } pragma[nomagic] predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap, Configuration config) { - exists(RetNodeEx ret, ReturnKindExt kind | - returnFlowsThrough(ret, kind, _, _, p, ap, _, config) and - parameterFlowsThroughRev(p, ap, kind, _, config) + exists(RetNodeEx ret, ReturnPosition pos | + returnFlowsThrough(ret, pos, _, _, p, ap, _, config) and + parameterFlowsThroughRev(p, ap, pos, _, config) ) } @@ -1933,20 +1911,21 @@ private module MkStage { predicate returnMayFlowThrough( RetNodeEx ret, Ap argAp, Ap ap, ReturnKindExt kind, Configuration config ) { - exists(ParamNodeEx p | - returnFlowsThrough(ret, kind, _, _, p, argAp, ap, config) and - parameterFlowsThroughRev(p, argAp, kind, ap, config) + exists(ParamNodeEx p, ReturnPosition pos | + returnFlowsThrough(ret, pos, _, _, p, argAp, ap, config) and + parameterFlowsThroughRev(p, argAp, pos, ap, config) and + kind = pos.getKind() ) } pragma[nomagic] - predicate revFlowInToReturnIsReturned( + private predicate revFlowThroughArg( DataFlowCall call, ArgNodeEx arg, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap, Configuration config ) { - exists(ReturnKindExt returnKind0, Ap returnAp0 | - revFlowInToReturn(call, arg, state, returnKind0, returnAp0, ap, config) and - revFlowIsReturned(call, returnCtx, returnAp, returnKind0, returnAp0, config) + exists(ParamNodeEx p, ReturnPosition pos, Ap innerReturnAp | + revFlowThrough(call, returnCtx, p, state, pos, returnAp, ap, innerReturnAp, config) and + flowThroughIntoCall(call, arg, p, _, ap, innerReturnAp, config) ) } @@ -1954,7 +1933,7 @@ private module MkStage { predicate callMayFlowThroughRev(DataFlowCall call, Configuration config) { exists(ArgNodeEx arg, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap | revFlow(arg, state, returnCtx, returnAp, ap, config) and - revFlowInToReturnIsReturned(call, arg, state, returnCtx, returnAp, ap, config) + revFlowThroughArg(call, arg, state, returnCtx, returnAp, ap, config) ) } @@ -1967,8 +1946,9 @@ private module MkStage { conscand = count(TypedContent f0, Ap ap | fwdConsCand(f0, ap, config)) and states = count(FlowState state | fwdFlow(_, state, _, _, _, _, config)) and tuples = - count(NodeEx n, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - Ap ap | fwdFlow(n, state, cc, summaryCtx, argAp, ap, config)) + count(NodeEx n, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap | + fwdFlow(n, state, cc, summaryCtx, argAp, ap, config) + ) or fwd = false and nodes = count(NodeEx node | revFlow(node, _, _, _, _, config)) and @@ -2823,13 +2803,12 @@ private Configuration unbindConf(Configuration conf) { pragma[nomagic] private predicate nodeMayUseSummary0( - NodeEx n, DataFlowCallable c, ParameterPosition pos, FlowState state, AccessPathApprox apa, - Configuration config + NodeEx n, ParamNodeEx p, FlowState state, AccessPathApprox apa, Configuration config ) { exists(AccessPathApprox apa0 | - c = n.getEnclosingCallable() and + Stage5::parameterMayFlowThrough(p, _, _) and Stage5::revFlow(n, state, TReturnCtxMaybeFlowThrough(_), _, apa0, config) and - Stage5::fwdFlow(n, state, any(CallContextCall ccc), TParameterPositionSome(pos), + Stage5::fwdFlow(n, state, any(CallContextCall ccc), TParamNodeSome(p.asNode()), TAccessPathApproxSome(apa), apa0, config) ) } @@ -2838,10 +2817,9 @@ pragma[nomagic] private predicate nodeMayUseSummary( NodeEx n, FlowState state, AccessPathApprox apa, Configuration config ) { - exists(DataFlowCallable c, ParameterPosition pos, ParamNodeEx p | + exists(ParamNodeEx p | Stage5::parameterMayFlowThrough(p, apa, config) and - nodeMayUseSummary0(n, c, pos, state, apa, config) and - p.isParameterOf(c, pos) + nodeMayUseSummary0(n, p, state, apa, config) ) } diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl5.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl5.qll index 6741ccc2f06..1228d00b6ba 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl5.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl5.qll @@ -622,7 +622,11 @@ private predicate parameterFlowThroughAllowed(ParamNodeEx p, ReturnKindExt kind) } private module Stage1 implements StageSig { - class Ap = Unit; + class Ap extends int { + // workaround for bad functionality-induced joins (happens when using `Unit`) + pragma[nomagic] + Ap() { this in [0 .. 1] and this < 1 } + } private class Cc = boolean; @@ -1327,8 +1331,8 @@ private module MkStage { */ pragma[nomagic] additional predicate fwdFlow( - NodeEx node, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - Ap ap, ApApprox apa, Configuration config + NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, + ApApprox apa, Configuration config ) { fwdFlow0(node, state, cc, summaryCtx, argAp, ap, apa, config) and PrevStage::revFlow(node, state, apa, config) and @@ -1337,21 +1341,21 @@ private module MkStage { pragma[inline] additional predicate fwdFlow( - NodeEx node, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - Ap ap, Configuration config + NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, + Configuration config ) { fwdFlow(node, state, cc, summaryCtx, argAp, ap, _, config) } pragma[nomagic] private predicate fwdFlow0( - NodeEx node, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - Ap ap, ApApprox apa, Configuration config + NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, + ApApprox apa, Configuration config ) { sourceNode(node, state, config) and (if hasSourceCallCtx(config) then cc = ccSomeCall() else cc = ccNone()) and argAp = apNone() and - summaryCtx = TParameterPositionNone() and + summaryCtx = TParamNodeNone() and ap = getApNil(node) and apa = getApprox(ap) or @@ -1372,7 +1376,7 @@ private module MkStage { fwdFlow(mid, pragma[only_bind_into](state), _, _, _, ap, apa, pragma[only_bind_into](config)) and jumpStep(mid, node, config) and cc = ccNone() and - summaryCtx = TParameterPositionNone() and + summaryCtx = TParamNodeNone() and argAp = apNone() ) or @@ -1380,7 +1384,7 @@ private module MkStage { fwdFlow(mid, state, _, _, _, nil, pragma[only_bind_into](config)) and additionalJumpStep(mid, node, config) and cc = ccNone() and - summaryCtx = TParameterPositionNone() and + summaryCtx = TParamNodeNone() and argAp = apNone() and ap = getApNil(node) and apa = getApprox(ap) @@ -1390,7 +1394,7 @@ private module MkStage { fwdFlow(mid, state0, _, _, _, nil, pragma[only_bind_into](config)) and additionalJumpStateStep(mid, state0, node, state, config) and cc = ccNone() and - summaryCtx = TParameterPositionNone() and + summaryCtx = TParamNodeNone() and argAp = apNone() and ap = getApNil(node) and apa = getApprox(ap) @@ -1414,10 +1418,10 @@ private module MkStage { fwdFlowIn(_, node, state, _, cc, _, _, ap, apa, config) and if PrevStage::parameterMayFlowThrough(node, apa, config) then ( - summaryCtx = TParameterPositionSome(node.(ParamNodeEx).getPosition()) and + summaryCtx = TParamNodeSome(node.asNode()) and argAp = apSome(ap) ) else ( - summaryCtx = TParameterPositionNone() and argAp = apNone() + summaryCtx = TParamNodeNone() and argAp = apNone() ) or // flow out of a callable @@ -1433,16 +1437,19 @@ private module MkStage { ) or // flow through a callable - exists(DataFlowCall call, ParameterPosition summaryCtx0, Ap argAp0 | - fwdFlowOutFromArg(call, node, state, summaryCtx0, argAp0, ap, apa, config) and - fwdFlowIsEntered(call, cc, summaryCtx, argAp, summaryCtx0, argAp0, config) + exists( + DataFlowCall call, CcCall ccc, RetNodeEx ret, boolean allowsFieldFlow, ApApprox innerArgApa + | + fwdFlowThrough(call, cc, state, ccc, summaryCtx, argAp, ap, apa, ret, innerArgApa, config) and + flowThroughOutOfCall(call, ccc, ret, node, allowsFieldFlow, innerArgApa, apa, config) and + if allowsFieldFlow = false then ap instanceof ApNil else any() ) } pragma[nomagic] private predicate fwdFlowStore( NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, FlowState state, Cc cc, - ParameterPositionOption summaryCtx, ApOption argAp, Configuration config + ParamNodeOption summaryCtx, ApOption argAp, Configuration config ) { exists(DataFlowType contentType, ApApprox apa1 | fwdFlow(node1, state, cc, summaryCtx, argAp, ap1, apa1, config) and @@ -1473,8 +1480,8 @@ private module MkStage { pragma[nomagic] private predicate fwdFlowRead0( - NodeEx node1, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - ApNonNil ap, Configuration config + NodeEx node1, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, ApNonNil ap, + Configuration config ) { fwdFlow(node1, state, cc, summaryCtx, argAp, ap, config) and PrevStage::readStepCand(node1, _, _, config) @@ -1483,7 +1490,7 @@ private module MkStage { pragma[nomagic] private predicate fwdFlowRead( Ap ap, Content c, NodeEx node1, NodeEx node2, FlowState state, Cc cc, - ParameterPositionOption summaryCtx, ApOption argAp, Configuration config + ParamNodeOption summaryCtx, ApOption argAp, Configuration config ) { fwdFlowRead0(node1, state, cc, summaryCtx, argAp, ap, config) and PrevStage::readStepCand(node1, c, node2, config) and @@ -1493,7 +1500,7 @@ private module MkStage { pragma[nomagic] private predicate fwdFlowIn( DataFlowCall call, ParamNodeEx p, FlowState state, Cc outercc, CcCall innercc, - ParameterPositionOption summaryCtx, ApOption argAp, Ap ap, ApApprox apa, Configuration config + ParamNodeOption summaryCtx, ApOption argAp, Ap ap, ApApprox apa, Configuration config ) { exists(ArgNodeEx arg, boolean allowsFieldFlow | fwdFlow(arg, state, outercc, summaryCtx, argAp, ap, apa, config) and @@ -1505,64 +1512,38 @@ private module MkStage { pragma[nomagic] private predicate fwdFlowRetFromArg( - RetNodeEx ret, FlowState state, CcCall ccc, ParameterPosition summaryCtx, ParamNodeEx p, - Ap argAp, ApApprox argApa, Ap ap, ApApprox apa, Configuration config + RetNodeEx ret, FlowState state, CcCall ccc, ParamNodeEx summaryCtx, Ap argAp, ApApprox argApa, + Ap ap, ApApprox apa, Configuration config ) { - exists(DataFlowCallable c, ReturnKindExt kind | + exists(ReturnKindExt kind | fwdFlow(pragma[only_bind_into](ret), state, ccc, - TParameterPositionSome(pragma[only_bind_into](summaryCtx)), apSome(argAp), ap, apa, config) and - getApprox(argAp) = argApa and - c = ret.getEnclosingCallable() and + TParamNodeSome(pragma[only_bind_into](summaryCtx.asNode())), + pragma[only_bind_into](apSome(argAp)), ap, pragma[only_bind_into](apa), + pragma[only_bind_into](config)) and kind = ret.getKind() and - p.isParameterOf(c, pragma[only_bind_into](summaryCtx)) and - parameterFlowThroughAllowed(p, kind) + parameterFlowThroughAllowed(summaryCtx, kind) and + argApa = getApprox(argAp) and + PrevStage::returnMayFlowThrough(ret, argApa, apa, kind, pragma[only_bind_into](config)) ) } pragma[inline] - private predicate fwdFlowInMayFlowThrough( - DataFlowCall call, Cc cc, CcCall innerCc, ParameterPositionOption summaryCtx, ApOption argAp, - ParamNodeEx param, Ap ap, ApApprox apa, Configuration config + private predicate fwdFlowThrough0( + DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, + ApOption argAp, Ap ap, ApApprox apa, RetNodeEx ret, ParamNodeEx innerSummaryCtx, + Ap innerArgAp, ApApprox innerArgApa, Configuration config ) { - fwdFlowIn(call, pragma[only_bind_into](param), _, cc, innerCc, summaryCtx, argAp, ap, - pragma[only_bind_into](apa), pragma[only_bind_into](config)) and - PrevStage::parameterMayFlowThrough(param, apa, config) - } - - // dedup before joining with `flowThroughOutOfCall` - pragma[nomagic] - private predicate fwdFlowInMayFlowThroughProj( - DataFlowCall call, CcCall innerCc, ApApprox apa, Configuration config - ) { - fwdFlowInMayFlowThrough(call, _, innerCc, _, _, _, _, apa, config) - } - - /** - * Same as `flowThroughOutOfCall`, but restricted to calls that are reached - * in the flow covered by `fwdFlow`, where data might flow through the target - * callable and back out at `call`. - */ - pragma[nomagic] - private predicate fwdFlowThroughOutOfCall( - DataFlowCall call, CcCall ccc, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow, - ApApprox argApa, ApApprox apa, Configuration config - ) { - fwdFlowInMayFlowThroughProj(call, ccc, argApa, config) and - flowThroughOutOfCall(call, ccc, ret, out, allowsFieldFlow, argApa, apa, config) + fwdFlowRetFromArg(ret, state, ccc, innerSummaryCtx, innerArgAp, innerArgApa, ap, apa, config) and + fwdFlowIsEntered(call, cc, ccc, summaryCtx, argAp, innerSummaryCtx, innerArgAp, config) } pragma[nomagic] - private predicate fwdFlowOutFromArg( - DataFlowCall call, NodeEx out, FlowState state, ParameterPosition summaryCtx, Ap argAp, Ap ap, - ApApprox apa, Configuration config + private predicate fwdFlowThrough( + DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, + ApOption argAp, Ap ap, ApApprox apa, RetNodeEx ret, ApApprox innerArgApa, Configuration config ) { - exists(RetNodeEx ret, boolean allowsFieldFlow, CcCall ccc, ApApprox argApa | - fwdFlowRetFromArg(pragma[only_bind_into](ret), state, pragma[only_bind_into](ccc), - summaryCtx, _, argAp, pragma[only_bind_into](argApa), ap, pragma[only_bind_into](apa), - config) and - fwdFlowThroughOutOfCall(call, ccc, ret, out, allowsFieldFlow, argApa, apa, config) and - (if allowsFieldFlow = false then ap instanceof ApNil else any()) - ) + fwdFlowThrough0(call, cc, state, ccc, summaryCtx, argAp, ap, apa, ret, _, _, innerArgApa, + config) } /** @@ -1571,12 +1552,14 @@ private module MkStage { */ pragma[nomagic] private predicate fwdFlowIsEntered( - DataFlowCall call, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - ParameterPosition pos, Ap ap, Configuration config + DataFlowCall call, Cc cc, CcCall innerCc, ParamNodeOption summaryCtx, ApOption argAp, + ParamNodeEx p, Ap ap, Configuration config ) { - exists(ParamNodeEx param | - fwdFlowInMayFlowThrough(call, cc, _, summaryCtx, argAp, param, ap, _, config) and - pos = param.getPosition() + exists(ApApprox apa | + fwdFlowIn(call, pragma[only_bind_into](p), _, cc, innerCc, summaryCtx, argAp, ap, + pragma[only_bind_into](apa), pragma[only_bind_into](config)) and + PrevStage::parameterMayFlowThrough(p, apa, config) and + PrevStage::callMayFlowThroughRev(call, pragma[only_bind_into](config)) ) } @@ -1596,23 +1579,31 @@ private module MkStage { fwdFlowConsCand(ap1, c, ap2, config) } + pragma[nomagic] + private predicate returnFlowsThrough0( + DataFlowCall call, FlowState state, CcCall ccc, Ap ap, ApApprox apa, RetNodeEx ret, + ParamNodeEx innerSummaryCtx, Ap innerArgAp, ApApprox innerArgApa, Configuration config + ) { + fwdFlowThrough0(call, _, state, ccc, _, _, ap, apa, ret, innerSummaryCtx, innerArgAp, + innerArgApa, config) + } + pragma[nomagic] private predicate returnFlowsThrough( - RetNodeEx ret, ReturnKindExt kind, FlowState state, CcCall ccc, ParamNodeEx p, Ap argAp, + RetNodeEx ret, ReturnPosition pos, FlowState state, CcCall ccc, ParamNodeEx p, Ap argAp, Ap ap, Configuration config ) { - exists(boolean allowsFieldFlow, ApApprox argApa, ApApprox apa | - fwdFlowRetFromArg(pragma[only_bind_into](ret), state, pragma[only_bind_into](ccc), _, p, - argAp, pragma[only_bind_into](argApa), ap, pragma[only_bind_into](apa), config) and - kind = ret.getKind() and - fwdFlowThroughOutOfCall(_, ccc, ret, _, allowsFieldFlow, argApa, apa, config) and - (if allowsFieldFlow = false then ap instanceof ApNil else any()) + exists(DataFlowCall call, ApApprox apa, boolean allowsFieldFlow, ApApprox innerArgApa | + returnFlowsThrough0(call, state, ccc, ap, apa, ret, p, argAp, innerArgApa, config) and + flowThroughOutOfCall(call, ccc, ret, _, allowsFieldFlow, innerArgApa, apa, config) and + pos = ret.getReturnPosition() and + if allowsFieldFlow = false then ap instanceof ApNil else any() ) } pragma[nomagic] private predicate flowThroughIntoCall( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap argAp, + DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap argAp, Ap ap, Configuration config ) { exists(ApApprox argApa | @@ -1620,7 +1611,7 @@ private module MkStage { allowsFieldFlow, argApa, pragma[only_bind_into](config)) and fwdFlow(arg, _, _, _, _, pragma[only_bind_into](argAp), argApa, pragma[only_bind_into](config)) and - returnFlowsThrough(_, _, _, _, p, pragma[only_bind_into](argAp), _, + returnFlowsThrough(_, _, _, _, p, pragma[only_bind_into](argAp), ap, pragma[only_bind_into](config)) and if allowsFieldFlow = false then argAp instanceof ApNil else any() ) @@ -1639,12 +1630,13 @@ private module MkStage { pragma[nomagic] private predicate flowOutOfCallAp( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, boolean allowsFieldFlow, + DataFlowCall call, RetNodeEx ret, ReturnPosition pos, NodeEx out, boolean allowsFieldFlow, Ap ap, Configuration config ) { exists(ApApprox apa | - flowOutOfCallApa(call, ret, kind, out, allowsFieldFlow, apa, config) and - fwdFlow(ret, _, _, _, _, ap, apa, config) + flowOutOfCallApa(call, ret, _, out, allowsFieldFlow, apa, config) and + fwdFlow(ret, _, _, _, _, ap, apa, config) and + pos = ret.getReturnPosition() ) } @@ -1739,17 +1731,17 @@ private module MkStage { ) or // flow through a callable - exists(DataFlowCall call, ReturnKindExt returnKind0, Ap returnAp0 | - revFlowInToReturn(call, node, state, returnKind0, returnAp0, ap, config) and - revFlowIsReturned(call, returnCtx, returnAp, returnKind0, returnAp0, config) + exists(DataFlowCall call, ParamNodeEx p, ReturnPosition pos, Ap innerReturnAp | + revFlowThrough(call, returnCtx, p, state, pos, returnAp, ap, innerReturnAp, config) and + flowThroughIntoCall(call, node, p, _, ap, innerReturnAp, config) ) or // flow out of a callable - exists(ReturnKindExt kind | - revFlowOut(_, node, kind, state, _, _, ap, config) and - if returnFlowsThrough(node, kind, state, _, _, _, ap, config) + exists(ReturnPosition pos | + revFlowOut(_, node, pos, state, _, _, ap, config) and + if returnFlowsThrough(node, pos, state, _, _, _, ap, config) then ( - returnCtx = TReturnCtxMaybeFlowThrough(kind) and + returnCtx = TReturnCtxMaybeFlowThrough(pos) and returnAp = apSome(ap) ) else ( returnCtx = TReturnCtxNoFlowThrough() and returnAp = apNone() @@ -1782,47 +1774,33 @@ private module MkStage { pragma[nomagic] private predicate revFlowOut( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, FlowState state, ReturnCtx returnCtx, + DataFlowCall call, RetNodeEx ret, ReturnPosition pos, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap, Configuration config ) { exists(NodeEx out, boolean allowsFieldFlow | revFlow(out, state, returnCtx, returnAp, ap, config) and - flowOutOfCallAp(call, ret, kind, out, allowsFieldFlow, ap, config) and + flowOutOfCallAp(call, ret, pos, out, allowsFieldFlow, ap, config) and if allowsFieldFlow = false then ap instanceof ApNil else any() ) } - /** - * Same as `flowThroughIntoCall`, but restricted to calls that are reached - * in the flow covered by `revFlow`, where data might flow through the target - * callable and back out at `call`. - */ - pragma[nomagic] - private predicate revFlowThroughIntoCall( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap argAp, - Configuration config - ) { - flowThroughIntoCall(call, arg, p, allowsFieldFlow, argAp, config) and - revFlowIsReturned(call, _, _, _, _, config) - } - pragma[nomagic] private predicate revFlowParamToReturn( - ParamNodeEx p, FlowState state, ReturnKindExt kind, Ap returnAp, Ap ap, Configuration config + ParamNodeEx p, FlowState state, ReturnPosition pos, Ap returnAp, Ap ap, Configuration config ) { - revFlow(p, state, TReturnCtxMaybeFlowThrough(kind), apSome(returnAp), ap, config) and - parameterFlowThroughAllowed(p, kind) + revFlow(pragma[only_bind_into](p), state, TReturnCtxMaybeFlowThrough(pos), apSome(returnAp), + pragma[only_bind_into](ap), pragma[only_bind_into](config)) and + parameterFlowThroughAllowed(p, pos.getKind()) and + PrevStage::parameterMayFlowThrough(p, getApprox(ap), config) } pragma[nomagic] - private predicate revFlowInToReturn( - DataFlowCall call, ArgNodeEx arg, FlowState state, ReturnKindExt kind, Ap returnAp, Ap ap, - Configuration config + private predicate revFlowThrough( + DataFlowCall call, ReturnCtx returnCtx, ParamNodeEx p, FlowState state, ReturnPosition pos, + ApOption returnAp, Ap ap, Ap innerReturnAp, Configuration config ) { - exists(ParamNodeEx p, boolean allowsFieldFlow | - revFlowParamToReturn(p, state, kind, returnAp, ap, config) and - revFlowThroughIntoCall(call, arg, p, allowsFieldFlow, ap, config) - ) + revFlowParamToReturn(p, state, pos, innerReturnAp, ap, config) and + revFlowIsReturned(call, returnCtx, returnAp, pos, innerReturnAp, config) } /** @@ -1832,12 +1810,12 @@ private module MkStage { */ pragma[nomagic] private predicate revFlowIsReturned( - DataFlowCall call, ReturnCtx returnCtx, ApOption returnAp, ReturnKindExt kind, Ap ap, + DataFlowCall call, ReturnCtx returnCtx, ApOption returnAp, ReturnPosition pos, Ap ap, Configuration config ) { exists(RetNodeEx ret, FlowState state, CcCall ccc | - revFlowOut(call, ret, kind, state, returnCtx, returnAp, ap, config) and - returnFlowsThrough(ret, kind, state, ccc, _, _, ap, config) and + revFlowOut(call, ret, pos, state, returnCtx, returnAp, ap, config) and + returnFlowsThrough(ret, pos, state, ccc, _, _, ap, config) and matchesCall(ccc, call) ) } @@ -1915,17 +1893,17 @@ private module MkStage { pragma[nomagic] private predicate parameterFlowsThroughRev( - ParamNodeEx p, Ap ap, ReturnKindExt kind, Ap returnAp, Configuration config + ParamNodeEx p, Ap ap, ReturnPosition pos, Ap returnAp, Configuration config ) { - revFlow(p, _, TReturnCtxMaybeFlowThrough(kind), apSome(returnAp), ap, config) and - parameterFlowThroughAllowed(p, kind) + revFlow(p, _, TReturnCtxMaybeFlowThrough(pos), apSome(returnAp), ap, config) and + parameterFlowThroughAllowed(p, pos.getKind()) } pragma[nomagic] predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap, Configuration config) { - exists(RetNodeEx ret, ReturnKindExt kind | - returnFlowsThrough(ret, kind, _, _, p, ap, _, config) and - parameterFlowsThroughRev(p, ap, kind, _, config) + exists(RetNodeEx ret, ReturnPosition pos | + returnFlowsThrough(ret, pos, _, _, p, ap, _, config) and + parameterFlowsThroughRev(p, ap, pos, _, config) ) } @@ -1933,20 +1911,21 @@ private module MkStage { predicate returnMayFlowThrough( RetNodeEx ret, Ap argAp, Ap ap, ReturnKindExt kind, Configuration config ) { - exists(ParamNodeEx p | - returnFlowsThrough(ret, kind, _, _, p, argAp, ap, config) and - parameterFlowsThroughRev(p, argAp, kind, ap, config) + exists(ParamNodeEx p, ReturnPosition pos | + returnFlowsThrough(ret, pos, _, _, p, argAp, ap, config) and + parameterFlowsThroughRev(p, argAp, pos, ap, config) and + kind = pos.getKind() ) } pragma[nomagic] - predicate revFlowInToReturnIsReturned( + private predicate revFlowThroughArg( DataFlowCall call, ArgNodeEx arg, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap, Configuration config ) { - exists(ReturnKindExt returnKind0, Ap returnAp0 | - revFlowInToReturn(call, arg, state, returnKind0, returnAp0, ap, config) and - revFlowIsReturned(call, returnCtx, returnAp, returnKind0, returnAp0, config) + exists(ParamNodeEx p, ReturnPosition pos, Ap innerReturnAp | + revFlowThrough(call, returnCtx, p, state, pos, returnAp, ap, innerReturnAp, config) and + flowThroughIntoCall(call, arg, p, _, ap, innerReturnAp, config) ) } @@ -1954,7 +1933,7 @@ private module MkStage { predicate callMayFlowThroughRev(DataFlowCall call, Configuration config) { exists(ArgNodeEx arg, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap | revFlow(arg, state, returnCtx, returnAp, ap, config) and - revFlowInToReturnIsReturned(call, arg, state, returnCtx, returnAp, ap, config) + revFlowThroughArg(call, arg, state, returnCtx, returnAp, ap, config) ) } @@ -1967,8 +1946,9 @@ private module MkStage { conscand = count(TypedContent f0, Ap ap | fwdConsCand(f0, ap, config)) and states = count(FlowState state | fwdFlow(_, state, _, _, _, _, config)) and tuples = - count(NodeEx n, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - Ap ap | fwdFlow(n, state, cc, summaryCtx, argAp, ap, config)) + count(NodeEx n, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap | + fwdFlow(n, state, cc, summaryCtx, argAp, ap, config) + ) or fwd = false and nodes = count(NodeEx node | revFlow(node, _, _, _, _, config)) and @@ -2823,13 +2803,12 @@ private Configuration unbindConf(Configuration conf) { pragma[nomagic] private predicate nodeMayUseSummary0( - NodeEx n, DataFlowCallable c, ParameterPosition pos, FlowState state, AccessPathApprox apa, - Configuration config + NodeEx n, ParamNodeEx p, FlowState state, AccessPathApprox apa, Configuration config ) { exists(AccessPathApprox apa0 | - c = n.getEnclosingCallable() and + Stage5::parameterMayFlowThrough(p, _, _) and Stage5::revFlow(n, state, TReturnCtxMaybeFlowThrough(_), _, apa0, config) and - Stage5::fwdFlow(n, state, any(CallContextCall ccc), TParameterPositionSome(pos), + Stage5::fwdFlow(n, state, any(CallContextCall ccc), TParamNodeSome(p.asNode()), TAccessPathApproxSome(apa), apa0, config) ) } @@ -2838,10 +2817,9 @@ pragma[nomagic] private predicate nodeMayUseSummary( NodeEx n, FlowState state, AccessPathApprox apa, Configuration config ) { - exists(DataFlowCallable c, ParameterPosition pos, ParamNodeEx p | + exists(ParamNodeEx p | Stage5::parameterMayFlowThrough(p, apa, config) and - nodeMayUseSummary0(n, c, pos, state, apa, config) and - p.isParameterOf(c, pos) + nodeMayUseSummary0(n, p, state, apa, config) ) } diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImplCommon.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImplCommon.qll index c66aefced8d..9aa6a529a5b 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImplCommon.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImplCommon.qll @@ -916,15 +916,15 @@ private module Cached { TDataFlowCallSome(DataFlowCall call) cached - newtype TParameterPositionOption = - TParameterPositionNone() or - TParameterPositionSome(ParameterPosition pos) + newtype TParamNodeOption = + TParamNodeNone() or + TParamNodeSome(ParamNode p) cached newtype TReturnCtx = TReturnCtxNone() or TReturnCtxNoFlowThrough() or - TReturnCtxMaybeFlowThrough(ReturnKindExt kind) + TReturnCtxMaybeFlowThrough(ReturnPosition pos) cached newtype TTypedContentApprox = @@ -1343,15 +1343,15 @@ class DataFlowCallOption extends TDataFlowCallOption { } } -/** An optional `ParameterPosition`. */ -class ParameterPositionOption extends TParameterPositionOption { +/** An optional `ParamNode`. */ +class ParamNodeOption extends TParamNodeOption { string toString() { - this = TParameterPositionNone() and + this = TParamNodeNone() and result = "(none)" or - exists(ParameterPosition pos | - this = TParameterPositionSome(pos) and - result = pos.toString() + exists(ParamNode p | + this = TParamNodeSome(p) and + result = p.toString() ) } } @@ -1363,7 +1363,7 @@ class ParameterPositionOption extends TParameterPositionOption { * * - `TReturnCtxNone()`: no return flow. * - `TReturnCtxNoFlowThrough()`: return flow, but flow through is not possible. - * - `TReturnCtxMaybeFlowThrough(ReturnKindExt kind)`: return flow, of kind `kind`, and + * - `TReturnCtxMaybeFlowThrough(ReturnPosition pos)`: return flow, of kind `pos`, and * flow through may be possible. */ class ReturnCtx extends TReturnCtx { @@ -1374,9 +1374,9 @@ class ReturnCtx extends TReturnCtx { this = TReturnCtxNoFlowThrough() and result = "(no flow through)" or - exists(ReturnKindExt kind | - this = TReturnCtxMaybeFlowThrough(kind) and - result = kind.toString() + exists(ReturnPosition pos | + this = TReturnCtxMaybeFlowThrough(pos) and + result = pos.toString() ) } } diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImplForContentDataFlow.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImplForContentDataFlow.qll index 6741ccc2f06..1228d00b6ba 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImplForContentDataFlow.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImplForContentDataFlow.qll @@ -622,7 +622,11 @@ private predicate parameterFlowThroughAllowed(ParamNodeEx p, ReturnKindExt kind) } private module Stage1 implements StageSig { - class Ap = Unit; + class Ap extends int { + // workaround for bad functionality-induced joins (happens when using `Unit`) + pragma[nomagic] + Ap() { this in [0 .. 1] and this < 1 } + } private class Cc = boolean; @@ -1327,8 +1331,8 @@ private module MkStage { */ pragma[nomagic] additional predicate fwdFlow( - NodeEx node, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - Ap ap, ApApprox apa, Configuration config + NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, + ApApprox apa, Configuration config ) { fwdFlow0(node, state, cc, summaryCtx, argAp, ap, apa, config) and PrevStage::revFlow(node, state, apa, config) and @@ -1337,21 +1341,21 @@ private module MkStage { pragma[inline] additional predicate fwdFlow( - NodeEx node, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - Ap ap, Configuration config + NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, + Configuration config ) { fwdFlow(node, state, cc, summaryCtx, argAp, ap, _, config) } pragma[nomagic] private predicate fwdFlow0( - NodeEx node, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - Ap ap, ApApprox apa, Configuration config + NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, + ApApprox apa, Configuration config ) { sourceNode(node, state, config) and (if hasSourceCallCtx(config) then cc = ccSomeCall() else cc = ccNone()) and argAp = apNone() and - summaryCtx = TParameterPositionNone() and + summaryCtx = TParamNodeNone() and ap = getApNil(node) and apa = getApprox(ap) or @@ -1372,7 +1376,7 @@ private module MkStage { fwdFlow(mid, pragma[only_bind_into](state), _, _, _, ap, apa, pragma[only_bind_into](config)) and jumpStep(mid, node, config) and cc = ccNone() and - summaryCtx = TParameterPositionNone() and + summaryCtx = TParamNodeNone() and argAp = apNone() ) or @@ -1380,7 +1384,7 @@ private module MkStage { fwdFlow(mid, state, _, _, _, nil, pragma[only_bind_into](config)) and additionalJumpStep(mid, node, config) and cc = ccNone() and - summaryCtx = TParameterPositionNone() and + summaryCtx = TParamNodeNone() and argAp = apNone() and ap = getApNil(node) and apa = getApprox(ap) @@ -1390,7 +1394,7 @@ private module MkStage { fwdFlow(mid, state0, _, _, _, nil, pragma[only_bind_into](config)) and additionalJumpStateStep(mid, state0, node, state, config) and cc = ccNone() and - summaryCtx = TParameterPositionNone() and + summaryCtx = TParamNodeNone() and argAp = apNone() and ap = getApNil(node) and apa = getApprox(ap) @@ -1414,10 +1418,10 @@ private module MkStage { fwdFlowIn(_, node, state, _, cc, _, _, ap, apa, config) and if PrevStage::parameterMayFlowThrough(node, apa, config) then ( - summaryCtx = TParameterPositionSome(node.(ParamNodeEx).getPosition()) and + summaryCtx = TParamNodeSome(node.asNode()) and argAp = apSome(ap) ) else ( - summaryCtx = TParameterPositionNone() and argAp = apNone() + summaryCtx = TParamNodeNone() and argAp = apNone() ) or // flow out of a callable @@ -1433,16 +1437,19 @@ private module MkStage { ) or // flow through a callable - exists(DataFlowCall call, ParameterPosition summaryCtx0, Ap argAp0 | - fwdFlowOutFromArg(call, node, state, summaryCtx0, argAp0, ap, apa, config) and - fwdFlowIsEntered(call, cc, summaryCtx, argAp, summaryCtx0, argAp0, config) + exists( + DataFlowCall call, CcCall ccc, RetNodeEx ret, boolean allowsFieldFlow, ApApprox innerArgApa + | + fwdFlowThrough(call, cc, state, ccc, summaryCtx, argAp, ap, apa, ret, innerArgApa, config) and + flowThroughOutOfCall(call, ccc, ret, node, allowsFieldFlow, innerArgApa, apa, config) and + if allowsFieldFlow = false then ap instanceof ApNil else any() ) } pragma[nomagic] private predicate fwdFlowStore( NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, FlowState state, Cc cc, - ParameterPositionOption summaryCtx, ApOption argAp, Configuration config + ParamNodeOption summaryCtx, ApOption argAp, Configuration config ) { exists(DataFlowType contentType, ApApprox apa1 | fwdFlow(node1, state, cc, summaryCtx, argAp, ap1, apa1, config) and @@ -1473,8 +1480,8 @@ private module MkStage { pragma[nomagic] private predicate fwdFlowRead0( - NodeEx node1, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - ApNonNil ap, Configuration config + NodeEx node1, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, ApNonNil ap, + Configuration config ) { fwdFlow(node1, state, cc, summaryCtx, argAp, ap, config) and PrevStage::readStepCand(node1, _, _, config) @@ -1483,7 +1490,7 @@ private module MkStage { pragma[nomagic] private predicate fwdFlowRead( Ap ap, Content c, NodeEx node1, NodeEx node2, FlowState state, Cc cc, - ParameterPositionOption summaryCtx, ApOption argAp, Configuration config + ParamNodeOption summaryCtx, ApOption argAp, Configuration config ) { fwdFlowRead0(node1, state, cc, summaryCtx, argAp, ap, config) and PrevStage::readStepCand(node1, c, node2, config) and @@ -1493,7 +1500,7 @@ private module MkStage { pragma[nomagic] private predicate fwdFlowIn( DataFlowCall call, ParamNodeEx p, FlowState state, Cc outercc, CcCall innercc, - ParameterPositionOption summaryCtx, ApOption argAp, Ap ap, ApApprox apa, Configuration config + ParamNodeOption summaryCtx, ApOption argAp, Ap ap, ApApprox apa, Configuration config ) { exists(ArgNodeEx arg, boolean allowsFieldFlow | fwdFlow(arg, state, outercc, summaryCtx, argAp, ap, apa, config) and @@ -1505,64 +1512,38 @@ private module MkStage { pragma[nomagic] private predicate fwdFlowRetFromArg( - RetNodeEx ret, FlowState state, CcCall ccc, ParameterPosition summaryCtx, ParamNodeEx p, - Ap argAp, ApApprox argApa, Ap ap, ApApprox apa, Configuration config + RetNodeEx ret, FlowState state, CcCall ccc, ParamNodeEx summaryCtx, Ap argAp, ApApprox argApa, + Ap ap, ApApprox apa, Configuration config ) { - exists(DataFlowCallable c, ReturnKindExt kind | + exists(ReturnKindExt kind | fwdFlow(pragma[only_bind_into](ret), state, ccc, - TParameterPositionSome(pragma[only_bind_into](summaryCtx)), apSome(argAp), ap, apa, config) and - getApprox(argAp) = argApa and - c = ret.getEnclosingCallable() and + TParamNodeSome(pragma[only_bind_into](summaryCtx.asNode())), + pragma[only_bind_into](apSome(argAp)), ap, pragma[only_bind_into](apa), + pragma[only_bind_into](config)) and kind = ret.getKind() and - p.isParameterOf(c, pragma[only_bind_into](summaryCtx)) and - parameterFlowThroughAllowed(p, kind) + parameterFlowThroughAllowed(summaryCtx, kind) and + argApa = getApprox(argAp) and + PrevStage::returnMayFlowThrough(ret, argApa, apa, kind, pragma[only_bind_into](config)) ) } pragma[inline] - private predicate fwdFlowInMayFlowThrough( - DataFlowCall call, Cc cc, CcCall innerCc, ParameterPositionOption summaryCtx, ApOption argAp, - ParamNodeEx param, Ap ap, ApApprox apa, Configuration config + private predicate fwdFlowThrough0( + DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, + ApOption argAp, Ap ap, ApApprox apa, RetNodeEx ret, ParamNodeEx innerSummaryCtx, + Ap innerArgAp, ApApprox innerArgApa, Configuration config ) { - fwdFlowIn(call, pragma[only_bind_into](param), _, cc, innerCc, summaryCtx, argAp, ap, - pragma[only_bind_into](apa), pragma[only_bind_into](config)) and - PrevStage::parameterMayFlowThrough(param, apa, config) - } - - // dedup before joining with `flowThroughOutOfCall` - pragma[nomagic] - private predicate fwdFlowInMayFlowThroughProj( - DataFlowCall call, CcCall innerCc, ApApprox apa, Configuration config - ) { - fwdFlowInMayFlowThrough(call, _, innerCc, _, _, _, _, apa, config) - } - - /** - * Same as `flowThroughOutOfCall`, but restricted to calls that are reached - * in the flow covered by `fwdFlow`, where data might flow through the target - * callable and back out at `call`. - */ - pragma[nomagic] - private predicate fwdFlowThroughOutOfCall( - DataFlowCall call, CcCall ccc, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow, - ApApprox argApa, ApApprox apa, Configuration config - ) { - fwdFlowInMayFlowThroughProj(call, ccc, argApa, config) and - flowThroughOutOfCall(call, ccc, ret, out, allowsFieldFlow, argApa, apa, config) + fwdFlowRetFromArg(ret, state, ccc, innerSummaryCtx, innerArgAp, innerArgApa, ap, apa, config) and + fwdFlowIsEntered(call, cc, ccc, summaryCtx, argAp, innerSummaryCtx, innerArgAp, config) } pragma[nomagic] - private predicate fwdFlowOutFromArg( - DataFlowCall call, NodeEx out, FlowState state, ParameterPosition summaryCtx, Ap argAp, Ap ap, - ApApprox apa, Configuration config + private predicate fwdFlowThrough( + DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, + ApOption argAp, Ap ap, ApApprox apa, RetNodeEx ret, ApApprox innerArgApa, Configuration config ) { - exists(RetNodeEx ret, boolean allowsFieldFlow, CcCall ccc, ApApprox argApa | - fwdFlowRetFromArg(pragma[only_bind_into](ret), state, pragma[only_bind_into](ccc), - summaryCtx, _, argAp, pragma[only_bind_into](argApa), ap, pragma[only_bind_into](apa), - config) and - fwdFlowThroughOutOfCall(call, ccc, ret, out, allowsFieldFlow, argApa, apa, config) and - (if allowsFieldFlow = false then ap instanceof ApNil else any()) - ) + fwdFlowThrough0(call, cc, state, ccc, summaryCtx, argAp, ap, apa, ret, _, _, innerArgApa, + config) } /** @@ -1571,12 +1552,14 @@ private module MkStage { */ pragma[nomagic] private predicate fwdFlowIsEntered( - DataFlowCall call, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - ParameterPosition pos, Ap ap, Configuration config + DataFlowCall call, Cc cc, CcCall innerCc, ParamNodeOption summaryCtx, ApOption argAp, + ParamNodeEx p, Ap ap, Configuration config ) { - exists(ParamNodeEx param | - fwdFlowInMayFlowThrough(call, cc, _, summaryCtx, argAp, param, ap, _, config) and - pos = param.getPosition() + exists(ApApprox apa | + fwdFlowIn(call, pragma[only_bind_into](p), _, cc, innerCc, summaryCtx, argAp, ap, + pragma[only_bind_into](apa), pragma[only_bind_into](config)) and + PrevStage::parameterMayFlowThrough(p, apa, config) and + PrevStage::callMayFlowThroughRev(call, pragma[only_bind_into](config)) ) } @@ -1596,23 +1579,31 @@ private module MkStage { fwdFlowConsCand(ap1, c, ap2, config) } + pragma[nomagic] + private predicate returnFlowsThrough0( + DataFlowCall call, FlowState state, CcCall ccc, Ap ap, ApApprox apa, RetNodeEx ret, + ParamNodeEx innerSummaryCtx, Ap innerArgAp, ApApprox innerArgApa, Configuration config + ) { + fwdFlowThrough0(call, _, state, ccc, _, _, ap, apa, ret, innerSummaryCtx, innerArgAp, + innerArgApa, config) + } + pragma[nomagic] private predicate returnFlowsThrough( - RetNodeEx ret, ReturnKindExt kind, FlowState state, CcCall ccc, ParamNodeEx p, Ap argAp, + RetNodeEx ret, ReturnPosition pos, FlowState state, CcCall ccc, ParamNodeEx p, Ap argAp, Ap ap, Configuration config ) { - exists(boolean allowsFieldFlow, ApApprox argApa, ApApprox apa | - fwdFlowRetFromArg(pragma[only_bind_into](ret), state, pragma[only_bind_into](ccc), _, p, - argAp, pragma[only_bind_into](argApa), ap, pragma[only_bind_into](apa), config) and - kind = ret.getKind() and - fwdFlowThroughOutOfCall(_, ccc, ret, _, allowsFieldFlow, argApa, apa, config) and - (if allowsFieldFlow = false then ap instanceof ApNil else any()) + exists(DataFlowCall call, ApApprox apa, boolean allowsFieldFlow, ApApprox innerArgApa | + returnFlowsThrough0(call, state, ccc, ap, apa, ret, p, argAp, innerArgApa, config) and + flowThroughOutOfCall(call, ccc, ret, _, allowsFieldFlow, innerArgApa, apa, config) and + pos = ret.getReturnPosition() and + if allowsFieldFlow = false then ap instanceof ApNil else any() ) } pragma[nomagic] private predicate flowThroughIntoCall( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap argAp, + DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap argAp, Ap ap, Configuration config ) { exists(ApApprox argApa | @@ -1620,7 +1611,7 @@ private module MkStage { allowsFieldFlow, argApa, pragma[only_bind_into](config)) and fwdFlow(arg, _, _, _, _, pragma[only_bind_into](argAp), argApa, pragma[only_bind_into](config)) and - returnFlowsThrough(_, _, _, _, p, pragma[only_bind_into](argAp), _, + returnFlowsThrough(_, _, _, _, p, pragma[only_bind_into](argAp), ap, pragma[only_bind_into](config)) and if allowsFieldFlow = false then argAp instanceof ApNil else any() ) @@ -1639,12 +1630,13 @@ private module MkStage { pragma[nomagic] private predicate flowOutOfCallAp( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, boolean allowsFieldFlow, + DataFlowCall call, RetNodeEx ret, ReturnPosition pos, NodeEx out, boolean allowsFieldFlow, Ap ap, Configuration config ) { exists(ApApprox apa | - flowOutOfCallApa(call, ret, kind, out, allowsFieldFlow, apa, config) and - fwdFlow(ret, _, _, _, _, ap, apa, config) + flowOutOfCallApa(call, ret, _, out, allowsFieldFlow, apa, config) and + fwdFlow(ret, _, _, _, _, ap, apa, config) and + pos = ret.getReturnPosition() ) } @@ -1739,17 +1731,17 @@ private module MkStage { ) or // flow through a callable - exists(DataFlowCall call, ReturnKindExt returnKind0, Ap returnAp0 | - revFlowInToReturn(call, node, state, returnKind0, returnAp0, ap, config) and - revFlowIsReturned(call, returnCtx, returnAp, returnKind0, returnAp0, config) + exists(DataFlowCall call, ParamNodeEx p, ReturnPosition pos, Ap innerReturnAp | + revFlowThrough(call, returnCtx, p, state, pos, returnAp, ap, innerReturnAp, config) and + flowThroughIntoCall(call, node, p, _, ap, innerReturnAp, config) ) or // flow out of a callable - exists(ReturnKindExt kind | - revFlowOut(_, node, kind, state, _, _, ap, config) and - if returnFlowsThrough(node, kind, state, _, _, _, ap, config) + exists(ReturnPosition pos | + revFlowOut(_, node, pos, state, _, _, ap, config) and + if returnFlowsThrough(node, pos, state, _, _, _, ap, config) then ( - returnCtx = TReturnCtxMaybeFlowThrough(kind) and + returnCtx = TReturnCtxMaybeFlowThrough(pos) and returnAp = apSome(ap) ) else ( returnCtx = TReturnCtxNoFlowThrough() and returnAp = apNone() @@ -1782,47 +1774,33 @@ private module MkStage { pragma[nomagic] private predicate revFlowOut( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, FlowState state, ReturnCtx returnCtx, + DataFlowCall call, RetNodeEx ret, ReturnPosition pos, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap, Configuration config ) { exists(NodeEx out, boolean allowsFieldFlow | revFlow(out, state, returnCtx, returnAp, ap, config) and - flowOutOfCallAp(call, ret, kind, out, allowsFieldFlow, ap, config) and + flowOutOfCallAp(call, ret, pos, out, allowsFieldFlow, ap, config) and if allowsFieldFlow = false then ap instanceof ApNil else any() ) } - /** - * Same as `flowThroughIntoCall`, but restricted to calls that are reached - * in the flow covered by `revFlow`, where data might flow through the target - * callable and back out at `call`. - */ - pragma[nomagic] - private predicate revFlowThroughIntoCall( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap argAp, - Configuration config - ) { - flowThroughIntoCall(call, arg, p, allowsFieldFlow, argAp, config) and - revFlowIsReturned(call, _, _, _, _, config) - } - pragma[nomagic] private predicate revFlowParamToReturn( - ParamNodeEx p, FlowState state, ReturnKindExt kind, Ap returnAp, Ap ap, Configuration config + ParamNodeEx p, FlowState state, ReturnPosition pos, Ap returnAp, Ap ap, Configuration config ) { - revFlow(p, state, TReturnCtxMaybeFlowThrough(kind), apSome(returnAp), ap, config) and - parameterFlowThroughAllowed(p, kind) + revFlow(pragma[only_bind_into](p), state, TReturnCtxMaybeFlowThrough(pos), apSome(returnAp), + pragma[only_bind_into](ap), pragma[only_bind_into](config)) and + parameterFlowThroughAllowed(p, pos.getKind()) and + PrevStage::parameterMayFlowThrough(p, getApprox(ap), config) } pragma[nomagic] - private predicate revFlowInToReturn( - DataFlowCall call, ArgNodeEx arg, FlowState state, ReturnKindExt kind, Ap returnAp, Ap ap, - Configuration config + private predicate revFlowThrough( + DataFlowCall call, ReturnCtx returnCtx, ParamNodeEx p, FlowState state, ReturnPosition pos, + ApOption returnAp, Ap ap, Ap innerReturnAp, Configuration config ) { - exists(ParamNodeEx p, boolean allowsFieldFlow | - revFlowParamToReturn(p, state, kind, returnAp, ap, config) and - revFlowThroughIntoCall(call, arg, p, allowsFieldFlow, ap, config) - ) + revFlowParamToReturn(p, state, pos, innerReturnAp, ap, config) and + revFlowIsReturned(call, returnCtx, returnAp, pos, innerReturnAp, config) } /** @@ -1832,12 +1810,12 @@ private module MkStage { */ pragma[nomagic] private predicate revFlowIsReturned( - DataFlowCall call, ReturnCtx returnCtx, ApOption returnAp, ReturnKindExt kind, Ap ap, + DataFlowCall call, ReturnCtx returnCtx, ApOption returnAp, ReturnPosition pos, Ap ap, Configuration config ) { exists(RetNodeEx ret, FlowState state, CcCall ccc | - revFlowOut(call, ret, kind, state, returnCtx, returnAp, ap, config) and - returnFlowsThrough(ret, kind, state, ccc, _, _, ap, config) and + revFlowOut(call, ret, pos, state, returnCtx, returnAp, ap, config) and + returnFlowsThrough(ret, pos, state, ccc, _, _, ap, config) and matchesCall(ccc, call) ) } @@ -1915,17 +1893,17 @@ private module MkStage { pragma[nomagic] private predicate parameterFlowsThroughRev( - ParamNodeEx p, Ap ap, ReturnKindExt kind, Ap returnAp, Configuration config + ParamNodeEx p, Ap ap, ReturnPosition pos, Ap returnAp, Configuration config ) { - revFlow(p, _, TReturnCtxMaybeFlowThrough(kind), apSome(returnAp), ap, config) and - parameterFlowThroughAllowed(p, kind) + revFlow(p, _, TReturnCtxMaybeFlowThrough(pos), apSome(returnAp), ap, config) and + parameterFlowThroughAllowed(p, pos.getKind()) } pragma[nomagic] predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap, Configuration config) { - exists(RetNodeEx ret, ReturnKindExt kind | - returnFlowsThrough(ret, kind, _, _, p, ap, _, config) and - parameterFlowsThroughRev(p, ap, kind, _, config) + exists(RetNodeEx ret, ReturnPosition pos | + returnFlowsThrough(ret, pos, _, _, p, ap, _, config) and + parameterFlowsThroughRev(p, ap, pos, _, config) ) } @@ -1933,20 +1911,21 @@ private module MkStage { predicate returnMayFlowThrough( RetNodeEx ret, Ap argAp, Ap ap, ReturnKindExt kind, Configuration config ) { - exists(ParamNodeEx p | - returnFlowsThrough(ret, kind, _, _, p, argAp, ap, config) and - parameterFlowsThroughRev(p, argAp, kind, ap, config) + exists(ParamNodeEx p, ReturnPosition pos | + returnFlowsThrough(ret, pos, _, _, p, argAp, ap, config) and + parameterFlowsThroughRev(p, argAp, pos, ap, config) and + kind = pos.getKind() ) } pragma[nomagic] - predicate revFlowInToReturnIsReturned( + private predicate revFlowThroughArg( DataFlowCall call, ArgNodeEx arg, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap, Configuration config ) { - exists(ReturnKindExt returnKind0, Ap returnAp0 | - revFlowInToReturn(call, arg, state, returnKind0, returnAp0, ap, config) and - revFlowIsReturned(call, returnCtx, returnAp, returnKind0, returnAp0, config) + exists(ParamNodeEx p, ReturnPosition pos, Ap innerReturnAp | + revFlowThrough(call, returnCtx, p, state, pos, returnAp, ap, innerReturnAp, config) and + flowThroughIntoCall(call, arg, p, _, ap, innerReturnAp, config) ) } @@ -1954,7 +1933,7 @@ private module MkStage { predicate callMayFlowThroughRev(DataFlowCall call, Configuration config) { exists(ArgNodeEx arg, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap | revFlow(arg, state, returnCtx, returnAp, ap, config) and - revFlowInToReturnIsReturned(call, arg, state, returnCtx, returnAp, ap, config) + revFlowThroughArg(call, arg, state, returnCtx, returnAp, ap, config) ) } @@ -1967,8 +1946,9 @@ private module MkStage { conscand = count(TypedContent f0, Ap ap | fwdConsCand(f0, ap, config)) and states = count(FlowState state | fwdFlow(_, state, _, _, _, _, config)) and tuples = - count(NodeEx n, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - Ap ap | fwdFlow(n, state, cc, summaryCtx, argAp, ap, config)) + count(NodeEx n, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap | + fwdFlow(n, state, cc, summaryCtx, argAp, ap, config) + ) or fwd = false and nodes = count(NodeEx node | revFlow(node, _, _, _, _, config)) and @@ -2823,13 +2803,12 @@ private Configuration unbindConf(Configuration conf) { pragma[nomagic] private predicate nodeMayUseSummary0( - NodeEx n, DataFlowCallable c, ParameterPosition pos, FlowState state, AccessPathApprox apa, - Configuration config + NodeEx n, ParamNodeEx p, FlowState state, AccessPathApprox apa, Configuration config ) { exists(AccessPathApprox apa0 | - c = n.getEnclosingCallable() and + Stage5::parameterMayFlowThrough(p, _, _) and Stage5::revFlow(n, state, TReturnCtxMaybeFlowThrough(_), _, apa0, config) and - Stage5::fwdFlow(n, state, any(CallContextCall ccc), TParameterPositionSome(pos), + Stage5::fwdFlow(n, state, any(CallContextCall ccc), TParamNodeSome(p.asNode()), TAccessPathApproxSome(apa), apa0, config) ) } @@ -2838,10 +2817,9 @@ pragma[nomagic] private predicate nodeMayUseSummary( NodeEx n, FlowState state, AccessPathApprox apa, Configuration config ) { - exists(DataFlowCallable c, ParameterPosition pos, ParamNodeEx p | + exists(ParamNodeEx p | Stage5::parameterMayFlowThrough(p, apa, config) and - nodeMayUseSummary0(n, c, pos, state, apa, config) and - p.isParameterOf(c, pos) + nodeMayUseSummary0(n, p, state, apa, config) ) } diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/FlowSummaryImpl.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/FlowSummaryImpl.qll index 61c541d8882..b61142c33a7 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/FlowSummaryImpl.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/FlowSummaryImpl.qll @@ -241,9 +241,15 @@ module Public { } /** - * Holds if the summary is auto generated. + * Holds if the summary is auto generated and not manually generated. */ predicate isAutoGenerated() { none() } + + /** + * Holds if the summary has the given provenance where `true` is + * `generated` and `false` is `manual`. + */ + predicate hasProvenance(boolean generated) { none() } } /** A callable where there is no flow via the callable. */ @@ -1012,6 +1018,10 @@ module Private { } override predicate isAutoGenerated() { this.relevantSummaryElementGenerated(_, _, _) } + + override predicate hasProvenance(boolean generated) { + summaryElement(this, _, _, _, generated) + } } /** Holds if component `c` of specification `spec` cannot be parsed. */ diff --git a/csharp/ql/lib/semmle/code/csharp/exprs/Expr.qll b/csharp/ql/lib/semmle/code/csharp/exprs/Expr.qll index 03a24b37345..4251a7ae8b6 100644 --- a/csharp/ql/lib/semmle/code/csharp/exprs/Expr.qll +++ b/csharp/ql/lib/semmle/code/csharp/exprs/Expr.qll @@ -321,6 +321,18 @@ private predicate hasChildPattern(ControlFlowElement pm, Expr child) { mid instanceof @tuple_expr and child = mid.getAChildExpr() ) + or + exists(Expr mid | + hasChildPattern(pm, mid) and + mid instanceof @list_pattern_expr and + child = mid.getAChildExpr() + ) + or + exists(Expr mid | + hasChildPattern(pm, mid) and + mid instanceof @slice_pattern_expr and + child = mid.getAChildExpr() + ) } /** @@ -506,6 +518,26 @@ class PositionalPatternExpr extends PatternExpr, @positional_pattern_expr { override string getAPrimaryQlClass() { result = "PositionalPatternExpr" } } +/** A list pattern. For example `[1, 2, int y]` in `x is [1, 2, int y]`. */ +class ListPatternExpr extends PatternExpr, @list_pattern_expr { + override string toString() { result = "[ ... ]" } + + /** Gets the `n`th pattern. */ + PatternExpr getPattern(int n) { result = this.getChild(n) } + + override string getAPrimaryQlClass() { result = "ListPatternExpr" } +} + +/** A slice pattern. For example `..` in `x is [1, .., 2]. */ +class SlicePatternExpr extends PatternExpr, @slice_pattern_expr { + override string toString() { result = ".." } + + /** Gets the subpattern, if any. */ + PatternExpr getPattern() { result = this.getChild(0) } + + override string getAPrimaryQlClass() { result = "SlicePatternExpr" } +} + /** A unary pattern. For example, `not 1`. */ class UnaryPatternExpr extends PatternExpr, @unary_pattern_expr { /** Gets the underlying pattern. */ diff --git a/csharp/ql/lib/semmlecode.csharp.dbscheme b/csharp/ql/lib/semmlecode.csharp.dbscheme index 4ac7d8bcac6..83aca6b3e4f 100644 --- a/csharp/ql/lib/semmlecode.csharp.dbscheme +++ b/csharp/ql/lib/semmlecode.csharp.dbscheme @@ -1134,6 +1134,9 @@ case @expr.kind of | 128 = @or_pattern_expr | 129 = @function_pointer_invocation_expr | 130 = @with_expr +/* C# 11.0 */ +| 131 = @list_pattern_expr +| 132 = @slice_pattern_expr /* Preprocessor */ | 999 = @define_symbol_expr ; diff --git a/csharp/ql/lib/upgrades/4ac7d8bcac6f664b1e83c858aa71f8dc761cc603/old.dbscheme b/csharp/ql/lib/upgrades/4ac7d8bcac6f664b1e83c858aa71f8dc761cc603/old.dbscheme new file mode 100644 index 00000000000..4ac7d8bcac6 --- /dev/null +++ b/csharp/ql/lib/upgrades/4ac7d8bcac6f664b1e83c858aa71f8dc761cc603/old.dbscheme @@ -0,0 +1,2064 @@ +/* This is a dummy line to alter the dbscheme, so we can make a database upgrade + * without actually changing any of the dbscheme predicates. It contains a date + * to allow for such updates in the future as well. + * + * 2021-07-14 + * + * DO NOT remove this comment carelessly, since it can revert the dbscheme back to a + * previously seen state (matching a previously seen SHA), which would make the upgrade + * mechanism not work properly. + */ + +/** + * An invocation of the compiler. Note that more than one file may be + * compiled per invocation. For example, this command compiles three + * source files: + * + * csc f1.cs f2.cs f3.cs + * + * The `id` simply identifies the invocation, while `cwd` is the working + * directory from which the compiler was invoked. + */ +compilations( + unique int id : @compilation, + string cwd : string ref +); + +/** + * The arguments that were passed to the extractor for a compiler + * invocation. If `id` is for the compiler invocation + * + * csc f1.cs f2.cs f3.cs + * + * then typically there will be rows for + * + * num | arg + * --- | --- + * 0 | --compiler + * 1 | *path to compiler* + * 2 | f1.cs + * 3 | f2.cs + * 4 | f3.cs + */ +#keyset[id, num] +compilation_args( + int id : @compilation ref, + int num : int ref, + string arg : string ref +); + +/** + * The source files that are compiled by a compiler invocation. + * If `id` is for the compiler invocation + * + * csc f1.cs f2.cs f3.cs + * + * then there will be rows for + * + * num | arg + * --- | --- + * 0 | f1.cs + * 1 | f2.cs + * 2 | f3.cs + */ +#keyset[id, num] +compilation_compiling_files( + int id : @compilation ref, + int num : int ref, + int file : @file ref +); + +/** + * The references used by a compiler invocation. + * If `id` is for the compiler invocation + * + * csc f1.cs f2.cs f3.cs /r:ref1.dll /r:ref2.dll /r:ref3.dll + * + * then there will be rows for + * + * num | arg + * --- | --- + * 0 | ref1.dll + * 1 | ref2.dll + * 2 | ref3.dll + */ +#keyset[id, num] +compilation_referencing_files( + int id : @compilation ref, + int num : int ref, + int file : @file ref +); + +/** + * The time taken by the extractor for a compiler invocation. + * + * For each file `num`, there will be rows for + * + * kind | seconds + * ---- | --- + * 1 | CPU seconds used by the extractor frontend + * 2 | Elapsed seconds during the extractor frontend + * 3 | CPU seconds used by the extractor backend + * 4 | Elapsed seconds during the extractor backend + */ +#keyset[id, num, kind] +compilation_time( + int id : @compilation ref, + int num : int ref, + /* kind: + 1 = frontend_cpu_seconds + 2 = frontend_elapsed_seconds + 3 = extractor_cpu_seconds + 4 = extractor_elapsed_seconds + */ + int kind : int ref, + float seconds : float ref +); + +/** + * An error or warning generated by the extractor. + * The diagnostic message `diagnostic` was generated during compiler + * invocation `compilation`, and is the `file_number_diagnostic_number`th + * message generated while extracting the `file_number`th file of that + * invocation. + */ +#keyset[compilation, file_number, file_number_diagnostic_number] +diagnostic_for( + unique int diagnostic : @diagnostic ref, + int compilation : @compilation ref, + int file_number : int ref, + int file_number_diagnostic_number : int ref +); + +diagnostics( + unique int id: @diagnostic, + int severity: int ref, + string error_tag: string ref, + string error_message: string ref, + string full_error_message: string ref, + int location: @location_default ref +); + +extractor_messages( + unique int id: @extractor_message, + int severity: int ref, + string origin : string ref, + string text : string ref, + string entity : string ref, + int location: @location_default ref, + string stack_trace : string ref +); + +/** + * If extraction was successful, then `cpu_seconds` and + * `elapsed_seconds` are the CPU time and elapsed time (respectively) + * that extraction took for compiler invocation `id`. + */ +compilation_finished( + unique int id : @compilation ref, + float cpu_seconds : float ref, + float elapsed_seconds : float ref +); + +compilation_assembly( + unique int id : @compilation ref, + int assembly: @assembly ref +) + +// Populated by the CSV extractor +externalData( + int id: @externalDataElement, + string path: string ref, + int column: int ref, + string value: string ref); + +sourceLocationPrefix( + string prefix: string ref); + +/* + * C# dbscheme + */ + +/** ELEMENTS **/ + +@element = @declaration | @stmt | @expr | @modifier | @attribute | @namespace_declaration + | @using_directive | @type_parameter_constraints | @externalDataElement + | @xmllocatable | @asp_element | @namespace | @preprocessor_directive; + +@declaration = @callable | @generic | @assignable | @namespace; + +@named_element = @namespace | @declaration; + +@declaration_with_accessors = @property | @indexer | @event; + +@assignable = @variable | @assignable_with_accessors | @event; + +@assignable_with_accessors = @property | @indexer; + +@attributable = @assembly | @field | @parameter | @operator | @method | @constructor + | @destructor | @callable_accessor | @value_or_ref_type | @declaration_with_accessors + | @local_function | @lambda_expr; + +/** LOCATIONS, ASEMMBLIES, MODULES, FILES and FOLDERS **/ + +@location = @location_default | @assembly; + +locations_default( + unique int id: @location_default, + int file: @file ref, + int beginLine: int ref, + int beginColumn: int ref, + int endLine: int ref, + int endColumn: int ref); + +locations_mapped( + unique int id: @location_default ref, + int mapped_to: @location_default ref); + +@sourceline = @file | @callable | @xmllocatable; + +numlines( + int element_id: @sourceline ref, + int num_lines: int ref, + int num_code: int ref, + int num_comment: int ref); + +assemblies( + unique int id: @assembly, + int file: @file ref, + string fullname: string ref, + string name: string ref, + string version: string ref); + +files( + unique int id: @file, + string name: string ref); + +folders( + unique int id: @folder, + string name: string ref); + +@container = @folder | @file ; + +containerparent( + int parent: @container ref, + unique int child: @container ref); + +file_extraction_mode( + unique int file: @file ref, + int mode: int ref + /* 0 = normal, 1 = standalone extractor */ + ); + +/** NAMESPACES **/ + +@type_container = @namespace | @type; + +namespaces( + unique int id: @namespace, + string name: string ref); + +namespace_declarations( + unique int id: @namespace_declaration, + int namespace_id: @namespace ref); + +namespace_declaration_location( + unique int id: @namespace_declaration ref, + int loc: @location ref); + +parent_namespace( + unique int child_id: @type_container ref, + int namespace_id: @namespace ref); + +@declaration_or_directive = @namespace_declaration | @type | @using_directive; + +parent_namespace_declaration( + int child_id: @declaration_or_directive ref, // cannot be unique because of partial classes + int namespace_id: @namespace_declaration ref); + +@using_directive = @using_namespace_directive | @using_static_directive; + +using_global( + unique int id: @using_directive ref +); + +using_namespace_directives( + unique int id: @using_namespace_directive, + int namespace_id: @namespace ref); + +using_static_directives( + unique int id: @using_static_directive, + int type_id: @type_or_ref ref); + +using_directive_location( + unique int id: @using_directive ref, + int loc: @location ref); + +@preprocessor_directive = @pragma_warning | @pragma_checksum | @directive_define | @directive_undefine | @directive_warning + | @directive_error | @directive_nullable | @directive_line | @directive_region | @directive_endregion | @directive_if + | @directive_elif | @directive_else | @directive_endif; + +@conditional_directive = @directive_if | @directive_elif; +@branch_directive = @directive_if | @directive_elif | @directive_else; + +directive_ifs( + unique int id: @directive_if, + int branchTaken: int ref, /* 0: false, 1: true */ + int conditionValue: int ref); /* 0: false, 1: true */ + +directive_elifs( + unique int id: @directive_elif, + int branchTaken: int ref, /* 0: false, 1: true */ + int conditionValue: int ref, /* 0: false, 1: true */ + int parent: @directive_if ref, + int index: int ref); + +directive_elses( + unique int id: @directive_else, + int branchTaken: int ref, /* 0: false, 1: true */ + int parent: @directive_if ref, + int index: int ref); + +#keyset[id, start] +directive_endifs( + unique int id: @directive_endif, + unique int start: @directive_if ref); + +directive_define_symbols( + unique int id: @define_symbol_expr ref, + string name: string ref); + +directive_regions( + unique int id: @directive_region, + string name: string ref); + +#keyset[id, start] +directive_endregions( + unique int id: @directive_endregion, + unique int start: @directive_region ref); + +directive_lines( + unique int id: @directive_line, + int kind: int ref); /* 0: default, 1: hidden, 2: numeric, 3: span */ + +directive_line_value( + unique int id: @directive_line ref, + int line: int ref); + +directive_line_file( + unique int id: @directive_line ref, + int file: @file ref); + +directive_line_offset( + unique int id: @directive_line ref, + int offset: int ref); + +directive_line_span( + unique int id: @directive_line ref, + int startLine: int ref, + int startColumn: int ref, + int endLine: int ref, + int endColumn: int ref); + +directive_nullables( + unique int id: @directive_nullable, + int setting: int ref, /* 0: disable, 1: enable, 2: restore */ + int target: int ref); /* 0: none, 1: annotations, 2: warnings */ + +directive_warnings( + unique int id: @directive_warning, + string message: string ref); + +directive_errors( + unique int id: @directive_error, + string message: string ref); + +directive_undefines( + unique int id: @directive_undefine, + string name: string ref); + +directive_defines( + unique int id: @directive_define, + string name: string ref); + +pragma_checksums( + unique int id: @pragma_checksum, + int file: @file ref, + string guid: string ref, + string bytes: string ref); + +pragma_warnings( + unique int id: @pragma_warning, + int kind: int ref /* 0 = disable, 1 = restore */); + +#keyset[id, index] +pragma_warning_error_codes( + int id: @pragma_warning ref, + string errorCode: string ref, + int index: int ref); + +preprocessor_directive_location( + unique int id: @preprocessor_directive ref, + int loc: @location ref); + +preprocessor_directive_compilation( + unique int id: @preprocessor_directive ref, + int compilation: @compilation ref); + +preprocessor_directive_active( + unique int id: @preprocessor_directive ref, + int active: int ref); /* 0: false, 1: true */ + +/** TYPES **/ + +types( + unique int id: @type, + int kind: int ref, + string name: string ref); + +case @type.kind of + 1 = @bool_type +| 2 = @char_type +| 3 = @decimal_type +| 4 = @sbyte_type +| 5 = @short_type +| 6 = @int_type +| 7 = @long_type +| 8 = @byte_type +| 9 = @ushort_type +| 10 = @uint_type +| 11 = @ulong_type +| 12 = @float_type +| 13 = @double_type +| 14 = @enum_type +| 15 = @struct_type +| 17 = @class_type +| 19 = @interface_type +| 20 = @delegate_type +| 21 = @null_type +| 22 = @type_parameter +| 23 = @pointer_type +| 24 = @nullable_type +| 25 = @array_type +| 26 = @void_type +| 27 = @int_ptr_type +| 28 = @uint_ptr_type +| 29 = @dynamic_type +| 30 = @arglist_type +| 31 = @unknown_type +| 32 = @tuple_type +| 33 = @function_pointer_type + ; + +@simple_type = @bool_type | @char_type | @integral_type | @floating_point_type | @decimal_type; +@integral_type = @signed_integral_type | @unsigned_integral_type; +@signed_integral_type = @sbyte_type | @short_type | @int_type | @long_type; +@unsigned_integral_type = @byte_type | @ushort_type | @uint_type | @ulong_type; +@floating_point_type = @float_type | @double_type; +@value_type = @simple_type | @enum_type | @struct_type | @nullable_type | @int_ptr_type + | @uint_ptr_type | @tuple_type; +@ref_type = @class_type | @interface_type | @array_type | @delegate_type | @null_type + | @dynamic_type; +@value_or_ref_type = @value_type | @ref_type; + +typerefs( + unique int id: @typeref, + string name: string ref); + +typeref_type( + int id: @typeref ref, + unique int typeId: @type ref); + +@type_or_ref = @type | @typeref; + +array_element_type( + unique int array: @array_type ref, + int dimension: int ref, + int rank: int ref, + int element: @type_or_ref ref); + +nullable_underlying_type( + unique int nullable: @nullable_type ref, + int underlying: @type_or_ref ref); + +pointer_referent_type( + unique int pointer: @pointer_type ref, + int referent: @type_or_ref ref); + +enum_underlying_type( + unique int enum_id: @enum_type ref, + int underlying_type_id: @type_or_ref ref); + +delegate_return_type( + unique int delegate_id: @delegate_type ref, + int return_type_id: @type_or_ref ref); + +function_pointer_return_type( + unique int function_pointer_id: @function_pointer_type ref, + int return_type_id: @type_or_ref ref); + +extend( + int sub: @type ref, + int super: @type_or_ref ref); + +anonymous_types( + unique int id: @type ref); + +@interface_or_ref = @interface_type | @typeref; + +implement( + int sub: @type ref, + int super: @type_or_ref ref); + +type_location( + int id: @type ref, + int loc: @location ref); + +tuple_underlying_type( + unique int tuple: @tuple_type ref, + int struct: @type_or_ref ref); + +#keyset[tuple, index] +tuple_element( + int tuple: @tuple_type ref, + int index: int ref, + unique int field: @field ref); + +attributes( + unique int id: @attribute, + int kind: int ref, + int type_id: @type_or_ref ref, + int target: @attributable ref); + +case @attribute.kind of + 0 = @attribute_default +| 1 = @attribute_return +| 2 = @attribute_assembly +| 3 = @attribute_module +; + +attribute_location( + int id: @attribute ref, + int loc: @location ref); + +@type_mention_parent = @element | @type_mention; + +type_mention( + unique int id: @type_mention, + int type_id: @type_or_ref ref, + int parent: @type_mention_parent ref); + +type_mention_location( + unique int id: @type_mention ref, + int loc: @location ref); + +@has_type_annotation = @assignable | @type_parameter | @callable | @expr | @delegate_type | @generic | @function_pointer_type; + +/** + * A direct annotation on an entity, for example `string? x;`. + * + * Annotations: + * 2 = reftype is not annotated "!" + * 3 = reftype is annotated "?" + * 4 = readonly ref type / in parameter + * 5 = ref type parameter, return or local variable + * 6 = out parameter + * + * Note that the annotation depends on the element it annotates. + * @assignable: The annotation is on the type of the assignable, for example the variable type. + * @type_parameter: The annotation is on the reftype constraint + * @callable: The annotation is on the return type + * @array_type: The annotation is on the element type + */ +type_annotation(int id: @has_type_annotation ref, int annotation: int ref); + +nullability(unique int nullability: @nullability, int kind: int ref); + +case @nullability.kind of + 0 = @oblivious +| 1 = @not_annotated +| 2 = @annotated +; + +#keyset[parent, index] +nullability_parent(int nullability: @nullability ref, int index: int ref, int parent: @nullability ref) + +type_nullability(int id: @has_type_annotation ref, int nullability: @nullability ref); + +/** + * The nullable flow state of an expression, as determined by Roslyn. + * 0 = none (default, not populated) + * 1 = not null + * 2 = maybe null + */ +expr_flowstate(unique int id: @expr ref, int state: int ref); + +/** GENERICS **/ + +@generic = @type | @method | @local_function; + +type_parameters( + unique int id: @type_parameter ref, + int index: int ref, + int generic_id: @generic ref, + int variance: int ref /* none = 0, out = 1, in = 2 */); + +#keyset[constructed_id, index] +type_arguments( + int id: @type_or_ref ref, + int index: int ref, + int constructed_id: @generic_or_ref ref); + +@generic_or_ref = @generic | @typeref; + +constructed_generic( + unique int constructed: @generic ref, + int generic: @generic_or_ref ref); + +type_parameter_constraints( + unique int id: @type_parameter_constraints, + int param_id: @type_parameter ref); + +type_parameter_constraints_location( + int id: @type_parameter_constraints ref, + int loc: @location ref); + +general_type_parameter_constraints( + int id: @type_parameter_constraints ref, + int kind: int ref /* class = 1, struct = 2, new = 3 */); + +specific_type_parameter_constraints( + int id: @type_parameter_constraints ref, + int base_id: @type_or_ref ref); + +specific_type_parameter_nullability( + int id: @type_parameter_constraints ref, + int base_id: @type_or_ref ref, + int nullability: @nullability ref); + +/** FUNCTION POINTERS */ + +function_pointer_calling_conventions( + int id: @function_pointer_type ref, + int kind: int ref); + +#keyset[id, index] +has_unmanaged_calling_conventions( + int id: @function_pointer_type ref, + int index: int ref, + int conv_id: @type_or_ref ref); + +/** MODIFIERS */ + +@modifiable = @modifiable_direct | @event_accessor; + +@modifiable_direct = @member | @accessor | @local_function | @anonymous_function_expr; + +modifiers( + unique int id: @modifier, + string name: string ref); + +has_modifiers( + int id: @modifiable_direct ref, + int mod_id: @modifier ref); + +compiler_generated(unique int id: @modifiable ref); + +/** MEMBERS **/ + +@member = @method | @constructor | @destructor | @field | @property | @event | @operator | @indexer | @type; + +@named_exprorstmt = @goto_stmt | @labeled_stmt | @expr; + +@virtualizable = @method | @property | @indexer | @event; + +exprorstmt_name( + unique int parent_id: @named_exprorstmt ref, + string name: string ref); + +nested_types( + unique int id: @type ref, + int declaring_type_id: @type ref, + int unbound_id: @type ref); + +properties( + unique int id: @property, + string name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @property ref); + +property_location( + int id: @property ref, + int loc: @location ref); + +indexers( + unique int id: @indexer, + string name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @indexer ref); + +indexer_location( + int id: @indexer ref, + int loc: @location ref); + +accessors( + unique int id: @accessor, + int kind: int ref, + string name: string ref, + int declaring_member_id: @member ref, + int unbound_id: @accessor ref); + +case @accessor.kind of + 1 = @getter +| 2 = @setter + ; + +init_only_accessors( + unique int id: @accessor ref); + +accessor_location( + int id: @accessor ref, + int loc: @location ref); + +events( + unique int id: @event, + string name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @event ref); + +event_location( + int id: @event ref, + int loc: @location ref); + +event_accessors( + unique int id: @event_accessor, + int kind: int ref, + string name: string ref, + int declaring_event_id: @event ref, + int unbound_id: @event_accessor ref); + +case @event_accessor.kind of + 1 = @add_event_accessor +| 2 = @remove_event_accessor + ; + +event_accessor_location( + int id: @event_accessor ref, + int loc: @location ref); + +operators( + unique int id: @operator, + string name: string ref, + string symbol: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @operator ref); + +operator_location( + int id: @operator ref, + int loc: @location ref); + +constant_value( + int id: @variable ref, + string value: string ref); + +/** CALLABLES **/ + +@callable = @method | @constructor | @destructor | @operator | @callable_accessor | @anonymous_function_expr | @local_function; + +@callable_accessor = @accessor | @event_accessor; + +methods( + unique int id: @method, + string name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @method ref); + +method_location( + int id: @method ref, + int loc: @location ref); + +constructors( + unique int id: @constructor, + string name: string ref, + int declaring_type_id: @type ref, + int unbound_id: @constructor ref); + +constructor_location( + int id: @constructor ref, + int loc: @location ref); + +destructors( + unique int id: @destructor, + string name: string ref, + int declaring_type_id: @type ref, + int unbound_id: @destructor ref); + +destructor_location( + int id: @destructor ref, + int loc: @location ref); + +overrides( + int id: @callable ref, + int base_id: @callable ref); + +explicitly_implements( + int id: @member ref, + int interface_id: @interface_or_ref ref); + +local_functions( + unique int id: @local_function, + string name: string ref, + int return_type: @type ref, + int unbound_id: @local_function ref); + +local_function_stmts( + unique int fn: @local_function_stmt ref, + int stmt: @local_function ref); + +/** VARIABLES **/ + +@variable = @local_scope_variable | @field; + +@local_scope_variable = @local_variable | @parameter; + +fields( + unique int id: @field, + int kind: int ref, + string name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @field ref); + +case @field.kind of + 1 = @addressable_field +| 2 = @constant + ; + +field_location( + int id: @field ref, + int loc: @location ref); + +localvars( + unique int id: @local_variable, + int kind: int ref, + string name: string ref, + int implicitly_typed: int ref /* 0 = no, 1 = yes */, + int type_id: @type_or_ref ref, + int parent_id: @local_var_decl_expr ref); + +case @local_variable.kind of + 1 = @addressable_local_variable +| 2 = @local_constant +| 3 = @local_variable_ref + ; + +localvar_location( + unique int id: @local_variable ref, + int loc: @location ref); + +@parameterizable = @callable | @delegate_type | @indexer | @function_pointer_type; + +#keyset[name, parent_id] +#keyset[index, parent_id] +params( + unique int id: @parameter, + string name: string ref, + int type_id: @type_or_ref ref, + int index: int ref, + int mode: int ref, /* value = 0, ref = 1, out = 2, array = 3, this = 4 */ + int parent_id: @parameterizable ref, + int unbound_id: @parameter ref); + +param_location( + int id: @parameter ref, + int loc: @location ref); + +/** STATEMENTS **/ + +@exprorstmt_parent = @control_flow_element | @top_level_exprorstmt_parent; + +statements( + unique int id: @stmt, + int kind: int ref); + +#keyset[index, parent] +stmt_parent( + unique int stmt: @stmt ref, + int index: int ref, + int parent: @control_flow_element ref); + +@top_level_stmt_parent = @callable; + +// [index, parent] is not a keyset because the same parent may be compiled multiple times +stmt_parent_top_level( + unique int stmt: @stmt ref, + int index: int ref, + int parent: @top_level_stmt_parent ref); + +case @stmt.kind of + 1 = @block_stmt +| 2 = @expr_stmt +| 3 = @if_stmt +| 4 = @switch_stmt +| 5 = @while_stmt +| 6 = @do_stmt +| 7 = @for_stmt +| 8 = @foreach_stmt +| 9 = @break_stmt +| 10 = @continue_stmt +| 11 = @goto_stmt +| 12 = @goto_case_stmt +| 13 = @goto_default_stmt +| 14 = @throw_stmt +| 15 = @return_stmt +| 16 = @yield_stmt +| 17 = @try_stmt +| 18 = @checked_stmt +| 19 = @unchecked_stmt +| 20 = @lock_stmt +| 21 = @using_block_stmt +| 22 = @var_decl_stmt +| 23 = @const_decl_stmt +| 24 = @empty_stmt +| 25 = @unsafe_stmt +| 26 = @fixed_stmt +| 27 = @label_stmt +| 28 = @catch +| 29 = @case_stmt +| 30 = @local_function_stmt +| 31 = @using_decl_stmt + ; + +@using_stmt = @using_block_stmt | @using_decl_stmt; + +@labeled_stmt = @label_stmt | @case; + +@decl_stmt = @var_decl_stmt | @const_decl_stmt | @using_decl_stmt; + +@cond_stmt = @if_stmt | @switch_stmt; + +@loop_stmt = @while_stmt | @do_stmt | @for_stmt | @foreach_stmt; + +@jump_stmt = @break_stmt | @goto_any_stmt | @continue_stmt | @throw_stmt | @return_stmt + | @yield_stmt; + +@goto_any_stmt = @goto_default_stmt | @goto_case_stmt | @goto_stmt; + + +stmt_location( + unique int id: @stmt ref, + int loc: @location ref); + +catch_type( + unique int catch_id: @catch ref, + int type_id: @type_or_ref ref, + int kind: int ref /* explicit = 1, implicit = 2 */); + +foreach_stmt_info( + unique int id: @foreach_stmt ref, + int kind: int ref /* non-async = 1, async = 2 */); + +@foreach_symbol = @method | @property | @type_or_ref; + +#keyset[id, kind] +foreach_stmt_desugar( + int id: @foreach_stmt ref, + int symbol: @foreach_symbol ref, + int kind: int ref /* GetEnumeratorMethod = 1, CurrentProperty = 2, MoveNextMethod = 3, DisposeMethod = 4, ElementType = 5 */); + +/** EXPRESSIONS **/ + +expressions( + unique int id: @expr, + int kind: int ref, + int type_id: @type_or_ref ref); + +#keyset[index, parent] +expr_parent( + unique int expr: @expr ref, + int index: int ref, + int parent: @control_flow_element ref); + +@top_level_expr_parent = @attribute | @field | @property | @indexer | @parameter | @directive_if | @directive_elif; + +@top_level_exprorstmt_parent = @top_level_expr_parent | @top_level_stmt_parent; + +// [index, parent] is not a keyset because the same parent may be compiled multiple times +expr_parent_top_level( + unique int expr: @expr ref, + int index: int ref, + int parent: @top_level_exprorstmt_parent ref); + +case @expr.kind of +/* literal */ + 1 = @bool_literal_expr +| 2 = @char_literal_expr +| 3 = @decimal_literal_expr +| 4 = @int_literal_expr +| 5 = @long_literal_expr +| 6 = @uint_literal_expr +| 7 = @ulong_literal_expr +| 8 = @float_literal_expr +| 9 = @double_literal_expr +| 10 = @string_literal_expr +| 11 = @null_literal_expr +/* primary & unary */ +| 12 = @this_access_expr +| 13 = @base_access_expr +| 14 = @local_variable_access_expr +| 15 = @parameter_access_expr +| 16 = @field_access_expr +| 17 = @property_access_expr +| 18 = @method_access_expr +| 19 = @event_access_expr +| 20 = @indexer_access_expr +| 21 = @array_access_expr +| 22 = @type_access_expr +| 23 = @typeof_expr +| 24 = @method_invocation_expr +| 25 = @delegate_invocation_expr +| 26 = @operator_invocation_expr +| 27 = @cast_expr +| 28 = @object_creation_expr +| 29 = @explicit_delegate_creation_expr +| 30 = @implicit_delegate_creation_expr +| 31 = @array_creation_expr +| 32 = @default_expr +| 33 = @plus_expr +| 34 = @minus_expr +| 35 = @bit_not_expr +| 36 = @log_not_expr +| 37 = @post_incr_expr +| 38 = @post_decr_expr +| 39 = @pre_incr_expr +| 40 = @pre_decr_expr +/* multiplicative */ +| 41 = @mul_expr +| 42 = @div_expr +| 43 = @rem_expr +/* additive */ +| 44 = @add_expr +| 45 = @sub_expr +/* shift */ +| 46 = @lshift_expr +| 47 = @rshift_expr +/* relational */ +| 48 = @lt_expr +| 49 = @gt_expr +| 50 = @le_expr +| 51 = @ge_expr +/* equality */ +| 52 = @eq_expr +| 53 = @ne_expr +/* logical */ +| 54 = @bit_and_expr +| 55 = @bit_xor_expr +| 56 = @bit_or_expr +| 57 = @log_and_expr +| 58 = @log_or_expr +/* type testing */ +| 59 = @is_expr +| 60 = @as_expr +/* null coalescing */ +| 61 = @null_coalescing_expr +/* conditional */ +| 62 = @conditional_expr +/* assignment */ +| 63 = @simple_assign_expr +| 64 = @assign_add_expr +| 65 = @assign_sub_expr +| 66 = @assign_mul_expr +| 67 = @assign_div_expr +| 68 = @assign_rem_expr +| 69 = @assign_and_expr +| 70 = @assign_xor_expr +| 71 = @assign_or_expr +| 72 = @assign_lshift_expr +| 73 = @assign_rshift_expr +/* more */ +| 74 = @object_init_expr +| 75 = @collection_init_expr +| 76 = @array_init_expr +| 77 = @checked_expr +| 78 = @unchecked_expr +| 79 = @constructor_init_expr +| 80 = @add_event_expr +| 81 = @remove_event_expr +| 82 = @par_expr +| 83 = @local_var_decl_expr +| 84 = @lambda_expr +| 85 = @anonymous_method_expr +| 86 = @namespace_expr +/* dynamic */ +| 92 = @dynamic_element_access_expr +| 93 = @dynamic_member_access_expr +/* unsafe */ +| 100 = @pointer_indirection_expr +| 101 = @address_of_expr +| 102 = @sizeof_expr +/* async */ +| 103 = @await_expr +/* C# 6.0 */ +| 104 = @nameof_expr +| 105 = @interpolated_string_expr +| 106 = @unknown_expr +/* C# 7.0 */ +| 107 = @throw_expr +| 108 = @tuple_expr +| 109 = @local_function_invocation_expr +| 110 = @ref_expr +| 111 = @discard_expr +/* C# 8.0 */ +| 112 = @range_expr +| 113 = @index_expr +| 114 = @switch_expr +| 115 = @recursive_pattern_expr +| 116 = @property_pattern_expr +| 117 = @positional_pattern_expr +| 118 = @switch_case_expr +| 119 = @assign_coalesce_expr +| 120 = @suppress_nullable_warning_expr +| 121 = @namespace_access_expr +/* C# 9.0 */ +| 122 = @lt_pattern_expr +| 123 = @gt_pattern_expr +| 124 = @le_pattern_expr +| 125 = @ge_pattern_expr +| 126 = @not_pattern_expr +| 127 = @and_pattern_expr +| 128 = @or_pattern_expr +| 129 = @function_pointer_invocation_expr +| 130 = @with_expr +/* Preprocessor */ +| 999 = @define_symbol_expr +; + +@switch = @switch_stmt | @switch_expr; +@case = @case_stmt | @switch_case_expr; +@pattern_match = @case | @is_expr; +@unary_pattern_expr = @not_pattern_expr; +@relational_pattern_expr = @gt_pattern_expr | @lt_pattern_expr | @ge_pattern_expr | @le_pattern_expr; +@binary_pattern_expr = @and_pattern_expr | @or_pattern_expr; + +@integer_literal_expr = @int_literal_expr | @long_literal_expr | @uint_literal_expr | @ulong_literal_expr; +@real_literal_expr = @float_literal_expr | @double_literal_expr | @decimal_literal_expr; +@literal_expr = @bool_literal_expr | @char_literal_expr | @integer_literal_expr | @real_literal_expr + | @string_literal_expr | @null_literal_expr; + +@assign_expr = @simple_assign_expr | @assign_op_expr | @local_var_decl_expr; +@assign_op_expr = @assign_arith_expr | @assign_bitwise_expr | @assign_event_expr | @assign_coalesce_expr; +@assign_event_expr = @add_event_expr | @remove_event_expr; + +@assign_arith_expr = @assign_add_expr | @assign_sub_expr | @assign_mul_expr | @assign_div_expr + | @assign_rem_expr +@assign_bitwise_expr = @assign_and_expr | @assign_or_expr | @assign_xor_expr + | @assign_lshift_expr | @assign_rshift_expr; + +@member_access_expr = @field_access_expr | @property_access_expr | @indexer_access_expr | @event_access_expr + | @method_access_expr | @type_access_expr | @dynamic_member_access_expr; +@access_expr = @member_access_expr | @this_access_expr | @base_access_expr | @assignable_access_expr | @namespace_access_expr; +@element_access_expr = @indexer_access_expr | @array_access_expr | @dynamic_element_access_expr; + +@local_variable_access = @local_variable_access_expr | @local_var_decl_expr; +@local_scope_variable_access_expr = @parameter_access_expr | @local_variable_access; +@variable_access_expr = @local_scope_variable_access_expr | @field_access_expr; + +@assignable_access_expr = @variable_access_expr | @property_access_expr | @element_access_expr + | @event_access_expr | @dynamic_member_access_expr; + +@objectorcollection_init_expr = @object_init_expr | @collection_init_expr; + +@delegate_creation_expr = @explicit_delegate_creation_expr | @implicit_delegate_creation_expr; + +@bin_arith_op_expr = @mul_expr | @div_expr | @rem_expr | @add_expr | @sub_expr; +@incr_op_expr = @pre_incr_expr | @post_incr_expr; +@decr_op_expr = @pre_decr_expr | @post_decr_expr; +@mut_op_expr = @incr_op_expr | @decr_op_expr; +@un_arith_op_expr = @plus_expr | @minus_expr | @mut_op_expr; +@arith_op_expr = @bin_arith_op_expr | @un_arith_op_expr; + +@ternary_log_op_expr = @conditional_expr; +@bin_log_op_expr = @log_and_expr | @log_or_expr | @null_coalescing_expr; +@un_log_op_expr = @log_not_expr; +@log_expr = @un_log_op_expr | @bin_log_op_expr | @ternary_log_op_expr; + +@bin_bit_op_expr = @bit_and_expr | @bit_or_expr | @bit_xor_expr | @lshift_expr + | @rshift_expr; +@un_bit_op_expr = @bit_not_expr; +@bit_expr = @un_bit_op_expr | @bin_bit_op_expr; + +@equality_op_expr = @eq_expr | @ne_expr; +@rel_op_expr = @gt_expr | @lt_expr| @ge_expr | @le_expr; +@comp_expr = @equality_op_expr | @rel_op_expr; + +@op_expr = @assign_expr | @un_op | @bin_op | @ternary_op; + +@ternary_op = @ternary_log_op_expr; +@bin_op = @bin_arith_op_expr | @bin_log_op_expr | @bin_bit_op_expr | @comp_expr; +@un_op = @un_arith_op_expr | @un_log_op_expr | @un_bit_op_expr | @sizeof_expr + | @pointer_indirection_expr | @address_of_expr; + +@anonymous_function_expr = @lambda_expr | @anonymous_method_expr; + +@call = @method_invocation_expr | @constructor_init_expr | @operator_invocation_expr + | @delegate_invocation_expr | @object_creation_expr | @call_access_expr + | @local_function_invocation_expr | @function_pointer_invocation_expr; + +@call_access_expr = @property_access_expr | @event_access_expr | @indexer_access_expr; + +@late_bindable_expr = @dynamic_element_access_expr | @dynamic_member_access_expr + | @object_creation_expr | @method_invocation_expr | @operator_invocation_expr; + +@throw_element = @throw_expr | @throw_stmt; + +@implicitly_typeable_object_creation_expr = @object_creation_expr | @explicit_delegate_creation_expr; + +implicitly_typed_array_creation( + unique int id: @array_creation_expr ref); + +explicitly_sized_array_creation( + unique int id: @array_creation_expr ref); + +stackalloc_array_creation( + unique int id: @array_creation_expr ref); + +implicitly_typed_object_creation( + unique int id: @implicitly_typeable_object_creation_expr ref); + +mutator_invocation_mode( + unique int id: @operator_invocation_expr ref, + int mode: int ref /* prefix = 1, postfix = 2*/); + +expr_compiler_generated( + unique int id: @expr ref); + +expr_value( + unique int id: @expr ref, + string value: string ref); + +expr_call( + unique int caller_id: @expr ref, + int target_id: @callable ref); + +expr_access( + unique int accesser_id: @access_expr ref, + int target_id: @accessible ref); + +@accessible = @method | @assignable | @local_function | @namespace; + +expr_location( + unique int id: @expr ref, + int loc: @location ref); + +dynamic_member_name( + unique int id: @late_bindable_expr ref, + string name: string ref); + +@qualifiable_expr = @member_access_expr + | @method_invocation_expr + | @element_access_expr; + +conditional_access( + unique int id: @qualifiable_expr ref); + +expr_argument( + unique int id: @expr ref, + int mode: int ref); + /* mode is the same as params: value = 0, ref = 1, out = 2 */ + +expr_argument_name( + unique int id: @expr ref, + string name: string ref); + +lambda_expr_return_type( + unique int id: @lambda_expr ref, + int type_id: @type_or_ref ref); + +/** CONTROL/DATA FLOW **/ + +@control_flow_element = @stmt | @expr; + +/* XML Files */ + +xmlEncoding ( + unique int id: @file ref, + string encoding: string ref); + +xmlDTDs( + unique int id: @xmldtd, + string root: string ref, + string publicId: string ref, + string systemId: string ref, + int fileid: @file ref); + +xmlElements( + unique int id: @xmlelement, + string name: string ref, + int parentid: @xmlparent ref, + int idx: int ref, + int fileid: @file ref); + +xmlAttrs( + unique int id: @xmlattribute, + int elementid: @xmlelement ref, + string name: string ref, + string value: string ref, + int idx: int ref, + int fileid: @file ref); + +xmlNs( + int id: @xmlnamespace, + string prefixName: string ref, + string URI: string ref, + int fileid: @file ref); + +xmlHasNs( + int elementId: @xmlnamespaceable ref, + int nsId: @xmlnamespace ref, + int fileid: @file ref); + +xmlComments( + unique int id: @xmlcomment, + string text: string ref, + int parentid: @xmlparent ref, + int fileid: @file ref); + +xmlChars( + unique int id: @xmlcharacters, + string text: string ref, + int parentid: @xmlparent ref, + int idx: int ref, + int isCDATA: int ref, + int fileid: @file ref); + +@xmlparent = @file | @xmlelement; +@xmlnamespaceable = @xmlelement | @xmlattribute; + +xmllocations( + int xmlElement: @xmllocatable ref, + int location: @location_default ref); + +@xmllocatable = @xmlcharacters | @xmlelement | @xmlcomment | @xmlattribute | @xmldtd | @file | @xmlnamespace; + +/* Comments */ + +commentline( + unique int id: @commentline, + int kind: int ref, + string text: string ref, + string rawtext: string ref); + +case @commentline.kind of + 0 = @singlelinecomment +| 1 = @xmldoccomment +| 2 = @multilinecomment; + +commentline_location( + unique int id: @commentline ref, + int loc: @location ref); + +commentblock( + unique int id : @commentblock); + +commentblock_location( + unique int id: @commentblock ref, + int loc: @location ref); + +commentblock_binding( + int id: @commentblock ref, + int entity: @element ref, + int bindtype: int ref); /* 0: Parent, 1: Best, 2: Before, 3: After */ + +commentblock_child( + int id: @commentblock ref, + int commentline: @commentline ref, + int index: int ref); + +/* ASP.NET */ + +case @asp_element.kind of + 0=@asp_close_tag +| 1=@asp_code +| 2=@asp_comment +| 3=@asp_data_binding +| 4=@asp_directive +| 5=@asp_open_tag +| 6=@asp_quoted_string +| 7=@asp_text +| 8=@asp_xml_directive; + +@asp_attribute = @asp_code | @asp_data_binding | @asp_quoted_string; + +asp_elements( + unique int id: @asp_element, + int kind: int ref, + int loc: @location ref); + +asp_comment_server(unique int comment: @asp_comment ref); +asp_code_inline(unique int code: @asp_code ref); +asp_directive_attribute( + int directive: @asp_directive ref, + int index: int ref, + string name: string ref, + int value: @asp_quoted_string ref); +asp_directive_name( + unique int directive: @asp_directive ref, + string name: string ref); +asp_element_body( + unique int element: @asp_element ref, + string body: string ref); +asp_tag_attribute( + int tag: @asp_open_tag ref, + int index: int ref, + string name: string ref, + int attribute: @asp_attribute ref); +asp_tag_name( + unique int tag: @asp_open_tag ref, + string name: string ref); +asp_tag_isempty(int tag: @asp_open_tag ref); + +/* Common Intermediate Language - CIL */ + +case @cil_instruction.opcode of + 0 = @cil_nop +| 1 = @cil_break +| 2 = @cil_ldarg_0 +| 3 = @cil_ldarg_1 +| 4 = @cil_ldarg_2 +| 5 = @cil_ldarg_3 +| 6 = @cil_ldloc_0 +| 7 = @cil_ldloc_1 +| 8 = @cil_ldloc_2 +| 9 = @cil_ldloc_3 +| 10 = @cil_stloc_0 +| 11 = @cil_stloc_1 +| 12 = @cil_stloc_2 +| 13 = @cil_stloc_3 +| 14 = @cil_ldarg_s +| 15 = @cil_ldarga_s +| 16 = @cil_starg_s +| 17 = @cil_ldloc_s +| 18 = @cil_ldloca_s +| 19 = @cil_stloc_s +| 20 = @cil_ldnull +| 21 = @cil_ldc_i4_m1 +| 22 = @cil_ldc_i4_0 +| 23 = @cil_ldc_i4_1 +| 24 = @cil_ldc_i4_2 +| 25 = @cil_ldc_i4_3 +| 26 = @cil_ldc_i4_4 +| 27 = @cil_ldc_i4_5 +| 28 = @cil_ldc_i4_6 +| 29 = @cil_ldc_i4_7 +| 30 = @cil_ldc_i4_8 +| 31 = @cil_ldc_i4_s +| 32 = @cil_ldc_i4 +| 33 = @cil_ldc_i8 +| 34 = @cil_ldc_r4 +| 35 = @cil_ldc_r8 +| 37 = @cil_dup +| 38 = @cil_pop +| 39 = @cil_jmp +| 40 = @cil_call +| 41 = @cil_calli +| 42 = @cil_ret +| 43 = @cil_br_s +| 44 = @cil_brfalse_s +| 45 = @cil_brtrue_s +| 46 = @cil_beq_s +| 47 = @cil_bge_s +| 48 = @cil_bgt_s +| 49 = @cil_ble_s +| 50 = @cil_blt_s +| 51 = @cil_bne_un_s +| 52 = @cil_bge_un_s +| 53 = @cil_bgt_un_s +| 54 = @cil_ble_un_s +| 55 = @cil_blt_un_s +| 56 = @cil_br +| 57 = @cil_brfalse +| 58 = @cil_brtrue +| 59 = @cil_beq +| 60 = @cil_bge +| 61 = @cil_bgt +| 62 = @cil_ble +| 63 = @cil_blt +| 64 = @cil_bne_un +| 65 = @cil_bge_un +| 66 = @cil_bgt_un +| 67 = @cil_ble_un +| 68 = @cil_blt_un +| 69 = @cil_switch +| 70 = @cil_ldind_i1 +| 71 = @cil_ldind_u1 +| 72 = @cil_ldind_i2 +| 73 = @cil_ldind_u2 +| 74 = @cil_ldind_i4 +| 75 = @cil_ldind_u4 +| 76 = @cil_ldind_i8 +| 77 = @cil_ldind_i +| 78 = @cil_ldind_r4 +| 79 = @cil_ldind_r8 +| 80 = @cil_ldind_ref +| 81 = @cil_stind_ref +| 82 = @cil_stind_i1 +| 83 = @cil_stind_i2 +| 84 = @cil_stind_i4 +| 85 = @cil_stind_i8 +| 86 = @cil_stind_r4 +| 87 = @cil_stind_r8 +| 88 = @cil_add +| 89 = @cil_sub +| 90 = @cil_mul +| 91 = @cil_div +| 92 = @cil_div_un +| 93 = @cil_rem +| 94 = @cil_rem_un +| 95 = @cil_and +| 96 = @cil_or +| 97 = @cil_xor +| 98 = @cil_shl +| 99 = @cil_shr +| 100 = @cil_shr_un +| 101 = @cil_neg +| 102 = @cil_not +| 103 = @cil_conv_i1 +| 104 = @cil_conv_i2 +| 105 = @cil_conv_i4 +| 106 = @cil_conv_i8 +| 107 = @cil_conv_r4 +| 108 = @cil_conv_r8 +| 109 = @cil_conv_u4 +| 110 = @cil_conv_u8 +| 111 = @cil_callvirt +| 112 = @cil_cpobj +| 113 = @cil_ldobj +| 114 = @cil_ldstr +| 115 = @cil_newobj +| 116 = @cil_castclass +| 117 = @cil_isinst +| 118 = @cil_conv_r_un +| 121 = @cil_unbox +| 122 = @cil_throw +| 123 = @cil_ldfld +| 124 = @cil_ldflda +| 125 = @cil_stfld +| 126 = @cil_ldsfld +| 127 = @cil_ldsflda +| 128 = @cil_stsfld +| 129 = @cil_stobj +| 130 = @cil_conv_ovf_i1_un +| 131 = @cil_conv_ovf_i2_un +| 132 = @cil_conv_ovf_i4_un +| 133 = @cil_conv_ovf_i8_un +| 134 = @cil_conv_ovf_u1_un +| 135 = @cil_conv_ovf_u2_un +| 136 = @cil_conv_ovf_u4_un +| 137 = @cil_conv_ovf_u8_un +| 138 = @cil_conv_ovf_i_un +| 139 = @cil_conv_ovf_u_un +| 140 = @cil_box +| 141 = @cil_newarr +| 142 = @cil_ldlen +| 143 = @cil_ldelema +| 144 = @cil_ldelem_i1 +| 145 = @cil_ldelem_u1 +| 146 = @cil_ldelem_i2 +| 147 = @cil_ldelem_u2 +| 148 = @cil_ldelem_i4 +| 149 = @cil_ldelem_u4 +| 150 = @cil_ldelem_i8 +| 151 = @cil_ldelem_i +| 152 = @cil_ldelem_r4 +| 153 = @cil_ldelem_r8 +| 154 = @cil_ldelem_ref +| 155 = @cil_stelem_i +| 156 = @cil_stelem_i1 +| 157 = @cil_stelem_i2 +| 158 = @cil_stelem_i4 +| 159 = @cil_stelem_i8 +| 160 = @cil_stelem_r4 +| 161 = @cil_stelem_r8 +| 162 = @cil_stelem_ref +| 163 = @cil_ldelem +| 164 = @cil_stelem +| 165 = @cil_unbox_any +| 179 = @cil_conv_ovf_i1 +| 180 = @cil_conv_ovf_u1 +| 181 = @cil_conv_ovf_i2 +| 182 = @cil_conv_ovf_u2 +| 183 = @cil_conv_ovf_i4 +| 184 = @cil_conv_ovf_u4 +| 185 = @cil_conv_ovf_i8 +| 186 = @cil_conv_ovf_u8 +| 194 = @cil_refanyval +| 195 = @cil_ckinfinite +| 198 = @cil_mkrefany +| 208 = @cil_ldtoken +| 209 = @cil_conv_u2 +| 210 = @cil_conv_u1 +| 211 = @cil_conv_i +| 212 = @cil_conv_ovf_i +| 213 = @cil_conv_ovf_u +| 214 = @cil_add_ovf +| 215 = @cil_add_ovf_un +| 216 = @cil_mul_ovf +| 217 = @cil_mul_ovf_un +| 218 = @cil_sub_ovf +| 219 = @cil_sub_ovf_un +| 220 = @cil_endfinally +| 221 = @cil_leave +| 222 = @cil_leave_s +| 223 = @cil_stind_i +| 224 = @cil_conv_u +| 65024 = @cil_arglist +| 65025 = @cil_ceq +| 65026 = @cil_cgt +| 65027 = @cil_cgt_un +| 65028 = @cil_clt +| 65029 = @cil_clt_un +| 65030 = @cil_ldftn +| 65031 = @cil_ldvirtftn +| 65033 = @cil_ldarg +| 65034 = @cil_ldarga +| 65035 = @cil_starg +| 65036 = @cil_ldloc +| 65037 = @cil_ldloca +| 65038 = @cil_stloc +| 65039 = @cil_localloc +| 65041 = @cil_endfilter +| 65042 = @cil_unaligned +| 65043 = @cil_volatile +| 65044 = @cil_tail +| 65045 = @cil_initobj +| 65046 = @cil_constrained +| 65047 = @cil_cpblk +| 65048 = @cil_initblk +| 65050 = @cil_rethrow +| 65052 = @cil_sizeof +| 65053 = @cil_refanytype +| 65054 = @cil_readonly +; + +// CIL ignored instructions + +@cil_ignore = @cil_nop | @cil_break | @cil_volatile | @cil_unaligned; + +// CIL local/parameter/field access + +@cil_ldarg_any = @cil_ldarg_0 | @cil_ldarg_1 | @cil_ldarg_2 | @cil_ldarg_3 | @cil_ldarg_s | @cil_ldarga_s | @cil_ldarg | @cil_ldarga; +@cil_starg_any = @cil_starg | @cil_starg_s; + +@cil_ldloc_any = @cil_ldloc_0 | @cil_ldloc_1 | @cil_ldloc_2 | @cil_ldloc_3 | @cil_ldloc_s | @cil_ldloca_s | @cil_ldloc | @cil_ldloca; +@cil_stloc_any = @cil_stloc_0 | @cil_stloc_1 | @cil_stloc_2 | @cil_stloc_3 | @cil_stloc_s | @cil_stloc; + +@cil_ldfld_any = @cil_ldfld | @cil_ldsfld | @cil_ldsflda | @cil_ldflda; +@cil_stfld_any = @cil_stfld | @cil_stsfld; + +@cil_local_access = @cil_stloc_any | @cil_ldloc_any; +@cil_arg_access = @cil_starg_any | @cil_ldarg_any; +@cil_read_access = @cil_ldloc_any | @cil_ldarg_any | @cil_ldfld_any; +@cil_write_access = @cil_stloc_any | @cil_starg_any | @cil_stfld_any; + +@cil_stack_access = @cil_local_access | @cil_arg_access; +@cil_field_access = @cil_ldfld_any | @cil_stfld_any; + +@cil_access = @cil_read_access | @cil_write_access; + +// CIL constant/literal instructions + +@cil_ldc_i = @cil_ldc_i4_any | @cil_ldc_i8; + +@cil_ldc_i4_any = @cil_ldc_i4_m1 | @cil_ldc_i4_0 | @cil_ldc_i4_1 | @cil_ldc_i4_2 | @cil_ldc_i4_3 | + @cil_ldc_i4_4 | @cil_ldc_i4_5 | @cil_ldc_i4_6 | @cil_ldc_i4_7 | @cil_ldc_i4_8 | @cil_ldc_i4_s | @cil_ldc_i4; + +@cil_ldc_r = @cil_ldc_r4 | @cil_ldc_r8; + +@cil_literal = @cil_ldnull | @cil_ldc_i | @cil_ldc_r | @cil_ldstr; + +// Control flow + +@cil_conditional_jump = @cil_binary_jump | @cil_unary_jump; +@cil_binary_jump = @cil_beq_s | @cil_bge_s | @cil_bgt_s | @cil_ble_s | @cil_blt_s | + @cil_bne_un_s | @cil_bge_un_s | @cil_bgt_un_s | @cil_ble_un_s | @cil_blt_un_s | + @cil_beq | @cil_bge | @cil_bgt | @cil_ble | @cil_blt | + @cil_bne_un | @cil_bge_un | @cil_bgt_un | @cil_ble_un | @cil_blt_un; +@cil_unary_jump = @cil_brfalse_s | @cil_brtrue_s | @cil_brfalse | @cil_brtrue | @cil_switch; +@cil_unconditional_jump = @cil_br | @cil_br_s | @cil_leave_any; +@cil_leave_any = @cil_leave | @cil_leave_s; +@cil_jump = @cil_unconditional_jump | @cil_conditional_jump; + +// CIL call instructions + +@cil_call_any = @cil_jmp | @cil_call | @cil_calli | @cil_tail | @cil_callvirt | @cil_newobj; + +// CIL expression instructions + +@cil_expr = @cil_literal | @cil_binary_expr | @cil_unary_expr | @cil_call_any | @cil_read_access | + @cil_newarr | @cil_ldtoken | @cil_sizeof | + @cil_ldftn | @cil_ldvirtftn | @cil_localloc | @cil_mkrefany | @cil_refanytype | @cil_arglist | @cil_dup; + +@cil_unary_expr = + @cil_conversion_operation | @cil_unary_arithmetic_operation | @cil_unary_bitwise_operation| + @cil_ldlen | @cil_isinst | @cil_box | @cil_ldobj | @cil_castclass | @cil_unbox_any | + @cil_ldind | @cil_unbox; + +@cil_conversion_operation = + @cil_conv_i1 | @cil_conv_i2 | @cil_conv_i4 | @cil_conv_i8 | + @cil_conv_u1 | @cil_conv_u2 | @cil_conv_u4 | @cil_conv_u8 | + @cil_conv_ovf_i | @cil_conv_ovf_i_un | @cil_conv_ovf_i1 | @cil_conv_ovf_i1_un | + @cil_conv_ovf_i2 | @cil_conv_ovf_i2_un | @cil_conv_ovf_i4 | @cil_conv_ovf_i4_un | + @cil_conv_ovf_i8 | @cil_conv_ovf_i8_un | @cil_conv_ovf_u | @cil_conv_ovf_u_un | + @cil_conv_ovf_u1 | @cil_conv_ovf_u1_un | @cil_conv_ovf_u2 | @cil_conv_ovf_u2_un | + @cil_conv_ovf_u4 | @cil_conv_ovf_u4_un | @cil_conv_ovf_u8 | @cil_conv_ovf_u8_un | + @cil_conv_r4 | @cil_conv_r8 | @cil_conv_ovf_u2 | @cil_conv_ovf_u2_un | + @cil_conv_i | @cil_conv_u | @cil_conv_r_un; + +@cil_ldind = @cil_ldind_i | @cil_ldind_i1 | @cil_ldind_i2 | @cil_ldind_i4 | @cil_ldind_i8 | + @cil_ldind_r4 | @cil_ldind_r8 | @cil_ldind_ref | @cil_ldind_u1 | @cil_ldind_u2 | @cil_ldind_u4; + +@cil_stind = @cil_stind_i | @cil_stind_i1 | @cil_stind_i2 | @cil_stind_i4 | @cil_stind_i8 | + @cil_stind_r4 | @cil_stind_r8 | @cil_stind_ref; + +@cil_bitwise_operation = @cil_binary_bitwise_operation | @cil_unary_bitwise_operation; + +@cil_binary_bitwise_operation = @cil_and | @cil_or | @cil_xor | @cil_shr | @cil_shr | @cil_shr_un | @cil_shl; + +@cil_binary_arithmetic_operation = @cil_add | @cil_sub | @cil_mul | @cil_div | @cil_div_un | + @cil_rem | @cil_rem_un | @cil_add_ovf | @cil_add_ovf_un | @cil_mul_ovf | @cil_mul_ovf_un | + @cil_sub_ovf | @cil_sub_ovf_un; + +@cil_unary_bitwise_operation = @cil_not; + +@cil_binary_expr = @cil_binary_arithmetic_operation | @cil_binary_bitwise_operation | @cil_read_array | @cil_comparison_operation; + +@cil_unary_arithmetic_operation = @cil_neg; + +@cil_comparison_operation = @cil_cgt_un | @cil_ceq | @cil_cgt | @cil_clt | @cil_clt_un; + +// Elements that retrieve an address of something +@cil_read_ref = @cil_ldloca_s | @cil_ldarga_s | @cil_ldflda | @cil_ldsflda | @cil_ldelema; + +// CIL array instructions + +@cil_read_array = + @cil_ldelem | @cil_ldelema | @cil_ldelem_i1 | @cil_ldelem_ref | @cil_ldelem_i | + @cil_ldelem_i1 | @cil_ldelem_i2 | @cil_ldelem_i4 | @cil_ldelem_i8 | @cil_ldelem_r4 | + @cil_ldelem_r8 | @cil_ldelem_u1 | @cil_ldelem_u2 | @cil_ldelem_u4; + +@cil_write_array = @cil_stelem | @cil_stelem_ref | + @cil_stelem_i | @cil_stelem_i1 | @cil_stelem_i2 | @cil_stelem_i4 | @cil_stelem_i8 | + @cil_stelem_r4 | @cil_stelem_r8; + +@cil_throw_any = @cil_throw | @cil_rethrow; + +#keyset[impl, index] +cil_instruction( + unique int id: @cil_instruction, + int opcode: int ref, + int index: int ref, + int impl: @cil_method_implementation ref); + +cil_jump( + unique int instruction: @cil_jump ref, + int target: @cil_instruction ref); + +cil_access( + unique int instruction: @cil_instruction ref, + int target: @cil_accessible ref); + +cil_value( + unique int instruction: @cil_literal ref, + string value: string ref); + +#keyset[instruction, index] +cil_switch( + int instruction: @cil_switch ref, + int index: int ref, + int target: @cil_instruction ref); + +cil_instruction_location( + unique int id: @cil_instruction ref, + int loc: @location ref); + +cil_type_location( + int id: @cil_type ref, + int loc: @location ref); + +cil_method_location( + int id: @cil_method ref, + int loc: @location ref); + +@cil_namespace = @namespace; + +@cil_type_container = @cil_type | @cil_namespace | @cil_method; + +case @cil_type.kind of + 0 = @cil_valueorreftype +| 1 = @cil_typeparameter +| 2 = @cil_array_type +| 3 = @cil_pointer_type +| 4 = @cil_function_pointer_type +; + +cil_type( + unique int id: @cil_type, + string name: string ref, + int kind: int ref, + int parent: @cil_type_container ref, + int sourceDecl: @cil_type ref); + +cil_pointer_type( + unique int id: @cil_pointer_type ref, + int pointee: @cil_type ref); + +cil_array_type( + unique int id: @cil_array_type ref, + int element_type: @cil_type ref, + int rank: int ref); + +cil_function_pointer_return_type( + unique int id: @cil_function_pointer_type ref, + int return_type: @cil_type ref); + +cil_method( + unique int id: @cil_method, + string name: string ref, + int parent: @cil_type ref, + int return_type: @cil_type ref); + +cil_method_source_declaration( + unique int method: @cil_method ref, + int source: @cil_method ref); + +cil_method_implementation( + unique int id: @cil_method_implementation, + int method: @cil_method ref, + int location: @assembly ref); + +cil_implements( + int id: @cil_method ref, + int decl: @cil_method ref); + +#keyset[parent, name] +cil_field( + unique int id: @cil_field, + int parent: @cil_type ref, + string name: string ref, + int field_type: @cil_type ref); + +@cil_element = @cil_instruction | @cil_declaration | @cil_handler | @cil_attribute | @cil_namespace; +@cil_named_element = @cil_declaration | @cil_namespace; +@cil_declaration = @cil_variable | @cil_method | @cil_type | @cil_member; +@cil_accessible = @cil_declaration; +@cil_variable = @cil_field | @cil_stack_variable; +@cil_stack_variable = @cil_local_variable | @cil_parameter; +@cil_member = @cil_method | @cil_type | @cil_field | @cil_property | @cil_event; +@cil_custom_modifier_receiver = @cil_method | @cil_property | @cil_parameter | @cil_field | @cil_function_pointer_type; +@cil_parameterizable = @cil_method | @cil_function_pointer_type; +@cil_has_type_annotation = @cil_stack_variable | @cil_property | @cil_method | @cil_function_pointer_type; + +#keyset[parameterizable, index] +cil_parameter( + unique int id: @cil_parameter, + int parameterizable: @cil_parameterizable ref, + int index: int ref, + int param_type: @cil_type ref); + +cil_parameter_in(unique int id: @cil_parameter ref); +cil_parameter_out(unique int id: @cil_parameter ref); + +cil_setter(unique int prop: @cil_property ref, + int method: @cil_method ref); + +#keyset[id, modifier] +cil_custom_modifiers( + int id: @cil_custom_modifier_receiver ref, + int modifier: @cil_type ref, + int kind: int ref); // modreq: 1, modopt: 0 + +cil_type_annotation( + int id: @cil_has_type_annotation ref, + int annotation: int ref); + +cil_getter(unique int prop: @cil_property ref, + int method: @cil_method ref); + +cil_adder(unique int event: @cil_event ref, + int method: @cil_method ref); + +cil_remover(unique int event: @cil_event ref, int method: @cil_method ref); + +cil_raiser(unique int event: @cil_event ref, int method: @cil_method ref); + +cil_property( + unique int id: @cil_property, + int parent: @cil_type ref, + string name: string ref, + int property_type: @cil_type ref); + +#keyset[parent, name] +cil_event(unique int id: @cil_event, + int parent: @cil_type ref, + string name: string ref, + int event_type: @cil_type ref); + +#keyset[impl, index] +cil_local_variable( + unique int id: @cil_local_variable, + int impl: @cil_method_implementation ref, + int index: int ref, + int var_type: @cil_type ref); + +cil_function_pointer_calling_conventions( + int id: @cil_function_pointer_type ref, + int kind: int ref); + +// CIL handlers (exception handlers etc). + +case @cil_handler.kind of + 0 = @cil_catch_handler +| 1 = @cil_filter_handler +| 2 = @cil_finally_handler +| 4 = @cil_fault_handler +; + +#keyset[impl, index] +cil_handler( + unique int id: @cil_handler, + int impl: @cil_method_implementation ref, + int index: int ref, + int kind: int ref, + int try_start: @cil_instruction ref, + int try_end: @cil_instruction ref, + int handler_start: @cil_instruction ref); + +cil_handler_filter( + unique int id: @cil_handler ref, + int filter_start: @cil_instruction ref); + +cil_handler_type( + unique int id: @cil_handler ref, + int catch_type: @cil_type ref); + +@cil_controlflow_node = @cil_entry_point | @cil_instruction; + +@cil_entry_point = @cil_method_implementation | @cil_handler; + +@cil_dataflow_node = @cil_instruction | @cil_variable | @cil_method; + +cil_method_stack_size( + unique int method: @cil_method_implementation ref, + int size: int ref); + +// CIL modifiers + +cil_public(int id: @cil_member ref); +cil_private(int id: @cil_member ref); +cil_protected(int id: @cil_member ref); +cil_internal(int id: @cil_member ref); +cil_static(int id: @cil_member ref); +cil_sealed(int id: @cil_member ref); +cil_virtual(int id: @cil_method ref); +cil_abstract(int id: @cil_member ref); +cil_class(int id: @cil_type ref); +cil_interface(int id: @cil_type ref); +cil_security(int id: @cil_member ref); +cil_requiresecobject(int id: @cil_method ref); +cil_specialname(int id: @cil_method ref); +cil_newslot(int id: @cil_method ref); + +cil_base_class(unique int id: @cil_type ref, int base: @cil_type ref); +cil_base_interface(int id: @cil_type ref, int base: @cil_type ref); +cil_enum_underlying_type(unique int id: @cil_type ref, int underlying: @cil_type ref); + +#keyset[unbound, index] +cil_type_parameter( + int unbound: @cil_member ref, + int index: int ref, + int param: @cil_typeparameter ref); + +#keyset[bound, index] +cil_type_argument( + int bound: @cil_member ref, + int index: int ref, + int t: @cil_type ref); + +// CIL type parameter constraints + +cil_typeparam_covariant(int tp: @cil_typeparameter ref); +cil_typeparam_contravariant(int tp: @cil_typeparameter ref); +cil_typeparam_class(int tp: @cil_typeparameter ref); +cil_typeparam_struct(int tp: @cil_typeparameter ref); +cil_typeparam_new(int tp: @cil_typeparameter ref); +cil_typeparam_constraint(int tp: @cil_typeparameter ref, int supertype: @cil_type ref); + +// CIL attributes + +cil_attribute( + unique int attributeid: @cil_attribute, + int element: @cil_declaration ref, + int constructor: @cil_method ref); + +#keyset[attribute_id, param] +cil_attribute_named_argument( + int attribute_id: @cil_attribute ref, + string param: string ref, + string value: string ref); + +#keyset[attribute_id, index] +cil_attribute_positional_argument( + int attribute_id: @cil_attribute ref, + int index: int ref, + string value: string ref); + + +// Common .Net data model covering both C# and CIL + +// Common elements +@dotnet_element = @element | @cil_element; +@dotnet_named_element = @named_element | @cil_named_element; +@dotnet_callable = @callable | @cil_method; +@dotnet_variable = @variable | @cil_variable; +@dotnet_field = @field | @cil_field; +@dotnet_parameter = @parameter | @cil_parameter; +@dotnet_declaration = @declaration | @cil_declaration; +@dotnet_member = @member | @cil_member; +@dotnet_event = @event | @cil_event; +@dotnet_property = @property | @cil_property | @indexer; +@dotnet_parameterizable = @parameterizable | @cil_parameterizable; + +// Common types +@dotnet_type = @type | @cil_type; +@dotnet_call = @call | @cil_call_any; +@dotnet_throw = @throw_element | @cil_throw_any; +@dotnet_valueorreftype = @cil_valueorreftype | @value_or_ref_type | @cil_array_type | @void_type; +@dotnet_typeparameter = @type_parameter | @cil_typeparameter; +@dotnet_array_type = @array_type | @cil_array_type; +@dotnet_pointer_type = @pointer_type | @cil_pointer_type; +@dotnet_type_parameter = @type_parameter | @cil_typeparameter; +@dotnet_generic = @dotnet_valueorreftype | @dotnet_callable; + +// Attributes +@dotnet_attribute = @attribute | @cil_attribute; + +// Expressions +@dotnet_expr = @expr | @cil_expr; + +// Literals +@dotnet_literal = @literal_expr | @cil_literal; +@dotnet_string_literal = @string_literal_expr | @cil_ldstr; +@dotnet_int_literal = @integer_literal_expr | @cil_ldc_i; +@dotnet_float_literal = @float_literal_expr | @cil_ldc_r; +@dotnet_null_literal = @null_literal_expr | @cil_ldnull; + +@metadata_entity = @cil_method | @cil_type | @cil_field | @cil_property | @field | @property | + @callable | @value_or_ref_type | @void_type; + +#keyset[entity, location] +metadata_handle(int entity : @metadata_entity ref, int location: @assembly ref, int handle: int ref) diff --git a/csharp/ql/lib/upgrades/4ac7d8bcac6f664b1e83c858aa71f8dc761cc603/semmlecode.csharp.dbscheme b/csharp/ql/lib/upgrades/4ac7d8bcac6f664b1e83c858aa71f8dc761cc603/semmlecode.csharp.dbscheme new file mode 100644 index 00000000000..83aca6b3e4f --- /dev/null +++ b/csharp/ql/lib/upgrades/4ac7d8bcac6f664b1e83c858aa71f8dc761cc603/semmlecode.csharp.dbscheme @@ -0,0 +1,2067 @@ +/* This is a dummy line to alter the dbscheme, so we can make a database upgrade + * without actually changing any of the dbscheme predicates. It contains a date + * to allow for such updates in the future as well. + * + * 2021-07-14 + * + * DO NOT remove this comment carelessly, since it can revert the dbscheme back to a + * previously seen state (matching a previously seen SHA), which would make the upgrade + * mechanism not work properly. + */ + +/** + * An invocation of the compiler. Note that more than one file may be + * compiled per invocation. For example, this command compiles three + * source files: + * + * csc f1.cs f2.cs f3.cs + * + * The `id` simply identifies the invocation, while `cwd` is the working + * directory from which the compiler was invoked. + */ +compilations( + unique int id : @compilation, + string cwd : string ref +); + +/** + * The arguments that were passed to the extractor for a compiler + * invocation. If `id` is for the compiler invocation + * + * csc f1.cs f2.cs f3.cs + * + * then typically there will be rows for + * + * num | arg + * --- | --- + * 0 | --compiler + * 1 | *path to compiler* + * 2 | f1.cs + * 3 | f2.cs + * 4 | f3.cs + */ +#keyset[id, num] +compilation_args( + int id : @compilation ref, + int num : int ref, + string arg : string ref +); + +/** + * The source files that are compiled by a compiler invocation. + * If `id` is for the compiler invocation + * + * csc f1.cs f2.cs f3.cs + * + * then there will be rows for + * + * num | arg + * --- | --- + * 0 | f1.cs + * 1 | f2.cs + * 2 | f3.cs + */ +#keyset[id, num] +compilation_compiling_files( + int id : @compilation ref, + int num : int ref, + int file : @file ref +); + +/** + * The references used by a compiler invocation. + * If `id` is for the compiler invocation + * + * csc f1.cs f2.cs f3.cs /r:ref1.dll /r:ref2.dll /r:ref3.dll + * + * then there will be rows for + * + * num | arg + * --- | --- + * 0 | ref1.dll + * 1 | ref2.dll + * 2 | ref3.dll + */ +#keyset[id, num] +compilation_referencing_files( + int id : @compilation ref, + int num : int ref, + int file : @file ref +); + +/** + * The time taken by the extractor for a compiler invocation. + * + * For each file `num`, there will be rows for + * + * kind | seconds + * ---- | --- + * 1 | CPU seconds used by the extractor frontend + * 2 | Elapsed seconds during the extractor frontend + * 3 | CPU seconds used by the extractor backend + * 4 | Elapsed seconds during the extractor backend + */ +#keyset[id, num, kind] +compilation_time( + int id : @compilation ref, + int num : int ref, + /* kind: + 1 = frontend_cpu_seconds + 2 = frontend_elapsed_seconds + 3 = extractor_cpu_seconds + 4 = extractor_elapsed_seconds + */ + int kind : int ref, + float seconds : float ref +); + +/** + * An error or warning generated by the extractor. + * The diagnostic message `diagnostic` was generated during compiler + * invocation `compilation`, and is the `file_number_diagnostic_number`th + * message generated while extracting the `file_number`th file of that + * invocation. + */ +#keyset[compilation, file_number, file_number_diagnostic_number] +diagnostic_for( + unique int diagnostic : @diagnostic ref, + int compilation : @compilation ref, + int file_number : int ref, + int file_number_diagnostic_number : int ref +); + +diagnostics( + unique int id: @diagnostic, + int severity: int ref, + string error_tag: string ref, + string error_message: string ref, + string full_error_message: string ref, + int location: @location_default ref +); + +extractor_messages( + unique int id: @extractor_message, + int severity: int ref, + string origin : string ref, + string text : string ref, + string entity : string ref, + int location: @location_default ref, + string stack_trace : string ref +); + +/** + * If extraction was successful, then `cpu_seconds` and + * `elapsed_seconds` are the CPU time and elapsed time (respectively) + * that extraction took for compiler invocation `id`. + */ +compilation_finished( + unique int id : @compilation ref, + float cpu_seconds : float ref, + float elapsed_seconds : float ref +); + +compilation_assembly( + unique int id : @compilation ref, + int assembly: @assembly ref +) + +// Populated by the CSV extractor +externalData( + int id: @externalDataElement, + string path: string ref, + int column: int ref, + string value: string ref); + +sourceLocationPrefix( + string prefix: string ref); + +/* + * C# dbscheme + */ + +/** ELEMENTS **/ + +@element = @declaration | @stmt | @expr | @modifier | @attribute | @namespace_declaration + | @using_directive | @type_parameter_constraints | @externalDataElement + | @xmllocatable | @asp_element | @namespace | @preprocessor_directive; + +@declaration = @callable | @generic | @assignable | @namespace; + +@named_element = @namespace | @declaration; + +@declaration_with_accessors = @property | @indexer | @event; + +@assignable = @variable | @assignable_with_accessors | @event; + +@assignable_with_accessors = @property | @indexer; + +@attributable = @assembly | @field | @parameter | @operator | @method | @constructor + | @destructor | @callable_accessor | @value_or_ref_type | @declaration_with_accessors + | @local_function | @lambda_expr; + +/** LOCATIONS, ASEMMBLIES, MODULES, FILES and FOLDERS **/ + +@location = @location_default | @assembly; + +locations_default( + unique int id: @location_default, + int file: @file ref, + int beginLine: int ref, + int beginColumn: int ref, + int endLine: int ref, + int endColumn: int ref); + +locations_mapped( + unique int id: @location_default ref, + int mapped_to: @location_default ref); + +@sourceline = @file | @callable | @xmllocatable; + +numlines( + int element_id: @sourceline ref, + int num_lines: int ref, + int num_code: int ref, + int num_comment: int ref); + +assemblies( + unique int id: @assembly, + int file: @file ref, + string fullname: string ref, + string name: string ref, + string version: string ref); + +files( + unique int id: @file, + string name: string ref); + +folders( + unique int id: @folder, + string name: string ref); + +@container = @folder | @file ; + +containerparent( + int parent: @container ref, + unique int child: @container ref); + +file_extraction_mode( + unique int file: @file ref, + int mode: int ref + /* 0 = normal, 1 = standalone extractor */ + ); + +/** NAMESPACES **/ + +@type_container = @namespace | @type; + +namespaces( + unique int id: @namespace, + string name: string ref); + +namespace_declarations( + unique int id: @namespace_declaration, + int namespace_id: @namespace ref); + +namespace_declaration_location( + unique int id: @namespace_declaration ref, + int loc: @location ref); + +parent_namespace( + unique int child_id: @type_container ref, + int namespace_id: @namespace ref); + +@declaration_or_directive = @namespace_declaration | @type | @using_directive; + +parent_namespace_declaration( + int child_id: @declaration_or_directive ref, // cannot be unique because of partial classes + int namespace_id: @namespace_declaration ref); + +@using_directive = @using_namespace_directive | @using_static_directive; + +using_global( + unique int id: @using_directive ref +); + +using_namespace_directives( + unique int id: @using_namespace_directive, + int namespace_id: @namespace ref); + +using_static_directives( + unique int id: @using_static_directive, + int type_id: @type_or_ref ref); + +using_directive_location( + unique int id: @using_directive ref, + int loc: @location ref); + +@preprocessor_directive = @pragma_warning | @pragma_checksum | @directive_define | @directive_undefine | @directive_warning + | @directive_error | @directive_nullable | @directive_line | @directive_region | @directive_endregion | @directive_if + | @directive_elif | @directive_else | @directive_endif; + +@conditional_directive = @directive_if | @directive_elif; +@branch_directive = @directive_if | @directive_elif | @directive_else; + +directive_ifs( + unique int id: @directive_if, + int branchTaken: int ref, /* 0: false, 1: true */ + int conditionValue: int ref); /* 0: false, 1: true */ + +directive_elifs( + unique int id: @directive_elif, + int branchTaken: int ref, /* 0: false, 1: true */ + int conditionValue: int ref, /* 0: false, 1: true */ + int parent: @directive_if ref, + int index: int ref); + +directive_elses( + unique int id: @directive_else, + int branchTaken: int ref, /* 0: false, 1: true */ + int parent: @directive_if ref, + int index: int ref); + +#keyset[id, start] +directive_endifs( + unique int id: @directive_endif, + unique int start: @directive_if ref); + +directive_define_symbols( + unique int id: @define_symbol_expr ref, + string name: string ref); + +directive_regions( + unique int id: @directive_region, + string name: string ref); + +#keyset[id, start] +directive_endregions( + unique int id: @directive_endregion, + unique int start: @directive_region ref); + +directive_lines( + unique int id: @directive_line, + int kind: int ref); /* 0: default, 1: hidden, 2: numeric, 3: span */ + +directive_line_value( + unique int id: @directive_line ref, + int line: int ref); + +directive_line_file( + unique int id: @directive_line ref, + int file: @file ref); + +directive_line_offset( + unique int id: @directive_line ref, + int offset: int ref); + +directive_line_span( + unique int id: @directive_line ref, + int startLine: int ref, + int startColumn: int ref, + int endLine: int ref, + int endColumn: int ref); + +directive_nullables( + unique int id: @directive_nullable, + int setting: int ref, /* 0: disable, 1: enable, 2: restore */ + int target: int ref); /* 0: none, 1: annotations, 2: warnings */ + +directive_warnings( + unique int id: @directive_warning, + string message: string ref); + +directive_errors( + unique int id: @directive_error, + string message: string ref); + +directive_undefines( + unique int id: @directive_undefine, + string name: string ref); + +directive_defines( + unique int id: @directive_define, + string name: string ref); + +pragma_checksums( + unique int id: @pragma_checksum, + int file: @file ref, + string guid: string ref, + string bytes: string ref); + +pragma_warnings( + unique int id: @pragma_warning, + int kind: int ref /* 0 = disable, 1 = restore */); + +#keyset[id, index] +pragma_warning_error_codes( + int id: @pragma_warning ref, + string errorCode: string ref, + int index: int ref); + +preprocessor_directive_location( + unique int id: @preprocessor_directive ref, + int loc: @location ref); + +preprocessor_directive_compilation( + unique int id: @preprocessor_directive ref, + int compilation: @compilation ref); + +preprocessor_directive_active( + unique int id: @preprocessor_directive ref, + int active: int ref); /* 0: false, 1: true */ + +/** TYPES **/ + +types( + unique int id: @type, + int kind: int ref, + string name: string ref); + +case @type.kind of + 1 = @bool_type +| 2 = @char_type +| 3 = @decimal_type +| 4 = @sbyte_type +| 5 = @short_type +| 6 = @int_type +| 7 = @long_type +| 8 = @byte_type +| 9 = @ushort_type +| 10 = @uint_type +| 11 = @ulong_type +| 12 = @float_type +| 13 = @double_type +| 14 = @enum_type +| 15 = @struct_type +| 17 = @class_type +| 19 = @interface_type +| 20 = @delegate_type +| 21 = @null_type +| 22 = @type_parameter +| 23 = @pointer_type +| 24 = @nullable_type +| 25 = @array_type +| 26 = @void_type +| 27 = @int_ptr_type +| 28 = @uint_ptr_type +| 29 = @dynamic_type +| 30 = @arglist_type +| 31 = @unknown_type +| 32 = @tuple_type +| 33 = @function_pointer_type + ; + +@simple_type = @bool_type | @char_type | @integral_type | @floating_point_type | @decimal_type; +@integral_type = @signed_integral_type | @unsigned_integral_type; +@signed_integral_type = @sbyte_type | @short_type | @int_type | @long_type; +@unsigned_integral_type = @byte_type | @ushort_type | @uint_type | @ulong_type; +@floating_point_type = @float_type | @double_type; +@value_type = @simple_type | @enum_type | @struct_type | @nullable_type | @int_ptr_type + | @uint_ptr_type | @tuple_type; +@ref_type = @class_type | @interface_type | @array_type | @delegate_type | @null_type + | @dynamic_type; +@value_or_ref_type = @value_type | @ref_type; + +typerefs( + unique int id: @typeref, + string name: string ref); + +typeref_type( + int id: @typeref ref, + unique int typeId: @type ref); + +@type_or_ref = @type | @typeref; + +array_element_type( + unique int array: @array_type ref, + int dimension: int ref, + int rank: int ref, + int element: @type_or_ref ref); + +nullable_underlying_type( + unique int nullable: @nullable_type ref, + int underlying: @type_or_ref ref); + +pointer_referent_type( + unique int pointer: @pointer_type ref, + int referent: @type_or_ref ref); + +enum_underlying_type( + unique int enum_id: @enum_type ref, + int underlying_type_id: @type_or_ref ref); + +delegate_return_type( + unique int delegate_id: @delegate_type ref, + int return_type_id: @type_or_ref ref); + +function_pointer_return_type( + unique int function_pointer_id: @function_pointer_type ref, + int return_type_id: @type_or_ref ref); + +extend( + int sub: @type ref, + int super: @type_or_ref ref); + +anonymous_types( + unique int id: @type ref); + +@interface_or_ref = @interface_type | @typeref; + +implement( + int sub: @type ref, + int super: @type_or_ref ref); + +type_location( + int id: @type ref, + int loc: @location ref); + +tuple_underlying_type( + unique int tuple: @tuple_type ref, + int struct: @type_or_ref ref); + +#keyset[tuple, index] +tuple_element( + int tuple: @tuple_type ref, + int index: int ref, + unique int field: @field ref); + +attributes( + unique int id: @attribute, + int kind: int ref, + int type_id: @type_or_ref ref, + int target: @attributable ref); + +case @attribute.kind of + 0 = @attribute_default +| 1 = @attribute_return +| 2 = @attribute_assembly +| 3 = @attribute_module +; + +attribute_location( + int id: @attribute ref, + int loc: @location ref); + +@type_mention_parent = @element | @type_mention; + +type_mention( + unique int id: @type_mention, + int type_id: @type_or_ref ref, + int parent: @type_mention_parent ref); + +type_mention_location( + unique int id: @type_mention ref, + int loc: @location ref); + +@has_type_annotation = @assignable | @type_parameter | @callable | @expr | @delegate_type | @generic | @function_pointer_type; + +/** + * A direct annotation on an entity, for example `string? x;`. + * + * Annotations: + * 2 = reftype is not annotated "!" + * 3 = reftype is annotated "?" + * 4 = readonly ref type / in parameter + * 5 = ref type parameter, return or local variable + * 6 = out parameter + * + * Note that the annotation depends on the element it annotates. + * @assignable: The annotation is on the type of the assignable, for example the variable type. + * @type_parameter: The annotation is on the reftype constraint + * @callable: The annotation is on the return type + * @array_type: The annotation is on the element type + */ +type_annotation(int id: @has_type_annotation ref, int annotation: int ref); + +nullability(unique int nullability: @nullability, int kind: int ref); + +case @nullability.kind of + 0 = @oblivious +| 1 = @not_annotated +| 2 = @annotated +; + +#keyset[parent, index] +nullability_parent(int nullability: @nullability ref, int index: int ref, int parent: @nullability ref) + +type_nullability(int id: @has_type_annotation ref, int nullability: @nullability ref); + +/** + * The nullable flow state of an expression, as determined by Roslyn. + * 0 = none (default, not populated) + * 1 = not null + * 2 = maybe null + */ +expr_flowstate(unique int id: @expr ref, int state: int ref); + +/** GENERICS **/ + +@generic = @type | @method | @local_function; + +type_parameters( + unique int id: @type_parameter ref, + int index: int ref, + int generic_id: @generic ref, + int variance: int ref /* none = 0, out = 1, in = 2 */); + +#keyset[constructed_id, index] +type_arguments( + int id: @type_or_ref ref, + int index: int ref, + int constructed_id: @generic_or_ref ref); + +@generic_or_ref = @generic | @typeref; + +constructed_generic( + unique int constructed: @generic ref, + int generic: @generic_or_ref ref); + +type_parameter_constraints( + unique int id: @type_parameter_constraints, + int param_id: @type_parameter ref); + +type_parameter_constraints_location( + int id: @type_parameter_constraints ref, + int loc: @location ref); + +general_type_parameter_constraints( + int id: @type_parameter_constraints ref, + int kind: int ref /* class = 1, struct = 2, new = 3 */); + +specific_type_parameter_constraints( + int id: @type_parameter_constraints ref, + int base_id: @type_or_ref ref); + +specific_type_parameter_nullability( + int id: @type_parameter_constraints ref, + int base_id: @type_or_ref ref, + int nullability: @nullability ref); + +/** FUNCTION POINTERS */ + +function_pointer_calling_conventions( + int id: @function_pointer_type ref, + int kind: int ref); + +#keyset[id, index] +has_unmanaged_calling_conventions( + int id: @function_pointer_type ref, + int index: int ref, + int conv_id: @type_or_ref ref); + +/** MODIFIERS */ + +@modifiable = @modifiable_direct | @event_accessor; + +@modifiable_direct = @member | @accessor | @local_function | @anonymous_function_expr; + +modifiers( + unique int id: @modifier, + string name: string ref); + +has_modifiers( + int id: @modifiable_direct ref, + int mod_id: @modifier ref); + +compiler_generated(unique int id: @modifiable ref); + +/** MEMBERS **/ + +@member = @method | @constructor | @destructor | @field | @property | @event | @operator | @indexer | @type; + +@named_exprorstmt = @goto_stmt | @labeled_stmt | @expr; + +@virtualizable = @method | @property | @indexer | @event; + +exprorstmt_name( + unique int parent_id: @named_exprorstmt ref, + string name: string ref); + +nested_types( + unique int id: @type ref, + int declaring_type_id: @type ref, + int unbound_id: @type ref); + +properties( + unique int id: @property, + string name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @property ref); + +property_location( + int id: @property ref, + int loc: @location ref); + +indexers( + unique int id: @indexer, + string name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @indexer ref); + +indexer_location( + int id: @indexer ref, + int loc: @location ref); + +accessors( + unique int id: @accessor, + int kind: int ref, + string name: string ref, + int declaring_member_id: @member ref, + int unbound_id: @accessor ref); + +case @accessor.kind of + 1 = @getter +| 2 = @setter + ; + +init_only_accessors( + unique int id: @accessor ref); + +accessor_location( + int id: @accessor ref, + int loc: @location ref); + +events( + unique int id: @event, + string name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @event ref); + +event_location( + int id: @event ref, + int loc: @location ref); + +event_accessors( + unique int id: @event_accessor, + int kind: int ref, + string name: string ref, + int declaring_event_id: @event ref, + int unbound_id: @event_accessor ref); + +case @event_accessor.kind of + 1 = @add_event_accessor +| 2 = @remove_event_accessor + ; + +event_accessor_location( + int id: @event_accessor ref, + int loc: @location ref); + +operators( + unique int id: @operator, + string name: string ref, + string symbol: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @operator ref); + +operator_location( + int id: @operator ref, + int loc: @location ref); + +constant_value( + int id: @variable ref, + string value: string ref); + +/** CALLABLES **/ + +@callable = @method | @constructor | @destructor | @operator | @callable_accessor | @anonymous_function_expr | @local_function; + +@callable_accessor = @accessor | @event_accessor; + +methods( + unique int id: @method, + string name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @method ref); + +method_location( + int id: @method ref, + int loc: @location ref); + +constructors( + unique int id: @constructor, + string name: string ref, + int declaring_type_id: @type ref, + int unbound_id: @constructor ref); + +constructor_location( + int id: @constructor ref, + int loc: @location ref); + +destructors( + unique int id: @destructor, + string name: string ref, + int declaring_type_id: @type ref, + int unbound_id: @destructor ref); + +destructor_location( + int id: @destructor ref, + int loc: @location ref); + +overrides( + int id: @callable ref, + int base_id: @callable ref); + +explicitly_implements( + int id: @member ref, + int interface_id: @interface_or_ref ref); + +local_functions( + unique int id: @local_function, + string name: string ref, + int return_type: @type ref, + int unbound_id: @local_function ref); + +local_function_stmts( + unique int fn: @local_function_stmt ref, + int stmt: @local_function ref); + +/** VARIABLES **/ + +@variable = @local_scope_variable | @field; + +@local_scope_variable = @local_variable | @parameter; + +fields( + unique int id: @field, + int kind: int ref, + string name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @field ref); + +case @field.kind of + 1 = @addressable_field +| 2 = @constant + ; + +field_location( + int id: @field ref, + int loc: @location ref); + +localvars( + unique int id: @local_variable, + int kind: int ref, + string name: string ref, + int implicitly_typed: int ref /* 0 = no, 1 = yes */, + int type_id: @type_or_ref ref, + int parent_id: @local_var_decl_expr ref); + +case @local_variable.kind of + 1 = @addressable_local_variable +| 2 = @local_constant +| 3 = @local_variable_ref + ; + +localvar_location( + unique int id: @local_variable ref, + int loc: @location ref); + +@parameterizable = @callable | @delegate_type | @indexer | @function_pointer_type; + +#keyset[name, parent_id] +#keyset[index, parent_id] +params( + unique int id: @parameter, + string name: string ref, + int type_id: @type_or_ref ref, + int index: int ref, + int mode: int ref, /* value = 0, ref = 1, out = 2, array = 3, this = 4 */ + int parent_id: @parameterizable ref, + int unbound_id: @parameter ref); + +param_location( + int id: @parameter ref, + int loc: @location ref); + +/** STATEMENTS **/ + +@exprorstmt_parent = @control_flow_element | @top_level_exprorstmt_parent; + +statements( + unique int id: @stmt, + int kind: int ref); + +#keyset[index, parent] +stmt_parent( + unique int stmt: @stmt ref, + int index: int ref, + int parent: @control_flow_element ref); + +@top_level_stmt_parent = @callable; + +// [index, parent] is not a keyset because the same parent may be compiled multiple times +stmt_parent_top_level( + unique int stmt: @stmt ref, + int index: int ref, + int parent: @top_level_stmt_parent ref); + +case @stmt.kind of + 1 = @block_stmt +| 2 = @expr_stmt +| 3 = @if_stmt +| 4 = @switch_stmt +| 5 = @while_stmt +| 6 = @do_stmt +| 7 = @for_stmt +| 8 = @foreach_stmt +| 9 = @break_stmt +| 10 = @continue_stmt +| 11 = @goto_stmt +| 12 = @goto_case_stmt +| 13 = @goto_default_stmt +| 14 = @throw_stmt +| 15 = @return_stmt +| 16 = @yield_stmt +| 17 = @try_stmt +| 18 = @checked_stmt +| 19 = @unchecked_stmt +| 20 = @lock_stmt +| 21 = @using_block_stmt +| 22 = @var_decl_stmt +| 23 = @const_decl_stmt +| 24 = @empty_stmt +| 25 = @unsafe_stmt +| 26 = @fixed_stmt +| 27 = @label_stmt +| 28 = @catch +| 29 = @case_stmt +| 30 = @local_function_stmt +| 31 = @using_decl_stmt + ; + +@using_stmt = @using_block_stmt | @using_decl_stmt; + +@labeled_stmt = @label_stmt | @case; + +@decl_stmt = @var_decl_stmt | @const_decl_stmt | @using_decl_stmt; + +@cond_stmt = @if_stmt | @switch_stmt; + +@loop_stmt = @while_stmt | @do_stmt | @for_stmt | @foreach_stmt; + +@jump_stmt = @break_stmt | @goto_any_stmt | @continue_stmt | @throw_stmt | @return_stmt + | @yield_stmt; + +@goto_any_stmt = @goto_default_stmt | @goto_case_stmt | @goto_stmt; + + +stmt_location( + unique int id: @stmt ref, + int loc: @location ref); + +catch_type( + unique int catch_id: @catch ref, + int type_id: @type_or_ref ref, + int kind: int ref /* explicit = 1, implicit = 2 */); + +foreach_stmt_info( + unique int id: @foreach_stmt ref, + int kind: int ref /* non-async = 1, async = 2 */); + +@foreach_symbol = @method | @property | @type_or_ref; + +#keyset[id, kind] +foreach_stmt_desugar( + int id: @foreach_stmt ref, + int symbol: @foreach_symbol ref, + int kind: int ref /* GetEnumeratorMethod = 1, CurrentProperty = 2, MoveNextMethod = 3, DisposeMethod = 4, ElementType = 5 */); + +/** EXPRESSIONS **/ + +expressions( + unique int id: @expr, + int kind: int ref, + int type_id: @type_or_ref ref); + +#keyset[index, parent] +expr_parent( + unique int expr: @expr ref, + int index: int ref, + int parent: @control_flow_element ref); + +@top_level_expr_parent = @attribute | @field | @property | @indexer | @parameter | @directive_if | @directive_elif; + +@top_level_exprorstmt_parent = @top_level_expr_parent | @top_level_stmt_parent; + +// [index, parent] is not a keyset because the same parent may be compiled multiple times +expr_parent_top_level( + unique int expr: @expr ref, + int index: int ref, + int parent: @top_level_exprorstmt_parent ref); + +case @expr.kind of +/* literal */ + 1 = @bool_literal_expr +| 2 = @char_literal_expr +| 3 = @decimal_literal_expr +| 4 = @int_literal_expr +| 5 = @long_literal_expr +| 6 = @uint_literal_expr +| 7 = @ulong_literal_expr +| 8 = @float_literal_expr +| 9 = @double_literal_expr +| 10 = @string_literal_expr +| 11 = @null_literal_expr +/* primary & unary */ +| 12 = @this_access_expr +| 13 = @base_access_expr +| 14 = @local_variable_access_expr +| 15 = @parameter_access_expr +| 16 = @field_access_expr +| 17 = @property_access_expr +| 18 = @method_access_expr +| 19 = @event_access_expr +| 20 = @indexer_access_expr +| 21 = @array_access_expr +| 22 = @type_access_expr +| 23 = @typeof_expr +| 24 = @method_invocation_expr +| 25 = @delegate_invocation_expr +| 26 = @operator_invocation_expr +| 27 = @cast_expr +| 28 = @object_creation_expr +| 29 = @explicit_delegate_creation_expr +| 30 = @implicit_delegate_creation_expr +| 31 = @array_creation_expr +| 32 = @default_expr +| 33 = @plus_expr +| 34 = @minus_expr +| 35 = @bit_not_expr +| 36 = @log_not_expr +| 37 = @post_incr_expr +| 38 = @post_decr_expr +| 39 = @pre_incr_expr +| 40 = @pre_decr_expr +/* multiplicative */ +| 41 = @mul_expr +| 42 = @div_expr +| 43 = @rem_expr +/* additive */ +| 44 = @add_expr +| 45 = @sub_expr +/* shift */ +| 46 = @lshift_expr +| 47 = @rshift_expr +/* relational */ +| 48 = @lt_expr +| 49 = @gt_expr +| 50 = @le_expr +| 51 = @ge_expr +/* equality */ +| 52 = @eq_expr +| 53 = @ne_expr +/* logical */ +| 54 = @bit_and_expr +| 55 = @bit_xor_expr +| 56 = @bit_or_expr +| 57 = @log_and_expr +| 58 = @log_or_expr +/* type testing */ +| 59 = @is_expr +| 60 = @as_expr +/* null coalescing */ +| 61 = @null_coalescing_expr +/* conditional */ +| 62 = @conditional_expr +/* assignment */ +| 63 = @simple_assign_expr +| 64 = @assign_add_expr +| 65 = @assign_sub_expr +| 66 = @assign_mul_expr +| 67 = @assign_div_expr +| 68 = @assign_rem_expr +| 69 = @assign_and_expr +| 70 = @assign_xor_expr +| 71 = @assign_or_expr +| 72 = @assign_lshift_expr +| 73 = @assign_rshift_expr +/* more */ +| 74 = @object_init_expr +| 75 = @collection_init_expr +| 76 = @array_init_expr +| 77 = @checked_expr +| 78 = @unchecked_expr +| 79 = @constructor_init_expr +| 80 = @add_event_expr +| 81 = @remove_event_expr +| 82 = @par_expr +| 83 = @local_var_decl_expr +| 84 = @lambda_expr +| 85 = @anonymous_method_expr +| 86 = @namespace_expr +/* dynamic */ +| 92 = @dynamic_element_access_expr +| 93 = @dynamic_member_access_expr +/* unsafe */ +| 100 = @pointer_indirection_expr +| 101 = @address_of_expr +| 102 = @sizeof_expr +/* async */ +| 103 = @await_expr +/* C# 6.0 */ +| 104 = @nameof_expr +| 105 = @interpolated_string_expr +| 106 = @unknown_expr +/* C# 7.0 */ +| 107 = @throw_expr +| 108 = @tuple_expr +| 109 = @local_function_invocation_expr +| 110 = @ref_expr +| 111 = @discard_expr +/* C# 8.0 */ +| 112 = @range_expr +| 113 = @index_expr +| 114 = @switch_expr +| 115 = @recursive_pattern_expr +| 116 = @property_pattern_expr +| 117 = @positional_pattern_expr +| 118 = @switch_case_expr +| 119 = @assign_coalesce_expr +| 120 = @suppress_nullable_warning_expr +| 121 = @namespace_access_expr +/* C# 9.0 */ +| 122 = @lt_pattern_expr +| 123 = @gt_pattern_expr +| 124 = @le_pattern_expr +| 125 = @ge_pattern_expr +| 126 = @not_pattern_expr +| 127 = @and_pattern_expr +| 128 = @or_pattern_expr +| 129 = @function_pointer_invocation_expr +| 130 = @with_expr +/* C# 11.0 */ +| 131 = @list_pattern_expr +| 132 = @slice_pattern_expr +/* Preprocessor */ +| 999 = @define_symbol_expr +; + +@switch = @switch_stmt | @switch_expr; +@case = @case_stmt | @switch_case_expr; +@pattern_match = @case | @is_expr; +@unary_pattern_expr = @not_pattern_expr; +@relational_pattern_expr = @gt_pattern_expr | @lt_pattern_expr | @ge_pattern_expr | @le_pattern_expr; +@binary_pattern_expr = @and_pattern_expr | @or_pattern_expr; + +@integer_literal_expr = @int_literal_expr | @long_literal_expr | @uint_literal_expr | @ulong_literal_expr; +@real_literal_expr = @float_literal_expr | @double_literal_expr | @decimal_literal_expr; +@literal_expr = @bool_literal_expr | @char_literal_expr | @integer_literal_expr | @real_literal_expr + | @string_literal_expr | @null_literal_expr; + +@assign_expr = @simple_assign_expr | @assign_op_expr | @local_var_decl_expr; +@assign_op_expr = @assign_arith_expr | @assign_bitwise_expr | @assign_event_expr | @assign_coalesce_expr; +@assign_event_expr = @add_event_expr | @remove_event_expr; + +@assign_arith_expr = @assign_add_expr | @assign_sub_expr | @assign_mul_expr | @assign_div_expr + | @assign_rem_expr +@assign_bitwise_expr = @assign_and_expr | @assign_or_expr | @assign_xor_expr + | @assign_lshift_expr | @assign_rshift_expr; + +@member_access_expr = @field_access_expr | @property_access_expr | @indexer_access_expr | @event_access_expr + | @method_access_expr | @type_access_expr | @dynamic_member_access_expr; +@access_expr = @member_access_expr | @this_access_expr | @base_access_expr | @assignable_access_expr | @namespace_access_expr; +@element_access_expr = @indexer_access_expr | @array_access_expr | @dynamic_element_access_expr; + +@local_variable_access = @local_variable_access_expr | @local_var_decl_expr; +@local_scope_variable_access_expr = @parameter_access_expr | @local_variable_access; +@variable_access_expr = @local_scope_variable_access_expr | @field_access_expr; + +@assignable_access_expr = @variable_access_expr | @property_access_expr | @element_access_expr + | @event_access_expr | @dynamic_member_access_expr; + +@objectorcollection_init_expr = @object_init_expr | @collection_init_expr; + +@delegate_creation_expr = @explicit_delegate_creation_expr | @implicit_delegate_creation_expr; + +@bin_arith_op_expr = @mul_expr | @div_expr | @rem_expr | @add_expr | @sub_expr; +@incr_op_expr = @pre_incr_expr | @post_incr_expr; +@decr_op_expr = @pre_decr_expr | @post_decr_expr; +@mut_op_expr = @incr_op_expr | @decr_op_expr; +@un_arith_op_expr = @plus_expr | @minus_expr | @mut_op_expr; +@arith_op_expr = @bin_arith_op_expr | @un_arith_op_expr; + +@ternary_log_op_expr = @conditional_expr; +@bin_log_op_expr = @log_and_expr | @log_or_expr | @null_coalescing_expr; +@un_log_op_expr = @log_not_expr; +@log_expr = @un_log_op_expr | @bin_log_op_expr | @ternary_log_op_expr; + +@bin_bit_op_expr = @bit_and_expr | @bit_or_expr | @bit_xor_expr | @lshift_expr + | @rshift_expr; +@un_bit_op_expr = @bit_not_expr; +@bit_expr = @un_bit_op_expr | @bin_bit_op_expr; + +@equality_op_expr = @eq_expr | @ne_expr; +@rel_op_expr = @gt_expr | @lt_expr| @ge_expr | @le_expr; +@comp_expr = @equality_op_expr | @rel_op_expr; + +@op_expr = @assign_expr | @un_op | @bin_op | @ternary_op; + +@ternary_op = @ternary_log_op_expr; +@bin_op = @bin_arith_op_expr | @bin_log_op_expr | @bin_bit_op_expr | @comp_expr; +@un_op = @un_arith_op_expr | @un_log_op_expr | @un_bit_op_expr | @sizeof_expr + | @pointer_indirection_expr | @address_of_expr; + +@anonymous_function_expr = @lambda_expr | @anonymous_method_expr; + +@call = @method_invocation_expr | @constructor_init_expr | @operator_invocation_expr + | @delegate_invocation_expr | @object_creation_expr | @call_access_expr + | @local_function_invocation_expr | @function_pointer_invocation_expr; + +@call_access_expr = @property_access_expr | @event_access_expr | @indexer_access_expr; + +@late_bindable_expr = @dynamic_element_access_expr | @dynamic_member_access_expr + | @object_creation_expr | @method_invocation_expr | @operator_invocation_expr; + +@throw_element = @throw_expr | @throw_stmt; + +@implicitly_typeable_object_creation_expr = @object_creation_expr | @explicit_delegate_creation_expr; + +implicitly_typed_array_creation( + unique int id: @array_creation_expr ref); + +explicitly_sized_array_creation( + unique int id: @array_creation_expr ref); + +stackalloc_array_creation( + unique int id: @array_creation_expr ref); + +implicitly_typed_object_creation( + unique int id: @implicitly_typeable_object_creation_expr ref); + +mutator_invocation_mode( + unique int id: @operator_invocation_expr ref, + int mode: int ref /* prefix = 1, postfix = 2*/); + +expr_compiler_generated( + unique int id: @expr ref); + +expr_value( + unique int id: @expr ref, + string value: string ref); + +expr_call( + unique int caller_id: @expr ref, + int target_id: @callable ref); + +expr_access( + unique int accesser_id: @access_expr ref, + int target_id: @accessible ref); + +@accessible = @method | @assignable | @local_function | @namespace; + +expr_location( + unique int id: @expr ref, + int loc: @location ref); + +dynamic_member_name( + unique int id: @late_bindable_expr ref, + string name: string ref); + +@qualifiable_expr = @member_access_expr + | @method_invocation_expr + | @element_access_expr; + +conditional_access( + unique int id: @qualifiable_expr ref); + +expr_argument( + unique int id: @expr ref, + int mode: int ref); + /* mode is the same as params: value = 0, ref = 1, out = 2 */ + +expr_argument_name( + unique int id: @expr ref, + string name: string ref); + +lambda_expr_return_type( + unique int id: @lambda_expr ref, + int type_id: @type_or_ref ref); + +/** CONTROL/DATA FLOW **/ + +@control_flow_element = @stmt | @expr; + +/* XML Files */ + +xmlEncoding ( + unique int id: @file ref, + string encoding: string ref); + +xmlDTDs( + unique int id: @xmldtd, + string root: string ref, + string publicId: string ref, + string systemId: string ref, + int fileid: @file ref); + +xmlElements( + unique int id: @xmlelement, + string name: string ref, + int parentid: @xmlparent ref, + int idx: int ref, + int fileid: @file ref); + +xmlAttrs( + unique int id: @xmlattribute, + int elementid: @xmlelement ref, + string name: string ref, + string value: string ref, + int idx: int ref, + int fileid: @file ref); + +xmlNs( + int id: @xmlnamespace, + string prefixName: string ref, + string URI: string ref, + int fileid: @file ref); + +xmlHasNs( + int elementId: @xmlnamespaceable ref, + int nsId: @xmlnamespace ref, + int fileid: @file ref); + +xmlComments( + unique int id: @xmlcomment, + string text: string ref, + int parentid: @xmlparent ref, + int fileid: @file ref); + +xmlChars( + unique int id: @xmlcharacters, + string text: string ref, + int parentid: @xmlparent ref, + int idx: int ref, + int isCDATA: int ref, + int fileid: @file ref); + +@xmlparent = @file | @xmlelement; +@xmlnamespaceable = @xmlelement | @xmlattribute; + +xmllocations( + int xmlElement: @xmllocatable ref, + int location: @location_default ref); + +@xmllocatable = @xmlcharacters | @xmlelement | @xmlcomment | @xmlattribute | @xmldtd | @file | @xmlnamespace; + +/* Comments */ + +commentline( + unique int id: @commentline, + int kind: int ref, + string text: string ref, + string rawtext: string ref); + +case @commentline.kind of + 0 = @singlelinecomment +| 1 = @xmldoccomment +| 2 = @multilinecomment; + +commentline_location( + unique int id: @commentline ref, + int loc: @location ref); + +commentblock( + unique int id : @commentblock); + +commentblock_location( + unique int id: @commentblock ref, + int loc: @location ref); + +commentblock_binding( + int id: @commentblock ref, + int entity: @element ref, + int bindtype: int ref); /* 0: Parent, 1: Best, 2: Before, 3: After */ + +commentblock_child( + int id: @commentblock ref, + int commentline: @commentline ref, + int index: int ref); + +/* ASP.NET */ + +case @asp_element.kind of + 0=@asp_close_tag +| 1=@asp_code +| 2=@asp_comment +| 3=@asp_data_binding +| 4=@asp_directive +| 5=@asp_open_tag +| 6=@asp_quoted_string +| 7=@asp_text +| 8=@asp_xml_directive; + +@asp_attribute = @asp_code | @asp_data_binding | @asp_quoted_string; + +asp_elements( + unique int id: @asp_element, + int kind: int ref, + int loc: @location ref); + +asp_comment_server(unique int comment: @asp_comment ref); +asp_code_inline(unique int code: @asp_code ref); +asp_directive_attribute( + int directive: @asp_directive ref, + int index: int ref, + string name: string ref, + int value: @asp_quoted_string ref); +asp_directive_name( + unique int directive: @asp_directive ref, + string name: string ref); +asp_element_body( + unique int element: @asp_element ref, + string body: string ref); +asp_tag_attribute( + int tag: @asp_open_tag ref, + int index: int ref, + string name: string ref, + int attribute: @asp_attribute ref); +asp_tag_name( + unique int tag: @asp_open_tag ref, + string name: string ref); +asp_tag_isempty(int tag: @asp_open_tag ref); + +/* Common Intermediate Language - CIL */ + +case @cil_instruction.opcode of + 0 = @cil_nop +| 1 = @cil_break +| 2 = @cil_ldarg_0 +| 3 = @cil_ldarg_1 +| 4 = @cil_ldarg_2 +| 5 = @cil_ldarg_3 +| 6 = @cil_ldloc_0 +| 7 = @cil_ldloc_1 +| 8 = @cil_ldloc_2 +| 9 = @cil_ldloc_3 +| 10 = @cil_stloc_0 +| 11 = @cil_stloc_1 +| 12 = @cil_stloc_2 +| 13 = @cil_stloc_3 +| 14 = @cil_ldarg_s +| 15 = @cil_ldarga_s +| 16 = @cil_starg_s +| 17 = @cil_ldloc_s +| 18 = @cil_ldloca_s +| 19 = @cil_stloc_s +| 20 = @cil_ldnull +| 21 = @cil_ldc_i4_m1 +| 22 = @cil_ldc_i4_0 +| 23 = @cil_ldc_i4_1 +| 24 = @cil_ldc_i4_2 +| 25 = @cil_ldc_i4_3 +| 26 = @cil_ldc_i4_4 +| 27 = @cil_ldc_i4_5 +| 28 = @cil_ldc_i4_6 +| 29 = @cil_ldc_i4_7 +| 30 = @cil_ldc_i4_8 +| 31 = @cil_ldc_i4_s +| 32 = @cil_ldc_i4 +| 33 = @cil_ldc_i8 +| 34 = @cil_ldc_r4 +| 35 = @cil_ldc_r8 +| 37 = @cil_dup +| 38 = @cil_pop +| 39 = @cil_jmp +| 40 = @cil_call +| 41 = @cil_calli +| 42 = @cil_ret +| 43 = @cil_br_s +| 44 = @cil_brfalse_s +| 45 = @cil_brtrue_s +| 46 = @cil_beq_s +| 47 = @cil_bge_s +| 48 = @cil_bgt_s +| 49 = @cil_ble_s +| 50 = @cil_blt_s +| 51 = @cil_bne_un_s +| 52 = @cil_bge_un_s +| 53 = @cil_bgt_un_s +| 54 = @cil_ble_un_s +| 55 = @cil_blt_un_s +| 56 = @cil_br +| 57 = @cil_brfalse +| 58 = @cil_brtrue +| 59 = @cil_beq +| 60 = @cil_bge +| 61 = @cil_bgt +| 62 = @cil_ble +| 63 = @cil_blt +| 64 = @cil_bne_un +| 65 = @cil_bge_un +| 66 = @cil_bgt_un +| 67 = @cil_ble_un +| 68 = @cil_blt_un +| 69 = @cil_switch +| 70 = @cil_ldind_i1 +| 71 = @cil_ldind_u1 +| 72 = @cil_ldind_i2 +| 73 = @cil_ldind_u2 +| 74 = @cil_ldind_i4 +| 75 = @cil_ldind_u4 +| 76 = @cil_ldind_i8 +| 77 = @cil_ldind_i +| 78 = @cil_ldind_r4 +| 79 = @cil_ldind_r8 +| 80 = @cil_ldind_ref +| 81 = @cil_stind_ref +| 82 = @cil_stind_i1 +| 83 = @cil_stind_i2 +| 84 = @cil_stind_i4 +| 85 = @cil_stind_i8 +| 86 = @cil_stind_r4 +| 87 = @cil_stind_r8 +| 88 = @cil_add +| 89 = @cil_sub +| 90 = @cil_mul +| 91 = @cil_div +| 92 = @cil_div_un +| 93 = @cil_rem +| 94 = @cil_rem_un +| 95 = @cil_and +| 96 = @cil_or +| 97 = @cil_xor +| 98 = @cil_shl +| 99 = @cil_shr +| 100 = @cil_shr_un +| 101 = @cil_neg +| 102 = @cil_not +| 103 = @cil_conv_i1 +| 104 = @cil_conv_i2 +| 105 = @cil_conv_i4 +| 106 = @cil_conv_i8 +| 107 = @cil_conv_r4 +| 108 = @cil_conv_r8 +| 109 = @cil_conv_u4 +| 110 = @cil_conv_u8 +| 111 = @cil_callvirt +| 112 = @cil_cpobj +| 113 = @cil_ldobj +| 114 = @cil_ldstr +| 115 = @cil_newobj +| 116 = @cil_castclass +| 117 = @cil_isinst +| 118 = @cil_conv_r_un +| 121 = @cil_unbox +| 122 = @cil_throw +| 123 = @cil_ldfld +| 124 = @cil_ldflda +| 125 = @cil_stfld +| 126 = @cil_ldsfld +| 127 = @cil_ldsflda +| 128 = @cil_stsfld +| 129 = @cil_stobj +| 130 = @cil_conv_ovf_i1_un +| 131 = @cil_conv_ovf_i2_un +| 132 = @cil_conv_ovf_i4_un +| 133 = @cil_conv_ovf_i8_un +| 134 = @cil_conv_ovf_u1_un +| 135 = @cil_conv_ovf_u2_un +| 136 = @cil_conv_ovf_u4_un +| 137 = @cil_conv_ovf_u8_un +| 138 = @cil_conv_ovf_i_un +| 139 = @cil_conv_ovf_u_un +| 140 = @cil_box +| 141 = @cil_newarr +| 142 = @cil_ldlen +| 143 = @cil_ldelema +| 144 = @cil_ldelem_i1 +| 145 = @cil_ldelem_u1 +| 146 = @cil_ldelem_i2 +| 147 = @cil_ldelem_u2 +| 148 = @cil_ldelem_i4 +| 149 = @cil_ldelem_u4 +| 150 = @cil_ldelem_i8 +| 151 = @cil_ldelem_i +| 152 = @cil_ldelem_r4 +| 153 = @cil_ldelem_r8 +| 154 = @cil_ldelem_ref +| 155 = @cil_stelem_i +| 156 = @cil_stelem_i1 +| 157 = @cil_stelem_i2 +| 158 = @cil_stelem_i4 +| 159 = @cil_stelem_i8 +| 160 = @cil_stelem_r4 +| 161 = @cil_stelem_r8 +| 162 = @cil_stelem_ref +| 163 = @cil_ldelem +| 164 = @cil_stelem +| 165 = @cil_unbox_any +| 179 = @cil_conv_ovf_i1 +| 180 = @cil_conv_ovf_u1 +| 181 = @cil_conv_ovf_i2 +| 182 = @cil_conv_ovf_u2 +| 183 = @cil_conv_ovf_i4 +| 184 = @cil_conv_ovf_u4 +| 185 = @cil_conv_ovf_i8 +| 186 = @cil_conv_ovf_u8 +| 194 = @cil_refanyval +| 195 = @cil_ckinfinite +| 198 = @cil_mkrefany +| 208 = @cil_ldtoken +| 209 = @cil_conv_u2 +| 210 = @cil_conv_u1 +| 211 = @cil_conv_i +| 212 = @cil_conv_ovf_i +| 213 = @cil_conv_ovf_u +| 214 = @cil_add_ovf +| 215 = @cil_add_ovf_un +| 216 = @cil_mul_ovf +| 217 = @cil_mul_ovf_un +| 218 = @cil_sub_ovf +| 219 = @cil_sub_ovf_un +| 220 = @cil_endfinally +| 221 = @cil_leave +| 222 = @cil_leave_s +| 223 = @cil_stind_i +| 224 = @cil_conv_u +| 65024 = @cil_arglist +| 65025 = @cil_ceq +| 65026 = @cil_cgt +| 65027 = @cil_cgt_un +| 65028 = @cil_clt +| 65029 = @cil_clt_un +| 65030 = @cil_ldftn +| 65031 = @cil_ldvirtftn +| 65033 = @cil_ldarg +| 65034 = @cil_ldarga +| 65035 = @cil_starg +| 65036 = @cil_ldloc +| 65037 = @cil_ldloca +| 65038 = @cil_stloc +| 65039 = @cil_localloc +| 65041 = @cil_endfilter +| 65042 = @cil_unaligned +| 65043 = @cil_volatile +| 65044 = @cil_tail +| 65045 = @cil_initobj +| 65046 = @cil_constrained +| 65047 = @cil_cpblk +| 65048 = @cil_initblk +| 65050 = @cil_rethrow +| 65052 = @cil_sizeof +| 65053 = @cil_refanytype +| 65054 = @cil_readonly +; + +// CIL ignored instructions + +@cil_ignore = @cil_nop | @cil_break | @cil_volatile | @cil_unaligned; + +// CIL local/parameter/field access + +@cil_ldarg_any = @cil_ldarg_0 | @cil_ldarg_1 | @cil_ldarg_2 | @cil_ldarg_3 | @cil_ldarg_s | @cil_ldarga_s | @cil_ldarg | @cil_ldarga; +@cil_starg_any = @cil_starg | @cil_starg_s; + +@cil_ldloc_any = @cil_ldloc_0 | @cil_ldloc_1 | @cil_ldloc_2 | @cil_ldloc_3 | @cil_ldloc_s | @cil_ldloca_s | @cil_ldloc | @cil_ldloca; +@cil_stloc_any = @cil_stloc_0 | @cil_stloc_1 | @cil_stloc_2 | @cil_stloc_3 | @cil_stloc_s | @cil_stloc; + +@cil_ldfld_any = @cil_ldfld | @cil_ldsfld | @cil_ldsflda | @cil_ldflda; +@cil_stfld_any = @cil_stfld | @cil_stsfld; + +@cil_local_access = @cil_stloc_any | @cil_ldloc_any; +@cil_arg_access = @cil_starg_any | @cil_ldarg_any; +@cil_read_access = @cil_ldloc_any | @cil_ldarg_any | @cil_ldfld_any; +@cil_write_access = @cil_stloc_any | @cil_starg_any | @cil_stfld_any; + +@cil_stack_access = @cil_local_access | @cil_arg_access; +@cil_field_access = @cil_ldfld_any | @cil_stfld_any; + +@cil_access = @cil_read_access | @cil_write_access; + +// CIL constant/literal instructions + +@cil_ldc_i = @cil_ldc_i4_any | @cil_ldc_i8; + +@cil_ldc_i4_any = @cil_ldc_i4_m1 | @cil_ldc_i4_0 | @cil_ldc_i4_1 | @cil_ldc_i4_2 | @cil_ldc_i4_3 | + @cil_ldc_i4_4 | @cil_ldc_i4_5 | @cil_ldc_i4_6 | @cil_ldc_i4_7 | @cil_ldc_i4_8 | @cil_ldc_i4_s | @cil_ldc_i4; + +@cil_ldc_r = @cil_ldc_r4 | @cil_ldc_r8; + +@cil_literal = @cil_ldnull | @cil_ldc_i | @cil_ldc_r | @cil_ldstr; + +// Control flow + +@cil_conditional_jump = @cil_binary_jump | @cil_unary_jump; +@cil_binary_jump = @cil_beq_s | @cil_bge_s | @cil_bgt_s | @cil_ble_s | @cil_blt_s | + @cil_bne_un_s | @cil_bge_un_s | @cil_bgt_un_s | @cil_ble_un_s | @cil_blt_un_s | + @cil_beq | @cil_bge | @cil_bgt | @cil_ble | @cil_blt | + @cil_bne_un | @cil_bge_un | @cil_bgt_un | @cil_ble_un | @cil_blt_un; +@cil_unary_jump = @cil_brfalse_s | @cil_brtrue_s | @cil_brfalse | @cil_brtrue | @cil_switch; +@cil_unconditional_jump = @cil_br | @cil_br_s | @cil_leave_any; +@cil_leave_any = @cil_leave | @cil_leave_s; +@cil_jump = @cil_unconditional_jump | @cil_conditional_jump; + +// CIL call instructions + +@cil_call_any = @cil_jmp | @cil_call | @cil_calli | @cil_tail | @cil_callvirt | @cil_newobj; + +// CIL expression instructions + +@cil_expr = @cil_literal | @cil_binary_expr | @cil_unary_expr | @cil_call_any | @cil_read_access | + @cil_newarr | @cil_ldtoken | @cil_sizeof | + @cil_ldftn | @cil_ldvirtftn | @cil_localloc | @cil_mkrefany | @cil_refanytype | @cil_arglist | @cil_dup; + +@cil_unary_expr = + @cil_conversion_operation | @cil_unary_arithmetic_operation | @cil_unary_bitwise_operation| + @cil_ldlen | @cil_isinst | @cil_box | @cil_ldobj | @cil_castclass | @cil_unbox_any | + @cil_ldind | @cil_unbox; + +@cil_conversion_operation = + @cil_conv_i1 | @cil_conv_i2 | @cil_conv_i4 | @cil_conv_i8 | + @cil_conv_u1 | @cil_conv_u2 | @cil_conv_u4 | @cil_conv_u8 | + @cil_conv_ovf_i | @cil_conv_ovf_i_un | @cil_conv_ovf_i1 | @cil_conv_ovf_i1_un | + @cil_conv_ovf_i2 | @cil_conv_ovf_i2_un | @cil_conv_ovf_i4 | @cil_conv_ovf_i4_un | + @cil_conv_ovf_i8 | @cil_conv_ovf_i8_un | @cil_conv_ovf_u | @cil_conv_ovf_u_un | + @cil_conv_ovf_u1 | @cil_conv_ovf_u1_un | @cil_conv_ovf_u2 | @cil_conv_ovf_u2_un | + @cil_conv_ovf_u4 | @cil_conv_ovf_u4_un | @cil_conv_ovf_u8 | @cil_conv_ovf_u8_un | + @cil_conv_r4 | @cil_conv_r8 | @cil_conv_ovf_u2 | @cil_conv_ovf_u2_un | + @cil_conv_i | @cil_conv_u | @cil_conv_r_un; + +@cil_ldind = @cil_ldind_i | @cil_ldind_i1 | @cil_ldind_i2 | @cil_ldind_i4 | @cil_ldind_i8 | + @cil_ldind_r4 | @cil_ldind_r8 | @cil_ldind_ref | @cil_ldind_u1 | @cil_ldind_u2 | @cil_ldind_u4; + +@cil_stind = @cil_stind_i | @cil_stind_i1 | @cil_stind_i2 | @cil_stind_i4 | @cil_stind_i8 | + @cil_stind_r4 | @cil_stind_r8 | @cil_stind_ref; + +@cil_bitwise_operation = @cil_binary_bitwise_operation | @cil_unary_bitwise_operation; + +@cil_binary_bitwise_operation = @cil_and | @cil_or | @cil_xor | @cil_shr | @cil_shr | @cil_shr_un | @cil_shl; + +@cil_binary_arithmetic_operation = @cil_add | @cil_sub | @cil_mul | @cil_div | @cil_div_un | + @cil_rem | @cil_rem_un | @cil_add_ovf | @cil_add_ovf_un | @cil_mul_ovf | @cil_mul_ovf_un | + @cil_sub_ovf | @cil_sub_ovf_un; + +@cil_unary_bitwise_operation = @cil_not; + +@cil_binary_expr = @cil_binary_arithmetic_operation | @cil_binary_bitwise_operation | @cil_read_array | @cil_comparison_operation; + +@cil_unary_arithmetic_operation = @cil_neg; + +@cil_comparison_operation = @cil_cgt_un | @cil_ceq | @cil_cgt | @cil_clt | @cil_clt_un; + +// Elements that retrieve an address of something +@cil_read_ref = @cil_ldloca_s | @cil_ldarga_s | @cil_ldflda | @cil_ldsflda | @cil_ldelema; + +// CIL array instructions + +@cil_read_array = + @cil_ldelem | @cil_ldelema | @cil_ldelem_i1 | @cil_ldelem_ref | @cil_ldelem_i | + @cil_ldelem_i1 | @cil_ldelem_i2 | @cil_ldelem_i4 | @cil_ldelem_i8 | @cil_ldelem_r4 | + @cil_ldelem_r8 | @cil_ldelem_u1 | @cil_ldelem_u2 | @cil_ldelem_u4; + +@cil_write_array = @cil_stelem | @cil_stelem_ref | + @cil_stelem_i | @cil_stelem_i1 | @cil_stelem_i2 | @cil_stelem_i4 | @cil_stelem_i8 | + @cil_stelem_r4 | @cil_stelem_r8; + +@cil_throw_any = @cil_throw | @cil_rethrow; + +#keyset[impl, index] +cil_instruction( + unique int id: @cil_instruction, + int opcode: int ref, + int index: int ref, + int impl: @cil_method_implementation ref); + +cil_jump( + unique int instruction: @cil_jump ref, + int target: @cil_instruction ref); + +cil_access( + unique int instruction: @cil_instruction ref, + int target: @cil_accessible ref); + +cil_value( + unique int instruction: @cil_literal ref, + string value: string ref); + +#keyset[instruction, index] +cil_switch( + int instruction: @cil_switch ref, + int index: int ref, + int target: @cil_instruction ref); + +cil_instruction_location( + unique int id: @cil_instruction ref, + int loc: @location ref); + +cil_type_location( + int id: @cil_type ref, + int loc: @location ref); + +cil_method_location( + int id: @cil_method ref, + int loc: @location ref); + +@cil_namespace = @namespace; + +@cil_type_container = @cil_type | @cil_namespace | @cil_method; + +case @cil_type.kind of + 0 = @cil_valueorreftype +| 1 = @cil_typeparameter +| 2 = @cil_array_type +| 3 = @cil_pointer_type +| 4 = @cil_function_pointer_type +; + +cil_type( + unique int id: @cil_type, + string name: string ref, + int kind: int ref, + int parent: @cil_type_container ref, + int sourceDecl: @cil_type ref); + +cil_pointer_type( + unique int id: @cil_pointer_type ref, + int pointee: @cil_type ref); + +cil_array_type( + unique int id: @cil_array_type ref, + int element_type: @cil_type ref, + int rank: int ref); + +cil_function_pointer_return_type( + unique int id: @cil_function_pointer_type ref, + int return_type: @cil_type ref); + +cil_method( + unique int id: @cil_method, + string name: string ref, + int parent: @cil_type ref, + int return_type: @cil_type ref); + +cil_method_source_declaration( + unique int method: @cil_method ref, + int source: @cil_method ref); + +cil_method_implementation( + unique int id: @cil_method_implementation, + int method: @cil_method ref, + int location: @assembly ref); + +cil_implements( + int id: @cil_method ref, + int decl: @cil_method ref); + +#keyset[parent, name] +cil_field( + unique int id: @cil_field, + int parent: @cil_type ref, + string name: string ref, + int field_type: @cil_type ref); + +@cil_element = @cil_instruction | @cil_declaration | @cil_handler | @cil_attribute | @cil_namespace; +@cil_named_element = @cil_declaration | @cil_namespace; +@cil_declaration = @cil_variable | @cil_method | @cil_type | @cil_member; +@cil_accessible = @cil_declaration; +@cil_variable = @cil_field | @cil_stack_variable; +@cil_stack_variable = @cil_local_variable | @cil_parameter; +@cil_member = @cil_method | @cil_type | @cil_field | @cil_property | @cil_event; +@cil_custom_modifier_receiver = @cil_method | @cil_property | @cil_parameter | @cil_field | @cil_function_pointer_type; +@cil_parameterizable = @cil_method | @cil_function_pointer_type; +@cil_has_type_annotation = @cil_stack_variable | @cil_property | @cil_method | @cil_function_pointer_type; + +#keyset[parameterizable, index] +cil_parameter( + unique int id: @cil_parameter, + int parameterizable: @cil_parameterizable ref, + int index: int ref, + int param_type: @cil_type ref); + +cil_parameter_in(unique int id: @cil_parameter ref); +cil_parameter_out(unique int id: @cil_parameter ref); + +cil_setter(unique int prop: @cil_property ref, + int method: @cil_method ref); + +#keyset[id, modifier] +cil_custom_modifiers( + int id: @cil_custom_modifier_receiver ref, + int modifier: @cil_type ref, + int kind: int ref); // modreq: 1, modopt: 0 + +cil_type_annotation( + int id: @cil_has_type_annotation ref, + int annotation: int ref); + +cil_getter(unique int prop: @cil_property ref, + int method: @cil_method ref); + +cil_adder(unique int event: @cil_event ref, + int method: @cil_method ref); + +cil_remover(unique int event: @cil_event ref, int method: @cil_method ref); + +cil_raiser(unique int event: @cil_event ref, int method: @cil_method ref); + +cil_property( + unique int id: @cil_property, + int parent: @cil_type ref, + string name: string ref, + int property_type: @cil_type ref); + +#keyset[parent, name] +cil_event(unique int id: @cil_event, + int parent: @cil_type ref, + string name: string ref, + int event_type: @cil_type ref); + +#keyset[impl, index] +cil_local_variable( + unique int id: @cil_local_variable, + int impl: @cil_method_implementation ref, + int index: int ref, + int var_type: @cil_type ref); + +cil_function_pointer_calling_conventions( + int id: @cil_function_pointer_type ref, + int kind: int ref); + +// CIL handlers (exception handlers etc). + +case @cil_handler.kind of + 0 = @cil_catch_handler +| 1 = @cil_filter_handler +| 2 = @cil_finally_handler +| 4 = @cil_fault_handler +; + +#keyset[impl, index] +cil_handler( + unique int id: @cil_handler, + int impl: @cil_method_implementation ref, + int index: int ref, + int kind: int ref, + int try_start: @cil_instruction ref, + int try_end: @cil_instruction ref, + int handler_start: @cil_instruction ref); + +cil_handler_filter( + unique int id: @cil_handler ref, + int filter_start: @cil_instruction ref); + +cil_handler_type( + unique int id: @cil_handler ref, + int catch_type: @cil_type ref); + +@cil_controlflow_node = @cil_entry_point | @cil_instruction; + +@cil_entry_point = @cil_method_implementation | @cil_handler; + +@cil_dataflow_node = @cil_instruction | @cil_variable | @cil_method; + +cil_method_stack_size( + unique int method: @cil_method_implementation ref, + int size: int ref); + +// CIL modifiers + +cil_public(int id: @cil_member ref); +cil_private(int id: @cil_member ref); +cil_protected(int id: @cil_member ref); +cil_internal(int id: @cil_member ref); +cil_static(int id: @cil_member ref); +cil_sealed(int id: @cil_member ref); +cil_virtual(int id: @cil_method ref); +cil_abstract(int id: @cil_member ref); +cil_class(int id: @cil_type ref); +cil_interface(int id: @cil_type ref); +cil_security(int id: @cil_member ref); +cil_requiresecobject(int id: @cil_method ref); +cil_specialname(int id: @cil_method ref); +cil_newslot(int id: @cil_method ref); + +cil_base_class(unique int id: @cil_type ref, int base: @cil_type ref); +cil_base_interface(int id: @cil_type ref, int base: @cil_type ref); +cil_enum_underlying_type(unique int id: @cil_type ref, int underlying: @cil_type ref); + +#keyset[unbound, index] +cil_type_parameter( + int unbound: @cil_member ref, + int index: int ref, + int param: @cil_typeparameter ref); + +#keyset[bound, index] +cil_type_argument( + int bound: @cil_member ref, + int index: int ref, + int t: @cil_type ref); + +// CIL type parameter constraints + +cil_typeparam_covariant(int tp: @cil_typeparameter ref); +cil_typeparam_contravariant(int tp: @cil_typeparameter ref); +cil_typeparam_class(int tp: @cil_typeparameter ref); +cil_typeparam_struct(int tp: @cil_typeparameter ref); +cil_typeparam_new(int tp: @cil_typeparameter ref); +cil_typeparam_constraint(int tp: @cil_typeparameter ref, int supertype: @cil_type ref); + +// CIL attributes + +cil_attribute( + unique int attributeid: @cil_attribute, + int element: @cil_declaration ref, + int constructor: @cil_method ref); + +#keyset[attribute_id, param] +cil_attribute_named_argument( + int attribute_id: @cil_attribute ref, + string param: string ref, + string value: string ref); + +#keyset[attribute_id, index] +cil_attribute_positional_argument( + int attribute_id: @cil_attribute ref, + int index: int ref, + string value: string ref); + + +// Common .Net data model covering both C# and CIL + +// Common elements +@dotnet_element = @element | @cil_element; +@dotnet_named_element = @named_element | @cil_named_element; +@dotnet_callable = @callable | @cil_method; +@dotnet_variable = @variable | @cil_variable; +@dotnet_field = @field | @cil_field; +@dotnet_parameter = @parameter | @cil_parameter; +@dotnet_declaration = @declaration | @cil_declaration; +@dotnet_member = @member | @cil_member; +@dotnet_event = @event | @cil_event; +@dotnet_property = @property | @cil_property | @indexer; +@dotnet_parameterizable = @parameterizable | @cil_parameterizable; + +// Common types +@dotnet_type = @type | @cil_type; +@dotnet_call = @call | @cil_call_any; +@dotnet_throw = @throw_element | @cil_throw_any; +@dotnet_valueorreftype = @cil_valueorreftype | @value_or_ref_type | @cil_array_type | @void_type; +@dotnet_typeparameter = @type_parameter | @cil_typeparameter; +@dotnet_array_type = @array_type | @cil_array_type; +@dotnet_pointer_type = @pointer_type | @cil_pointer_type; +@dotnet_type_parameter = @type_parameter | @cil_typeparameter; +@dotnet_generic = @dotnet_valueorreftype | @dotnet_callable; + +// Attributes +@dotnet_attribute = @attribute | @cil_attribute; + +// Expressions +@dotnet_expr = @expr | @cil_expr; + +// Literals +@dotnet_literal = @literal_expr | @cil_literal; +@dotnet_string_literal = @string_literal_expr | @cil_ldstr; +@dotnet_int_literal = @integer_literal_expr | @cil_ldc_i; +@dotnet_float_literal = @float_literal_expr | @cil_ldc_r; +@dotnet_null_literal = @null_literal_expr | @cil_ldnull; + +@metadata_entity = @cil_method | @cil_type | @cil_field | @cil_property | @field | @property | + @callable | @value_or_ref_type | @void_type; + +#keyset[entity, location] +metadata_handle(int entity : @metadata_entity ref, int location: @assembly ref, int handle: int ref) diff --git a/csharp/ql/lib/upgrades/4ac7d8bcac6f664b1e83c858aa71f8dc761cc603/upgrade.properties b/csharp/ql/lib/upgrades/4ac7d8bcac6f664b1e83c858aa71f8dc761cc603/upgrade.properties new file mode 100644 index 00000000000..676f413d36d --- /dev/null +++ b/csharp/ql/lib/upgrades/4ac7d8bcac6f664b1e83c858aa71f8dc761cc603/upgrade.properties @@ -0,0 +1,2 @@ +description: Add list- and slice pattern expressions kinds. +compatibility: backwards diff --git a/csharp/ql/src/change-notes/2022-12-15-rename-mad-extensibles.md b/csharp/ql/src/change-notes/2022-12-15-rename-mad-extensibles.md new file mode 100644 index 00000000000..39532da22c8 --- /dev/null +++ b/csharp/ql/src/change-notes/2022-12-15-rename-mad-extensibles.md @@ -0,0 +1,4 @@ +--- +category: minorAnalysis +--- +* The extensible predicates for Models as Data have been renamed (the `ext` prefix has been removed). As an example `extSummaryModel` has been renamed to `summaryModel`. \ No newline at end of file diff --git a/csharp/ql/src/utils/modelgenerator/internal/CaptureModelsSpecific.qll b/csharp/ql/src/utils/modelgenerator/internal/CaptureModelsSpecific.qll index 2cc9657ce50..1fc7636ca65 100644 --- a/csharp/ql/src/utils/modelgenerator/internal/CaptureModelsSpecific.qll +++ b/csharp/ql/src/utils/modelgenerator/internal/CaptureModelsSpecific.qll @@ -39,6 +39,7 @@ private predicate isRelevantForModels(CS::Callable api) { not api instanceof CS::ConversionOperator and not api instanceof Util::MainMethod and not api instanceof CS::Destructor and + not api instanceof CS::AnonymousFunctionExpr and not api.(CS::Constructor).isParameterless() } diff --git a/csharp/ql/test/library-tests/csharp11/ListPattern.cs b/csharp/ql/test/library-tests/csharp11/ListPattern.cs new file mode 100644 index 00000000000..2bede367969 --- /dev/null +++ b/csharp/ql/test/library-tests/csharp11/ListPattern.cs @@ -0,0 +1,38 @@ +using System.Collections.Generic; + +class ListPattern +{ + public void M1(int[] x) + { + if (x is []) { } + if (x is [1]) { } + if (x is [_, 2]) { } + if (x is [var y, 3, 4]) { } + if (x is [5 or 6, _, 7]) { } + if (x is [var a, .., 2]) { } + if (x is [var b, .. { Length: 2 or 5 }, 2]) { } + } + + public void M2(string[] x) + { + switch (x) + { + case []: + break; + case ["A"]: + break; + case [_, "B"]: + break; + case [var y, "C", "D"]: + break; + case ["E" or "F", _, "G"]: + break; + case [var a, .., "H"]: + break; + case [var b, .. var c, "I"]: + break; + default: + break; + } + } +} \ No newline at end of file diff --git a/csharp/ql/test/library-tests/csharp11/listPattern.expected b/csharp/ql/test/library-tests/csharp11/listPattern.expected new file mode 100644 index 00000000000..7fcaa6be75c --- /dev/null +++ b/csharp/ql/test/library-tests/csharp11/listPattern.expected @@ -0,0 +1,20 @@ +listPattern +| ListPattern.cs:7:18:7:19 | [ ... ] | | +| ListPattern.cs:8:18:8:20 | [ ... ] | 1 | +| ListPattern.cs:9:18:9:23 | [ ... ] | _, 2 | +| ListPattern.cs:10:18:10:30 | [ ... ] | Int32 y, 3, 4 | +| ListPattern.cs:11:18:11:31 | [ ... ] | ... or ..., _, 7 | +| ListPattern.cs:12:18:12:31 | [ ... ] | Int32 a, .., 2 | +| ListPattern.cs:13:18:13:50 | [ ... ] | Int32 b, .., 2 | +| ListPattern.cs:20:18:20:19 | [ ... ] | | +| ListPattern.cs:22:18:22:22 | [ ... ] | "A" | +| ListPattern.cs:24:18:24:25 | [ ... ] | _, "B" | +| ListPattern.cs:26:18:26:34 | [ ... ] | String y, "C", "D" | +| ListPattern.cs:28:18:28:37 | [ ... ] | ... or ..., _, "G" | +| ListPattern.cs:30:18:30:33 | [ ... ] | String a, .., "H" | +| ListPattern.cs:32:18:32:39 | [ ... ] | String b, .., "I" | +slicePattern +| ListPattern.cs:12:26:12:27 | .. | ..: | +| ListPattern.cs:13:26:13:46 | .. | ..:{ ... } | +| ListPattern.cs:30:26:30:27 | .. | ..: | +| ListPattern.cs:32:26:32:33 | .. | ..:String[] c | diff --git a/csharp/ql/test/library-tests/csharp11/listPattern.ql b/csharp/ql/test/library-tests/csharp11/listPattern.ql new file mode 100644 index 00000000000..005530f2c24 --- /dev/null +++ b/csharp/ql/test/library-tests/csharp11/listPattern.ql @@ -0,0 +1,19 @@ +import csharp + +private string childPatterns(ListPatternExpr e) { + result = concat(string child, int n | child = e.getPattern(n).toString() | child, ", " order by n) +} + +query predicate listPattern(ListPatternExpr pattern, string children) { + pattern.getFile().getStem() = "ListPattern" and + children = childPatterns(pattern) +} + +query predicate slicePattern(SlicePatternExpr pattern, string s) { + pattern.getFile().getStem() = "ListPattern" and + exists(string child | + if exists(pattern.getPattern()) then child = pattern.getPattern().toString() else child = "" + | + s = pattern.toString() + ":" + child + ) +} 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 new file mode 100644 index 00000000000..a1c2a2d4d66 --- /dev/null +++ b/csharp/ql/test/library-tests/dataflow/external-models/ExternalFlow.ext.yml @@ -0,0 +1,31 @@ +extensions: + - addsTo: + pack: codeql/csharp-all + extensible: summaryModel + data: + # "namespace", "type", "overrides", "name", "signature", "ext", "inputspec", "outputspec", "kind", "provenance" + - ["My.Qltest", "D", false, "StepArgRes", "(System.Object)","", "Argument[0]", "ReturnValue", "taint", "manual"] + - ["My.Qltest", "D", false, "StepArgArg", "(System.Object,System.Object)", "", "Argument[0]", "Argument[1]", "taint", "manual"] + - ["My.Qltest", "D", false, "StepArgQual", "(System.Object)", "", "Argument[0]", "Argument[this]", "taint", "manual"] + - ["My.Qltest", "D", false, "StepFieldGetter", "()", "", "Argument[this].Field[My.Qltest.D.Field]", "ReturnValue", "value", "manual"] + - ["My.Qltest", "D", false, "StepFieldSetter", "(System.Object)", "", "Argument[0]", "Argument[this].Field[My.Qltest.D.Field]", "value", "manual"] + - ["My.Qltest", "D", false, "StepFieldSetter", "(System.Object)", "", "Argument[this]", "ReturnValue.Field[My.Qltest.D.Field2]", "value", "manual"] + - ["My.Qltest", "D", false, "StepPropertyGetter", "()", "", "Argument[this].Property[My.Qltest.D.Property]", "ReturnValue", "value", "manual"] + - ["My.Qltest", "D", false, "StepPropertySetter", "(System.Object)", "", "Argument[0]", "Argument[this].Property[My.Qltest.D.Property]", "value", "manual"] + - ["My.Qltest", "D", false, "StepElementGetter", "()", "", "Argument[this].Element", "ReturnValue", "value", "manual"] + - ["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, "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"] + - ["My.Qltest", "D", false, "Reverse", "(System.Object[])", "", "Argument[0].WithElement", "ReturnValue", "value", "manual"] + - ["My.Qltest", "E", true, "get_MyProp", "()", "", "Argument[this].Field[My.Qltest.E.MyField]", "ReturnValue", "value", "manual"] + - ["My.Qltest", "E", true, "set_MyProp", "(System.Object)", "", "Argument[0]", "Argument[this].Field[My.Qltest.E.MyField]", "value", "manual"] + - ["My.Qltest", "G", false, "GeneratedFlow", "(System.Object)", "", "Argument[0]", "ReturnValue", "value", "generated"] + - ["My.Qltest", "G", false, "GeneratedFlowArgs", "(System.Object,System.Object)", "", "Argument[0]", "ReturnValue", "value", "generated"] + - ["My.Qltest", "G", false, "GeneratedFlowArgs", "(System.Object,System.Object)", "", "Argument[1]", "ReturnValue", "value", "generated"] + - ["My.Qltest", "G", false, "MixedFlowArgs", "(System.Object,System.Object)", "", "Argument[0]", "ReturnValue", "value", "generated"] + - ["My.Qltest", "G", false, "MixedFlowArgs", "(System.Object,System.Object)", "", "Argument[1]", "ReturnValue", "value", "manual"] diff --git a/csharp/ql/test/library-tests/dataflow/external-models/ext/test.model.yml b/csharp/ql/test/library-tests/dataflow/external-models/ext/test.model.yml deleted file mode 100644 index 5de0644e793..00000000000 --- a/csharp/ql/test/library-tests/dataflow/external-models/ext/test.model.yml +++ /dev/null @@ -1,85 +0,0 @@ -extensions: - - - addsTo: - pack: codeql/csharp-all - extensible: extSourceModel - data: - # "namespace", "type", "overrides", "name", "signature", "ext", "spec", "kind", "provenance", - - ["My.Qltest", "A", false, "Src1", "()", "", "ReturnValue", "local", "manual"] - - ["My.Qltest", "A", false, "Src1", "(System.String)", "", "ReturnValue", "local", "manual"] - - ["My.Qltest", "A", false, "Src1", "", "", "ReturnValue", "local", "manual"] - - ["My.Qltest", "A", false, "Src2", "()", "", "ReturnValue", "local", "manual"] - - ["My.Qltest", "A", false, "Src3", "()", "", "ReturnValue", "local", "manual"] - - ["My.Qltest", "A", true, "Src2", "()", "", "ReturnValue", "local", "manual"] - - ["My.Qltest", "A", true, "Src3", "()", "", "ReturnValue", "local", "manual"] - - ["My.Qltest", "A", false, "SrcArg", "(System.Object)", "", "Argument[0]", "local", "manual"] - - ["My.Qltest", "A", false, "SrcArg", "(System.Object)", "", "Argument", "local", "manual"] - - ["My.Qltest", "A", true, "SrcParam", "(System.Object)", "", "Parameter[0]", "local", "manual"] - - ["My.Qltest", "SourceAttribute", false, "", "", "Attribute", "ReturnValue", "local", "manual"] - - ["My.Qltest", "SourceAttribute", false, "", "", "Attribute", "Parameter", "local", "manual"] - - ["My.Qltest", "SourceAttribute", false, "", "", "Attribute", "", "local", "manual"] - - ["My.Qltest", "A", false, "SrcTwoArg", "(System.String,System.String)", "", "ReturnValue", "local", "manual"] - - - addsTo: - pack: codeql/csharp-all - extensible: extSinkModel - data: - # "namespace", "type", "overrides", "name", "signature", "ext", "spec", "kind", "provenance" - - ["My.Qltest", "B", false, "Sink1", "(System.Object)", "", "Argument[0]", "code", "manual"] - - ["My.Qltest", "B", false, "SinkMethod", "()", "", "ReturnValue", "xss", "manual"] - - ["My.Qltest", "SinkAttribute", false, "", "", "Attribute", "ReturnValue", "html", "manual"] - - ["My.Qltest", "SinkAttribute", false, "", "", "Attribute", "Argument", "remote", "manual"] - - ["My.Qltest", "SinkAttribute", false, "", "", "Attribute", "", "sql", "manual"] - - # Summaries relevant for the ExternalFlow testcase. - - addsTo: - pack: codeql/csharp-all - extensible: extSummaryModel - data: - # "namespace", "type", "overrides", "name", "signature", "ext", "inputspec", "outputspec", "kind", "provenance" - - ["My.Qltest", "D", false, "StepArgRes", "(System.Object)","", "Argument[0]", "ReturnValue", "taint", "manual"] - - ["My.Qltest", "D", false, "StepArgArg", "(System.Object,System.Object)", "", "Argument[0]", "Argument[1]", "taint", "manual"] - - ["My.Qltest", "D", false, "StepArgQual", "(System.Object)", "", "Argument[0]", "Argument[this]", "taint", "manual"] - - ["My.Qltest", "D", false, "StepFieldGetter", "()", "", "Argument[this].Field[My.Qltest.D.Field]", "ReturnValue", "value", "manual"] - - ["My.Qltest", "D", false, "StepFieldSetter", "(System.Object)", "", "Argument[0]", "Argument[this].Field[My.Qltest.D.Field]", "value", "manual"] - - ["My.Qltest", "D", false, "StepFieldSetter", "(System.Object)", "", "Argument[this]", "ReturnValue.Field[My.Qltest.D.Field2]", "value", "manual"] - - ["My.Qltest", "D", false, "StepPropertyGetter", "()", "", "Argument[this].Property[My.Qltest.D.Property]", "ReturnValue", "value", "manual"] - - ["My.Qltest", "D", false, "StepPropertySetter", "(System.Object)", "", "Argument[0]", "Argument[this].Property[My.Qltest.D.Property]", "value", "manual"] - - ["My.Qltest", "D", false, "StepElementGetter", "()", "", "Argument[this].Element", "ReturnValue", "value", "manual"] - - ["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, "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"] - - ["My.Qltest", "D", false, "Reverse", "(System.Object[])", "", "Argument[0].WithElement", "ReturnValue", "value", "manual"] - - ["My.Qltest", "E", true, "get_MyProp", "()", "", "Argument[this].Field[My.Qltest.E.MyField]", "ReturnValue", "value", "manual"] - - ["My.Qltest", "E", true, "set_MyProp", "(System.Object)", "", "Argument[0]", "Argument[this].Field[My.Qltest.E.MyField]", "value", "manual"] - - ["My.Qltest", "G", false, "GeneratedFlow", "(System.Object)", "", "Argument[0]", "ReturnValue", "value", "generated"] - - ["My.Qltest", "G", false, "GeneratedFlowArgs", "(System.Object,System.Object)", "", "Argument[0]", "ReturnValue", "value", "generated"] - - ["My.Qltest", "G", false, "GeneratedFlowArgs", "(System.Object,System.Object)", "", "Argument[1]", "ReturnValue", "value", "generated"] - - ["My.Qltest", "G", false, "MixedFlowArgs", "(System.Object,System.Object)", "", "Argument[0]", "ReturnValue", "value", "generated"] - - ["My.Qltest", "G", false, "MixedFlowArgs", "(System.Object,System.Object)", "", "Argument[1]", "ReturnValue", "value", "manual"] - - # Summaries relevant for the Steps testcase. - - addsTo: - pack: codeql/csharp-all - extensible: extSummaryModel - # "namespace", "type", "overrides", "name", "signature", "ext", "inputspec", "outputspec", "kind", "provenance" - data: - - ["My.Qltest", "C", false, "StepArgRes", "(System.Object)", "", "Argument[0]", "ReturnValue", "taint", "manual"] - - ["My.Qltest", "C", false, "StepArgArg", "(System.Object,System.Object)", "", "Argument[0]", "Argument[1]", "taint", "manual"] - - ["My.Qltest", "C", false, "StepArgQual", "(System.Object)", "", "Argument[0]", "Argument[this]", "taint", "manual"] - - ["My.Qltest", "C", false, "StepQualRes", "()", "", "Argument[this]", "ReturnValue", "taint", "manual"] - - ["My.Qltest", "C", false, "StepQualArg", "(System.Object)", "", "Argument[this]", "Argument[0]", "taint", "manual"] - - ["My.Qltest", "C", false, "StepFieldGetter", "()", "", "Argument[this].Field[My.Qltest.C.Field]", "ReturnValue", "value", "manual"] - - ["My.Qltest", "C", false, "StepFieldSetter", "(System.Int32)", "", "Argument[0]", "Argument[this].Field[My.Qltest.C.Field]", "value", "manual"] - - ["My.Qltest", "C", false, "StepPropertyGetter", "()", "", "Argument[this].Property[My.Qltest.C.Property]", "ReturnValue", "value", "manual"] - - ["My.Qltest", "C", false, "StepPropertySetter", "(System.Int32)", "", "Argument[0]", "Argument[this].Property[My.Qltest.C.Property]", "value", "manual"] - - ["My.Qltest", "C", false, "StepElementGetter", "()", "", "Argument[this].Element", "ReturnValue", "value", "manual"] - - ["My.Qltest", "C", false, "StepElementSetter", "(System.Int32)", "", "Argument[0]", "Argument[this].Element", "value", "manual"] - - ["My.Qltest", "C+Generic<,>", false, "StepGeneric", "(T)", "", "Argument[0]", "ReturnValue", "value", "manual"] - - ["My.Qltest", "C+Generic<,>", false, "StepGeneric2<>", "(S)", "", "Argument[0]", "ReturnValue", "value", "manual"] - - ["My.Qltest", "C+Base<>", true, "StepOverride", "(T)", "", "Argument[0]", "ReturnValue", "value", "manual"] diff --git a/csharp/ql/test/library-tests/dataflow/external-models/sinks.ext.yml b/csharp/ql/test/library-tests/dataflow/external-models/sinks.ext.yml new file mode 100644 index 00000000000..3198057f42c --- /dev/null +++ b/csharp/ql/test/library-tests/dataflow/external-models/sinks.ext.yml @@ -0,0 +1,11 @@ +extensions: + - addsTo: + pack: codeql/csharp-all + extensible: sinkModel + data: + # "namespace", "type", "overrides", "name", "signature", "ext", "spec", "kind", "provenance" + - ["My.Qltest", "B", false, "Sink1", "(System.Object)", "", "Argument[0]", "code", "manual"] + - ["My.Qltest", "B", false, "SinkMethod", "()", "", "ReturnValue", "xss", "manual"] + - ["My.Qltest", "SinkAttribute", false, "", "", "Attribute", "ReturnValue", "html", "manual"] + - ["My.Qltest", "SinkAttribute", false, "", "", "Attribute", "Argument", "remote", "manual"] + - ["My.Qltest", "SinkAttribute", false, "", "", "Attribute", "", "sql", "manual"] diff --git a/csharp/ql/test/library-tests/dataflow/external-models/srcs.ext.yml b/csharp/ql/test/library-tests/dataflow/external-models/srcs.ext.yml new file mode 100644 index 00000000000..163d2636ab0 --- /dev/null +++ b/csharp/ql/test/library-tests/dataflow/external-models/srcs.ext.yml @@ -0,0 +1,20 @@ +extensions: + - addsTo: + pack: codeql/csharp-all + extensible: sourceModel + data: + # "namespace", "type", "overrides", "name", "signature", "ext", "spec", "kind", "provenance", + - ["My.Qltest", "A", false, "Src1", "()", "", "ReturnValue", "local", "manual"] + - ["My.Qltest", "A", false, "Src1", "(System.String)", "", "ReturnValue", "local", "manual"] + - ["My.Qltest", "A", false, "Src1", "", "", "ReturnValue", "local", "manual"] + - ["My.Qltest", "A", false, "Src2", "()", "", "ReturnValue", "local", "manual"] + - ["My.Qltest", "A", false, "Src3", "()", "", "ReturnValue", "local", "manual"] + - ["My.Qltest", "A", true, "Src2", "()", "", "ReturnValue", "local", "manual"] + - ["My.Qltest", "A", true, "Src3", "()", "", "ReturnValue", "local", "manual"] + - ["My.Qltest", "A", false, "SrcArg", "(System.Object)", "", "Argument[0]", "local", "manual"] + - ["My.Qltest", "A", false, "SrcArg", "(System.Object)", "", "Argument", "local", "manual"] + - ["My.Qltest", "A", true, "SrcParam", "(System.Object)", "", "Parameter[0]", "local", "manual"] + - ["My.Qltest", "SourceAttribute", false, "", "", "Attribute", "ReturnValue", "local", "manual"] + - ["My.Qltest", "SourceAttribute", false, "", "", "Attribute", "Parameter", "local", "manual"] + - ["My.Qltest", "SourceAttribute", false, "", "", "Attribute", "", "local", "manual"] + - ["My.Qltest", "A", false, "SrcTwoArg", "(System.String,System.String)", "", "ReturnValue", "local", "manual"] \ No newline at end of file diff --git a/csharp/ql/test/library-tests/dataflow/external-models/steps.ext.yml b/csharp/ql/test/library-tests/dataflow/external-models/steps.ext.yml new file mode 100644 index 00000000000..7507f5a8883 --- /dev/null +++ b/csharp/ql/test/library-tests/dataflow/external-models/steps.ext.yml @@ -0,0 +1,20 @@ +extensions: + - addsTo: + pack: codeql/csharp-all + extensible: summaryModel + # "namespace", "type", "overrides", "name", "signature", "ext", "inputspec", "outputspec", "kind", "provenance" + data: + - ["My.Qltest", "C", false, "StepArgRes", "(System.Object)", "", "Argument[0]", "ReturnValue", "taint", "manual"] + - ["My.Qltest", "C", false, "StepArgArg", "(System.Object,System.Object)", "", "Argument[0]", "Argument[1]", "taint", "manual"] + - ["My.Qltest", "C", false, "StepArgQual", "(System.Object)", "", "Argument[0]", "Argument[this]", "taint", "manual"] + - ["My.Qltest", "C", false, "StepQualRes", "()", "", "Argument[this]", "ReturnValue", "taint", "manual"] + - ["My.Qltest", "C", false, "StepQualArg", "(System.Object)", "", "Argument[this]", "Argument[0]", "taint", "manual"] + - ["My.Qltest", "C", false, "StepFieldGetter", "()", "", "Argument[this].Field[My.Qltest.C.Field]", "ReturnValue", "value", "manual"] + - ["My.Qltest", "C", false, "StepFieldSetter", "(System.Int32)", "", "Argument[0]", "Argument[this].Field[My.Qltest.C.Field]", "value", "manual"] + - ["My.Qltest", "C", false, "StepPropertyGetter", "()", "", "Argument[this].Property[My.Qltest.C.Property]", "ReturnValue", "value", "manual"] + - ["My.Qltest", "C", false, "StepPropertySetter", "(System.Int32)", "", "Argument[0]", "Argument[this].Property[My.Qltest.C.Property]", "value", "manual"] + - ["My.Qltest", "C", false, "StepElementGetter", "()", "", "Argument[this].Element", "ReturnValue", "value", "manual"] + - ["My.Qltest", "C", false, "StepElementSetter", "(System.Int32)", "", "Argument[0]", "Argument[this].Element", "value", "manual"] + - ["My.Qltest", "C+Generic<,>", false, "StepGeneric", "(T)", "", "Argument[0]", "ReturnValue", "value", "manual"] + - ["My.Qltest", "C+Generic<,>", false, "StepGeneric2<>", "(S)", "", "Argument[0]", "ReturnValue", "value", "manual"] + - ["My.Qltest", "C+Base<>", true, "StepOverride", "(T)", "", "Argument[0]", "ReturnValue", "value", "manual"] diff --git a/csharp/ql/test/library-tests/dataflow/external-models/steps.ql b/csharp/ql/test/library-tests/dataflow/external-models/steps.ql index 2e216a672d7..f7635eae882 100644 --- a/csharp/ql/test/library-tests/dataflow/external-models/steps.ql +++ b/csharp/ql/test/library-tests/dataflow/external-models/steps.ql @@ -6,30 +6,24 @@ import semmle.code.csharp.dataflow.FlowSummary import semmle.code.csharp.dataflow.internal.DataFlowDispatch as DataFlowDispatch import semmle.code.csharp.dataflow.internal.FlowSummaryImpl as FlowSummaryImpl -private SummarizedCallable getRelevantSummarizedCallable() { - exists(SummarizedCallable sc | - sc.getDeclaringType*().getName() = "C" and - sc instanceof DataFlowDispatch::DataFlowSummarizedCallable and - result = sc - ) -} - query predicate summaryThroughStep( DataFlow::Node node1, DataFlow::Node node2, boolean preservesValue ) { FlowSummaryImpl::Private::Steps::summaryThroughStepValue(node1, node2, - getRelevantSummarizedCallable()) and + any(DataFlowDispatch::DataFlowSummarizedCallable sc)) and preservesValue = true or FlowSummaryImpl::Private::Steps::summaryThroughStepTaint(node1, node2, - getRelevantSummarizedCallable()) and + any(DataFlowDispatch::DataFlowSummarizedCallable sc)) and preservesValue = false } query predicate summaryGetterStep(DataFlow::Node arg, DataFlow::Node out, Content c) { - FlowSummaryImpl::Private::Steps::summaryGetterStep(arg, c, out, getRelevantSummarizedCallable()) + FlowSummaryImpl::Private::Steps::summaryGetterStep(arg, c, out, + any(DataFlowDispatch::DataFlowSummarizedCallable sc)) } query predicate summarySetterStep(DataFlow::Node arg, DataFlow::Node out, Content c) { - FlowSummaryImpl::Private::Steps::summarySetterStep(arg, c, out, getRelevantSummarizedCallable()) + FlowSummaryImpl::Private::Steps::summarySetterStep(arg, c, out, + any(DataFlowDispatch::DataFlowSummarizedCallable sc)) } diff --git a/csharp/ql/test/qlpack.yml b/csharp/ql/test/qlpack.yml index 3e526fe5800..b0ce8ef1920 100644 --- a/csharp/ql/test/qlpack.yml +++ b/csharp/ql/test/qlpack.yml @@ -4,6 +4,4 @@ dependencies: codeql/csharp-all: ${workspace} codeql/csharp-queries: ${workspace} extractor: csharp -dataExtensions: - - library-tests/dataflow/external-models/ext/*.model.yml tests: . diff --git a/go/ql/lib/semmle/go/dataflow/internal/DataFlowImpl.qll b/go/ql/lib/semmle/go/dataflow/internal/DataFlowImpl.qll index 6741ccc2f06..1228d00b6ba 100644 --- a/go/ql/lib/semmle/go/dataflow/internal/DataFlowImpl.qll +++ b/go/ql/lib/semmle/go/dataflow/internal/DataFlowImpl.qll @@ -622,7 +622,11 @@ private predicate parameterFlowThroughAllowed(ParamNodeEx p, ReturnKindExt kind) } private module Stage1 implements StageSig { - class Ap = Unit; + class Ap extends int { + // workaround for bad functionality-induced joins (happens when using `Unit`) + pragma[nomagic] + Ap() { this in [0 .. 1] and this < 1 } + } private class Cc = boolean; @@ -1327,8 +1331,8 @@ private module MkStage { */ pragma[nomagic] additional predicate fwdFlow( - NodeEx node, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - Ap ap, ApApprox apa, Configuration config + NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, + ApApprox apa, Configuration config ) { fwdFlow0(node, state, cc, summaryCtx, argAp, ap, apa, config) and PrevStage::revFlow(node, state, apa, config) and @@ -1337,21 +1341,21 @@ private module MkStage { pragma[inline] additional predicate fwdFlow( - NodeEx node, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - Ap ap, Configuration config + NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, + Configuration config ) { fwdFlow(node, state, cc, summaryCtx, argAp, ap, _, config) } pragma[nomagic] private predicate fwdFlow0( - NodeEx node, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - Ap ap, ApApprox apa, Configuration config + NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, + ApApprox apa, Configuration config ) { sourceNode(node, state, config) and (if hasSourceCallCtx(config) then cc = ccSomeCall() else cc = ccNone()) and argAp = apNone() and - summaryCtx = TParameterPositionNone() and + summaryCtx = TParamNodeNone() and ap = getApNil(node) and apa = getApprox(ap) or @@ -1372,7 +1376,7 @@ private module MkStage { fwdFlow(mid, pragma[only_bind_into](state), _, _, _, ap, apa, pragma[only_bind_into](config)) and jumpStep(mid, node, config) and cc = ccNone() and - summaryCtx = TParameterPositionNone() and + summaryCtx = TParamNodeNone() and argAp = apNone() ) or @@ -1380,7 +1384,7 @@ private module MkStage { fwdFlow(mid, state, _, _, _, nil, pragma[only_bind_into](config)) and additionalJumpStep(mid, node, config) and cc = ccNone() and - summaryCtx = TParameterPositionNone() and + summaryCtx = TParamNodeNone() and argAp = apNone() and ap = getApNil(node) and apa = getApprox(ap) @@ -1390,7 +1394,7 @@ private module MkStage { fwdFlow(mid, state0, _, _, _, nil, pragma[only_bind_into](config)) and additionalJumpStateStep(mid, state0, node, state, config) and cc = ccNone() and - summaryCtx = TParameterPositionNone() and + summaryCtx = TParamNodeNone() and argAp = apNone() and ap = getApNil(node) and apa = getApprox(ap) @@ -1414,10 +1418,10 @@ private module MkStage { fwdFlowIn(_, node, state, _, cc, _, _, ap, apa, config) and if PrevStage::parameterMayFlowThrough(node, apa, config) then ( - summaryCtx = TParameterPositionSome(node.(ParamNodeEx).getPosition()) and + summaryCtx = TParamNodeSome(node.asNode()) and argAp = apSome(ap) ) else ( - summaryCtx = TParameterPositionNone() and argAp = apNone() + summaryCtx = TParamNodeNone() and argAp = apNone() ) or // flow out of a callable @@ -1433,16 +1437,19 @@ private module MkStage { ) or // flow through a callable - exists(DataFlowCall call, ParameterPosition summaryCtx0, Ap argAp0 | - fwdFlowOutFromArg(call, node, state, summaryCtx0, argAp0, ap, apa, config) and - fwdFlowIsEntered(call, cc, summaryCtx, argAp, summaryCtx0, argAp0, config) + exists( + DataFlowCall call, CcCall ccc, RetNodeEx ret, boolean allowsFieldFlow, ApApprox innerArgApa + | + fwdFlowThrough(call, cc, state, ccc, summaryCtx, argAp, ap, apa, ret, innerArgApa, config) and + flowThroughOutOfCall(call, ccc, ret, node, allowsFieldFlow, innerArgApa, apa, config) and + if allowsFieldFlow = false then ap instanceof ApNil else any() ) } pragma[nomagic] private predicate fwdFlowStore( NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, FlowState state, Cc cc, - ParameterPositionOption summaryCtx, ApOption argAp, Configuration config + ParamNodeOption summaryCtx, ApOption argAp, Configuration config ) { exists(DataFlowType contentType, ApApprox apa1 | fwdFlow(node1, state, cc, summaryCtx, argAp, ap1, apa1, config) and @@ -1473,8 +1480,8 @@ private module MkStage { pragma[nomagic] private predicate fwdFlowRead0( - NodeEx node1, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - ApNonNil ap, Configuration config + NodeEx node1, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, ApNonNil ap, + Configuration config ) { fwdFlow(node1, state, cc, summaryCtx, argAp, ap, config) and PrevStage::readStepCand(node1, _, _, config) @@ -1483,7 +1490,7 @@ private module MkStage { pragma[nomagic] private predicate fwdFlowRead( Ap ap, Content c, NodeEx node1, NodeEx node2, FlowState state, Cc cc, - ParameterPositionOption summaryCtx, ApOption argAp, Configuration config + ParamNodeOption summaryCtx, ApOption argAp, Configuration config ) { fwdFlowRead0(node1, state, cc, summaryCtx, argAp, ap, config) and PrevStage::readStepCand(node1, c, node2, config) and @@ -1493,7 +1500,7 @@ private module MkStage { pragma[nomagic] private predicate fwdFlowIn( DataFlowCall call, ParamNodeEx p, FlowState state, Cc outercc, CcCall innercc, - ParameterPositionOption summaryCtx, ApOption argAp, Ap ap, ApApprox apa, Configuration config + ParamNodeOption summaryCtx, ApOption argAp, Ap ap, ApApprox apa, Configuration config ) { exists(ArgNodeEx arg, boolean allowsFieldFlow | fwdFlow(arg, state, outercc, summaryCtx, argAp, ap, apa, config) and @@ -1505,64 +1512,38 @@ private module MkStage { pragma[nomagic] private predicate fwdFlowRetFromArg( - RetNodeEx ret, FlowState state, CcCall ccc, ParameterPosition summaryCtx, ParamNodeEx p, - Ap argAp, ApApprox argApa, Ap ap, ApApprox apa, Configuration config + RetNodeEx ret, FlowState state, CcCall ccc, ParamNodeEx summaryCtx, Ap argAp, ApApprox argApa, + Ap ap, ApApprox apa, Configuration config ) { - exists(DataFlowCallable c, ReturnKindExt kind | + exists(ReturnKindExt kind | fwdFlow(pragma[only_bind_into](ret), state, ccc, - TParameterPositionSome(pragma[only_bind_into](summaryCtx)), apSome(argAp), ap, apa, config) and - getApprox(argAp) = argApa and - c = ret.getEnclosingCallable() and + TParamNodeSome(pragma[only_bind_into](summaryCtx.asNode())), + pragma[only_bind_into](apSome(argAp)), ap, pragma[only_bind_into](apa), + pragma[only_bind_into](config)) and kind = ret.getKind() and - p.isParameterOf(c, pragma[only_bind_into](summaryCtx)) and - parameterFlowThroughAllowed(p, kind) + parameterFlowThroughAllowed(summaryCtx, kind) and + argApa = getApprox(argAp) and + PrevStage::returnMayFlowThrough(ret, argApa, apa, kind, pragma[only_bind_into](config)) ) } pragma[inline] - private predicate fwdFlowInMayFlowThrough( - DataFlowCall call, Cc cc, CcCall innerCc, ParameterPositionOption summaryCtx, ApOption argAp, - ParamNodeEx param, Ap ap, ApApprox apa, Configuration config + private predicate fwdFlowThrough0( + DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, + ApOption argAp, Ap ap, ApApprox apa, RetNodeEx ret, ParamNodeEx innerSummaryCtx, + Ap innerArgAp, ApApprox innerArgApa, Configuration config ) { - fwdFlowIn(call, pragma[only_bind_into](param), _, cc, innerCc, summaryCtx, argAp, ap, - pragma[only_bind_into](apa), pragma[only_bind_into](config)) and - PrevStage::parameterMayFlowThrough(param, apa, config) - } - - // dedup before joining with `flowThroughOutOfCall` - pragma[nomagic] - private predicate fwdFlowInMayFlowThroughProj( - DataFlowCall call, CcCall innerCc, ApApprox apa, Configuration config - ) { - fwdFlowInMayFlowThrough(call, _, innerCc, _, _, _, _, apa, config) - } - - /** - * Same as `flowThroughOutOfCall`, but restricted to calls that are reached - * in the flow covered by `fwdFlow`, where data might flow through the target - * callable and back out at `call`. - */ - pragma[nomagic] - private predicate fwdFlowThroughOutOfCall( - DataFlowCall call, CcCall ccc, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow, - ApApprox argApa, ApApprox apa, Configuration config - ) { - fwdFlowInMayFlowThroughProj(call, ccc, argApa, config) and - flowThroughOutOfCall(call, ccc, ret, out, allowsFieldFlow, argApa, apa, config) + fwdFlowRetFromArg(ret, state, ccc, innerSummaryCtx, innerArgAp, innerArgApa, ap, apa, config) and + fwdFlowIsEntered(call, cc, ccc, summaryCtx, argAp, innerSummaryCtx, innerArgAp, config) } pragma[nomagic] - private predicate fwdFlowOutFromArg( - DataFlowCall call, NodeEx out, FlowState state, ParameterPosition summaryCtx, Ap argAp, Ap ap, - ApApprox apa, Configuration config + private predicate fwdFlowThrough( + DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, + ApOption argAp, Ap ap, ApApprox apa, RetNodeEx ret, ApApprox innerArgApa, Configuration config ) { - exists(RetNodeEx ret, boolean allowsFieldFlow, CcCall ccc, ApApprox argApa | - fwdFlowRetFromArg(pragma[only_bind_into](ret), state, pragma[only_bind_into](ccc), - summaryCtx, _, argAp, pragma[only_bind_into](argApa), ap, pragma[only_bind_into](apa), - config) and - fwdFlowThroughOutOfCall(call, ccc, ret, out, allowsFieldFlow, argApa, apa, config) and - (if allowsFieldFlow = false then ap instanceof ApNil else any()) - ) + fwdFlowThrough0(call, cc, state, ccc, summaryCtx, argAp, ap, apa, ret, _, _, innerArgApa, + config) } /** @@ -1571,12 +1552,14 @@ private module MkStage { */ pragma[nomagic] private predicate fwdFlowIsEntered( - DataFlowCall call, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - ParameterPosition pos, Ap ap, Configuration config + DataFlowCall call, Cc cc, CcCall innerCc, ParamNodeOption summaryCtx, ApOption argAp, + ParamNodeEx p, Ap ap, Configuration config ) { - exists(ParamNodeEx param | - fwdFlowInMayFlowThrough(call, cc, _, summaryCtx, argAp, param, ap, _, config) and - pos = param.getPosition() + exists(ApApprox apa | + fwdFlowIn(call, pragma[only_bind_into](p), _, cc, innerCc, summaryCtx, argAp, ap, + pragma[only_bind_into](apa), pragma[only_bind_into](config)) and + PrevStage::parameterMayFlowThrough(p, apa, config) and + PrevStage::callMayFlowThroughRev(call, pragma[only_bind_into](config)) ) } @@ -1596,23 +1579,31 @@ private module MkStage { fwdFlowConsCand(ap1, c, ap2, config) } + pragma[nomagic] + private predicate returnFlowsThrough0( + DataFlowCall call, FlowState state, CcCall ccc, Ap ap, ApApprox apa, RetNodeEx ret, + ParamNodeEx innerSummaryCtx, Ap innerArgAp, ApApprox innerArgApa, Configuration config + ) { + fwdFlowThrough0(call, _, state, ccc, _, _, ap, apa, ret, innerSummaryCtx, innerArgAp, + innerArgApa, config) + } + pragma[nomagic] private predicate returnFlowsThrough( - RetNodeEx ret, ReturnKindExt kind, FlowState state, CcCall ccc, ParamNodeEx p, Ap argAp, + RetNodeEx ret, ReturnPosition pos, FlowState state, CcCall ccc, ParamNodeEx p, Ap argAp, Ap ap, Configuration config ) { - exists(boolean allowsFieldFlow, ApApprox argApa, ApApprox apa | - fwdFlowRetFromArg(pragma[only_bind_into](ret), state, pragma[only_bind_into](ccc), _, p, - argAp, pragma[only_bind_into](argApa), ap, pragma[only_bind_into](apa), config) and - kind = ret.getKind() and - fwdFlowThroughOutOfCall(_, ccc, ret, _, allowsFieldFlow, argApa, apa, config) and - (if allowsFieldFlow = false then ap instanceof ApNil else any()) + exists(DataFlowCall call, ApApprox apa, boolean allowsFieldFlow, ApApprox innerArgApa | + returnFlowsThrough0(call, state, ccc, ap, apa, ret, p, argAp, innerArgApa, config) and + flowThroughOutOfCall(call, ccc, ret, _, allowsFieldFlow, innerArgApa, apa, config) and + pos = ret.getReturnPosition() and + if allowsFieldFlow = false then ap instanceof ApNil else any() ) } pragma[nomagic] private predicate flowThroughIntoCall( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap argAp, + DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap argAp, Ap ap, Configuration config ) { exists(ApApprox argApa | @@ -1620,7 +1611,7 @@ private module MkStage { allowsFieldFlow, argApa, pragma[only_bind_into](config)) and fwdFlow(arg, _, _, _, _, pragma[only_bind_into](argAp), argApa, pragma[only_bind_into](config)) and - returnFlowsThrough(_, _, _, _, p, pragma[only_bind_into](argAp), _, + returnFlowsThrough(_, _, _, _, p, pragma[only_bind_into](argAp), ap, pragma[only_bind_into](config)) and if allowsFieldFlow = false then argAp instanceof ApNil else any() ) @@ -1639,12 +1630,13 @@ private module MkStage { pragma[nomagic] private predicate flowOutOfCallAp( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, boolean allowsFieldFlow, + DataFlowCall call, RetNodeEx ret, ReturnPosition pos, NodeEx out, boolean allowsFieldFlow, Ap ap, Configuration config ) { exists(ApApprox apa | - flowOutOfCallApa(call, ret, kind, out, allowsFieldFlow, apa, config) and - fwdFlow(ret, _, _, _, _, ap, apa, config) + flowOutOfCallApa(call, ret, _, out, allowsFieldFlow, apa, config) and + fwdFlow(ret, _, _, _, _, ap, apa, config) and + pos = ret.getReturnPosition() ) } @@ -1739,17 +1731,17 @@ private module MkStage { ) or // flow through a callable - exists(DataFlowCall call, ReturnKindExt returnKind0, Ap returnAp0 | - revFlowInToReturn(call, node, state, returnKind0, returnAp0, ap, config) and - revFlowIsReturned(call, returnCtx, returnAp, returnKind0, returnAp0, config) + exists(DataFlowCall call, ParamNodeEx p, ReturnPosition pos, Ap innerReturnAp | + revFlowThrough(call, returnCtx, p, state, pos, returnAp, ap, innerReturnAp, config) and + flowThroughIntoCall(call, node, p, _, ap, innerReturnAp, config) ) or // flow out of a callable - exists(ReturnKindExt kind | - revFlowOut(_, node, kind, state, _, _, ap, config) and - if returnFlowsThrough(node, kind, state, _, _, _, ap, config) + exists(ReturnPosition pos | + revFlowOut(_, node, pos, state, _, _, ap, config) and + if returnFlowsThrough(node, pos, state, _, _, _, ap, config) then ( - returnCtx = TReturnCtxMaybeFlowThrough(kind) and + returnCtx = TReturnCtxMaybeFlowThrough(pos) and returnAp = apSome(ap) ) else ( returnCtx = TReturnCtxNoFlowThrough() and returnAp = apNone() @@ -1782,47 +1774,33 @@ private module MkStage { pragma[nomagic] private predicate revFlowOut( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, FlowState state, ReturnCtx returnCtx, + DataFlowCall call, RetNodeEx ret, ReturnPosition pos, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap, Configuration config ) { exists(NodeEx out, boolean allowsFieldFlow | revFlow(out, state, returnCtx, returnAp, ap, config) and - flowOutOfCallAp(call, ret, kind, out, allowsFieldFlow, ap, config) and + flowOutOfCallAp(call, ret, pos, out, allowsFieldFlow, ap, config) and if allowsFieldFlow = false then ap instanceof ApNil else any() ) } - /** - * Same as `flowThroughIntoCall`, but restricted to calls that are reached - * in the flow covered by `revFlow`, where data might flow through the target - * callable and back out at `call`. - */ - pragma[nomagic] - private predicate revFlowThroughIntoCall( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap argAp, - Configuration config - ) { - flowThroughIntoCall(call, arg, p, allowsFieldFlow, argAp, config) and - revFlowIsReturned(call, _, _, _, _, config) - } - pragma[nomagic] private predicate revFlowParamToReturn( - ParamNodeEx p, FlowState state, ReturnKindExt kind, Ap returnAp, Ap ap, Configuration config + ParamNodeEx p, FlowState state, ReturnPosition pos, Ap returnAp, Ap ap, Configuration config ) { - revFlow(p, state, TReturnCtxMaybeFlowThrough(kind), apSome(returnAp), ap, config) and - parameterFlowThroughAllowed(p, kind) + revFlow(pragma[only_bind_into](p), state, TReturnCtxMaybeFlowThrough(pos), apSome(returnAp), + pragma[only_bind_into](ap), pragma[only_bind_into](config)) and + parameterFlowThroughAllowed(p, pos.getKind()) and + PrevStage::parameterMayFlowThrough(p, getApprox(ap), config) } pragma[nomagic] - private predicate revFlowInToReturn( - DataFlowCall call, ArgNodeEx arg, FlowState state, ReturnKindExt kind, Ap returnAp, Ap ap, - Configuration config + private predicate revFlowThrough( + DataFlowCall call, ReturnCtx returnCtx, ParamNodeEx p, FlowState state, ReturnPosition pos, + ApOption returnAp, Ap ap, Ap innerReturnAp, Configuration config ) { - exists(ParamNodeEx p, boolean allowsFieldFlow | - revFlowParamToReturn(p, state, kind, returnAp, ap, config) and - revFlowThroughIntoCall(call, arg, p, allowsFieldFlow, ap, config) - ) + revFlowParamToReturn(p, state, pos, innerReturnAp, ap, config) and + revFlowIsReturned(call, returnCtx, returnAp, pos, innerReturnAp, config) } /** @@ -1832,12 +1810,12 @@ private module MkStage { */ pragma[nomagic] private predicate revFlowIsReturned( - DataFlowCall call, ReturnCtx returnCtx, ApOption returnAp, ReturnKindExt kind, Ap ap, + DataFlowCall call, ReturnCtx returnCtx, ApOption returnAp, ReturnPosition pos, Ap ap, Configuration config ) { exists(RetNodeEx ret, FlowState state, CcCall ccc | - revFlowOut(call, ret, kind, state, returnCtx, returnAp, ap, config) and - returnFlowsThrough(ret, kind, state, ccc, _, _, ap, config) and + revFlowOut(call, ret, pos, state, returnCtx, returnAp, ap, config) and + returnFlowsThrough(ret, pos, state, ccc, _, _, ap, config) and matchesCall(ccc, call) ) } @@ -1915,17 +1893,17 @@ private module MkStage { pragma[nomagic] private predicate parameterFlowsThroughRev( - ParamNodeEx p, Ap ap, ReturnKindExt kind, Ap returnAp, Configuration config + ParamNodeEx p, Ap ap, ReturnPosition pos, Ap returnAp, Configuration config ) { - revFlow(p, _, TReturnCtxMaybeFlowThrough(kind), apSome(returnAp), ap, config) and - parameterFlowThroughAllowed(p, kind) + revFlow(p, _, TReturnCtxMaybeFlowThrough(pos), apSome(returnAp), ap, config) and + parameterFlowThroughAllowed(p, pos.getKind()) } pragma[nomagic] predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap, Configuration config) { - exists(RetNodeEx ret, ReturnKindExt kind | - returnFlowsThrough(ret, kind, _, _, p, ap, _, config) and - parameterFlowsThroughRev(p, ap, kind, _, config) + exists(RetNodeEx ret, ReturnPosition pos | + returnFlowsThrough(ret, pos, _, _, p, ap, _, config) and + parameterFlowsThroughRev(p, ap, pos, _, config) ) } @@ -1933,20 +1911,21 @@ private module MkStage { predicate returnMayFlowThrough( RetNodeEx ret, Ap argAp, Ap ap, ReturnKindExt kind, Configuration config ) { - exists(ParamNodeEx p | - returnFlowsThrough(ret, kind, _, _, p, argAp, ap, config) and - parameterFlowsThroughRev(p, argAp, kind, ap, config) + exists(ParamNodeEx p, ReturnPosition pos | + returnFlowsThrough(ret, pos, _, _, p, argAp, ap, config) and + parameterFlowsThroughRev(p, argAp, pos, ap, config) and + kind = pos.getKind() ) } pragma[nomagic] - predicate revFlowInToReturnIsReturned( + private predicate revFlowThroughArg( DataFlowCall call, ArgNodeEx arg, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap, Configuration config ) { - exists(ReturnKindExt returnKind0, Ap returnAp0 | - revFlowInToReturn(call, arg, state, returnKind0, returnAp0, ap, config) and - revFlowIsReturned(call, returnCtx, returnAp, returnKind0, returnAp0, config) + exists(ParamNodeEx p, ReturnPosition pos, Ap innerReturnAp | + revFlowThrough(call, returnCtx, p, state, pos, returnAp, ap, innerReturnAp, config) and + flowThroughIntoCall(call, arg, p, _, ap, innerReturnAp, config) ) } @@ -1954,7 +1933,7 @@ private module MkStage { predicate callMayFlowThroughRev(DataFlowCall call, Configuration config) { exists(ArgNodeEx arg, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap | revFlow(arg, state, returnCtx, returnAp, ap, config) and - revFlowInToReturnIsReturned(call, arg, state, returnCtx, returnAp, ap, config) + revFlowThroughArg(call, arg, state, returnCtx, returnAp, ap, config) ) } @@ -1967,8 +1946,9 @@ private module MkStage { conscand = count(TypedContent f0, Ap ap | fwdConsCand(f0, ap, config)) and states = count(FlowState state | fwdFlow(_, state, _, _, _, _, config)) and tuples = - count(NodeEx n, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - Ap ap | fwdFlow(n, state, cc, summaryCtx, argAp, ap, config)) + count(NodeEx n, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap | + fwdFlow(n, state, cc, summaryCtx, argAp, ap, config) + ) or fwd = false and nodes = count(NodeEx node | revFlow(node, _, _, _, _, config)) and @@ -2823,13 +2803,12 @@ private Configuration unbindConf(Configuration conf) { pragma[nomagic] private predicate nodeMayUseSummary0( - NodeEx n, DataFlowCallable c, ParameterPosition pos, FlowState state, AccessPathApprox apa, - Configuration config + NodeEx n, ParamNodeEx p, FlowState state, AccessPathApprox apa, Configuration config ) { exists(AccessPathApprox apa0 | - c = n.getEnclosingCallable() and + Stage5::parameterMayFlowThrough(p, _, _) and Stage5::revFlow(n, state, TReturnCtxMaybeFlowThrough(_), _, apa0, config) and - Stage5::fwdFlow(n, state, any(CallContextCall ccc), TParameterPositionSome(pos), + Stage5::fwdFlow(n, state, any(CallContextCall ccc), TParamNodeSome(p.asNode()), TAccessPathApproxSome(apa), apa0, config) ) } @@ -2838,10 +2817,9 @@ pragma[nomagic] private predicate nodeMayUseSummary( NodeEx n, FlowState state, AccessPathApprox apa, Configuration config ) { - exists(DataFlowCallable c, ParameterPosition pos, ParamNodeEx p | + exists(ParamNodeEx p | Stage5::parameterMayFlowThrough(p, apa, config) and - nodeMayUseSummary0(n, c, pos, state, apa, config) and - p.isParameterOf(c, pos) + nodeMayUseSummary0(n, p, state, apa, config) ) } diff --git a/go/ql/lib/semmle/go/dataflow/internal/DataFlowImpl2.qll b/go/ql/lib/semmle/go/dataflow/internal/DataFlowImpl2.qll index 6741ccc2f06..1228d00b6ba 100644 --- a/go/ql/lib/semmle/go/dataflow/internal/DataFlowImpl2.qll +++ b/go/ql/lib/semmle/go/dataflow/internal/DataFlowImpl2.qll @@ -622,7 +622,11 @@ private predicate parameterFlowThroughAllowed(ParamNodeEx p, ReturnKindExt kind) } private module Stage1 implements StageSig { - class Ap = Unit; + class Ap extends int { + // workaround for bad functionality-induced joins (happens when using `Unit`) + pragma[nomagic] + Ap() { this in [0 .. 1] and this < 1 } + } private class Cc = boolean; @@ -1327,8 +1331,8 @@ private module MkStage { */ pragma[nomagic] additional predicate fwdFlow( - NodeEx node, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - Ap ap, ApApprox apa, Configuration config + NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, + ApApprox apa, Configuration config ) { fwdFlow0(node, state, cc, summaryCtx, argAp, ap, apa, config) and PrevStage::revFlow(node, state, apa, config) and @@ -1337,21 +1341,21 @@ private module MkStage { pragma[inline] additional predicate fwdFlow( - NodeEx node, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - Ap ap, Configuration config + NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, + Configuration config ) { fwdFlow(node, state, cc, summaryCtx, argAp, ap, _, config) } pragma[nomagic] private predicate fwdFlow0( - NodeEx node, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - Ap ap, ApApprox apa, Configuration config + NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, + ApApprox apa, Configuration config ) { sourceNode(node, state, config) and (if hasSourceCallCtx(config) then cc = ccSomeCall() else cc = ccNone()) and argAp = apNone() and - summaryCtx = TParameterPositionNone() and + summaryCtx = TParamNodeNone() and ap = getApNil(node) and apa = getApprox(ap) or @@ -1372,7 +1376,7 @@ private module MkStage { fwdFlow(mid, pragma[only_bind_into](state), _, _, _, ap, apa, pragma[only_bind_into](config)) and jumpStep(mid, node, config) and cc = ccNone() and - summaryCtx = TParameterPositionNone() and + summaryCtx = TParamNodeNone() and argAp = apNone() ) or @@ -1380,7 +1384,7 @@ private module MkStage { fwdFlow(mid, state, _, _, _, nil, pragma[only_bind_into](config)) and additionalJumpStep(mid, node, config) and cc = ccNone() and - summaryCtx = TParameterPositionNone() and + summaryCtx = TParamNodeNone() and argAp = apNone() and ap = getApNil(node) and apa = getApprox(ap) @@ -1390,7 +1394,7 @@ private module MkStage { fwdFlow(mid, state0, _, _, _, nil, pragma[only_bind_into](config)) and additionalJumpStateStep(mid, state0, node, state, config) and cc = ccNone() and - summaryCtx = TParameterPositionNone() and + summaryCtx = TParamNodeNone() and argAp = apNone() and ap = getApNil(node) and apa = getApprox(ap) @@ -1414,10 +1418,10 @@ private module MkStage { fwdFlowIn(_, node, state, _, cc, _, _, ap, apa, config) and if PrevStage::parameterMayFlowThrough(node, apa, config) then ( - summaryCtx = TParameterPositionSome(node.(ParamNodeEx).getPosition()) and + summaryCtx = TParamNodeSome(node.asNode()) and argAp = apSome(ap) ) else ( - summaryCtx = TParameterPositionNone() and argAp = apNone() + summaryCtx = TParamNodeNone() and argAp = apNone() ) or // flow out of a callable @@ -1433,16 +1437,19 @@ private module MkStage { ) or // flow through a callable - exists(DataFlowCall call, ParameterPosition summaryCtx0, Ap argAp0 | - fwdFlowOutFromArg(call, node, state, summaryCtx0, argAp0, ap, apa, config) and - fwdFlowIsEntered(call, cc, summaryCtx, argAp, summaryCtx0, argAp0, config) + exists( + DataFlowCall call, CcCall ccc, RetNodeEx ret, boolean allowsFieldFlow, ApApprox innerArgApa + | + fwdFlowThrough(call, cc, state, ccc, summaryCtx, argAp, ap, apa, ret, innerArgApa, config) and + flowThroughOutOfCall(call, ccc, ret, node, allowsFieldFlow, innerArgApa, apa, config) and + if allowsFieldFlow = false then ap instanceof ApNil else any() ) } pragma[nomagic] private predicate fwdFlowStore( NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, FlowState state, Cc cc, - ParameterPositionOption summaryCtx, ApOption argAp, Configuration config + ParamNodeOption summaryCtx, ApOption argAp, Configuration config ) { exists(DataFlowType contentType, ApApprox apa1 | fwdFlow(node1, state, cc, summaryCtx, argAp, ap1, apa1, config) and @@ -1473,8 +1480,8 @@ private module MkStage { pragma[nomagic] private predicate fwdFlowRead0( - NodeEx node1, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - ApNonNil ap, Configuration config + NodeEx node1, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, ApNonNil ap, + Configuration config ) { fwdFlow(node1, state, cc, summaryCtx, argAp, ap, config) and PrevStage::readStepCand(node1, _, _, config) @@ -1483,7 +1490,7 @@ private module MkStage { pragma[nomagic] private predicate fwdFlowRead( Ap ap, Content c, NodeEx node1, NodeEx node2, FlowState state, Cc cc, - ParameterPositionOption summaryCtx, ApOption argAp, Configuration config + ParamNodeOption summaryCtx, ApOption argAp, Configuration config ) { fwdFlowRead0(node1, state, cc, summaryCtx, argAp, ap, config) and PrevStage::readStepCand(node1, c, node2, config) and @@ -1493,7 +1500,7 @@ private module MkStage { pragma[nomagic] private predicate fwdFlowIn( DataFlowCall call, ParamNodeEx p, FlowState state, Cc outercc, CcCall innercc, - ParameterPositionOption summaryCtx, ApOption argAp, Ap ap, ApApprox apa, Configuration config + ParamNodeOption summaryCtx, ApOption argAp, Ap ap, ApApprox apa, Configuration config ) { exists(ArgNodeEx arg, boolean allowsFieldFlow | fwdFlow(arg, state, outercc, summaryCtx, argAp, ap, apa, config) and @@ -1505,64 +1512,38 @@ private module MkStage { pragma[nomagic] private predicate fwdFlowRetFromArg( - RetNodeEx ret, FlowState state, CcCall ccc, ParameterPosition summaryCtx, ParamNodeEx p, - Ap argAp, ApApprox argApa, Ap ap, ApApprox apa, Configuration config + RetNodeEx ret, FlowState state, CcCall ccc, ParamNodeEx summaryCtx, Ap argAp, ApApprox argApa, + Ap ap, ApApprox apa, Configuration config ) { - exists(DataFlowCallable c, ReturnKindExt kind | + exists(ReturnKindExt kind | fwdFlow(pragma[only_bind_into](ret), state, ccc, - TParameterPositionSome(pragma[only_bind_into](summaryCtx)), apSome(argAp), ap, apa, config) and - getApprox(argAp) = argApa and - c = ret.getEnclosingCallable() and + TParamNodeSome(pragma[only_bind_into](summaryCtx.asNode())), + pragma[only_bind_into](apSome(argAp)), ap, pragma[only_bind_into](apa), + pragma[only_bind_into](config)) and kind = ret.getKind() and - p.isParameterOf(c, pragma[only_bind_into](summaryCtx)) and - parameterFlowThroughAllowed(p, kind) + parameterFlowThroughAllowed(summaryCtx, kind) and + argApa = getApprox(argAp) and + PrevStage::returnMayFlowThrough(ret, argApa, apa, kind, pragma[only_bind_into](config)) ) } pragma[inline] - private predicate fwdFlowInMayFlowThrough( - DataFlowCall call, Cc cc, CcCall innerCc, ParameterPositionOption summaryCtx, ApOption argAp, - ParamNodeEx param, Ap ap, ApApprox apa, Configuration config + private predicate fwdFlowThrough0( + DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, + ApOption argAp, Ap ap, ApApprox apa, RetNodeEx ret, ParamNodeEx innerSummaryCtx, + Ap innerArgAp, ApApprox innerArgApa, Configuration config ) { - fwdFlowIn(call, pragma[only_bind_into](param), _, cc, innerCc, summaryCtx, argAp, ap, - pragma[only_bind_into](apa), pragma[only_bind_into](config)) and - PrevStage::parameterMayFlowThrough(param, apa, config) - } - - // dedup before joining with `flowThroughOutOfCall` - pragma[nomagic] - private predicate fwdFlowInMayFlowThroughProj( - DataFlowCall call, CcCall innerCc, ApApprox apa, Configuration config - ) { - fwdFlowInMayFlowThrough(call, _, innerCc, _, _, _, _, apa, config) - } - - /** - * Same as `flowThroughOutOfCall`, but restricted to calls that are reached - * in the flow covered by `fwdFlow`, where data might flow through the target - * callable and back out at `call`. - */ - pragma[nomagic] - private predicate fwdFlowThroughOutOfCall( - DataFlowCall call, CcCall ccc, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow, - ApApprox argApa, ApApprox apa, Configuration config - ) { - fwdFlowInMayFlowThroughProj(call, ccc, argApa, config) and - flowThroughOutOfCall(call, ccc, ret, out, allowsFieldFlow, argApa, apa, config) + fwdFlowRetFromArg(ret, state, ccc, innerSummaryCtx, innerArgAp, innerArgApa, ap, apa, config) and + fwdFlowIsEntered(call, cc, ccc, summaryCtx, argAp, innerSummaryCtx, innerArgAp, config) } pragma[nomagic] - private predicate fwdFlowOutFromArg( - DataFlowCall call, NodeEx out, FlowState state, ParameterPosition summaryCtx, Ap argAp, Ap ap, - ApApprox apa, Configuration config + private predicate fwdFlowThrough( + DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, + ApOption argAp, Ap ap, ApApprox apa, RetNodeEx ret, ApApprox innerArgApa, Configuration config ) { - exists(RetNodeEx ret, boolean allowsFieldFlow, CcCall ccc, ApApprox argApa | - fwdFlowRetFromArg(pragma[only_bind_into](ret), state, pragma[only_bind_into](ccc), - summaryCtx, _, argAp, pragma[only_bind_into](argApa), ap, pragma[only_bind_into](apa), - config) and - fwdFlowThroughOutOfCall(call, ccc, ret, out, allowsFieldFlow, argApa, apa, config) and - (if allowsFieldFlow = false then ap instanceof ApNil else any()) - ) + fwdFlowThrough0(call, cc, state, ccc, summaryCtx, argAp, ap, apa, ret, _, _, innerArgApa, + config) } /** @@ -1571,12 +1552,14 @@ private module MkStage { */ pragma[nomagic] private predicate fwdFlowIsEntered( - DataFlowCall call, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - ParameterPosition pos, Ap ap, Configuration config + DataFlowCall call, Cc cc, CcCall innerCc, ParamNodeOption summaryCtx, ApOption argAp, + ParamNodeEx p, Ap ap, Configuration config ) { - exists(ParamNodeEx param | - fwdFlowInMayFlowThrough(call, cc, _, summaryCtx, argAp, param, ap, _, config) and - pos = param.getPosition() + exists(ApApprox apa | + fwdFlowIn(call, pragma[only_bind_into](p), _, cc, innerCc, summaryCtx, argAp, ap, + pragma[only_bind_into](apa), pragma[only_bind_into](config)) and + PrevStage::parameterMayFlowThrough(p, apa, config) and + PrevStage::callMayFlowThroughRev(call, pragma[only_bind_into](config)) ) } @@ -1596,23 +1579,31 @@ private module MkStage { fwdFlowConsCand(ap1, c, ap2, config) } + pragma[nomagic] + private predicate returnFlowsThrough0( + DataFlowCall call, FlowState state, CcCall ccc, Ap ap, ApApprox apa, RetNodeEx ret, + ParamNodeEx innerSummaryCtx, Ap innerArgAp, ApApprox innerArgApa, Configuration config + ) { + fwdFlowThrough0(call, _, state, ccc, _, _, ap, apa, ret, innerSummaryCtx, innerArgAp, + innerArgApa, config) + } + pragma[nomagic] private predicate returnFlowsThrough( - RetNodeEx ret, ReturnKindExt kind, FlowState state, CcCall ccc, ParamNodeEx p, Ap argAp, + RetNodeEx ret, ReturnPosition pos, FlowState state, CcCall ccc, ParamNodeEx p, Ap argAp, Ap ap, Configuration config ) { - exists(boolean allowsFieldFlow, ApApprox argApa, ApApprox apa | - fwdFlowRetFromArg(pragma[only_bind_into](ret), state, pragma[only_bind_into](ccc), _, p, - argAp, pragma[only_bind_into](argApa), ap, pragma[only_bind_into](apa), config) and - kind = ret.getKind() and - fwdFlowThroughOutOfCall(_, ccc, ret, _, allowsFieldFlow, argApa, apa, config) and - (if allowsFieldFlow = false then ap instanceof ApNil else any()) + exists(DataFlowCall call, ApApprox apa, boolean allowsFieldFlow, ApApprox innerArgApa | + returnFlowsThrough0(call, state, ccc, ap, apa, ret, p, argAp, innerArgApa, config) and + flowThroughOutOfCall(call, ccc, ret, _, allowsFieldFlow, innerArgApa, apa, config) and + pos = ret.getReturnPosition() and + if allowsFieldFlow = false then ap instanceof ApNil else any() ) } pragma[nomagic] private predicate flowThroughIntoCall( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap argAp, + DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap argAp, Ap ap, Configuration config ) { exists(ApApprox argApa | @@ -1620,7 +1611,7 @@ private module MkStage { allowsFieldFlow, argApa, pragma[only_bind_into](config)) and fwdFlow(arg, _, _, _, _, pragma[only_bind_into](argAp), argApa, pragma[only_bind_into](config)) and - returnFlowsThrough(_, _, _, _, p, pragma[only_bind_into](argAp), _, + returnFlowsThrough(_, _, _, _, p, pragma[only_bind_into](argAp), ap, pragma[only_bind_into](config)) and if allowsFieldFlow = false then argAp instanceof ApNil else any() ) @@ -1639,12 +1630,13 @@ private module MkStage { pragma[nomagic] private predicate flowOutOfCallAp( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, boolean allowsFieldFlow, + DataFlowCall call, RetNodeEx ret, ReturnPosition pos, NodeEx out, boolean allowsFieldFlow, Ap ap, Configuration config ) { exists(ApApprox apa | - flowOutOfCallApa(call, ret, kind, out, allowsFieldFlow, apa, config) and - fwdFlow(ret, _, _, _, _, ap, apa, config) + flowOutOfCallApa(call, ret, _, out, allowsFieldFlow, apa, config) and + fwdFlow(ret, _, _, _, _, ap, apa, config) and + pos = ret.getReturnPosition() ) } @@ -1739,17 +1731,17 @@ private module MkStage { ) or // flow through a callable - exists(DataFlowCall call, ReturnKindExt returnKind0, Ap returnAp0 | - revFlowInToReturn(call, node, state, returnKind0, returnAp0, ap, config) and - revFlowIsReturned(call, returnCtx, returnAp, returnKind0, returnAp0, config) + exists(DataFlowCall call, ParamNodeEx p, ReturnPosition pos, Ap innerReturnAp | + revFlowThrough(call, returnCtx, p, state, pos, returnAp, ap, innerReturnAp, config) and + flowThroughIntoCall(call, node, p, _, ap, innerReturnAp, config) ) or // flow out of a callable - exists(ReturnKindExt kind | - revFlowOut(_, node, kind, state, _, _, ap, config) and - if returnFlowsThrough(node, kind, state, _, _, _, ap, config) + exists(ReturnPosition pos | + revFlowOut(_, node, pos, state, _, _, ap, config) and + if returnFlowsThrough(node, pos, state, _, _, _, ap, config) then ( - returnCtx = TReturnCtxMaybeFlowThrough(kind) and + returnCtx = TReturnCtxMaybeFlowThrough(pos) and returnAp = apSome(ap) ) else ( returnCtx = TReturnCtxNoFlowThrough() and returnAp = apNone() @@ -1782,47 +1774,33 @@ private module MkStage { pragma[nomagic] private predicate revFlowOut( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, FlowState state, ReturnCtx returnCtx, + DataFlowCall call, RetNodeEx ret, ReturnPosition pos, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap, Configuration config ) { exists(NodeEx out, boolean allowsFieldFlow | revFlow(out, state, returnCtx, returnAp, ap, config) and - flowOutOfCallAp(call, ret, kind, out, allowsFieldFlow, ap, config) and + flowOutOfCallAp(call, ret, pos, out, allowsFieldFlow, ap, config) and if allowsFieldFlow = false then ap instanceof ApNil else any() ) } - /** - * Same as `flowThroughIntoCall`, but restricted to calls that are reached - * in the flow covered by `revFlow`, where data might flow through the target - * callable and back out at `call`. - */ - pragma[nomagic] - private predicate revFlowThroughIntoCall( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap argAp, - Configuration config - ) { - flowThroughIntoCall(call, arg, p, allowsFieldFlow, argAp, config) and - revFlowIsReturned(call, _, _, _, _, config) - } - pragma[nomagic] private predicate revFlowParamToReturn( - ParamNodeEx p, FlowState state, ReturnKindExt kind, Ap returnAp, Ap ap, Configuration config + ParamNodeEx p, FlowState state, ReturnPosition pos, Ap returnAp, Ap ap, Configuration config ) { - revFlow(p, state, TReturnCtxMaybeFlowThrough(kind), apSome(returnAp), ap, config) and - parameterFlowThroughAllowed(p, kind) + revFlow(pragma[only_bind_into](p), state, TReturnCtxMaybeFlowThrough(pos), apSome(returnAp), + pragma[only_bind_into](ap), pragma[only_bind_into](config)) and + parameterFlowThroughAllowed(p, pos.getKind()) and + PrevStage::parameterMayFlowThrough(p, getApprox(ap), config) } pragma[nomagic] - private predicate revFlowInToReturn( - DataFlowCall call, ArgNodeEx arg, FlowState state, ReturnKindExt kind, Ap returnAp, Ap ap, - Configuration config + private predicate revFlowThrough( + DataFlowCall call, ReturnCtx returnCtx, ParamNodeEx p, FlowState state, ReturnPosition pos, + ApOption returnAp, Ap ap, Ap innerReturnAp, Configuration config ) { - exists(ParamNodeEx p, boolean allowsFieldFlow | - revFlowParamToReturn(p, state, kind, returnAp, ap, config) and - revFlowThroughIntoCall(call, arg, p, allowsFieldFlow, ap, config) - ) + revFlowParamToReturn(p, state, pos, innerReturnAp, ap, config) and + revFlowIsReturned(call, returnCtx, returnAp, pos, innerReturnAp, config) } /** @@ -1832,12 +1810,12 @@ private module MkStage { */ pragma[nomagic] private predicate revFlowIsReturned( - DataFlowCall call, ReturnCtx returnCtx, ApOption returnAp, ReturnKindExt kind, Ap ap, + DataFlowCall call, ReturnCtx returnCtx, ApOption returnAp, ReturnPosition pos, Ap ap, Configuration config ) { exists(RetNodeEx ret, FlowState state, CcCall ccc | - revFlowOut(call, ret, kind, state, returnCtx, returnAp, ap, config) and - returnFlowsThrough(ret, kind, state, ccc, _, _, ap, config) and + revFlowOut(call, ret, pos, state, returnCtx, returnAp, ap, config) and + returnFlowsThrough(ret, pos, state, ccc, _, _, ap, config) and matchesCall(ccc, call) ) } @@ -1915,17 +1893,17 @@ private module MkStage { pragma[nomagic] private predicate parameterFlowsThroughRev( - ParamNodeEx p, Ap ap, ReturnKindExt kind, Ap returnAp, Configuration config + ParamNodeEx p, Ap ap, ReturnPosition pos, Ap returnAp, Configuration config ) { - revFlow(p, _, TReturnCtxMaybeFlowThrough(kind), apSome(returnAp), ap, config) and - parameterFlowThroughAllowed(p, kind) + revFlow(p, _, TReturnCtxMaybeFlowThrough(pos), apSome(returnAp), ap, config) and + parameterFlowThroughAllowed(p, pos.getKind()) } pragma[nomagic] predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap, Configuration config) { - exists(RetNodeEx ret, ReturnKindExt kind | - returnFlowsThrough(ret, kind, _, _, p, ap, _, config) and - parameterFlowsThroughRev(p, ap, kind, _, config) + exists(RetNodeEx ret, ReturnPosition pos | + returnFlowsThrough(ret, pos, _, _, p, ap, _, config) and + parameterFlowsThroughRev(p, ap, pos, _, config) ) } @@ -1933,20 +1911,21 @@ private module MkStage { predicate returnMayFlowThrough( RetNodeEx ret, Ap argAp, Ap ap, ReturnKindExt kind, Configuration config ) { - exists(ParamNodeEx p | - returnFlowsThrough(ret, kind, _, _, p, argAp, ap, config) and - parameterFlowsThroughRev(p, argAp, kind, ap, config) + exists(ParamNodeEx p, ReturnPosition pos | + returnFlowsThrough(ret, pos, _, _, p, argAp, ap, config) and + parameterFlowsThroughRev(p, argAp, pos, ap, config) and + kind = pos.getKind() ) } pragma[nomagic] - predicate revFlowInToReturnIsReturned( + private predicate revFlowThroughArg( DataFlowCall call, ArgNodeEx arg, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap, Configuration config ) { - exists(ReturnKindExt returnKind0, Ap returnAp0 | - revFlowInToReturn(call, arg, state, returnKind0, returnAp0, ap, config) and - revFlowIsReturned(call, returnCtx, returnAp, returnKind0, returnAp0, config) + exists(ParamNodeEx p, ReturnPosition pos, Ap innerReturnAp | + revFlowThrough(call, returnCtx, p, state, pos, returnAp, ap, innerReturnAp, config) and + flowThroughIntoCall(call, arg, p, _, ap, innerReturnAp, config) ) } @@ -1954,7 +1933,7 @@ private module MkStage { predicate callMayFlowThroughRev(DataFlowCall call, Configuration config) { exists(ArgNodeEx arg, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap | revFlow(arg, state, returnCtx, returnAp, ap, config) and - revFlowInToReturnIsReturned(call, arg, state, returnCtx, returnAp, ap, config) + revFlowThroughArg(call, arg, state, returnCtx, returnAp, ap, config) ) } @@ -1967,8 +1946,9 @@ private module MkStage { conscand = count(TypedContent f0, Ap ap | fwdConsCand(f0, ap, config)) and states = count(FlowState state | fwdFlow(_, state, _, _, _, _, config)) and tuples = - count(NodeEx n, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - Ap ap | fwdFlow(n, state, cc, summaryCtx, argAp, ap, config)) + count(NodeEx n, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap | + fwdFlow(n, state, cc, summaryCtx, argAp, ap, config) + ) or fwd = false and nodes = count(NodeEx node | revFlow(node, _, _, _, _, config)) and @@ -2823,13 +2803,12 @@ private Configuration unbindConf(Configuration conf) { pragma[nomagic] private predicate nodeMayUseSummary0( - NodeEx n, DataFlowCallable c, ParameterPosition pos, FlowState state, AccessPathApprox apa, - Configuration config + NodeEx n, ParamNodeEx p, FlowState state, AccessPathApprox apa, Configuration config ) { exists(AccessPathApprox apa0 | - c = n.getEnclosingCallable() and + Stage5::parameterMayFlowThrough(p, _, _) and Stage5::revFlow(n, state, TReturnCtxMaybeFlowThrough(_), _, apa0, config) and - Stage5::fwdFlow(n, state, any(CallContextCall ccc), TParameterPositionSome(pos), + Stage5::fwdFlow(n, state, any(CallContextCall ccc), TParamNodeSome(p.asNode()), TAccessPathApproxSome(apa), apa0, config) ) } @@ -2838,10 +2817,9 @@ pragma[nomagic] private predicate nodeMayUseSummary( NodeEx n, FlowState state, AccessPathApprox apa, Configuration config ) { - exists(DataFlowCallable c, ParameterPosition pos, ParamNodeEx p | + exists(ParamNodeEx p | Stage5::parameterMayFlowThrough(p, apa, config) and - nodeMayUseSummary0(n, c, pos, state, apa, config) and - p.isParameterOf(c, pos) + nodeMayUseSummary0(n, p, state, apa, config) ) } diff --git a/go/ql/lib/semmle/go/dataflow/internal/DataFlowImplCommon.qll b/go/ql/lib/semmle/go/dataflow/internal/DataFlowImplCommon.qll index c66aefced8d..9aa6a529a5b 100644 --- a/go/ql/lib/semmle/go/dataflow/internal/DataFlowImplCommon.qll +++ b/go/ql/lib/semmle/go/dataflow/internal/DataFlowImplCommon.qll @@ -916,15 +916,15 @@ private module Cached { TDataFlowCallSome(DataFlowCall call) cached - newtype TParameterPositionOption = - TParameterPositionNone() or - TParameterPositionSome(ParameterPosition pos) + newtype TParamNodeOption = + TParamNodeNone() or + TParamNodeSome(ParamNode p) cached newtype TReturnCtx = TReturnCtxNone() or TReturnCtxNoFlowThrough() or - TReturnCtxMaybeFlowThrough(ReturnKindExt kind) + TReturnCtxMaybeFlowThrough(ReturnPosition pos) cached newtype TTypedContentApprox = @@ -1343,15 +1343,15 @@ class DataFlowCallOption extends TDataFlowCallOption { } } -/** An optional `ParameterPosition`. */ -class ParameterPositionOption extends TParameterPositionOption { +/** An optional `ParamNode`. */ +class ParamNodeOption extends TParamNodeOption { string toString() { - this = TParameterPositionNone() and + this = TParamNodeNone() and result = "(none)" or - exists(ParameterPosition pos | - this = TParameterPositionSome(pos) and - result = pos.toString() + exists(ParamNode p | + this = TParamNodeSome(p) and + result = p.toString() ) } } @@ -1363,7 +1363,7 @@ class ParameterPositionOption extends TParameterPositionOption { * * - `TReturnCtxNone()`: no return flow. * - `TReturnCtxNoFlowThrough()`: return flow, but flow through is not possible. - * - `TReturnCtxMaybeFlowThrough(ReturnKindExt kind)`: return flow, of kind `kind`, and + * - `TReturnCtxMaybeFlowThrough(ReturnPosition pos)`: return flow, of kind `pos`, and * flow through may be possible. */ class ReturnCtx extends TReturnCtx { @@ -1374,9 +1374,9 @@ class ReturnCtx extends TReturnCtx { this = TReturnCtxNoFlowThrough() and result = "(no flow through)" or - exists(ReturnKindExt kind | - this = TReturnCtxMaybeFlowThrough(kind) and - result = kind.toString() + exists(ReturnPosition pos | + this = TReturnCtxMaybeFlowThrough(pos) and + result = pos.toString() ) } } diff --git a/go/ql/lib/semmle/go/dataflow/internal/DataFlowPrivate.qll b/go/ql/lib/semmle/go/dataflow/internal/DataFlowPrivate.qll index 980052915d3..b65fb3d7d5d 100644 --- a/go/ql/lib/semmle/go/dataflow/internal/DataFlowPrivate.qll +++ b/go/ql/lib/semmle/go/dataflow/internal/DataFlowPrivate.qll @@ -199,21 +199,17 @@ predicate expectsContent(Node n, ContentSet c) { } /** Gets the type of `n` used for type pruning. */ -DataFlowType getNodeType(Node n) { - result = n.getType() - or - result = FlowSummaryImpl::Private::summaryNodeType(n) -} +DataFlowType getNodeType(Node n) { result = TTodoDataFlowType() and exists(n) } /** Gets a string representation of a type returned by `getNodeType()`. */ -string ppReprType(Type t) { result = t.toString() } +string ppReprType(DataFlowType t) { none() } /** * 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`. */ pragma[inline] -predicate compatibleTypes(Type t1, Type t2) { +predicate compatibleTypes(DataFlowType t1, DataFlowType t2) { any() // stub implementation } @@ -227,7 +223,14 @@ class CastNode extends ExprNode { class DataFlowExpr = Expr; -class DataFlowType = Type; +private newtype TDataFlowType = + TTodoDataFlowType() or + TTodoDataFlowType2() // Add a dummy value to prevent bad functionality-induced joins arising from a type of size 1. + +class DataFlowType extends TDataFlowType { + /** Gets a textual representation of this element. */ + string toString() { result = "" } +} class DataFlowLocation = Location; diff --git a/go/ql/lib/semmle/go/dataflow/internal/DataFlowUtil.qll b/go/ql/lib/semmle/go/dataflow/internal/DataFlowUtil.qll index b38c3c291bd..a604f1b875b 100644 --- a/go/ql/lib/semmle/go/dataflow/internal/DataFlowUtil.qll +++ b/go/ql/lib/semmle/go/dataflow/internal/DataFlowUtil.qll @@ -149,7 +149,7 @@ private newtype TContent = */ class Content extends TContent { /** Gets the type of the contained data for the purpose of type pruning. */ - DataFlowType getType() { result instanceof EmptyInterfaceType } + DataFlowType getType() { any() } /** Gets a textual representation of this element. */ abstract string toString(); @@ -177,7 +177,7 @@ class FieldContent extends Content, TFieldContent { /** Gets the field associated with this `FieldContent`. */ Field getField() { result = f } - override DataFlowType getType() { result = f.getType() } + override DataFlowType getType() { any() } override string toString() { result = f.toString() } @@ -205,7 +205,7 @@ class PointerContent extends Content, TPointerContent { /** Gets the pointer type that containers with this content must have. */ PointerType getPointerType() { result = t } - override DataFlowType getType() { result = t.getBaseType() } + override DataFlowType getType() { any() } override string toString() { result = "pointer" } } @@ -228,7 +228,7 @@ class SyntheticFieldContent extends Content, TSyntheticFieldContent { /** Gets the field associated with this `SyntheticFieldContent`. */ SyntheticField getField() { result = s } - override DataFlowType getType() { result = s.getType() } + override DataFlowType getType() { any() } override string toString() { result = s.toString() } } diff --git a/go/ql/lib/semmle/go/dataflow/internal/FlowSummaryImpl.qll b/go/ql/lib/semmle/go/dataflow/internal/FlowSummaryImpl.qll index 61c541d8882..b61142c33a7 100644 --- a/go/ql/lib/semmle/go/dataflow/internal/FlowSummaryImpl.qll +++ b/go/ql/lib/semmle/go/dataflow/internal/FlowSummaryImpl.qll @@ -241,9 +241,15 @@ module Public { } /** - * Holds if the summary is auto generated. + * Holds if the summary is auto generated and not manually generated. */ predicate isAutoGenerated() { none() } + + /** + * Holds if the summary has the given provenance where `true` is + * `generated` and `false` is `manual`. + */ + predicate hasProvenance(boolean generated) { none() } } /** A callable where there is no flow via the callable. */ @@ -1012,6 +1018,10 @@ module Private { } override predicate isAutoGenerated() { this.relevantSummaryElementGenerated(_, _, _) } + + override predicate hasProvenance(boolean generated) { + summaryElement(this, _, _, _, generated) + } } /** Holds if component `c` of specification `spec` cannot be parsed. */ diff --git a/go/ql/lib/semmle/go/dataflow/internal/FlowSummaryImplSpecific.qll b/go/ql/lib/semmle/go/dataflow/internal/FlowSummaryImplSpecific.qll index 0797cd7a979..fd82938968a 100644 --- a/go/ql/lib/semmle/go/dataflow/internal/FlowSummaryImplSpecific.qll +++ b/go/ql/lib/semmle/go/dataflow/internal/FlowSummaryImplSpecific.qll @@ -40,24 +40,23 @@ DataFlowCall summaryDataFlowCall(Node receiver) { DataFlowType getContentType(Content c) { result = c.getType() } /** Gets the return type of kind `rk` for callable `c`. */ -DataFlowType getReturnType(SummarizedCallable c, ReturnKind rk) { - result = c.getType().getResultType(rk.getIndex()) -} +DataFlowType getReturnType(SummarizedCallable c, ReturnKind rk) { any() } /** * Gets the type of the `i`th parameter in a synthesized call that targets a * callback of type `t`. */ -DataFlowType getCallbackParameterType(DataFlowType t, int i) { none() } +bindingset[t, pos] +DataFlowType getCallbackParameterType(DataFlowType t, ArgumentPosition pos) { any() } /** * Gets the return type of kind `rk` in a synthesized call that targets a * callback of type `t`. */ -DataFlowType getCallbackReturnType(DataFlowType t, ReturnKind rk) { none() } +DataFlowType getCallbackReturnType(DataFlowType t, ReturnKind rk) { any() } /** Gets the type of synthetic global `sg`. */ -DataFlowType getSyntheticGlobalType(SummaryComponent::SyntheticGlobal sg) { none() } +DataFlowType getSyntheticGlobalType(SummaryComponent::SyntheticGlobal sg) { any() } /** * Holds if an external flow summary exists for `c` with input specification diff --git a/go/ql/test/experimental/CWE-090/LDAPInjection.expected b/go/ql/test/experimental/CWE-090/LDAPInjection.expected index 6395227df6e..8e1165fab60 100644 --- a/go/ql/test/experimental/CWE-090/LDAPInjection.expected +++ b/go/ql/test/experimental/CWE-090/LDAPInjection.expected @@ -1,53 +1,53 @@ edges -| LDAPInjection.go:57:15:57:29 | call to UserAgent : string | LDAPInjection.go:59:3:59:11 | untrusted | -| LDAPInjection.go:57:15:57:29 | call to UserAgent : string | LDAPInjection.go:61:3:61:51 | ...+... | -| LDAPInjection.go:57:15:57:29 | call to UserAgent : string | LDAPInjection.go:62:3:62:33 | slice literal | -| LDAPInjection.go:57:15:57:29 | call to UserAgent : string | LDAPInjection.go:62:24:62:32 | untrusted : string | -| LDAPInjection.go:57:15:57:29 | call to UserAgent : string | LDAPInjection.go:66:3:66:11 | untrusted | -| LDAPInjection.go:57:15:57:29 | call to UserAgent : string | LDAPInjection.go:68:3:68:51 | ...+... | -| LDAPInjection.go:57:15:57:29 | call to UserAgent : string | LDAPInjection.go:69:3:69:33 | slice literal | -| LDAPInjection.go:57:15:57:29 | call to UserAgent : string | LDAPInjection.go:69:24:69:32 | untrusted : string | -| LDAPInjection.go:57:15:57:29 | call to UserAgent : string | LDAPInjection.go:73:3:73:11 | untrusted | -| LDAPInjection.go:57:15:57:29 | call to UserAgent : string | LDAPInjection.go:75:3:75:51 | ...+... | -| LDAPInjection.go:57:15:57:29 | call to UserAgent : string | LDAPInjection.go:76:3:76:33 | slice literal | -| LDAPInjection.go:57:15:57:29 | call to UserAgent : string | LDAPInjection.go:76:24:76:32 | untrusted : string | -| LDAPInjection.go:57:15:57:29 | call to UserAgent : string | LDAPInjection.go:80:22:80:30 | untrusted | -| LDAPInjection.go:57:15:57:29 | call to UserAgent : string | LDAPInjection.go:81:25:81:33 | untrusted | -| LDAPInjection.go:62:3:62:33 | slice literal [array] : string | LDAPInjection.go:62:3:62:33 | slice literal | -| LDAPInjection.go:62:24:62:32 | untrusted : string | LDAPInjection.go:62:3:62:33 | slice literal [array] : string | -| LDAPInjection.go:69:3:69:33 | slice literal [array] : string | LDAPInjection.go:69:3:69:33 | slice literal | -| LDAPInjection.go:69:24:69:32 | untrusted : string | LDAPInjection.go:69:3:69:33 | slice literal [array] : string | -| LDAPInjection.go:76:3:76:33 | slice literal [array] : string | LDAPInjection.go:76:3:76:33 | slice literal | -| LDAPInjection.go:76:24:76:32 | untrusted : string | LDAPInjection.go:76:3:76:33 | slice literal [array] : string | +| LDAPInjection.go:57:15:57:29 | call to UserAgent | LDAPInjection.go:59:3:59:11 | untrusted | +| LDAPInjection.go:57:15:57:29 | call to UserAgent | LDAPInjection.go:61:3:61:51 | ...+... | +| LDAPInjection.go:57:15:57:29 | call to UserAgent | LDAPInjection.go:62:3:62:33 | slice literal | +| LDAPInjection.go:57:15:57:29 | call to UserAgent | LDAPInjection.go:62:24:62:32 | untrusted | +| LDAPInjection.go:57:15:57:29 | call to UserAgent | LDAPInjection.go:66:3:66:11 | untrusted | +| LDAPInjection.go:57:15:57:29 | call to UserAgent | LDAPInjection.go:68:3:68:51 | ...+... | +| LDAPInjection.go:57:15:57:29 | call to UserAgent | LDAPInjection.go:69:3:69:33 | slice literal | +| LDAPInjection.go:57:15:57:29 | call to UserAgent | LDAPInjection.go:69:24:69:32 | untrusted | +| LDAPInjection.go:57:15:57:29 | call to UserAgent | LDAPInjection.go:73:3:73:11 | untrusted | +| LDAPInjection.go:57:15:57:29 | call to UserAgent | LDAPInjection.go:75:3:75:51 | ...+... | +| LDAPInjection.go:57:15:57:29 | call to UserAgent | LDAPInjection.go:76:3:76:33 | slice literal | +| LDAPInjection.go:57:15:57:29 | call to UserAgent | LDAPInjection.go:76:24:76:32 | untrusted | +| LDAPInjection.go:57:15:57:29 | call to UserAgent | LDAPInjection.go:80:22:80:30 | untrusted | +| LDAPInjection.go:57:15:57:29 | call to UserAgent | LDAPInjection.go:81:25:81:33 | untrusted | +| LDAPInjection.go:62:3:62:33 | slice literal [array] | LDAPInjection.go:62:3:62:33 | slice literal | +| LDAPInjection.go:62:24:62:32 | untrusted | LDAPInjection.go:62:3:62:33 | slice literal [array] | +| LDAPInjection.go:69:3:69:33 | slice literal [array] | LDAPInjection.go:69:3:69:33 | slice literal | +| LDAPInjection.go:69:24:69:32 | untrusted | LDAPInjection.go:69:3:69:33 | slice literal [array] | +| LDAPInjection.go:76:3:76:33 | slice literal [array] | LDAPInjection.go:76:3:76:33 | slice literal | +| LDAPInjection.go:76:24:76:32 | untrusted | LDAPInjection.go:76:3:76:33 | slice literal [array] | nodes -| LDAPInjection.go:57:15:57:29 | call to UserAgent : string | semmle.label | call to UserAgent : string | +| LDAPInjection.go:57:15:57:29 | call to UserAgent | semmle.label | call to UserAgent | | LDAPInjection.go:59:3:59:11 | untrusted | semmle.label | untrusted | | LDAPInjection.go:61:3:61:51 | ...+... | semmle.label | ...+... | | LDAPInjection.go:62:3:62:33 | slice literal | semmle.label | slice literal | -| LDAPInjection.go:62:3:62:33 | slice literal [array] : string | semmle.label | slice literal [array] : string | -| LDAPInjection.go:62:24:62:32 | untrusted : string | semmle.label | untrusted : string | +| LDAPInjection.go:62:3:62:33 | slice literal [array] | semmle.label | slice literal [array] | +| LDAPInjection.go:62:24:62:32 | untrusted | semmle.label | untrusted | | LDAPInjection.go:66:3:66:11 | untrusted | semmle.label | untrusted | | LDAPInjection.go:68:3:68:51 | ...+... | semmle.label | ...+... | | LDAPInjection.go:69:3:69:33 | slice literal | semmle.label | slice literal | -| LDAPInjection.go:69:3:69:33 | slice literal [array] : string | semmle.label | slice literal [array] : string | -| LDAPInjection.go:69:24:69:32 | untrusted : string | semmle.label | untrusted : string | +| LDAPInjection.go:69:3:69:33 | slice literal [array] | semmle.label | slice literal [array] | +| LDAPInjection.go:69:24:69:32 | untrusted | semmle.label | untrusted | | LDAPInjection.go:73:3:73:11 | untrusted | semmle.label | untrusted | | LDAPInjection.go:75:3:75:51 | ...+... | semmle.label | ...+... | | LDAPInjection.go:76:3:76:33 | slice literal | semmle.label | slice literal | -| LDAPInjection.go:76:3:76:33 | slice literal [array] : string | semmle.label | slice literal [array] : string | -| LDAPInjection.go:76:24:76:32 | untrusted : string | semmle.label | untrusted : string | +| LDAPInjection.go:76:3:76:33 | slice literal [array] | semmle.label | slice literal [array] | +| LDAPInjection.go:76:24:76:32 | untrusted | semmle.label | untrusted | | LDAPInjection.go:80:22:80:30 | untrusted | semmle.label | untrusted | | LDAPInjection.go:81:25:81:33 | untrusted | semmle.label | untrusted | subpaths #select -| LDAPInjection.go:59:3:59:11 | untrusted | LDAPInjection.go:57:15:57:29 | call to UserAgent : string | LDAPInjection.go:59:3:59:11 | untrusted | LDAP query parameter depends on a $@. | LDAPInjection.go:57:15:57:29 | call to UserAgent | user-provided value | -| LDAPInjection.go:61:3:61:51 | ...+... | LDAPInjection.go:57:15:57:29 | call to UserAgent : string | LDAPInjection.go:61:3:61:51 | ...+... | LDAP query parameter depends on a $@. | LDAPInjection.go:57:15:57:29 | call to UserAgent | user-provided value | -| LDAPInjection.go:62:3:62:33 | slice literal | LDAPInjection.go:57:15:57:29 | call to UserAgent : string | LDAPInjection.go:62:3:62:33 | slice literal | LDAP query parameter depends on a $@. | LDAPInjection.go:57:15:57:29 | call to UserAgent | user-provided value | -| LDAPInjection.go:66:3:66:11 | untrusted | LDAPInjection.go:57:15:57:29 | call to UserAgent : string | LDAPInjection.go:66:3:66:11 | untrusted | LDAP query parameter depends on a $@. | LDAPInjection.go:57:15:57:29 | call to UserAgent | user-provided value | -| LDAPInjection.go:68:3:68:51 | ...+... | LDAPInjection.go:57:15:57:29 | call to UserAgent : string | LDAPInjection.go:68:3:68:51 | ...+... | LDAP query parameter depends on a $@. | LDAPInjection.go:57:15:57:29 | call to UserAgent | user-provided value | -| LDAPInjection.go:69:3:69:33 | slice literal | LDAPInjection.go:57:15:57:29 | call to UserAgent : string | LDAPInjection.go:69:3:69:33 | slice literal | LDAP query parameter depends on a $@. | LDAPInjection.go:57:15:57:29 | call to UserAgent | user-provided value | -| LDAPInjection.go:73:3:73:11 | untrusted | LDAPInjection.go:57:15:57:29 | call to UserAgent : string | LDAPInjection.go:73:3:73:11 | untrusted | LDAP query parameter depends on a $@. | LDAPInjection.go:57:15:57:29 | call to UserAgent | user-provided value | -| LDAPInjection.go:75:3:75:51 | ...+... | LDAPInjection.go:57:15:57:29 | call to UserAgent : string | LDAPInjection.go:75:3:75:51 | ...+... | LDAP query parameter depends on a $@. | LDAPInjection.go:57:15:57:29 | call to UserAgent | user-provided value | -| LDAPInjection.go:76:3:76:33 | slice literal | LDAPInjection.go:57:15:57:29 | call to UserAgent : string | LDAPInjection.go:76:3:76:33 | slice literal | LDAP query parameter depends on a $@. | LDAPInjection.go:57:15:57:29 | call to UserAgent | user-provided value | -| LDAPInjection.go:80:22:80:30 | untrusted | LDAPInjection.go:57:15:57:29 | call to UserAgent : string | LDAPInjection.go:80:22:80:30 | untrusted | LDAP query parameter depends on a $@. | LDAPInjection.go:57:15:57:29 | call to UserAgent | user-provided value | -| LDAPInjection.go:81:25:81:33 | untrusted | LDAPInjection.go:57:15:57:29 | call to UserAgent : string | LDAPInjection.go:81:25:81:33 | untrusted | LDAP query parameter depends on a $@. | LDAPInjection.go:57:15:57:29 | call to UserAgent | user-provided value | +| LDAPInjection.go:59:3:59:11 | untrusted | LDAPInjection.go:57:15:57:29 | call to UserAgent | LDAPInjection.go:59:3:59:11 | untrusted | LDAP query parameter depends on a $@. | LDAPInjection.go:57:15:57:29 | call to UserAgent | user-provided value | +| LDAPInjection.go:61:3:61:51 | ...+... | LDAPInjection.go:57:15:57:29 | call to UserAgent | LDAPInjection.go:61:3:61:51 | ...+... | LDAP query parameter depends on a $@. | LDAPInjection.go:57:15:57:29 | call to UserAgent | user-provided value | +| LDAPInjection.go:62:3:62:33 | slice literal | LDAPInjection.go:57:15:57:29 | call to UserAgent | LDAPInjection.go:62:3:62:33 | slice literal | LDAP query parameter depends on a $@. | LDAPInjection.go:57:15:57:29 | call to UserAgent | user-provided value | +| LDAPInjection.go:66:3:66:11 | untrusted | LDAPInjection.go:57:15:57:29 | call to UserAgent | LDAPInjection.go:66:3:66:11 | untrusted | LDAP query parameter depends on a $@. | LDAPInjection.go:57:15:57:29 | call to UserAgent | user-provided value | +| LDAPInjection.go:68:3:68:51 | ...+... | LDAPInjection.go:57:15:57:29 | call to UserAgent | LDAPInjection.go:68:3:68:51 | ...+... | LDAP query parameter depends on a $@. | LDAPInjection.go:57:15:57:29 | call to UserAgent | user-provided value | +| LDAPInjection.go:69:3:69:33 | slice literal | LDAPInjection.go:57:15:57:29 | call to UserAgent | LDAPInjection.go:69:3:69:33 | slice literal | LDAP query parameter depends on a $@. | LDAPInjection.go:57:15:57:29 | call to UserAgent | user-provided value | +| LDAPInjection.go:73:3:73:11 | untrusted | LDAPInjection.go:57:15:57:29 | call to UserAgent | LDAPInjection.go:73:3:73:11 | untrusted | LDAP query parameter depends on a $@. | LDAPInjection.go:57:15:57:29 | call to UserAgent | user-provided value | +| LDAPInjection.go:75:3:75:51 | ...+... | LDAPInjection.go:57:15:57:29 | call to UserAgent | LDAPInjection.go:75:3:75:51 | ...+... | LDAP query parameter depends on a $@. | LDAPInjection.go:57:15:57:29 | call to UserAgent | user-provided value | +| LDAPInjection.go:76:3:76:33 | slice literal | LDAPInjection.go:57:15:57:29 | call to UserAgent | LDAPInjection.go:76:3:76:33 | slice literal | LDAP query parameter depends on a $@. | LDAPInjection.go:57:15:57:29 | call to UserAgent | user-provided value | +| LDAPInjection.go:80:22:80:30 | untrusted | LDAPInjection.go:57:15:57:29 | call to UserAgent | LDAPInjection.go:80:22:80:30 | untrusted | LDAP query parameter depends on a $@. | LDAPInjection.go:57:15:57:29 | call to UserAgent | user-provided value | +| LDAPInjection.go:81:25:81:33 | untrusted | LDAPInjection.go:57:15:57:29 | call to UserAgent | LDAPInjection.go:81:25:81:33 | untrusted | LDAP query parameter depends on a $@. | LDAPInjection.go:57:15:57:29 | call to UserAgent | user-provided value | diff --git a/go/ql/test/experimental/CWE-1004/CookieWithoutHttpOnly.expected b/go/ql/test/experimental/CWE-1004/CookieWithoutHttpOnly.expected index 27cc282c58c..1a22c7d1fc3 100644 --- a/go/ql/test/experimental/CWE-1004/CookieWithoutHttpOnly.expected +++ b/go/ql/test/experimental/CWE-1004/CookieWithoutHttpOnly.expected @@ -1,598 +1,598 @@ edges -| CookieWithoutHttpOnly.go:12:10:12:18 | "session" : string | CookieWithoutHttpOnly.go:15:20:15:21 | &... | -| CookieWithoutHttpOnly.go:12:10:12:18 | "session" : string | CookieWithoutHttpOnly.go:15:20:15:21 | &... : pointer type | -| CookieWithoutHttpOnly.go:12:10:12:18 | "session" : string | CookieWithoutHttpOnly.go:15:21:15:21 | c : Cookie | -| CookieWithoutHttpOnly.go:15:20:15:21 | &... : pointer type | CookieWithoutHttpOnly.go:15:20:15:21 | &... | -| CookieWithoutHttpOnly.go:15:20:15:21 | &... : pointer type | CookieWithoutHttpOnly.go:15:20:15:21 | &... : pointer type | -| CookieWithoutHttpOnly.go:15:20:15:21 | &... : pointer type | CookieWithoutHttpOnly.go:15:21:15:21 | c : Cookie | -| CookieWithoutHttpOnly.go:15:20:15:21 | &... [pointer] : Cookie | CookieWithoutHttpOnly.go:15:20:15:21 | &... | -| CookieWithoutHttpOnly.go:15:20:15:21 | &... [pointer] : Cookie | CookieWithoutHttpOnly.go:15:20:15:21 | &... : pointer type | -| CookieWithoutHttpOnly.go:15:20:15:21 | &... [pointer] : Cookie | CookieWithoutHttpOnly.go:15:21:15:21 | c : Cookie | -| CookieWithoutHttpOnly.go:15:21:15:21 | c : Cookie | CookieWithoutHttpOnly.go:15:20:15:21 | &... [pointer] : Cookie | -| CookieWithoutHttpOnly.go:20:13:20:21 | "session" : string | CookieWithoutHttpOnly.go:24:20:24:21 | &... | -| CookieWithoutHttpOnly.go:20:13:20:21 | "session" : string | CookieWithoutHttpOnly.go:24:20:24:21 | &... : pointer type | -| CookieWithoutHttpOnly.go:20:13:20:21 | "session" : string | CookieWithoutHttpOnly.go:24:21:24:21 | c : Cookie | -| CookieWithoutHttpOnly.go:22:13:22:17 | false : bool | CookieWithoutHttpOnly.go:24:20:24:21 | &... | -| CookieWithoutHttpOnly.go:22:13:22:17 | false : bool | CookieWithoutHttpOnly.go:24:20:24:21 | &... : pointer type | -| CookieWithoutHttpOnly.go:22:13:22:17 | false : bool | CookieWithoutHttpOnly.go:24:21:24:21 | c : Cookie | -| CookieWithoutHttpOnly.go:24:20:24:21 | &... : pointer type | CookieWithoutHttpOnly.go:24:20:24:21 | &... | -| CookieWithoutHttpOnly.go:24:20:24:21 | &... : pointer type | CookieWithoutHttpOnly.go:24:20:24:21 | &... | -| CookieWithoutHttpOnly.go:24:20:24:21 | &... : pointer type | CookieWithoutHttpOnly.go:24:20:24:21 | &... : pointer type | -| CookieWithoutHttpOnly.go:24:20:24:21 | &... : pointer type | CookieWithoutHttpOnly.go:24:20:24:21 | &... : pointer type | -| CookieWithoutHttpOnly.go:24:20:24:21 | &... : pointer type | CookieWithoutHttpOnly.go:24:21:24:21 | c : Cookie | -| CookieWithoutHttpOnly.go:24:20:24:21 | &... : pointer type | CookieWithoutHttpOnly.go:24:21:24:21 | c : Cookie | -| CookieWithoutHttpOnly.go:24:20:24:21 | &... [pointer] : Cookie | CookieWithoutHttpOnly.go:24:20:24:21 | &... | -| CookieWithoutHttpOnly.go:24:20:24:21 | &... [pointer] : Cookie | CookieWithoutHttpOnly.go:24:20:24:21 | &... | -| CookieWithoutHttpOnly.go:24:20:24:21 | &... [pointer] : Cookie | CookieWithoutHttpOnly.go:24:20:24:21 | &... : pointer type | -| CookieWithoutHttpOnly.go:24:20:24:21 | &... [pointer] : Cookie | CookieWithoutHttpOnly.go:24:20:24:21 | &... : pointer type | -| CookieWithoutHttpOnly.go:24:20:24:21 | &... [pointer] : Cookie | CookieWithoutHttpOnly.go:24:21:24:21 | c : Cookie | -| CookieWithoutHttpOnly.go:24:20:24:21 | &... [pointer] : Cookie | CookieWithoutHttpOnly.go:24:21:24:21 | c : Cookie | -| CookieWithoutHttpOnly.go:24:21:24:21 | c : Cookie | CookieWithoutHttpOnly.go:24:20:24:21 | &... [pointer] : Cookie | -| CookieWithoutHttpOnly.go:24:21:24:21 | c : Cookie | CookieWithoutHttpOnly.go:24:20:24:21 | &... [pointer] : Cookie | -| CookieWithoutHttpOnly.go:29:13:29:21 | "session" : string | CookieWithoutHttpOnly.go:33:20:33:21 | &... | -| CookieWithoutHttpOnly.go:29:13:29:21 | "session" : string | CookieWithoutHttpOnly.go:33:20:33:21 | &... : pointer type | -| CookieWithoutHttpOnly.go:29:13:29:21 | "session" : string | CookieWithoutHttpOnly.go:33:21:33:21 | c : Cookie | -| CookieWithoutHttpOnly.go:31:13:31:16 | true : bool | CookieWithoutHttpOnly.go:33:20:33:21 | &... | -| CookieWithoutHttpOnly.go:31:13:31:16 | true : bool | CookieWithoutHttpOnly.go:33:20:33:21 | &... : pointer type | -| CookieWithoutHttpOnly.go:31:13:31:16 | true : bool | CookieWithoutHttpOnly.go:33:21:33:21 | c : Cookie | -| CookieWithoutHttpOnly.go:33:20:33:21 | &... : pointer type | CookieWithoutHttpOnly.go:33:20:33:21 | &... | -| CookieWithoutHttpOnly.go:33:20:33:21 | &... : pointer type | CookieWithoutHttpOnly.go:33:20:33:21 | &... | -| CookieWithoutHttpOnly.go:33:20:33:21 | &... : pointer type | CookieWithoutHttpOnly.go:33:20:33:21 | &... : pointer type | -| CookieWithoutHttpOnly.go:33:20:33:21 | &... : pointer type | CookieWithoutHttpOnly.go:33:20:33:21 | &... : pointer type | -| CookieWithoutHttpOnly.go:33:20:33:21 | &... : pointer type | CookieWithoutHttpOnly.go:33:21:33:21 | c : Cookie | -| CookieWithoutHttpOnly.go:33:20:33:21 | &... : pointer type | CookieWithoutHttpOnly.go:33:21:33:21 | c : Cookie | -| CookieWithoutHttpOnly.go:33:20:33:21 | &... [pointer] : Cookie | CookieWithoutHttpOnly.go:33:20:33:21 | &... | -| CookieWithoutHttpOnly.go:33:20:33:21 | &... [pointer] : Cookie | CookieWithoutHttpOnly.go:33:20:33:21 | &... | -| CookieWithoutHttpOnly.go:33:20:33:21 | &... [pointer] : Cookie | CookieWithoutHttpOnly.go:33:20:33:21 | &... : pointer type | -| CookieWithoutHttpOnly.go:33:20:33:21 | &... [pointer] : Cookie | CookieWithoutHttpOnly.go:33:20:33:21 | &... : pointer type | -| CookieWithoutHttpOnly.go:33:20:33:21 | &... [pointer] : Cookie | CookieWithoutHttpOnly.go:33:21:33:21 | c : Cookie | -| CookieWithoutHttpOnly.go:33:20:33:21 | &... [pointer] : Cookie | CookieWithoutHttpOnly.go:33:21:33:21 | c : Cookie | -| CookieWithoutHttpOnly.go:33:21:33:21 | c : Cookie | CookieWithoutHttpOnly.go:33:20:33:21 | &... [pointer] : Cookie | -| CookieWithoutHttpOnly.go:33:21:33:21 | c : Cookie | CookieWithoutHttpOnly.go:33:20:33:21 | &... [pointer] : Cookie | -| CookieWithoutHttpOnly.go:38:10:38:18 | "session" : string | CookieWithoutHttpOnly.go:42:20:42:21 | &... | -| CookieWithoutHttpOnly.go:38:10:38:18 | "session" : string | CookieWithoutHttpOnly.go:42:20:42:21 | &... : pointer type | -| CookieWithoutHttpOnly.go:38:10:38:18 | "session" : string | CookieWithoutHttpOnly.go:42:21:42:21 | c : Cookie | -| CookieWithoutHttpOnly.go:41:15:41:18 | true : bool | CookieWithoutHttpOnly.go:42:20:42:21 | &... | -| CookieWithoutHttpOnly.go:41:15:41:18 | true : bool | CookieWithoutHttpOnly.go:42:20:42:21 | &... : pointer type | -| CookieWithoutHttpOnly.go:41:15:41:18 | true : bool | CookieWithoutHttpOnly.go:42:21:42:21 | c : Cookie | -| CookieWithoutHttpOnly.go:42:20:42:21 | &... : pointer type | CookieWithoutHttpOnly.go:42:20:42:21 | &... | -| CookieWithoutHttpOnly.go:42:20:42:21 | &... : pointer type | CookieWithoutHttpOnly.go:42:20:42:21 | &... | -| CookieWithoutHttpOnly.go:42:20:42:21 | &... : pointer type | CookieWithoutHttpOnly.go:42:20:42:21 | &... : pointer type | -| CookieWithoutHttpOnly.go:42:20:42:21 | &... : pointer type | CookieWithoutHttpOnly.go:42:20:42:21 | &... : pointer type | -| CookieWithoutHttpOnly.go:42:20:42:21 | &... : pointer type | CookieWithoutHttpOnly.go:42:21:42:21 | c : Cookie | -| CookieWithoutHttpOnly.go:42:20:42:21 | &... : pointer type | CookieWithoutHttpOnly.go:42:21:42:21 | c : Cookie | -| CookieWithoutHttpOnly.go:42:20:42:21 | &... [pointer] : Cookie | CookieWithoutHttpOnly.go:42:20:42:21 | &... | -| CookieWithoutHttpOnly.go:42:20:42:21 | &... [pointer] : Cookie | CookieWithoutHttpOnly.go:42:20:42:21 | &... | -| CookieWithoutHttpOnly.go:42:20:42:21 | &... [pointer] : Cookie | CookieWithoutHttpOnly.go:42:20:42:21 | &... : pointer type | -| CookieWithoutHttpOnly.go:42:20:42:21 | &... [pointer] : Cookie | CookieWithoutHttpOnly.go:42:20:42:21 | &... : pointer type | -| CookieWithoutHttpOnly.go:42:20:42:21 | &... [pointer] : Cookie | CookieWithoutHttpOnly.go:42:21:42:21 | c : Cookie | -| CookieWithoutHttpOnly.go:42:20:42:21 | &... [pointer] : Cookie | CookieWithoutHttpOnly.go:42:21:42:21 | c : Cookie | -| CookieWithoutHttpOnly.go:42:21:42:21 | c : Cookie | CookieWithoutHttpOnly.go:42:20:42:21 | &... [pointer] : Cookie | -| CookieWithoutHttpOnly.go:42:21:42:21 | c : Cookie | CookieWithoutHttpOnly.go:42:20:42:21 | &... [pointer] : Cookie | -| CookieWithoutHttpOnly.go:47:10:47:18 | "session" : string | CookieWithoutHttpOnly.go:51:20:51:21 | &... | -| CookieWithoutHttpOnly.go:47:10:47:18 | "session" : string | CookieWithoutHttpOnly.go:51:20:51:21 | &... : pointer type | -| CookieWithoutHttpOnly.go:47:10:47:18 | "session" : string | CookieWithoutHttpOnly.go:51:21:51:21 | c : Cookie | -| CookieWithoutHttpOnly.go:50:15:50:19 | false : bool | CookieWithoutHttpOnly.go:51:20:51:21 | &... | -| CookieWithoutHttpOnly.go:50:15:50:19 | false : bool | CookieWithoutHttpOnly.go:51:20:51:21 | &... : pointer type | -| CookieWithoutHttpOnly.go:50:15:50:19 | false : bool | CookieWithoutHttpOnly.go:51:21:51:21 | c : Cookie | -| CookieWithoutHttpOnly.go:51:20:51:21 | &... : pointer type | CookieWithoutHttpOnly.go:51:20:51:21 | &... | -| CookieWithoutHttpOnly.go:51:20:51:21 | &... : pointer type | CookieWithoutHttpOnly.go:51:20:51:21 | &... | -| CookieWithoutHttpOnly.go:51:20:51:21 | &... : pointer type | CookieWithoutHttpOnly.go:51:20:51:21 | &... : pointer type | -| CookieWithoutHttpOnly.go:51:20:51:21 | &... : pointer type | CookieWithoutHttpOnly.go:51:20:51:21 | &... : pointer type | -| CookieWithoutHttpOnly.go:51:20:51:21 | &... : pointer type | CookieWithoutHttpOnly.go:51:21:51:21 | c : Cookie | -| CookieWithoutHttpOnly.go:51:20:51:21 | &... : pointer type | CookieWithoutHttpOnly.go:51:21:51:21 | c : Cookie | -| CookieWithoutHttpOnly.go:51:20:51:21 | &... [pointer] : Cookie | CookieWithoutHttpOnly.go:51:20:51:21 | &... | -| CookieWithoutHttpOnly.go:51:20:51:21 | &... [pointer] : Cookie | CookieWithoutHttpOnly.go:51:20:51:21 | &... | -| CookieWithoutHttpOnly.go:51:20:51:21 | &... [pointer] : Cookie | CookieWithoutHttpOnly.go:51:20:51:21 | &... : pointer type | -| CookieWithoutHttpOnly.go:51:20:51:21 | &... [pointer] : Cookie | CookieWithoutHttpOnly.go:51:20:51:21 | &... : pointer type | -| CookieWithoutHttpOnly.go:51:20:51:21 | &... [pointer] : Cookie | CookieWithoutHttpOnly.go:51:21:51:21 | c : Cookie | -| CookieWithoutHttpOnly.go:51:20:51:21 | &... [pointer] : Cookie | CookieWithoutHttpOnly.go:51:21:51:21 | c : Cookie | -| CookieWithoutHttpOnly.go:51:21:51:21 | c : Cookie | CookieWithoutHttpOnly.go:51:20:51:21 | &... [pointer] : Cookie | -| CookieWithoutHttpOnly.go:51:21:51:21 | c : Cookie | CookieWithoutHttpOnly.go:51:20:51:21 | &... [pointer] : Cookie | -| CookieWithoutHttpOnly.go:55:2:55:4 | definition of val : bool | CookieWithoutHttpOnly.go:61:20:61:21 | &... | -| CookieWithoutHttpOnly.go:55:2:55:4 | definition of val : bool | CookieWithoutHttpOnly.go:61:20:61:21 | &... : pointer type | -| CookieWithoutHttpOnly.go:55:2:55:4 | definition of val : bool | CookieWithoutHttpOnly.go:61:21:61:21 | c : Cookie | -| CookieWithoutHttpOnly.go:55:9:55:13 | false : bool | CookieWithoutHttpOnly.go:61:20:61:21 | &... | -| CookieWithoutHttpOnly.go:55:9:55:13 | false : bool | CookieWithoutHttpOnly.go:61:20:61:21 | &... : pointer type | -| CookieWithoutHttpOnly.go:55:9:55:13 | false : bool | CookieWithoutHttpOnly.go:61:21:61:21 | c : Cookie | -| CookieWithoutHttpOnly.go:57:13:57:21 | "session" : string | CookieWithoutHttpOnly.go:61:20:61:21 | &... | -| CookieWithoutHttpOnly.go:57:13:57:21 | "session" : string | CookieWithoutHttpOnly.go:61:20:61:21 | &... : pointer type | -| CookieWithoutHttpOnly.go:57:13:57:21 | "session" : string | CookieWithoutHttpOnly.go:61:21:61:21 | c : Cookie | -| CookieWithoutHttpOnly.go:59:13:59:15 | val : bool | CookieWithoutHttpOnly.go:61:20:61:21 | &... | -| CookieWithoutHttpOnly.go:59:13:59:15 | val : bool | CookieWithoutHttpOnly.go:61:20:61:21 | &... : pointer type | -| CookieWithoutHttpOnly.go:59:13:59:15 | val : bool | CookieWithoutHttpOnly.go:61:21:61:21 | c : Cookie | -| CookieWithoutHttpOnly.go:61:20:61:21 | &... : pointer type | CookieWithoutHttpOnly.go:61:20:61:21 | &... | -| CookieWithoutHttpOnly.go:61:20:61:21 | &... : pointer type | CookieWithoutHttpOnly.go:61:20:61:21 | &... | -| CookieWithoutHttpOnly.go:61:20:61:21 | &... : pointer type | CookieWithoutHttpOnly.go:61:20:61:21 | &... : pointer type | -| CookieWithoutHttpOnly.go:61:20:61:21 | &... : pointer type | CookieWithoutHttpOnly.go:61:20:61:21 | &... : pointer type | -| CookieWithoutHttpOnly.go:61:20:61:21 | &... : pointer type | CookieWithoutHttpOnly.go:61:21:61:21 | c : Cookie | -| CookieWithoutHttpOnly.go:61:20:61:21 | &... : pointer type | CookieWithoutHttpOnly.go:61:21:61:21 | c : Cookie | -| CookieWithoutHttpOnly.go:61:20:61:21 | &... [pointer] : Cookie | CookieWithoutHttpOnly.go:61:20:61:21 | &... | -| CookieWithoutHttpOnly.go:61:20:61:21 | &... [pointer] : Cookie | CookieWithoutHttpOnly.go:61:20:61:21 | &... | -| CookieWithoutHttpOnly.go:61:20:61:21 | &... [pointer] : Cookie | CookieWithoutHttpOnly.go:61:20:61:21 | &... : pointer type | -| CookieWithoutHttpOnly.go:61:20:61:21 | &... [pointer] : Cookie | CookieWithoutHttpOnly.go:61:20:61:21 | &... : pointer type | -| CookieWithoutHttpOnly.go:61:20:61:21 | &... [pointer] : Cookie | CookieWithoutHttpOnly.go:61:21:61:21 | c : Cookie | -| CookieWithoutHttpOnly.go:61:20:61:21 | &... [pointer] : Cookie | CookieWithoutHttpOnly.go:61:21:61:21 | c : Cookie | -| CookieWithoutHttpOnly.go:61:21:61:21 | c : Cookie | CookieWithoutHttpOnly.go:61:20:61:21 | &... [pointer] : Cookie | -| CookieWithoutHttpOnly.go:61:21:61:21 | c : Cookie | CookieWithoutHttpOnly.go:61:20:61:21 | &... [pointer] : Cookie | -| CookieWithoutHttpOnly.go:65:2:65:4 | definition of val : bool | CookieWithoutHttpOnly.go:71:20:71:21 | &... | -| CookieWithoutHttpOnly.go:65:2:65:4 | definition of val : bool | CookieWithoutHttpOnly.go:71:20:71:21 | &... : pointer type | -| CookieWithoutHttpOnly.go:65:2:65:4 | definition of val : bool | CookieWithoutHttpOnly.go:71:21:71:21 | c : Cookie | -| CookieWithoutHttpOnly.go:65:9:65:12 | true : bool | CookieWithoutHttpOnly.go:71:20:71:21 | &... | -| CookieWithoutHttpOnly.go:65:9:65:12 | true : bool | CookieWithoutHttpOnly.go:71:20:71:21 | &... : pointer type | -| CookieWithoutHttpOnly.go:65:9:65:12 | true : bool | CookieWithoutHttpOnly.go:71:21:71:21 | c : Cookie | -| CookieWithoutHttpOnly.go:67:13:67:21 | "session" : string | CookieWithoutHttpOnly.go:71:20:71:21 | &... | -| CookieWithoutHttpOnly.go:67:13:67:21 | "session" : string | CookieWithoutHttpOnly.go:71:20:71:21 | &... : pointer type | -| CookieWithoutHttpOnly.go:67:13:67:21 | "session" : string | CookieWithoutHttpOnly.go:71:21:71:21 | c : Cookie | -| CookieWithoutHttpOnly.go:69:13:69:15 | val : bool | CookieWithoutHttpOnly.go:71:20:71:21 | &... | -| CookieWithoutHttpOnly.go:69:13:69:15 | val : bool | CookieWithoutHttpOnly.go:71:20:71:21 | &... : pointer type | -| CookieWithoutHttpOnly.go:69:13:69:15 | val : bool | CookieWithoutHttpOnly.go:71:21:71:21 | c : Cookie | -| CookieWithoutHttpOnly.go:71:20:71:21 | &... : pointer type | CookieWithoutHttpOnly.go:71:20:71:21 | &... | -| CookieWithoutHttpOnly.go:71:20:71:21 | &... : pointer type | CookieWithoutHttpOnly.go:71:20:71:21 | &... | -| CookieWithoutHttpOnly.go:71:20:71:21 | &... : pointer type | CookieWithoutHttpOnly.go:71:20:71:21 | &... : pointer type | -| CookieWithoutHttpOnly.go:71:20:71:21 | &... : pointer type | CookieWithoutHttpOnly.go:71:20:71:21 | &... : pointer type | -| CookieWithoutHttpOnly.go:71:20:71:21 | &... : pointer type | CookieWithoutHttpOnly.go:71:21:71:21 | c : Cookie | -| CookieWithoutHttpOnly.go:71:20:71:21 | &... : pointer type | CookieWithoutHttpOnly.go:71:21:71:21 | c : Cookie | -| CookieWithoutHttpOnly.go:71:20:71:21 | &... [pointer] : Cookie | CookieWithoutHttpOnly.go:71:20:71:21 | &... | -| CookieWithoutHttpOnly.go:71:20:71:21 | &... [pointer] : Cookie | CookieWithoutHttpOnly.go:71:20:71:21 | &... | -| CookieWithoutHttpOnly.go:71:20:71:21 | &... [pointer] : Cookie | CookieWithoutHttpOnly.go:71:20:71:21 | &... : pointer type | -| CookieWithoutHttpOnly.go:71:20:71:21 | &... [pointer] : Cookie | CookieWithoutHttpOnly.go:71:20:71:21 | &... : pointer type | -| CookieWithoutHttpOnly.go:71:20:71:21 | &... [pointer] : Cookie | CookieWithoutHttpOnly.go:71:21:71:21 | c : Cookie | -| CookieWithoutHttpOnly.go:71:20:71:21 | &... [pointer] : Cookie | CookieWithoutHttpOnly.go:71:21:71:21 | c : Cookie | -| CookieWithoutHttpOnly.go:71:21:71:21 | c : Cookie | CookieWithoutHttpOnly.go:71:20:71:21 | &... [pointer] : Cookie | -| CookieWithoutHttpOnly.go:71:21:71:21 | c : Cookie | CookieWithoutHttpOnly.go:71:20:71:21 | &... [pointer] : Cookie | -| CookieWithoutHttpOnly.go:75:2:75:4 | definition of val : bool | CookieWithoutHttpOnly.go:81:20:81:21 | &... | -| CookieWithoutHttpOnly.go:75:2:75:4 | definition of val : bool | CookieWithoutHttpOnly.go:81:20:81:21 | &... : pointer type | -| CookieWithoutHttpOnly.go:75:2:75:4 | definition of val : bool | CookieWithoutHttpOnly.go:81:21:81:21 | c : Cookie | -| CookieWithoutHttpOnly.go:75:9:75:12 | true : bool | CookieWithoutHttpOnly.go:81:20:81:21 | &... | -| CookieWithoutHttpOnly.go:75:9:75:12 | true : bool | CookieWithoutHttpOnly.go:81:20:81:21 | &... : pointer type | -| CookieWithoutHttpOnly.go:75:9:75:12 | true : bool | CookieWithoutHttpOnly.go:81:21:81:21 | c : Cookie | -| CookieWithoutHttpOnly.go:77:10:77:18 | "session" : string | CookieWithoutHttpOnly.go:81:20:81:21 | &... | -| CookieWithoutHttpOnly.go:77:10:77:18 | "session" : string | CookieWithoutHttpOnly.go:81:20:81:21 | &... : pointer type | -| CookieWithoutHttpOnly.go:77:10:77:18 | "session" : string | CookieWithoutHttpOnly.go:81:21:81:21 | c : Cookie | -| CookieWithoutHttpOnly.go:80:15:80:17 | val : bool | CookieWithoutHttpOnly.go:81:20:81:21 | &... | -| CookieWithoutHttpOnly.go:80:15:80:17 | val : bool | CookieWithoutHttpOnly.go:81:20:81:21 | &... : pointer type | -| CookieWithoutHttpOnly.go:80:15:80:17 | val : bool | CookieWithoutHttpOnly.go:81:21:81:21 | c : Cookie | -| CookieWithoutHttpOnly.go:81:20:81:21 | &... : pointer type | CookieWithoutHttpOnly.go:81:20:81:21 | &... | -| CookieWithoutHttpOnly.go:81:20:81:21 | &... : pointer type | CookieWithoutHttpOnly.go:81:20:81:21 | &... | -| CookieWithoutHttpOnly.go:81:20:81:21 | &... : pointer type | CookieWithoutHttpOnly.go:81:20:81:21 | &... : pointer type | -| CookieWithoutHttpOnly.go:81:20:81:21 | &... : pointer type | CookieWithoutHttpOnly.go:81:20:81:21 | &... : pointer type | -| CookieWithoutHttpOnly.go:81:20:81:21 | &... : pointer type | CookieWithoutHttpOnly.go:81:21:81:21 | c : Cookie | -| CookieWithoutHttpOnly.go:81:20:81:21 | &... : pointer type | CookieWithoutHttpOnly.go:81:21:81:21 | c : Cookie | -| CookieWithoutHttpOnly.go:81:20:81:21 | &... [pointer] : Cookie | CookieWithoutHttpOnly.go:81:20:81:21 | &... | -| CookieWithoutHttpOnly.go:81:20:81:21 | &... [pointer] : Cookie | CookieWithoutHttpOnly.go:81:20:81:21 | &... | -| CookieWithoutHttpOnly.go:81:20:81:21 | &... [pointer] : Cookie | CookieWithoutHttpOnly.go:81:20:81:21 | &... : pointer type | -| CookieWithoutHttpOnly.go:81:20:81:21 | &... [pointer] : Cookie | CookieWithoutHttpOnly.go:81:20:81:21 | &... : pointer type | -| CookieWithoutHttpOnly.go:81:20:81:21 | &... [pointer] : Cookie | CookieWithoutHttpOnly.go:81:21:81:21 | c : Cookie | -| CookieWithoutHttpOnly.go:81:20:81:21 | &... [pointer] : Cookie | CookieWithoutHttpOnly.go:81:21:81:21 | c : Cookie | -| CookieWithoutHttpOnly.go:81:21:81:21 | c : Cookie | CookieWithoutHttpOnly.go:81:20:81:21 | &... [pointer] : Cookie | -| CookieWithoutHttpOnly.go:81:21:81:21 | c : Cookie | CookieWithoutHttpOnly.go:81:20:81:21 | &... [pointer] : Cookie | -| CookieWithoutHttpOnly.go:85:2:85:4 | definition of val : bool | CookieWithoutHttpOnly.go:91:20:91:21 | &... | -| CookieWithoutHttpOnly.go:85:2:85:4 | definition of val : bool | CookieWithoutHttpOnly.go:91:20:91:21 | &... : pointer type | -| CookieWithoutHttpOnly.go:85:2:85:4 | definition of val : bool | CookieWithoutHttpOnly.go:91:21:91:21 | c : Cookie | -| CookieWithoutHttpOnly.go:85:9:85:13 | false : bool | CookieWithoutHttpOnly.go:91:20:91:21 | &... | -| CookieWithoutHttpOnly.go:85:9:85:13 | false : bool | CookieWithoutHttpOnly.go:91:20:91:21 | &... : pointer type | -| CookieWithoutHttpOnly.go:85:9:85:13 | false : bool | CookieWithoutHttpOnly.go:91:21:91:21 | c : Cookie | -| CookieWithoutHttpOnly.go:87:10:87:18 | "session" : string | CookieWithoutHttpOnly.go:91:20:91:21 | &... | -| CookieWithoutHttpOnly.go:87:10:87:18 | "session" : string | CookieWithoutHttpOnly.go:91:20:91:21 | &... : pointer type | -| CookieWithoutHttpOnly.go:87:10:87:18 | "session" : string | CookieWithoutHttpOnly.go:91:21:91:21 | c : Cookie | -| CookieWithoutHttpOnly.go:90:15:90:17 | val : bool | CookieWithoutHttpOnly.go:91:20:91:21 | &... | -| CookieWithoutHttpOnly.go:90:15:90:17 | val : bool | CookieWithoutHttpOnly.go:91:20:91:21 | &... : pointer type | -| CookieWithoutHttpOnly.go:90:15:90:17 | val : bool | CookieWithoutHttpOnly.go:91:21:91:21 | c : Cookie | -| CookieWithoutHttpOnly.go:91:20:91:21 | &... : pointer type | CookieWithoutHttpOnly.go:91:20:91:21 | &... | -| CookieWithoutHttpOnly.go:91:20:91:21 | &... : pointer type | CookieWithoutHttpOnly.go:91:20:91:21 | &... | -| CookieWithoutHttpOnly.go:91:20:91:21 | &... : pointer type | CookieWithoutHttpOnly.go:91:20:91:21 | &... : pointer type | -| CookieWithoutHttpOnly.go:91:20:91:21 | &... : pointer type | CookieWithoutHttpOnly.go:91:20:91:21 | &... : pointer type | -| CookieWithoutHttpOnly.go:91:20:91:21 | &... : pointer type | CookieWithoutHttpOnly.go:91:21:91:21 | c : Cookie | -| CookieWithoutHttpOnly.go:91:20:91:21 | &... : pointer type | CookieWithoutHttpOnly.go:91:21:91:21 | c : Cookie | -| CookieWithoutHttpOnly.go:91:20:91:21 | &... [pointer] : Cookie | CookieWithoutHttpOnly.go:91:20:91:21 | &... | -| CookieWithoutHttpOnly.go:91:20:91:21 | &... [pointer] : Cookie | CookieWithoutHttpOnly.go:91:20:91:21 | &... | -| CookieWithoutHttpOnly.go:91:20:91:21 | &... [pointer] : Cookie | CookieWithoutHttpOnly.go:91:20:91:21 | &... : pointer type | -| CookieWithoutHttpOnly.go:91:20:91:21 | &... [pointer] : Cookie | CookieWithoutHttpOnly.go:91:20:91:21 | &... : pointer type | -| CookieWithoutHttpOnly.go:91:20:91:21 | &... [pointer] : Cookie | CookieWithoutHttpOnly.go:91:21:91:21 | c : Cookie | -| CookieWithoutHttpOnly.go:91:20:91:21 | &... [pointer] : Cookie | CookieWithoutHttpOnly.go:91:21:91:21 | c : Cookie | -| CookieWithoutHttpOnly.go:91:21:91:21 | c : Cookie | CookieWithoutHttpOnly.go:91:20:91:21 | &... [pointer] : Cookie | -| CookieWithoutHttpOnly.go:91:21:91:21 | c : Cookie | CookieWithoutHttpOnly.go:91:20:91:21 | &... [pointer] : Cookie | -| CookieWithoutHttpOnly.go:99:15:99:19 | false : bool | CookieWithoutHttpOnly.go:100:20:100:21 | &... | -| CookieWithoutHttpOnly.go:99:15:99:19 | false : bool | CookieWithoutHttpOnly.go:100:20:100:21 | &... : pointer type | -| CookieWithoutHttpOnly.go:99:15:99:19 | false : bool | CookieWithoutHttpOnly.go:100:21:100:21 | c : Cookie | -| CookieWithoutHttpOnly.go:100:20:100:21 | &... : pointer type | CookieWithoutHttpOnly.go:100:20:100:21 | &... | -| CookieWithoutHttpOnly.go:100:20:100:21 | &... : pointer type | CookieWithoutHttpOnly.go:100:20:100:21 | &... : pointer type | -| CookieWithoutHttpOnly.go:100:20:100:21 | &... : pointer type | CookieWithoutHttpOnly.go:100:21:100:21 | c : Cookie | -| CookieWithoutHttpOnly.go:100:20:100:21 | &... [pointer] : Cookie | CookieWithoutHttpOnly.go:100:20:100:21 | &... | -| CookieWithoutHttpOnly.go:100:20:100:21 | &... [pointer] : Cookie | CookieWithoutHttpOnly.go:100:20:100:21 | &... : pointer type | -| CookieWithoutHttpOnly.go:100:20:100:21 | &... [pointer] : Cookie | CookieWithoutHttpOnly.go:100:21:100:21 | c : Cookie | -| CookieWithoutHttpOnly.go:100:21:100:21 | c : Cookie | CookieWithoutHttpOnly.go:100:20:100:21 | &... [pointer] : Cookie | -| CookieWithoutHttpOnly.go:104:10:104:18 | "session" : string | CookieWithoutHttpOnly.go:110:20:110:21 | &... | -| CookieWithoutHttpOnly.go:104:10:104:18 | "session" : string | CookieWithoutHttpOnly.go:110:20:110:21 | &... : pointer type | -| CookieWithoutHttpOnly.go:104:10:104:18 | "session" : string | CookieWithoutHttpOnly.go:110:21:110:21 | c : Cookie | -| CookieWithoutHttpOnly.go:109:15:109:19 | false : bool | CookieWithoutHttpOnly.go:110:20:110:21 | &... | -| CookieWithoutHttpOnly.go:109:15:109:19 | false : bool | CookieWithoutHttpOnly.go:110:20:110:21 | &... : pointer type | -| CookieWithoutHttpOnly.go:109:15:109:19 | false : bool | CookieWithoutHttpOnly.go:110:21:110:21 | c : Cookie | -| CookieWithoutHttpOnly.go:110:20:110:21 | &... : pointer type | CookieWithoutHttpOnly.go:110:20:110:21 | &... | -| CookieWithoutHttpOnly.go:110:20:110:21 | &... : pointer type | CookieWithoutHttpOnly.go:110:20:110:21 | &... | -| CookieWithoutHttpOnly.go:110:20:110:21 | &... : pointer type | CookieWithoutHttpOnly.go:110:20:110:21 | &... : pointer type | -| CookieWithoutHttpOnly.go:110:20:110:21 | &... : pointer type | CookieWithoutHttpOnly.go:110:20:110:21 | &... : pointer type | -| CookieWithoutHttpOnly.go:110:20:110:21 | &... : pointer type | CookieWithoutHttpOnly.go:110:21:110:21 | c : Cookie | -| CookieWithoutHttpOnly.go:110:20:110:21 | &... : pointer type | CookieWithoutHttpOnly.go:110:21:110:21 | c : Cookie | -| CookieWithoutHttpOnly.go:110:20:110:21 | &... [pointer] : Cookie | CookieWithoutHttpOnly.go:110:20:110:21 | &... | -| CookieWithoutHttpOnly.go:110:20:110:21 | &... [pointer] : Cookie | CookieWithoutHttpOnly.go:110:20:110:21 | &... | -| CookieWithoutHttpOnly.go:110:20:110:21 | &... [pointer] : Cookie | CookieWithoutHttpOnly.go:110:20:110:21 | &... : pointer type | -| CookieWithoutHttpOnly.go:110:20:110:21 | &... [pointer] : Cookie | CookieWithoutHttpOnly.go:110:20:110:21 | &... : pointer type | -| CookieWithoutHttpOnly.go:110:20:110:21 | &... [pointer] : Cookie | CookieWithoutHttpOnly.go:110:21:110:21 | c : Cookie | -| CookieWithoutHttpOnly.go:110:20:110:21 | &... [pointer] : Cookie | CookieWithoutHttpOnly.go:110:21:110:21 | c : Cookie | -| CookieWithoutHttpOnly.go:110:21:110:21 | c : Cookie | CookieWithoutHttpOnly.go:110:20:110:21 | &... [pointer] : Cookie | -| CookieWithoutHttpOnly.go:110:21:110:21 | c : Cookie | CookieWithoutHttpOnly.go:110:20:110:21 | &... [pointer] : Cookie | -| CookieWithoutHttpOnly.go:114:13:114:24 | "login_name" : string | CookieWithoutHttpOnly.go:120:20:120:21 | &... | -| CookieWithoutHttpOnly.go:114:13:114:24 | "login_name" : string | CookieWithoutHttpOnly.go:120:20:120:21 | &... : pointer type | -| CookieWithoutHttpOnly.go:114:13:114:24 | "login_name" : string | CookieWithoutHttpOnly.go:120:21:120:21 | c : Cookie | -| CookieWithoutHttpOnly.go:116:10:116:16 | session : string | CookieWithoutHttpOnly.go:120:20:120:21 | &... | -| CookieWithoutHttpOnly.go:116:10:116:16 | session : string | CookieWithoutHttpOnly.go:120:20:120:21 | &... : pointer type | -| CookieWithoutHttpOnly.go:116:10:116:16 | session : string | CookieWithoutHttpOnly.go:120:21:120:21 | c : Cookie | -| CookieWithoutHttpOnly.go:119:15:119:19 | false : bool | CookieWithoutHttpOnly.go:120:20:120:21 | &... | -| CookieWithoutHttpOnly.go:119:15:119:19 | false : bool | CookieWithoutHttpOnly.go:120:20:120:21 | &... : pointer type | -| CookieWithoutHttpOnly.go:119:15:119:19 | false : bool | CookieWithoutHttpOnly.go:120:21:120:21 | c : Cookie | -| CookieWithoutHttpOnly.go:120:20:120:21 | &... : pointer type | CookieWithoutHttpOnly.go:120:20:120:21 | &... | -| CookieWithoutHttpOnly.go:120:20:120:21 | &... : pointer type | CookieWithoutHttpOnly.go:120:20:120:21 | &... | -| CookieWithoutHttpOnly.go:120:20:120:21 | &... : pointer type | CookieWithoutHttpOnly.go:120:20:120:21 | &... : pointer type | -| CookieWithoutHttpOnly.go:120:20:120:21 | &... : pointer type | CookieWithoutHttpOnly.go:120:20:120:21 | &... : pointer type | -| CookieWithoutHttpOnly.go:120:20:120:21 | &... : pointer type | CookieWithoutHttpOnly.go:120:21:120:21 | c : Cookie | -| CookieWithoutHttpOnly.go:120:20:120:21 | &... : pointer type | CookieWithoutHttpOnly.go:120:21:120:21 | c : Cookie | -| CookieWithoutHttpOnly.go:120:20:120:21 | &... [pointer] : Cookie | CookieWithoutHttpOnly.go:120:20:120:21 | &... | -| CookieWithoutHttpOnly.go:120:20:120:21 | &... [pointer] : Cookie | CookieWithoutHttpOnly.go:120:20:120:21 | &... | -| CookieWithoutHttpOnly.go:120:20:120:21 | &... [pointer] : Cookie | CookieWithoutHttpOnly.go:120:20:120:21 | &... : pointer type | -| CookieWithoutHttpOnly.go:120:20:120:21 | &... [pointer] : Cookie | CookieWithoutHttpOnly.go:120:20:120:21 | &... : pointer type | -| CookieWithoutHttpOnly.go:120:20:120:21 | &... [pointer] : Cookie | CookieWithoutHttpOnly.go:120:21:120:21 | c : Cookie | -| CookieWithoutHttpOnly.go:120:20:120:21 | &... [pointer] : Cookie | CookieWithoutHttpOnly.go:120:21:120:21 | c : Cookie | -| CookieWithoutHttpOnly.go:120:21:120:21 | c : Cookie | CookieWithoutHttpOnly.go:120:20:120:21 | &... [pointer] : Cookie | -| CookieWithoutHttpOnly.go:120:21:120:21 | c : Cookie | CookieWithoutHttpOnly.go:120:20:120:21 | &... [pointer] : Cookie | -| CookieWithoutHttpOnly.go:123:13:123:49 | call to NewCookieStore : pointer type | CookieWithoutHttpOnly.go:126:16:126:20 | store : pointer type | -| CookieWithoutHttpOnly.go:123:13:123:49 | call to NewCookieStore : pointer type | CookieWithoutHttpOnly.go:134:16:134:20 | store : pointer type | -| CookieWithoutHttpOnly.go:123:13:123:49 | call to NewCookieStore : pointer type | CookieWithoutHttpOnly.go:146:16:146:20 | store : pointer type | -| CookieWithoutHttpOnly.go:123:13:123:49 | call to NewCookieStore : pointer type | CookieWithoutHttpOnly.go:158:16:158:20 | store : pointer type | -| CookieWithoutHttpOnly.go:123:13:123:49 | call to NewCookieStore : pointer type | CookieWithoutHttpOnly.go:170:16:170:20 | store : pointer type | -| CookieWithoutHttpOnly.go:123:13:123:49 | call to NewCookieStore : pointer type | CookieWithoutHttpOnly.go:183:16:183:20 | store : pointer type | -| CookieWithoutHttpOnly.go:123:13:123:49 | call to NewCookieStore : pointer type | CookieWithoutHttpOnly.go:195:16:195:20 | store : pointer type | -| CookieWithoutHttpOnly.go:126:16:126:20 | store : pointer type | CookieWithoutHttpOnly.go:129:2:129:8 | session | -| CookieWithoutHttpOnly.go:133:2:133:9 | definition of httpOnly : bool | CookieWithoutHttpOnly.go:135:2:135:8 | implicit dereference : Session | -| CookieWithoutHttpOnly.go:133:2:133:9 | definition of httpOnly : bool | CookieWithoutHttpOnly.go:137:2:137:8 | implicit dereference : Session | -| CookieWithoutHttpOnly.go:133:2:133:9 | definition of httpOnly : bool | CookieWithoutHttpOnly.go:142:2:142:8 | session | -| CookieWithoutHttpOnly.go:133:14:133:18 | false : bool | CookieWithoutHttpOnly.go:135:2:135:8 | implicit dereference : Session | -| CookieWithoutHttpOnly.go:133:14:133:18 | false : bool | CookieWithoutHttpOnly.go:137:2:137:8 | implicit dereference : Session | -| CookieWithoutHttpOnly.go:133:14:133:18 | false : bool | CookieWithoutHttpOnly.go:142:2:142:8 | session | -| CookieWithoutHttpOnly.go:134:2:134:8 | definition of session [pointer] : Session | CookieWithoutHttpOnly.go:135:2:135:8 | session [pointer] : Session | -| CookieWithoutHttpOnly.go:134:2:134:8 | definition of session [pointer] : Session | CookieWithoutHttpOnly.go:135:2:135:8 | session [pointer] : Session | -| CookieWithoutHttpOnly.go:134:2:134:8 | definition of session [pointer] : Session | CookieWithoutHttpOnly.go:137:2:137:8 | session [pointer] : Session | -| CookieWithoutHttpOnly.go:134:2:134:8 | definition of session [pointer] : Session | CookieWithoutHttpOnly.go:137:2:137:8 | session [pointer] : Session | -| CookieWithoutHttpOnly.go:134:2:134:8 | definition of session [pointer] : Session | CookieWithoutHttpOnly.go:142:2:142:8 | session | -| CookieWithoutHttpOnly.go:134:2:134:8 | definition of session [pointer] : Session | CookieWithoutHttpOnly.go:142:2:142:8 | session | -| CookieWithoutHttpOnly.go:134:16:134:20 | store : pointer type | CookieWithoutHttpOnly.go:142:2:142:8 | session | -| CookieWithoutHttpOnly.go:135:2:135:8 | implicit dereference : Session | CookieWithoutHttpOnly.go:134:2:134:8 | definition of session [pointer] : Session | -| CookieWithoutHttpOnly.go:135:2:135:8 | implicit dereference : Session | CookieWithoutHttpOnly.go:134:2:134:8 | definition of session [pointer] : Session | -| CookieWithoutHttpOnly.go:135:2:135:8 | implicit dereference : Session | CookieWithoutHttpOnly.go:135:2:135:8 | implicit dereference : Session | -| CookieWithoutHttpOnly.go:135:2:135:8 | implicit dereference : Session | CookieWithoutHttpOnly.go:135:2:135:8 | implicit dereference : Session | -| CookieWithoutHttpOnly.go:135:2:135:8 | implicit dereference : Session | CookieWithoutHttpOnly.go:137:2:137:8 | implicit dereference : Session | -| CookieWithoutHttpOnly.go:135:2:135:8 | implicit dereference : Session | CookieWithoutHttpOnly.go:137:2:137:8 | implicit dereference : Session | -| CookieWithoutHttpOnly.go:135:2:135:8 | implicit dereference : Session | CookieWithoutHttpOnly.go:142:2:142:8 | session | -| CookieWithoutHttpOnly.go:135:2:135:8 | implicit dereference : Session | CookieWithoutHttpOnly.go:142:2:142:8 | session | -| CookieWithoutHttpOnly.go:135:2:135:8 | session [pointer] : Session | CookieWithoutHttpOnly.go:135:2:135:8 | implicit dereference : Session | -| CookieWithoutHttpOnly.go:135:2:135:8 | session [pointer] : Session | CookieWithoutHttpOnly.go:135:2:135:8 | implicit dereference : Session | -| CookieWithoutHttpOnly.go:137:2:137:8 | implicit dereference : Session | CookieWithoutHttpOnly.go:134:2:134:8 | definition of session [pointer] : Session | -| CookieWithoutHttpOnly.go:137:2:137:8 | implicit dereference : Session | CookieWithoutHttpOnly.go:134:2:134:8 | definition of session [pointer] : Session | -| CookieWithoutHttpOnly.go:137:2:137:8 | implicit dereference : Session | CookieWithoutHttpOnly.go:135:2:135:8 | implicit dereference : Session | -| CookieWithoutHttpOnly.go:137:2:137:8 | implicit dereference : Session | CookieWithoutHttpOnly.go:135:2:135:8 | implicit dereference : Session | -| CookieWithoutHttpOnly.go:137:2:137:8 | implicit dereference : Session | CookieWithoutHttpOnly.go:137:2:137:8 | implicit dereference : Session | -| CookieWithoutHttpOnly.go:137:2:137:8 | implicit dereference : Session | CookieWithoutHttpOnly.go:137:2:137:8 | implicit dereference : Session | -| CookieWithoutHttpOnly.go:137:2:137:8 | implicit dereference : Session | CookieWithoutHttpOnly.go:142:2:142:8 | session | -| CookieWithoutHttpOnly.go:137:2:137:8 | implicit dereference : Session | CookieWithoutHttpOnly.go:142:2:142:8 | session | -| CookieWithoutHttpOnly.go:137:2:137:8 | session [pointer] : Session | CookieWithoutHttpOnly.go:137:2:137:8 | implicit dereference : Session | -| CookieWithoutHttpOnly.go:137:2:137:8 | session [pointer] : Session | CookieWithoutHttpOnly.go:137:2:137:8 | implicit dereference : Session | -| CookieWithoutHttpOnly.go:137:21:140:2 | struct literal : Options | CookieWithoutHttpOnly.go:135:2:135:8 | implicit dereference : Session | -| CookieWithoutHttpOnly.go:137:21:140:2 | struct literal : Options | CookieWithoutHttpOnly.go:137:2:137:8 | implicit dereference : Session | -| CookieWithoutHttpOnly.go:137:21:140:2 | struct literal : Options | CookieWithoutHttpOnly.go:142:2:142:8 | session | -| CookieWithoutHttpOnly.go:139:13:139:20 | httpOnly : bool | CookieWithoutHttpOnly.go:135:2:135:8 | implicit dereference : Session | -| CookieWithoutHttpOnly.go:139:13:139:20 | httpOnly : bool | CookieWithoutHttpOnly.go:137:2:137:8 | implicit dereference : Session | -| CookieWithoutHttpOnly.go:139:13:139:20 | httpOnly : bool | CookieWithoutHttpOnly.go:142:2:142:8 | session | -| CookieWithoutHttpOnly.go:146:2:146:8 | definition of session [pointer] : Session | CookieWithoutHttpOnly.go:147:2:147:8 | session [pointer] : Session | -| CookieWithoutHttpOnly.go:146:2:146:8 | definition of session [pointer] : Session | CookieWithoutHttpOnly.go:149:2:149:8 | session [pointer] : Session | -| CookieWithoutHttpOnly.go:146:2:146:8 | definition of session [pointer] : Session | CookieWithoutHttpOnly.go:153:2:153:8 | session | -| CookieWithoutHttpOnly.go:146:16:146:20 | store : pointer type | CookieWithoutHttpOnly.go:153:2:153:8 | session | -| CookieWithoutHttpOnly.go:147:2:147:8 | implicit dereference : Session | CookieWithoutHttpOnly.go:146:2:146:8 | definition of session [pointer] : Session | -| CookieWithoutHttpOnly.go:147:2:147:8 | implicit dereference : Session | CookieWithoutHttpOnly.go:147:2:147:8 | implicit dereference : Session | -| CookieWithoutHttpOnly.go:147:2:147:8 | implicit dereference : Session | CookieWithoutHttpOnly.go:149:2:149:8 | implicit dereference : Session | -| CookieWithoutHttpOnly.go:147:2:147:8 | implicit dereference : Session | CookieWithoutHttpOnly.go:153:2:153:8 | session | -| CookieWithoutHttpOnly.go:147:2:147:8 | session [pointer] : Session | CookieWithoutHttpOnly.go:147:2:147:8 | implicit dereference : Session | -| CookieWithoutHttpOnly.go:149:2:149:8 | implicit dereference : Session | CookieWithoutHttpOnly.go:146:2:146:8 | definition of session [pointer] : Session | -| CookieWithoutHttpOnly.go:149:2:149:8 | implicit dereference : Session | CookieWithoutHttpOnly.go:147:2:147:8 | implicit dereference : Session | -| CookieWithoutHttpOnly.go:149:2:149:8 | implicit dereference : Session | CookieWithoutHttpOnly.go:149:2:149:8 | implicit dereference : Session | -| CookieWithoutHttpOnly.go:149:2:149:8 | implicit dereference : Session | CookieWithoutHttpOnly.go:153:2:153:8 | session | -| CookieWithoutHttpOnly.go:149:2:149:8 | session [pointer] : Session | CookieWithoutHttpOnly.go:149:2:149:8 | implicit dereference : Session | -| CookieWithoutHttpOnly.go:149:21:151:2 | struct literal : Options | CookieWithoutHttpOnly.go:147:2:147:8 | implicit dereference : Session | -| CookieWithoutHttpOnly.go:149:21:151:2 | struct literal : Options | CookieWithoutHttpOnly.go:149:2:149:8 | implicit dereference : Session | -| CookieWithoutHttpOnly.go:149:21:151:2 | struct literal : Options | CookieWithoutHttpOnly.go:153:2:153:8 | session | -| CookieWithoutHttpOnly.go:157:2:157:9 | definition of httpOnly : bool | CookieWithoutHttpOnly.go:159:2:159:8 | implicit dereference : Session | -| CookieWithoutHttpOnly.go:157:2:157:9 | definition of httpOnly : bool | CookieWithoutHttpOnly.go:161:2:161:8 | implicit dereference : Session | -| CookieWithoutHttpOnly.go:157:2:157:9 | definition of httpOnly : bool | CookieWithoutHttpOnly.go:166:2:166:8 | session | -| CookieWithoutHttpOnly.go:157:14:157:17 | true : bool | CookieWithoutHttpOnly.go:159:2:159:8 | implicit dereference : Session | -| CookieWithoutHttpOnly.go:157:14:157:17 | true : bool | CookieWithoutHttpOnly.go:161:2:161:8 | implicit dereference : Session | -| CookieWithoutHttpOnly.go:157:14:157:17 | true : bool | CookieWithoutHttpOnly.go:166:2:166:8 | session | -| CookieWithoutHttpOnly.go:158:2:158:8 | definition of session [pointer] : Session | CookieWithoutHttpOnly.go:159:2:159:8 | session [pointer] : Session | -| CookieWithoutHttpOnly.go:158:2:158:8 | definition of session [pointer] : Session | CookieWithoutHttpOnly.go:159:2:159:8 | session [pointer] : Session | -| CookieWithoutHttpOnly.go:158:2:158:8 | definition of session [pointer] : Session | CookieWithoutHttpOnly.go:161:2:161:8 | session [pointer] : Session | -| CookieWithoutHttpOnly.go:158:2:158:8 | definition of session [pointer] : Session | CookieWithoutHttpOnly.go:161:2:161:8 | session [pointer] : Session | -| CookieWithoutHttpOnly.go:158:2:158:8 | definition of session [pointer] : Session | CookieWithoutHttpOnly.go:166:2:166:8 | session | -| CookieWithoutHttpOnly.go:158:2:158:8 | definition of session [pointer] : Session | CookieWithoutHttpOnly.go:166:2:166:8 | session | -| CookieWithoutHttpOnly.go:158:16:158:20 | store : pointer type | CookieWithoutHttpOnly.go:166:2:166:8 | session | -| CookieWithoutHttpOnly.go:159:2:159:8 | implicit dereference : Session | CookieWithoutHttpOnly.go:158:2:158:8 | definition of session [pointer] : Session | -| CookieWithoutHttpOnly.go:159:2:159:8 | implicit dereference : Session | CookieWithoutHttpOnly.go:158:2:158:8 | definition of session [pointer] : Session | -| CookieWithoutHttpOnly.go:159:2:159:8 | implicit dereference : Session | CookieWithoutHttpOnly.go:159:2:159:8 | implicit dereference : Session | -| CookieWithoutHttpOnly.go:159:2:159:8 | implicit dereference : Session | CookieWithoutHttpOnly.go:159:2:159:8 | implicit dereference : Session | -| CookieWithoutHttpOnly.go:159:2:159:8 | implicit dereference : Session | CookieWithoutHttpOnly.go:161:2:161:8 | implicit dereference : Session | -| CookieWithoutHttpOnly.go:159:2:159:8 | implicit dereference : Session | CookieWithoutHttpOnly.go:161:2:161:8 | implicit dereference : Session | -| CookieWithoutHttpOnly.go:159:2:159:8 | implicit dereference : Session | CookieWithoutHttpOnly.go:166:2:166:8 | session | -| CookieWithoutHttpOnly.go:159:2:159:8 | implicit dereference : Session | CookieWithoutHttpOnly.go:166:2:166:8 | session | -| CookieWithoutHttpOnly.go:159:2:159:8 | session [pointer] : Session | CookieWithoutHttpOnly.go:159:2:159:8 | implicit dereference : Session | -| CookieWithoutHttpOnly.go:159:2:159:8 | session [pointer] : Session | CookieWithoutHttpOnly.go:159:2:159:8 | implicit dereference : Session | -| CookieWithoutHttpOnly.go:161:2:161:8 | implicit dereference : Session | CookieWithoutHttpOnly.go:158:2:158:8 | definition of session [pointer] : Session | -| CookieWithoutHttpOnly.go:161:2:161:8 | implicit dereference : Session | CookieWithoutHttpOnly.go:158:2:158:8 | definition of session [pointer] : Session | -| CookieWithoutHttpOnly.go:161:2:161:8 | implicit dereference : Session | CookieWithoutHttpOnly.go:159:2:159:8 | implicit dereference : Session | -| CookieWithoutHttpOnly.go:161:2:161:8 | implicit dereference : Session | CookieWithoutHttpOnly.go:159:2:159:8 | implicit dereference : Session | -| CookieWithoutHttpOnly.go:161:2:161:8 | implicit dereference : Session | CookieWithoutHttpOnly.go:161:2:161:8 | implicit dereference : Session | -| CookieWithoutHttpOnly.go:161:2:161:8 | implicit dereference : Session | CookieWithoutHttpOnly.go:161:2:161:8 | implicit dereference : Session | -| CookieWithoutHttpOnly.go:161:2:161:8 | implicit dereference : Session | CookieWithoutHttpOnly.go:166:2:166:8 | session | -| CookieWithoutHttpOnly.go:161:2:161:8 | implicit dereference : Session | CookieWithoutHttpOnly.go:166:2:166:8 | session | -| CookieWithoutHttpOnly.go:161:2:161:8 | session [pointer] : Session | CookieWithoutHttpOnly.go:161:2:161:8 | implicit dereference : Session | -| CookieWithoutHttpOnly.go:161:2:161:8 | session [pointer] : Session | CookieWithoutHttpOnly.go:161:2:161:8 | implicit dereference : Session | -| CookieWithoutHttpOnly.go:161:21:164:2 | struct literal : Options | CookieWithoutHttpOnly.go:159:2:159:8 | implicit dereference : Session | -| CookieWithoutHttpOnly.go:161:21:164:2 | struct literal : Options | CookieWithoutHttpOnly.go:161:2:161:8 | implicit dereference : Session | -| CookieWithoutHttpOnly.go:161:21:164:2 | struct literal : Options | CookieWithoutHttpOnly.go:166:2:166:8 | session | -| CookieWithoutHttpOnly.go:163:13:163:20 | httpOnly : bool | CookieWithoutHttpOnly.go:159:2:159:8 | implicit dereference : Session | -| CookieWithoutHttpOnly.go:163:13:163:20 | httpOnly : bool | CookieWithoutHttpOnly.go:161:2:161:8 | implicit dereference : Session | -| CookieWithoutHttpOnly.go:163:13:163:20 | httpOnly : bool | CookieWithoutHttpOnly.go:166:2:166:8 | session | -| CookieWithoutHttpOnly.go:169:56:169:63 | argument corresponding to httpOnly : bool | CookieWithoutHttpOnly.go:171:2:171:8 | implicit dereference : Session | -| CookieWithoutHttpOnly.go:169:56:169:63 | argument corresponding to httpOnly : bool | CookieWithoutHttpOnly.go:173:2:173:8 | implicit dereference : Session | -| CookieWithoutHttpOnly.go:169:56:169:63 | argument corresponding to httpOnly : bool | CookieWithoutHttpOnly.go:178:2:178:8 | session | -| CookieWithoutHttpOnly.go:169:56:169:63 | definition of httpOnly : bool | CookieWithoutHttpOnly.go:171:2:171:8 | implicit dereference : Session | -| CookieWithoutHttpOnly.go:169:56:169:63 | definition of httpOnly : bool | CookieWithoutHttpOnly.go:173:2:173:8 | implicit dereference : Session | -| CookieWithoutHttpOnly.go:169:56:169:63 | definition of httpOnly : bool | CookieWithoutHttpOnly.go:178:2:178:8 | session | -| CookieWithoutHttpOnly.go:170:2:170:8 | definition of session [pointer] : Session | CookieWithoutHttpOnly.go:171:2:171:8 | session [pointer] : Session | -| CookieWithoutHttpOnly.go:170:2:170:8 | definition of session [pointer] : Session | CookieWithoutHttpOnly.go:171:2:171:8 | session [pointer] : Session | -| CookieWithoutHttpOnly.go:170:2:170:8 | definition of session [pointer] : Session | CookieWithoutHttpOnly.go:173:2:173:8 | session [pointer] : Session | -| CookieWithoutHttpOnly.go:170:2:170:8 | definition of session [pointer] : Session | CookieWithoutHttpOnly.go:173:2:173:8 | session [pointer] : Session | -| CookieWithoutHttpOnly.go:170:2:170:8 | definition of session [pointer] : Session | CookieWithoutHttpOnly.go:178:2:178:8 | session | -| CookieWithoutHttpOnly.go:170:2:170:8 | definition of session [pointer] : Session | CookieWithoutHttpOnly.go:178:2:178:8 | session | -| CookieWithoutHttpOnly.go:170:16:170:20 | store : pointer type | CookieWithoutHttpOnly.go:178:2:178:8 | session | -| CookieWithoutHttpOnly.go:171:2:171:8 | implicit dereference : Session | CookieWithoutHttpOnly.go:170:2:170:8 | definition of session [pointer] : Session | -| CookieWithoutHttpOnly.go:171:2:171:8 | implicit dereference : Session | CookieWithoutHttpOnly.go:170:2:170:8 | definition of session [pointer] : Session | -| CookieWithoutHttpOnly.go:171:2:171:8 | implicit dereference : Session | CookieWithoutHttpOnly.go:171:2:171:8 | implicit dereference : Session | -| CookieWithoutHttpOnly.go:171:2:171:8 | implicit dereference : Session | CookieWithoutHttpOnly.go:171:2:171:8 | implicit dereference : Session | -| CookieWithoutHttpOnly.go:171:2:171:8 | implicit dereference : Session | CookieWithoutHttpOnly.go:173:2:173:8 | implicit dereference : Session | -| CookieWithoutHttpOnly.go:171:2:171:8 | implicit dereference : Session | CookieWithoutHttpOnly.go:173:2:173:8 | implicit dereference : Session | -| CookieWithoutHttpOnly.go:171:2:171:8 | implicit dereference : Session | CookieWithoutHttpOnly.go:178:2:178:8 | session | -| CookieWithoutHttpOnly.go:171:2:171:8 | implicit dereference : Session | CookieWithoutHttpOnly.go:178:2:178:8 | session | -| CookieWithoutHttpOnly.go:171:2:171:8 | session [pointer] : Session | CookieWithoutHttpOnly.go:171:2:171:8 | implicit dereference : Session | -| CookieWithoutHttpOnly.go:171:2:171:8 | session [pointer] : Session | CookieWithoutHttpOnly.go:171:2:171:8 | implicit dereference : Session | -| CookieWithoutHttpOnly.go:173:2:173:8 | implicit dereference : Session | CookieWithoutHttpOnly.go:170:2:170:8 | definition of session [pointer] : Session | -| CookieWithoutHttpOnly.go:173:2:173:8 | implicit dereference : Session | CookieWithoutHttpOnly.go:170:2:170:8 | definition of session [pointer] : Session | -| CookieWithoutHttpOnly.go:173:2:173:8 | implicit dereference : Session | CookieWithoutHttpOnly.go:171:2:171:8 | implicit dereference : Session | -| CookieWithoutHttpOnly.go:173:2:173:8 | implicit dereference : Session | CookieWithoutHttpOnly.go:171:2:171:8 | implicit dereference : Session | -| CookieWithoutHttpOnly.go:173:2:173:8 | implicit dereference : Session | CookieWithoutHttpOnly.go:173:2:173:8 | implicit dereference : Session | -| CookieWithoutHttpOnly.go:173:2:173:8 | implicit dereference : Session | CookieWithoutHttpOnly.go:173:2:173:8 | implicit dereference : Session | -| CookieWithoutHttpOnly.go:173:2:173:8 | implicit dereference : Session | CookieWithoutHttpOnly.go:178:2:178:8 | session | -| CookieWithoutHttpOnly.go:173:2:173:8 | implicit dereference : Session | CookieWithoutHttpOnly.go:178:2:178:8 | session | -| CookieWithoutHttpOnly.go:173:2:173:8 | session [pointer] : Session | CookieWithoutHttpOnly.go:173:2:173:8 | implicit dereference : Session | -| CookieWithoutHttpOnly.go:173:2:173:8 | session [pointer] : Session | CookieWithoutHttpOnly.go:173:2:173:8 | implicit dereference : Session | -| CookieWithoutHttpOnly.go:173:21:176:2 | struct literal : Options | CookieWithoutHttpOnly.go:171:2:171:8 | implicit dereference : Session | -| CookieWithoutHttpOnly.go:173:21:176:2 | struct literal : Options | CookieWithoutHttpOnly.go:173:2:173:8 | implicit dereference : Session | -| CookieWithoutHttpOnly.go:173:21:176:2 | struct literal : Options | CookieWithoutHttpOnly.go:178:2:178:8 | session | -| CookieWithoutHttpOnly.go:175:13:175:20 | httpOnly : bool | CookieWithoutHttpOnly.go:171:2:171:8 | implicit dereference : Session | -| CookieWithoutHttpOnly.go:175:13:175:20 | httpOnly : bool | CookieWithoutHttpOnly.go:173:2:173:8 | implicit dereference : Session | -| CookieWithoutHttpOnly.go:175:13:175:20 | httpOnly : bool | CookieWithoutHttpOnly.go:178:2:178:8 | session | -| CookieWithoutHttpOnly.go:183:16:183:20 | store : pointer type | CookieWithoutHttpOnly.go:191:19:191:25 | session | -| CookieWithoutHttpOnly.go:195:16:195:20 | store : pointer type | CookieWithoutHttpOnly.go:202:19:202:25 | session | +| CookieWithoutHttpOnly.go:12:10:12:18 | "session" | CookieWithoutHttpOnly.go:15:20:15:21 | &... | +| CookieWithoutHttpOnly.go:12:10:12:18 | "session" | CookieWithoutHttpOnly.go:15:20:15:21 | &... | +| CookieWithoutHttpOnly.go:12:10:12:18 | "session" | CookieWithoutHttpOnly.go:15:21:15:21 | c | +| CookieWithoutHttpOnly.go:15:20:15:21 | &... | CookieWithoutHttpOnly.go:15:20:15:21 | &... | +| CookieWithoutHttpOnly.go:15:20:15:21 | &... | CookieWithoutHttpOnly.go:15:20:15:21 | &... | +| CookieWithoutHttpOnly.go:15:20:15:21 | &... | CookieWithoutHttpOnly.go:15:21:15:21 | c | +| CookieWithoutHttpOnly.go:15:20:15:21 | &... [pointer] | CookieWithoutHttpOnly.go:15:20:15:21 | &... | +| CookieWithoutHttpOnly.go:15:20:15:21 | &... [pointer] | CookieWithoutHttpOnly.go:15:20:15:21 | &... | +| CookieWithoutHttpOnly.go:15:20:15:21 | &... [pointer] | CookieWithoutHttpOnly.go:15:21:15:21 | c | +| CookieWithoutHttpOnly.go:15:21:15:21 | c | CookieWithoutHttpOnly.go:15:20:15:21 | &... [pointer] | +| CookieWithoutHttpOnly.go:20:13:20:21 | "session" | CookieWithoutHttpOnly.go:24:20:24:21 | &... | +| CookieWithoutHttpOnly.go:20:13:20:21 | "session" | CookieWithoutHttpOnly.go:24:20:24:21 | &... | +| CookieWithoutHttpOnly.go:20:13:20:21 | "session" | CookieWithoutHttpOnly.go:24:21:24:21 | c | +| CookieWithoutHttpOnly.go:22:13:22:17 | false | CookieWithoutHttpOnly.go:24:20:24:21 | &... | +| CookieWithoutHttpOnly.go:22:13:22:17 | false | CookieWithoutHttpOnly.go:24:20:24:21 | &... | +| CookieWithoutHttpOnly.go:22:13:22:17 | false | CookieWithoutHttpOnly.go:24:21:24:21 | c | +| CookieWithoutHttpOnly.go:24:20:24:21 | &... | CookieWithoutHttpOnly.go:24:20:24:21 | &... | +| CookieWithoutHttpOnly.go:24:20:24:21 | &... | CookieWithoutHttpOnly.go:24:20:24:21 | &... | +| CookieWithoutHttpOnly.go:24:20:24:21 | &... | CookieWithoutHttpOnly.go:24:20:24:21 | &... | +| CookieWithoutHttpOnly.go:24:20:24:21 | &... | CookieWithoutHttpOnly.go:24:20:24:21 | &... | +| CookieWithoutHttpOnly.go:24:20:24:21 | &... | CookieWithoutHttpOnly.go:24:21:24:21 | c | +| CookieWithoutHttpOnly.go:24:20:24:21 | &... | CookieWithoutHttpOnly.go:24:21:24:21 | c | +| CookieWithoutHttpOnly.go:24:20:24:21 | &... [pointer] | CookieWithoutHttpOnly.go:24:20:24:21 | &... | +| CookieWithoutHttpOnly.go:24:20:24:21 | &... [pointer] | CookieWithoutHttpOnly.go:24:20:24:21 | &... | +| CookieWithoutHttpOnly.go:24:20:24:21 | &... [pointer] | CookieWithoutHttpOnly.go:24:20:24:21 | &... | +| CookieWithoutHttpOnly.go:24:20:24:21 | &... [pointer] | CookieWithoutHttpOnly.go:24:20:24:21 | &... | +| CookieWithoutHttpOnly.go:24:20:24:21 | &... [pointer] | CookieWithoutHttpOnly.go:24:21:24:21 | c | +| CookieWithoutHttpOnly.go:24:20:24:21 | &... [pointer] | CookieWithoutHttpOnly.go:24:21:24:21 | c | +| CookieWithoutHttpOnly.go:24:21:24:21 | c | CookieWithoutHttpOnly.go:24:20:24:21 | &... [pointer] | +| CookieWithoutHttpOnly.go:24:21:24:21 | c | CookieWithoutHttpOnly.go:24:20:24:21 | &... [pointer] | +| CookieWithoutHttpOnly.go:29:13:29:21 | "session" | CookieWithoutHttpOnly.go:33:20:33:21 | &... | +| CookieWithoutHttpOnly.go:29:13:29:21 | "session" | CookieWithoutHttpOnly.go:33:20:33:21 | &... | +| CookieWithoutHttpOnly.go:29:13:29:21 | "session" | CookieWithoutHttpOnly.go:33:21:33:21 | c | +| CookieWithoutHttpOnly.go:31:13:31:16 | true | CookieWithoutHttpOnly.go:33:20:33:21 | &... | +| CookieWithoutHttpOnly.go:31:13:31:16 | true | CookieWithoutHttpOnly.go:33:20:33:21 | &... | +| CookieWithoutHttpOnly.go:31:13:31:16 | true | CookieWithoutHttpOnly.go:33:21:33:21 | c | +| CookieWithoutHttpOnly.go:33:20:33:21 | &... | CookieWithoutHttpOnly.go:33:20:33:21 | &... | +| CookieWithoutHttpOnly.go:33:20:33:21 | &... | CookieWithoutHttpOnly.go:33:20:33:21 | &... | +| CookieWithoutHttpOnly.go:33:20:33:21 | &... | CookieWithoutHttpOnly.go:33:20:33:21 | &... | +| CookieWithoutHttpOnly.go:33:20:33:21 | &... | CookieWithoutHttpOnly.go:33:20:33:21 | &... | +| CookieWithoutHttpOnly.go:33:20:33:21 | &... | CookieWithoutHttpOnly.go:33:21:33:21 | c | +| CookieWithoutHttpOnly.go:33:20:33:21 | &... | CookieWithoutHttpOnly.go:33:21:33:21 | c | +| CookieWithoutHttpOnly.go:33:20:33:21 | &... [pointer] | CookieWithoutHttpOnly.go:33:20:33:21 | &... | +| CookieWithoutHttpOnly.go:33:20:33:21 | &... [pointer] | CookieWithoutHttpOnly.go:33:20:33:21 | &... | +| CookieWithoutHttpOnly.go:33:20:33:21 | &... [pointer] | CookieWithoutHttpOnly.go:33:20:33:21 | &... | +| CookieWithoutHttpOnly.go:33:20:33:21 | &... [pointer] | CookieWithoutHttpOnly.go:33:20:33:21 | &... | +| CookieWithoutHttpOnly.go:33:20:33:21 | &... [pointer] | CookieWithoutHttpOnly.go:33:21:33:21 | c | +| CookieWithoutHttpOnly.go:33:20:33:21 | &... [pointer] | CookieWithoutHttpOnly.go:33:21:33:21 | c | +| CookieWithoutHttpOnly.go:33:21:33:21 | c | CookieWithoutHttpOnly.go:33:20:33:21 | &... [pointer] | +| CookieWithoutHttpOnly.go:33:21:33:21 | c | CookieWithoutHttpOnly.go:33:20:33:21 | &... [pointer] | +| CookieWithoutHttpOnly.go:38:10:38:18 | "session" | CookieWithoutHttpOnly.go:42:20:42:21 | &... | +| CookieWithoutHttpOnly.go:38:10:38:18 | "session" | CookieWithoutHttpOnly.go:42:20:42:21 | &... | +| CookieWithoutHttpOnly.go:38:10:38:18 | "session" | CookieWithoutHttpOnly.go:42:21:42:21 | c | +| CookieWithoutHttpOnly.go:41:15:41:18 | true | CookieWithoutHttpOnly.go:42:20:42:21 | &... | +| CookieWithoutHttpOnly.go:41:15:41:18 | true | CookieWithoutHttpOnly.go:42:20:42:21 | &... | +| CookieWithoutHttpOnly.go:41:15:41:18 | true | CookieWithoutHttpOnly.go:42:21:42:21 | c | +| CookieWithoutHttpOnly.go:42:20:42:21 | &... | CookieWithoutHttpOnly.go:42:20:42:21 | &... | +| CookieWithoutHttpOnly.go:42:20:42:21 | &... | CookieWithoutHttpOnly.go:42:20:42:21 | &... | +| CookieWithoutHttpOnly.go:42:20:42:21 | &... | CookieWithoutHttpOnly.go:42:20:42:21 | &... | +| CookieWithoutHttpOnly.go:42:20:42:21 | &... | CookieWithoutHttpOnly.go:42:20:42:21 | &... | +| CookieWithoutHttpOnly.go:42:20:42:21 | &... | CookieWithoutHttpOnly.go:42:21:42:21 | c | +| CookieWithoutHttpOnly.go:42:20:42:21 | &... | CookieWithoutHttpOnly.go:42:21:42:21 | c | +| CookieWithoutHttpOnly.go:42:20:42:21 | &... [pointer] | CookieWithoutHttpOnly.go:42:20:42:21 | &... | +| CookieWithoutHttpOnly.go:42:20:42:21 | &... [pointer] | CookieWithoutHttpOnly.go:42:20:42:21 | &... | +| CookieWithoutHttpOnly.go:42:20:42:21 | &... [pointer] | CookieWithoutHttpOnly.go:42:20:42:21 | &... | +| CookieWithoutHttpOnly.go:42:20:42:21 | &... [pointer] | CookieWithoutHttpOnly.go:42:20:42:21 | &... | +| CookieWithoutHttpOnly.go:42:20:42:21 | &... [pointer] | CookieWithoutHttpOnly.go:42:21:42:21 | c | +| CookieWithoutHttpOnly.go:42:20:42:21 | &... [pointer] | CookieWithoutHttpOnly.go:42:21:42:21 | c | +| CookieWithoutHttpOnly.go:42:21:42:21 | c | CookieWithoutHttpOnly.go:42:20:42:21 | &... [pointer] | +| CookieWithoutHttpOnly.go:42:21:42:21 | c | CookieWithoutHttpOnly.go:42:20:42:21 | &... [pointer] | +| CookieWithoutHttpOnly.go:47:10:47:18 | "session" | CookieWithoutHttpOnly.go:51:20:51:21 | &... | +| CookieWithoutHttpOnly.go:47:10:47:18 | "session" | CookieWithoutHttpOnly.go:51:20:51:21 | &... | +| CookieWithoutHttpOnly.go:47:10:47:18 | "session" | CookieWithoutHttpOnly.go:51:21:51:21 | c | +| CookieWithoutHttpOnly.go:50:15:50:19 | false | CookieWithoutHttpOnly.go:51:20:51:21 | &... | +| CookieWithoutHttpOnly.go:50:15:50:19 | false | CookieWithoutHttpOnly.go:51:20:51:21 | &... | +| CookieWithoutHttpOnly.go:50:15:50:19 | false | CookieWithoutHttpOnly.go:51:21:51:21 | c | +| CookieWithoutHttpOnly.go:51:20:51:21 | &... | CookieWithoutHttpOnly.go:51:20:51:21 | &... | +| CookieWithoutHttpOnly.go:51:20:51:21 | &... | CookieWithoutHttpOnly.go:51:20:51:21 | &... | +| CookieWithoutHttpOnly.go:51:20:51:21 | &... | CookieWithoutHttpOnly.go:51:20:51:21 | &... | +| CookieWithoutHttpOnly.go:51:20:51:21 | &... | CookieWithoutHttpOnly.go:51:20:51:21 | &... | +| CookieWithoutHttpOnly.go:51:20:51:21 | &... | CookieWithoutHttpOnly.go:51:21:51:21 | c | +| CookieWithoutHttpOnly.go:51:20:51:21 | &... | CookieWithoutHttpOnly.go:51:21:51:21 | c | +| CookieWithoutHttpOnly.go:51:20:51:21 | &... [pointer] | CookieWithoutHttpOnly.go:51:20:51:21 | &... | +| CookieWithoutHttpOnly.go:51:20:51:21 | &... [pointer] | CookieWithoutHttpOnly.go:51:20:51:21 | &... | +| CookieWithoutHttpOnly.go:51:20:51:21 | &... [pointer] | CookieWithoutHttpOnly.go:51:20:51:21 | &... | +| CookieWithoutHttpOnly.go:51:20:51:21 | &... [pointer] | CookieWithoutHttpOnly.go:51:20:51:21 | &... | +| CookieWithoutHttpOnly.go:51:20:51:21 | &... [pointer] | CookieWithoutHttpOnly.go:51:21:51:21 | c | +| CookieWithoutHttpOnly.go:51:20:51:21 | &... [pointer] | CookieWithoutHttpOnly.go:51:21:51:21 | c | +| CookieWithoutHttpOnly.go:51:21:51:21 | c | CookieWithoutHttpOnly.go:51:20:51:21 | &... [pointer] | +| CookieWithoutHttpOnly.go:51:21:51:21 | c | CookieWithoutHttpOnly.go:51:20:51:21 | &... [pointer] | +| CookieWithoutHttpOnly.go:55:2:55:4 | definition of val | CookieWithoutHttpOnly.go:61:20:61:21 | &... | +| CookieWithoutHttpOnly.go:55:2:55:4 | definition of val | CookieWithoutHttpOnly.go:61:20:61:21 | &... | +| CookieWithoutHttpOnly.go:55:2:55:4 | definition of val | CookieWithoutHttpOnly.go:61:21:61:21 | c | +| CookieWithoutHttpOnly.go:55:9:55:13 | false | CookieWithoutHttpOnly.go:61:20:61:21 | &... | +| CookieWithoutHttpOnly.go:55:9:55:13 | false | CookieWithoutHttpOnly.go:61:20:61:21 | &... | +| CookieWithoutHttpOnly.go:55:9:55:13 | false | CookieWithoutHttpOnly.go:61:21:61:21 | c | +| CookieWithoutHttpOnly.go:57:13:57:21 | "session" | CookieWithoutHttpOnly.go:61:20:61:21 | &... | +| CookieWithoutHttpOnly.go:57:13:57:21 | "session" | CookieWithoutHttpOnly.go:61:20:61:21 | &... | +| CookieWithoutHttpOnly.go:57:13:57:21 | "session" | CookieWithoutHttpOnly.go:61:21:61:21 | c | +| CookieWithoutHttpOnly.go:59:13:59:15 | val | CookieWithoutHttpOnly.go:61:20:61:21 | &... | +| CookieWithoutHttpOnly.go:59:13:59:15 | val | CookieWithoutHttpOnly.go:61:20:61:21 | &... | +| CookieWithoutHttpOnly.go:59:13:59:15 | val | CookieWithoutHttpOnly.go:61:21:61:21 | c | +| CookieWithoutHttpOnly.go:61:20:61:21 | &... | CookieWithoutHttpOnly.go:61:20:61:21 | &... | +| CookieWithoutHttpOnly.go:61:20:61:21 | &... | CookieWithoutHttpOnly.go:61:20:61:21 | &... | +| CookieWithoutHttpOnly.go:61:20:61:21 | &... | CookieWithoutHttpOnly.go:61:20:61:21 | &... | +| CookieWithoutHttpOnly.go:61:20:61:21 | &... | CookieWithoutHttpOnly.go:61:20:61:21 | &... | +| CookieWithoutHttpOnly.go:61:20:61:21 | &... | CookieWithoutHttpOnly.go:61:21:61:21 | c | +| CookieWithoutHttpOnly.go:61:20:61:21 | &... | CookieWithoutHttpOnly.go:61:21:61:21 | c | +| CookieWithoutHttpOnly.go:61:20:61:21 | &... [pointer] | CookieWithoutHttpOnly.go:61:20:61:21 | &... | +| CookieWithoutHttpOnly.go:61:20:61:21 | &... [pointer] | CookieWithoutHttpOnly.go:61:20:61:21 | &... | +| CookieWithoutHttpOnly.go:61:20:61:21 | &... [pointer] | CookieWithoutHttpOnly.go:61:20:61:21 | &... | +| CookieWithoutHttpOnly.go:61:20:61:21 | &... [pointer] | CookieWithoutHttpOnly.go:61:20:61:21 | &... | +| CookieWithoutHttpOnly.go:61:20:61:21 | &... [pointer] | CookieWithoutHttpOnly.go:61:21:61:21 | c | +| CookieWithoutHttpOnly.go:61:20:61:21 | &... [pointer] | CookieWithoutHttpOnly.go:61:21:61:21 | c | +| CookieWithoutHttpOnly.go:61:21:61:21 | c | CookieWithoutHttpOnly.go:61:20:61:21 | &... [pointer] | +| CookieWithoutHttpOnly.go:61:21:61:21 | c | CookieWithoutHttpOnly.go:61:20:61:21 | &... [pointer] | +| CookieWithoutHttpOnly.go:65:2:65:4 | definition of val | CookieWithoutHttpOnly.go:71:20:71:21 | &... | +| CookieWithoutHttpOnly.go:65:2:65:4 | definition of val | CookieWithoutHttpOnly.go:71:20:71:21 | &... | +| CookieWithoutHttpOnly.go:65:2:65:4 | definition of val | CookieWithoutHttpOnly.go:71:21:71:21 | c | +| CookieWithoutHttpOnly.go:65:9:65:12 | true | CookieWithoutHttpOnly.go:71:20:71:21 | &... | +| CookieWithoutHttpOnly.go:65:9:65:12 | true | CookieWithoutHttpOnly.go:71:20:71:21 | &... | +| CookieWithoutHttpOnly.go:65:9:65:12 | true | CookieWithoutHttpOnly.go:71:21:71:21 | c | +| CookieWithoutHttpOnly.go:67:13:67:21 | "session" | CookieWithoutHttpOnly.go:71:20:71:21 | &... | +| CookieWithoutHttpOnly.go:67:13:67:21 | "session" | CookieWithoutHttpOnly.go:71:20:71:21 | &... | +| CookieWithoutHttpOnly.go:67:13:67:21 | "session" | CookieWithoutHttpOnly.go:71:21:71:21 | c | +| CookieWithoutHttpOnly.go:69:13:69:15 | val | CookieWithoutHttpOnly.go:71:20:71:21 | &... | +| CookieWithoutHttpOnly.go:69:13:69:15 | val | CookieWithoutHttpOnly.go:71:20:71:21 | &... | +| CookieWithoutHttpOnly.go:69:13:69:15 | val | CookieWithoutHttpOnly.go:71:21:71:21 | c | +| CookieWithoutHttpOnly.go:71:20:71:21 | &... | CookieWithoutHttpOnly.go:71:20:71:21 | &... | +| CookieWithoutHttpOnly.go:71:20:71:21 | &... | CookieWithoutHttpOnly.go:71:20:71:21 | &... | +| CookieWithoutHttpOnly.go:71:20:71:21 | &... | CookieWithoutHttpOnly.go:71:20:71:21 | &... | +| CookieWithoutHttpOnly.go:71:20:71:21 | &... | CookieWithoutHttpOnly.go:71:20:71:21 | &... | +| CookieWithoutHttpOnly.go:71:20:71:21 | &... | CookieWithoutHttpOnly.go:71:21:71:21 | c | +| CookieWithoutHttpOnly.go:71:20:71:21 | &... | CookieWithoutHttpOnly.go:71:21:71:21 | c | +| CookieWithoutHttpOnly.go:71:20:71:21 | &... [pointer] | CookieWithoutHttpOnly.go:71:20:71:21 | &... | +| CookieWithoutHttpOnly.go:71:20:71:21 | &... [pointer] | CookieWithoutHttpOnly.go:71:20:71:21 | &... | +| CookieWithoutHttpOnly.go:71:20:71:21 | &... [pointer] | CookieWithoutHttpOnly.go:71:20:71:21 | &... | +| CookieWithoutHttpOnly.go:71:20:71:21 | &... [pointer] | CookieWithoutHttpOnly.go:71:20:71:21 | &... | +| CookieWithoutHttpOnly.go:71:20:71:21 | &... [pointer] | CookieWithoutHttpOnly.go:71:21:71:21 | c | +| CookieWithoutHttpOnly.go:71:20:71:21 | &... [pointer] | CookieWithoutHttpOnly.go:71:21:71:21 | c | +| CookieWithoutHttpOnly.go:71:21:71:21 | c | CookieWithoutHttpOnly.go:71:20:71:21 | &... [pointer] | +| CookieWithoutHttpOnly.go:71:21:71:21 | c | CookieWithoutHttpOnly.go:71:20:71:21 | &... [pointer] | +| CookieWithoutHttpOnly.go:75:2:75:4 | definition of val | CookieWithoutHttpOnly.go:81:20:81:21 | &... | +| CookieWithoutHttpOnly.go:75:2:75:4 | definition of val | CookieWithoutHttpOnly.go:81:20:81:21 | &... | +| CookieWithoutHttpOnly.go:75:2:75:4 | definition of val | CookieWithoutHttpOnly.go:81:21:81:21 | c | +| CookieWithoutHttpOnly.go:75:9:75:12 | true | CookieWithoutHttpOnly.go:81:20:81:21 | &... | +| CookieWithoutHttpOnly.go:75:9:75:12 | true | CookieWithoutHttpOnly.go:81:20:81:21 | &... | +| CookieWithoutHttpOnly.go:75:9:75:12 | true | CookieWithoutHttpOnly.go:81:21:81:21 | c | +| CookieWithoutHttpOnly.go:77:10:77:18 | "session" | CookieWithoutHttpOnly.go:81:20:81:21 | &... | +| CookieWithoutHttpOnly.go:77:10:77:18 | "session" | CookieWithoutHttpOnly.go:81:20:81:21 | &... | +| CookieWithoutHttpOnly.go:77:10:77:18 | "session" | CookieWithoutHttpOnly.go:81:21:81:21 | c | +| CookieWithoutHttpOnly.go:80:15:80:17 | val | CookieWithoutHttpOnly.go:81:20:81:21 | &... | +| CookieWithoutHttpOnly.go:80:15:80:17 | val | CookieWithoutHttpOnly.go:81:20:81:21 | &... | +| CookieWithoutHttpOnly.go:80:15:80:17 | val | CookieWithoutHttpOnly.go:81:21:81:21 | c | +| CookieWithoutHttpOnly.go:81:20:81:21 | &... | CookieWithoutHttpOnly.go:81:20:81:21 | &... | +| CookieWithoutHttpOnly.go:81:20:81:21 | &... | CookieWithoutHttpOnly.go:81:20:81:21 | &... | +| CookieWithoutHttpOnly.go:81:20:81:21 | &... | CookieWithoutHttpOnly.go:81:20:81:21 | &... | +| CookieWithoutHttpOnly.go:81:20:81:21 | &... | CookieWithoutHttpOnly.go:81:20:81:21 | &... | +| CookieWithoutHttpOnly.go:81:20:81:21 | &... | CookieWithoutHttpOnly.go:81:21:81:21 | c | +| CookieWithoutHttpOnly.go:81:20:81:21 | &... | CookieWithoutHttpOnly.go:81:21:81:21 | c | +| CookieWithoutHttpOnly.go:81:20:81:21 | &... [pointer] | CookieWithoutHttpOnly.go:81:20:81:21 | &... | +| CookieWithoutHttpOnly.go:81:20:81:21 | &... [pointer] | CookieWithoutHttpOnly.go:81:20:81:21 | &... | +| CookieWithoutHttpOnly.go:81:20:81:21 | &... [pointer] | CookieWithoutHttpOnly.go:81:20:81:21 | &... | +| CookieWithoutHttpOnly.go:81:20:81:21 | &... [pointer] | CookieWithoutHttpOnly.go:81:20:81:21 | &... | +| CookieWithoutHttpOnly.go:81:20:81:21 | &... [pointer] | CookieWithoutHttpOnly.go:81:21:81:21 | c | +| CookieWithoutHttpOnly.go:81:20:81:21 | &... [pointer] | CookieWithoutHttpOnly.go:81:21:81:21 | c | +| CookieWithoutHttpOnly.go:81:21:81:21 | c | CookieWithoutHttpOnly.go:81:20:81:21 | &... [pointer] | +| CookieWithoutHttpOnly.go:81:21:81:21 | c | CookieWithoutHttpOnly.go:81:20:81:21 | &... [pointer] | +| CookieWithoutHttpOnly.go:85:2:85:4 | definition of val | CookieWithoutHttpOnly.go:91:20:91:21 | &... | +| CookieWithoutHttpOnly.go:85:2:85:4 | definition of val | CookieWithoutHttpOnly.go:91:20:91:21 | &... | +| CookieWithoutHttpOnly.go:85:2:85:4 | definition of val | CookieWithoutHttpOnly.go:91:21:91:21 | c | +| CookieWithoutHttpOnly.go:85:9:85:13 | false | CookieWithoutHttpOnly.go:91:20:91:21 | &... | +| CookieWithoutHttpOnly.go:85:9:85:13 | false | CookieWithoutHttpOnly.go:91:20:91:21 | &... | +| CookieWithoutHttpOnly.go:85:9:85:13 | false | CookieWithoutHttpOnly.go:91:21:91:21 | c | +| CookieWithoutHttpOnly.go:87:10:87:18 | "session" | CookieWithoutHttpOnly.go:91:20:91:21 | &... | +| CookieWithoutHttpOnly.go:87:10:87:18 | "session" | CookieWithoutHttpOnly.go:91:20:91:21 | &... | +| CookieWithoutHttpOnly.go:87:10:87:18 | "session" | CookieWithoutHttpOnly.go:91:21:91:21 | c | +| CookieWithoutHttpOnly.go:90:15:90:17 | val | CookieWithoutHttpOnly.go:91:20:91:21 | &... | +| CookieWithoutHttpOnly.go:90:15:90:17 | val | CookieWithoutHttpOnly.go:91:20:91:21 | &... | +| CookieWithoutHttpOnly.go:90:15:90:17 | val | CookieWithoutHttpOnly.go:91:21:91:21 | c | +| CookieWithoutHttpOnly.go:91:20:91:21 | &... | CookieWithoutHttpOnly.go:91:20:91:21 | &... | +| CookieWithoutHttpOnly.go:91:20:91:21 | &... | CookieWithoutHttpOnly.go:91:20:91:21 | &... | +| CookieWithoutHttpOnly.go:91:20:91:21 | &... | CookieWithoutHttpOnly.go:91:20:91:21 | &... | +| CookieWithoutHttpOnly.go:91:20:91:21 | &... | CookieWithoutHttpOnly.go:91:20:91:21 | &... | +| CookieWithoutHttpOnly.go:91:20:91:21 | &... | CookieWithoutHttpOnly.go:91:21:91:21 | c | +| CookieWithoutHttpOnly.go:91:20:91:21 | &... | CookieWithoutHttpOnly.go:91:21:91:21 | c | +| CookieWithoutHttpOnly.go:91:20:91:21 | &... [pointer] | CookieWithoutHttpOnly.go:91:20:91:21 | &... | +| CookieWithoutHttpOnly.go:91:20:91:21 | &... [pointer] | CookieWithoutHttpOnly.go:91:20:91:21 | &... | +| CookieWithoutHttpOnly.go:91:20:91:21 | &... [pointer] | CookieWithoutHttpOnly.go:91:20:91:21 | &... | +| CookieWithoutHttpOnly.go:91:20:91:21 | &... [pointer] | CookieWithoutHttpOnly.go:91:20:91:21 | &... | +| CookieWithoutHttpOnly.go:91:20:91:21 | &... [pointer] | CookieWithoutHttpOnly.go:91:21:91:21 | c | +| CookieWithoutHttpOnly.go:91:20:91:21 | &... [pointer] | CookieWithoutHttpOnly.go:91:21:91:21 | c | +| CookieWithoutHttpOnly.go:91:21:91:21 | c | CookieWithoutHttpOnly.go:91:20:91:21 | &... [pointer] | +| CookieWithoutHttpOnly.go:91:21:91:21 | c | CookieWithoutHttpOnly.go:91:20:91:21 | &... [pointer] | +| CookieWithoutHttpOnly.go:99:15:99:19 | false | CookieWithoutHttpOnly.go:100:20:100:21 | &... | +| CookieWithoutHttpOnly.go:99:15:99:19 | false | CookieWithoutHttpOnly.go:100:20:100:21 | &... | +| CookieWithoutHttpOnly.go:99:15:99:19 | false | CookieWithoutHttpOnly.go:100:21:100:21 | c | +| CookieWithoutHttpOnly.go:100:20:100:21 | &... | CookieWithoutHttpOnly.go:100:20:100:21 | &... | +| CookieWithoutHttpOnly.go:100:20:100:21 | &... | CookieWithoutHttpOnly.go:100:20:100:21 | &... | +| CookieWithoutHttpOnly.go:100:20:100:21 | &... | CookieWithoutHttpOnly.go:100:21:100:21 | c | +| CookieWithoutHttpOnly.go:100:20:100:21 | &... [pointer] | CookieWithoutHttpOnly.go:100:20:100:21 | &... | +| CookieWithoutHttpOnly.go:100:20:100:21 | &... [pointer] | CookieWithoutHttpOnly.go:100:20:100:21 | &... | +| CookieWithoutHttpOnly.go:100:20:100:21 | &... [pointer] | CookieWithoutHttpOnly.go:100:21:100:21 | c | +| CookieWithoutHttpOnly.go:100:21:100:21 | c | CookieWithoutHttpOnly.go:100:20:100:21 | &... [pointer] | +| CookieWithoutHttpOnly.go:104:10:104:18 | "session" | CookieWithoutHttpOnly.go:110:20:110:21 | &... | +| CookieWithoutHttpOnly.go:104:10:104:18 | "session" | CookieWithoutHttpOnly.go:110:20:110:21 | &... | +| CookieWithoutHttpOnly.go:104:10:104:18 | "session" | CookieWithoutHttpOnly.go:110:21:110:21 | c | +| CookieWithoutHttpOnly.go:109:15:109:19 | false | CookieWithoutHttpOnly.go:110:20:110:21 | &... | +| CookieWithoutHttpOnly.go:109:15:109:19 | false | CookieWithoutHttpOnly.go:110:20:110:21 | &... | +| CookieWithoutHttpOnly.go:109:15:109:19 | false | CookieWithoutHttpOnly.go:110:21:110:21 | c | +| CookieWithoutHttpOnly.go:110:20:110:21 | &... | CookieWithoutHttpOnly.go:110:20:110:21 | &... | +| CookieWithoutHttpOnly.go:110:20:110:21 | &... | CookieWithoutHttpOnly.go:110:20:110:21 | &... | +| CookieWithoutHttpOnly.go:110:20:110:21 | &... | CookieWithoutHttpOnly.go:110:20:110:21 | &... | +| CookieWithoutHttpOnly.go:110:20:110:21 | &... | CookieWithoutHttpOnly.go:110:20:110:21 | &... | +| CookieWithoutHttpOnly.go:110:20:110:21 | &... | CookieWithoutHttpOnly.go:110:21:110:21 | c | +| CookieWithoutHttpOnly.go:110:20:110:21 | &... | CookieWithoutHttpOnly.go:110:21:110:21 | c | +| CookieWithoutHttpOnly.go:110:20:110:21 | &... [pointer] | CookieWithoutHttpOnly.go:110:20:110:21 | &... | +| CookieWithoutHttpOnly.go:110:20:110:21 | &... [pointer] | CookieWithoutHttpOnly.go:110:20:110:21 | &... | +| CookieWithoutHttpOnly.go:110:20:110:21 | &... [pointer] | CookieWithoutHttpOnly.go:110:20:110:21 | &... | +| CookieWithoutHttpOnly.go:110:20:110:21 | &... [pointer] | CookieWithoutHttpOnly.go:110:20:110:21 | &... | +| CookieWithoutHttpOnly.go:110:20:110:21 | &... [pointer] | CookieWithoutHttpOnly.go:110:21:110:21 | c | +| CookieWithoutHttpOnly.go:110:20:110:21 | &... [pointer] | CookieWithoutHttpOnly.go:110:21:110:21 | c | +| CookieWithoutHttpOnly.go:110:21:110:21 | c | CookieWithoutHttpOnly.go:110:20:110:21 | &... [pointer] | +| CookieWithoutHttpOnly.go:110:21:110:21 | c | CookieWithoutHttpOnly.go:110:20:110:21 | &... [pointer] | +| CookieWithoutHttpOnly.go:114:13:114:24 | "login_name" | CookieWithoutHttpOnly.go:120:20:120:21 | &... | +| CookieWithoutHttpOnly.go:114:13:114:24 | "login_name" | CookieWithoutHttpOnly.go:120:20:120:21 | &... | +| CookieWithoutHttpOnly.go:114:13:114:24 | "login_name" | CookieWithoutHttpOnly.go:120:21:120:21 | c | +| CookieWithoutHttpOnly.go:116:10:116:16 | session | CookieWithoutHttpOnly.go:120:20:120:21 | &... | +| CookieWithoutHttpOnly.go:116:10:116:16 | session | CookieWithoutHttpOnly.go:120:20:120:21 | &... | +| CookieWithoutHttpOnly.go:116:10:116:16 | session | CookieWithoutHttpOnly.go:120:21:120:21 | c | +| CookieWithoutHttpOnly.go:119:15:119:19 | false | CookieWithoutHttpOnly.go:120:20:120:21 | &... | +| CookieWithoutHttpOnly.go:119:15:119:19 | false | CookieWithoutHttpOnly.go:120:20:120:21 | &... | +| CookieWithoutHttpOnly.go:119:15:119:19 | false | CookieWithoutHttpOnly.go:120:21:120:21 | c | +| CookieWithoutHttpOnly.go:120:20:120:21 | &... | CookieWithoutHttpOnly.go:120:20:120:21 | &... | +| CookieWithoutHttpOnly.go:120:20:120:21 | &... | CookieWithoutHttpOnly.go:120:20:120:21 | &... | +| CookieWithoutHttpOnly.go:120:20:120:21 | &... | CookieWithoutHttpOnly.go:120:20:120:21 | &... | +| CookieWithoutHttpOnly.go:120:20:120:21 | &... | CookieWithoutHttpOnly.go:120:20:120:21 | &... | +| CookieWithoutHttpOnly.go:120:20:120:21 | &... | CookieWithoutHttpOnly.go:120:21:120:21 | c | +| CookieWithoutHttpOnly.go:120:20:120:21 | &... | CookieWithoutHttpOnly.go:120:21:120:21 | c | +| CookieWithoutHttpOnly.go:120:20:120:21 | &... [pointer] | CookieWithoutHttpOnly.go:120:20:120:21 | &... | +| CookieWithoutHttpOnly.go:120:20:120:21 | &... [pointer] | CookieWithoutHttpOnly.go:120:20:120:21 | &... | +| CookieWithoutHttpOnly.go:120:20:120:21 | &... [pointer] | CookieWithoutHttpOnly.go:120:20:120:21 | &... | +| CookieWithoutHttpOnly.go:120:20:120:21 | &... [pointer] | CookieWithoutHttpOnly.go:120:20:120:21 | &... | +| CookieWithoutHttpOnly.go:120:20:120:21 | &... [pointer] | CookieWithoutHttpOnly.go:120:21:120:21 | c | +| CookieWithoutHttpOnly.go:120:20:120:21 | &... [pointer] | CookieWithoutHttpOnly.go:120:21:120:21 | c | +| CookieWithoutHttpOnly.go:120:21:120:21 | c | CookieWithoutHttpOnly.go:120:20:120:21 | &... [pointer] | +| CookieWithoutHttpOnly.go:120:21:120:21 | c | CookieWithoutHttpOnly.go:120:20:120:21 | &... [pointer] | +| CookieWithoutHttpOnly.go:123:13:123:49 | call to NewCookieStore | CookieWithoutHttpOnly.go:126:16:126:20 | store | +| CookieWithoutHttpOnly.go:123:13:123:49 | call to NewCookieStore | CookieWithoutHttpOnly.go:134:16:134:20 | store | +| CookieWithoutHttpOnly.go:123:13:123:49 | call to NewCookieStore | CookieWithoutHttpOnly.go:146:16:146:20 | store | +| CookieWithoutHttpOnly.go:123:13:123:49 | call to NewCookieStore | CookieWithoutHttpOnly.go:158:16:158:20 | store | +| CookieWithoutHttpOnly.go:123:13:123:49 | call to NewCookieStore | CookieWithoutHttpOnly.go:170:16:170:20 | store | +| CookieWithoutHttpOnly.go:123:13:123:49 | call to NewCookieStore | CookieWithoutHttpOnly.go:183:16:183:20 | store | +| CookieWithoutHttpOnly.go:123:13:123:49 | call to NewCookieStore | CookieWithoutHttpOnly.go:195:16:195:20 | store | +| CookieWithoutHttpOnly.go:126:16:126:20 | store | CookieWithoutHttpOnly.go:129:2:129:8 | session | +| CookieWithoutHttpOnly.go:133:2:133:9 | definition of httpOnly | CookieWithoutHttpOnly.go:135:2:135:8 | implicit dereference | +| CookieWithoutHttpOnly.go:133:2:133:9 | definition of httpOnly | CookieWithoutHttpOnly.go:137:2:137:8 | implicit dereference | +| CookieWithoutHttpOnly.go:133:2:133:9 | definition of httpOnly | CookieWithoutHttpOnly.go:142:2:142:8 | session | +| CookieWithoutHttpOnly.go:133:14:133:18 | false | CookieWithoutHttpOnly.go:135:2:135:8 | implicit dereference | +| CookieWithoutHttpOnly.go:133:14:133:18 | false | CookieWithoutHttpOnly.go:137:2:137:8 | implicit dereference | +| CookieWithoutHttpOnly.go:133:14:133:18 | false | CookieWithoutHttpOnly.go:142:2:142:8 | session | +| CookieWithoutHttpOnly.go:134:2:134:8 | definition of session [pointer] | CookieWithoutHttpOnly.go:135:2:135:8 | session [pointer] | +| CookieWithoutHttpOnly.go:134:2:134:8 | definition of session [pointer] | CookieWithoutHttpOnly.go:135:2:135:8 | session [pointer] | +| CookieWithoutHttpOnly.go:134:2:134:8 | definition of session [pointer] | CookieWithoutHttpOnly.go:137:2:137:8 | session [pointer] | +| CookieWithoutHttpOnly.go:134:2:134:8 | definition of session [pointer] | CookieWithoutHttpOnly.go:137:2:137:8 | session [pointer] | +| CookieWithoutHttpOnly.go:134:2:134:8 | definition of session [pointer] | CookieWithoutHttpOnly.go:142:2:142:8 | session | +| CookieWithoutHttpOnly.go:134:2:134:8 | definition of session [pointer] | CookieWithoutHttpOnly.go:142:2:142:8 | session | +| CookieWithoutHttpOnly.go:134:16:134:20 | store | CookieWithoutHttpOnly.go:142:2:142:8 | session | +| CookieWithoutHttpOnly.go:135:2:135:8 | implicit dereference | CookieWithoutHttpOnly.go:134:2:134:8 | definition of session [pointer] | +| CookieWithoutHttpOnly.go:135:2:135:8 | implicit dereference | CookieWithoutHttpOnly.go:134:2:134:8 | definition of session [pointer] | +| CookieWithoutHttpOnly.go:135:2:135:8 | implicit dereference | CookieWithoutHttpOnly.go:135:2:135:8 | implicit dereference | +| CookieWithoutHttpOnly.go:135:2:135:8 | implicit dereference | CookieWithoutHttpOnly.go:135:2:135:8 | implicit dereference | +| CookieWithoutHttpOnly.go:135:2:135:8 | implicit dereference | CookieWithoutHttpOnly.go:137:2:137:8 | implicit dereference | +| CookieWithoutHttpOnly.go:135:2:135:8 | implicit dereference | CookieWithoutHttpOnly.go:137:2:137:8 | implicit dereference | +| CookieWithoutHttpOnly.go:135:2:135:8 | implicit dereference | CookieWithoutHttpOnly.go:142:2:142:8 | session | +| CookieWithoutHttpOnly.go:135:2:135:8 | implicit dereference | CookieWithoutHttpOnly.go:142:2:142:8 | session | +| CookieWithoutHttpOnly.go:135:2:135:8 | session [pointer] | CookieWithoutHttpOnly.go:135:2:135:8 | implicit dereference | +| CookieWithoutHttpOnly.go:135:2:135:8 | session [pointer] | CookieWithoutHttpOnly.go:135:2:135:8 | implicit dereference | +| CookieWithoutHttpOnly.go:137:2:137:8 | implicit dereference | CookieWithoutHttpOnly.go:134:2:134:8 | definition of session [pointer] | +| CookieWithoutHttpOnly.go:137:2:137:8 | implicit dereference | CookieWithoutHttpOnly.go:134:2:134:8 | definition of session [pointer] | +| CookieWithoutHttpOnly.go:137:2:137:8 | implicit dereference | CookieWithoutHttpOnly.go:135:2:135:8 | implicit dereference | +| CookieWithoutHttpOnly.go:137:2:137:8 | implicit dereference | CookieWithoutHttpOnly.go:135:2:135:8 | implicit dereference | +| CookieWithoutHttpOnly.go:137:2:137:8 | implicit dereference | CookieWithoutHttpOnly.go:137:2:137:8 | implicit dereference | +| CookieWithoutHttpOnly.go:137:2:137:8 | implicit dereference | CookieWithoutHttpOnly.go:137:2:137:8 | implicit dereference | +| CookieWithoutHttpOnly.go:137:2:137:8 | implicit dereference | CookieWithoutHttpOnly.go:142:2:142:8 | session | +| CookieWithoutHttpOnly.go:137:2:137:8 | implicit dereference | CookieWithoutHttpOnly.go:142:2:142:8 | session | +| CookieWithoutHttpOnly.go:137:2:137:8 | session [pointer] | CookieWithoutHttpOnly.go:137:2:137:8 | implicit dereference | +| CookieWithoutHttpOnly.go:137:2:137:8 | session [pointer] | CookieWithoutHttpOnly.go:137:2:137:8 | implicit dereference | +| CookieWithoutHttpOnly.go:137:21:140:2 | struct literal | CookieWithoutHttpOnly.go:135:2:135:8 | implicit dereference | +| CookieWithoutHttpOnly.go:137:21:140:2 | struct literal | CookieWithoutHttpOnly.go:137:2:137:8 | implicit dereference | +| CookieWithoutHttpOnly.go:137:21:140:2 | struct literal | CookieWithoutHttpOnly.go:142:2:142:8 | session | +| CookieWithoutHttpOnly.go:139:13:139:20 | httpOnly | CookieWithoutHttpOnly.go:135:2:135:8 | implicit dereference | +| CookieWithoutHttpOnly.go:139:13:139:20 | httpOnly | CookieWithoutHttpOnly.go:137:2:137:8 | implicit dereference | +| CookieWithoutHttpOnly.go:139:13:139:20 | httpOnly | CookieWithoutHttpOnly.go:142:2:142:8 | session | +| CookieWithoutHttpOnly.go:146:2:146:8 | definition of session [pointer] | CookieWithoutHttpOnly.go:147:2:147:8 | session [pointer] | +| CookieWithoutHttpOnly.go:146:2:146:8 | definition of session [pointer] | CookieWithoutHttpOnly.go:149:2:149:8 | session [pointer] | +| CookieWithoutHttpOnly.go:146:2:146:8 | definition of session [pointer] | CookieWithoutHttpOnly.go:153:2:153:8 | session | +| CookieWithoutHttpOnly.go:146:16:146:20 | store | CookieWithoutHttpOnly.go:153:2:153:8 | session | +| CookieWithoutHttpOnly.go:147:2:147:8 | implicit dereference | CookieWithoutHttpOnly.go:146:2:146:8 | definition of session [pointer] | +| CookieWithoutHttpOnly.go:147:2:147:8 | implicit dereference | CookieWithoutHttpOnly.go:147:2:147:8 | implicit dereference | +| CookieWithoutHttpOnly.go:147:2:147:8 | implicit dereference | CookieWithoutHttpOnly.go:149:2:149:8 | implicit dereference | +| CookieWithoutHttpOnly.go:147:2:147:8 | implicit dereference | CookieWithoutHttpOnly.go:153:2:153:8 | session | +| CookieWithoutHttpOnly.go:147:2:147:8 | session [pointer] | CookieWithoutHttpOnly.go:147:2:147:8 | implicit dereference | +| CookieWithoutHttpOnly.go:149:2:149:8 | implicit dereference | CookieWithoutHttpOnly.go:146:2:146:8 | definition of session [pointer] | +| CookieWithoutHttpOnly.go:149:2:149:8 | implicit dereference | CookieWithoutHttpOnly.go:147:2:147:8 | implicit dereference | +| CookieWithoutHttpOnly.go:149:2:149:8 | implicit dereference | CookieWithoutHttpOnly.go:149:2:149:8 | implicit dereference | +| CookieWithoutHttpOnly.go:149:2:149:8 | implicit dereference | CookieWithoutHttpOnly.go:153:2:153:8 | session | +| CookieWithoutHttpOnly.go:149:2:149:8 | session [pointer] | CookieWithoutHttpOnly.go:149:2:149:8 | implicit dereference | +| CookieWithoutHttpOnly.go:149:21:151:2 | struct literal | CookieWithoutHttpOnly.go:147:2:147:8 | implicit dereference | +| CookieWithoutHttpOnly.go:149:21:151:2 | struct literal | CookieWithoutHttpOnly.go:149:2:149:8 | implicit dereference | +| CookieWithoutHttpOnly.go:149:21:151:2 | struct literal | CookieWithoutHttpOnly.go:153:2:153:8 | session | +| CookieWithoutHttpOnly.go:157:2:157:9 | definition of httpOnly | CookieWithoutHttpOnly.go:159:2:159:8 | implicit dereference | +| CookieWithoutHttpOnly.go:157:2:157:9 | definition of httpOnly | CookieWithoutHttpOnly.go:161:2:161:8 | implicit dereference | +| CookieWithoutHttpOnly.go:157:2:157:9 | definition of httpOnly | CookieWithoutHttpOnly.go:166:2:166:8 | session | +| CookieWithoutHttpOnly.go:157:14:157:17 | true | CookieWithoutHttpOnly.go:159:2:159:8 | implicit dereference | +| CookieWithoutHttpOnly.go:157:14:157:17 | true | CookieWithoutHttpOnly.go:161:2:161:8 | implicit dereference | +| CookieWithoutHttpOnly.go:157:14:157:17 | true | CookieWithoutHttpOnly.go:166:2:166:8 | session | +| CookieWithoutHttpOnly.go:158:2:158:8 | definition of session [pointer] | CookieWithoutHttpOnly.go:159:2:159:8 | session [pointer] | +| CookieWithoutHttpOnly.go:158:2:158:8 | definition of session [pointer] | CookieWithoutHttpOnly.go:159:2:159:8 | session [pointer] | +| CookieWithoutHttpOnly.go:158:2:158:8 | definition of session [pointer] | CookieWithoutHttpOnly.go:161:2:161:8 | session [pointer] | +| CookieWithoutHttpOnly.go:158:2:158:8 | definition of session [pointer] | CookieWithoutHttpOnly.go:161:2:161:8 | session [pointer] | +| CookieWithoutHttpOnly.go:158:2:158:8 | definition of session [pointer] | CookieWithoutHttpOnly.go:166:2:166:8 | session | +| CookieWithoutHttpOnly.go:158:2:158:8 | definition of session [pointer] | CookieWithoutHttpOnly.go:166:2:166:8 | session | +| CookieWithoutHttpOnly.go:158:16:158:20 | store | CookieWithoutHttpOnly.go:166:2:166:8 | session | +| CookieWithoutHttpOnly.go:159:2:159:8 | implicit dereference | CookieWithoutHttpOnly.go:158:2:158:8 | definition of session [pointer] | +| CookieWithoutHttpOnly.go:159:2:159:8 | implicit dereference | CookieWithoutHttpOnly.go:158:2:158:8 | definition of session [pointer] | +| CookieWithoutHttpOnly.go:159:2:159:8 | implicit dereference | CookieWithoutHttpOnly.go:159:2:159:8 | implicit dereference | +| CookieWithoutHttpOnly.go:159:2:159:8 | implicit dereference | CookieWithoutHttpOnly.go:159:2:159:8 | implicit dereference | +| CookieWithoutHttpOnly.go:159:2:159:8 | implicit dereference | CookieWithoutHttpOnly.go:161:2:161:8 | implicit dereference | +| CookieWithoutHttpOnly.go:159:2:159:8 | implicit dereference | CookieWithoutHttpOnly.go:161:2:161:8 | implicit dereference | +| CookieWithoutHttpOnly.go:159:2:159:8 | implicit dereference | CookieWithoutHttpOnly.go:166:2:166:8 | session | +| CookieWithoutHttpOnly.go:159:2:159:8 | implicit dereference | CookieWithoutHttpOnly.go:166:2:166:8 | session | +| CookieWithoutHttpOnly.go:159:2:159:8 | session [pointer] | CookieWithoutHttpOnly.go:159:2:159:8 | implicit dereference | +| CookieWithoutHttpOnly.go:159:2:159:8 | session [pointer] | CookieWithoutHttpOnly.go:159:2:159:8 | implicit dereference | +| CookieWithoutHttpOnly.go:161:2:161:8 | implicit dereference | CookieWithoutHttpOnly.go:158:2:158:8 | definition of session [pointer] | +| CookieWithoutHttpOnly.go:161:2:161:8 | implicit dereference | CookieWithoutHttpOnly.go:158:2:158:8 | definition of session [pointer] | +| CookieWithoutHttpOnly.go:161:2:161:8 | implicit dereference | CookieWithoutHttpOnly.go:159:2:159:8 | implicit dereference | +| CookieWithoutHttpOnly.go:161:2:161:8 | implicit dereference | CookieWithoutHttpOnly.go:159:2:159:8 | implicit dereference | +| CookieWithoutHttpOnly.go:161:2:161:8 | implicit dereference | CookieWithoutHttpOnly.go:161:2:161:8 | implicit dereference | +| CookieWithoutHttpOnly.go:161:2:161:8 | implicit dereference | CookieWithoutHttpOnly.go:161:2:161:8 | implicit dereference | +| CookieWithoutHttpOnly.go:161:2:161:8 | implicit dereference | CookieWithoutHttpOnly.go:166:2:166:8 | session | +| CookieWithoutHttpOnly.go:161:2:161:8 | implicit dereference | CookieWithoutHttpOnly.go:166:2:166:8 | session | +| CookieWithoutHttpOnly.go:161:2:161:8 | session [pointer] | CookieWithoutHttpOnly.go:161:2:161:8 | implicit dereference | +| CookieWithoutHttpOnly.go:161:2:161:8 | session [pointer] | CookieWithoutHttpOnly.go:161:2:161:8 | implicit dereference | +| CookieWithoutHttpOnly.go:161:21:164:2 | struct literal | CookieWithoutHttpOnly.go:159:2:159:8 | implicit dereference | +| CookieWithoutHttpOnly.go:161:21:164:2 | struct literal | CookieWithoutHttpOnly.go:161:2:161:8 | implicit dereference | +| CookieWithoutHttpOnly.go:161:21:164:2 | struct literal | CookieWithoutHttpOnly.go:166:2:166:8 | session | +| CookieWithoutHttpOnly.go:163:13:163:20 | httpOnly | CookieWithoutHttpOnly.go:159:2:159:8 | implicit dereference | +| CookieWithoutHttpOnly.go:163:13:163:20 | httpOnly | CookieWithoutHttpOnly.go:161:2:161:8 | implicit dereference | +| CookieWithoutHttpOnly.go:163:13:163:20 | httpOnly | CookieWithoutHttpOnly.go:166:2:166:8 | session | +| CookieWithoutHttpOnly.go:169:56:169:63 | argument corresponding to httpOnly | CookieWithoutHttpOnly.go:171:2:171:8 | implicit dereference | +| CookieWithoutHttpOnly.go:169:56:169:63 | argument corresponding to httpOnly | CookieWithoutHttpOnly.go:173:2:173:8 | implicit dereference | +| CookieWithoutHttpOnly.go:169:56:169:63 | argument corresponding to httpOnly | CookieWithoutHttpOnly.go:178:2:178:8 | session | +| CookieWithoutHttpOnly.go:169:56:169:63 | definition of httpOnly | CookieWithoutHttpOnly.go:171:2:171:8 | implicit dereference | +| CookieWithoutHttpOnly.go:169:56:169:63 | definition of httpOnly | CookieWithoutHttpOnly.go:173:2:173:8 | implicit dereference | +| CookieWithoutHttpOnly.go:169:56:169:63 | definition of httpOnly | CookieWithoutHttpOnly.go:178:2:178:8 | session | +| CookieWithoutHttpOnly.go:170:2:170:8 | definition of session [pointer] | CookieWithoutHttpOnly.go:171:2:171:8 | session [pointer] | +| CookieWithoutHttpOnly.go:170:2:170:8 | definition of session [pointer] | CookieWithoutHttpOnly.go:171:2:171:8 | session [pointer] | +| CookieWithoutHttpOnly.go:170:2:170:8 | definition of session [pointer] | CookieWithoutHttpOnly.go:173:2:173:8 | session [pointer] | +| CookieWithoutHttpOnly.go:170:2:170:8 | definition of session [pointer] | CookieWithoutHttpOnly.go:173:2:173:8 | session [pointer] | +| CookieWithoutHttpOnly.go:170:2:170:8 | definition of session [pointer] | CookieWithoutHttpOnly.go:178:2:178:8 | session | +| CookieWithoutHttpOnly.go:170:2:170:8 | definition of session [pointer] | CookieWithoutHttpOnly.go:178:2:178:8 | session | +| CookieWithoutHttpOnly.go:170:16:170:20 | store | CookieWithoutHttpOnly.go:178:2:178:8 | session | +| CookieWithoutHttpOnly.go:171:2:171:8 | implicit dereference | CookieWithoutHttpOnly.go:170:2:170:8 | definition of session [pointer] | +| CookieWithoutHttpOnly.go:171:2:171:8 | implicit dereference | CookieWithoutHttpOnly.go:170:2:170:8 | definition of session [pointer] | +| CookieWithoutHttpOnly.go:171:2:171:8 | implicit dereference | CookieWithoutHttpOnly.go:171:2:171:8 | implicit dereference | +| CookieWithoutHttpOnly.go:171:2:171:8 | implicit dereference | CookieWithoutHttpOnly.go:171:2:171:8 | implicit dereference | +| CookieWithoutHttpOnly.go:171:2:171:8 | implicit dereference | CookieWithoutHttpOnly.go:173:2:173:8 | implicit dereference | +| CookieWithoutHttpOnly.go:171:2:171:8 | implicit dereference | CookieWithoutHttpOnly.go:173:2:173:8 | implicit dereference | +| CookieWithoutHttpOnly.go:171:2:171:8 | implicit dereference | CookieWithoutHttpOnly.go:178:2:178:8 | session | +| CookieWithoutHttpOnly.go:171:2:171:8 | implicit dereference | CookieWithoutHttpOnly.go:178:2:178:8 | session | +| CookieWithoutHttpOnly.go:171:2:171:8 | session [pointer] | CookieWithoutHttpOnly.go:171:2:171:8 | implicit dereference | +| CookieWithoutHttpOnly.go:171:2:171:8 | session [pointer] | CookieWithoutHttpOnly.go:171:2:171:8 | implicit dereference | +| CookieWithoutHttpOnly.go:173:2:173:8 | implicit dereference | CookieWithoutHttpOnly.go:170:2:170:8 | definition of session [pointer] | +| CookieWithoutHttpOnly.go:173:2:173:8 | implicit dereference | CookieWithoutHttpOnly.go:170:2:170:8 | definition of session [pointer] | +| CookieWithoutHttpOnly.go:173:2:173:8 | implicit dereference | CookieWithoutHttpOnly.go:171:2:171:8 | implicit dereference | +| CookieWithoutHttpOnly.go:173:2:173:8 | implicit dereference | CookieWithoutHttpOnly.go:171:2:171:8 | implicit dereference | +| CookieWithoutHttpOnly.go:173:2:173:8 | implicit dereference | CookieWithoutHttpOnly.go:173:2:173:8 | implicit dereference | +| CookieWithoutHttpOnly.go:173:2:173:8 | implicit dereference | CookieWithoutHttpOnly.go:173:2:173:8 | implicit dereference | +| CookieWithoutHttpOnly.go:173:2:173:8 | implicit dereference | CookieWithoutHttpOnly.go:178:2:178:8 | session | +| CookieWithoutHttpOnly.go:173:2:173:8 | implicit dereference | CookieWithoutHttpOnly.go:178:2:178:8 | session | +| CookieWithoutHttpOnly.go:173:2:173:8 | session [pointer] | CookieWithoutHttpOnly.go:173:2:173:8 | implicit dereference | +| CookieWithoutHttpOnly.go:173:2:173:8 | session [pointer] | CookieWithoutHttpOnly.go:173:2:173:8 | implicit dereference | +| CookieWithoutHttpOnly.go:173:21:176:2 | struct literal | CookieWithoutHttpOnly.go:171:2:171:8 | implicit dereference | +| CookieWithoutHttpOnly.go:173:21:176:2 | struct literal | CookieWithoutHttpOnly.go:173:2:173:8 | implicit dereference | +| CookieWithoutHttpOnly.go:173:21:176:2 | struct literal | CookieWithoutHttpOnly.go:178:2:178:8 | session | +| CookieWithoutHttpOnly.go:175:13:175:20 | httpOnly | CookieWithoutHttpOnly.go:171:2:171:8 | implicit dereference | +| CookieWithoutHttpOnly.go:175:13:175:20 | httpOnly | CookieWithoutHttpOnly.go:173:2:173:8 | implicit dereference | +| CookieWithoutHttpOnly.go:175:13:175:20 | httpOnly | CookieWithoutHttpOnly.go:178:2:178:8 | session | +| CookieWithoutHttpOnly.go:183:16:183:20 | store | CookieWithoutHttpOnly.go:191:19:191:25 | session | +| CookieWithoutHttpOnly.go:195:16:195:20 | store | CookieWithoutHttpOnly.go:202:19:202:25 | session | nodes -| CookieWithoutHttpOnly.go:12:10:12:18 | "session" : string | semmle.label | "session" : string | +| CookieWithoutHttpOnly.go:12:10:12:18 | "session" | semmle.label | "session" | | CookieWithoutHttpOnly.go:15:20:15:21 | &... | semmle.label | &... | -| CookieWithoutHttpOnly.go:15:20:15:21 | &... : pointer type | semmle.label | &... : pointer type | -| CookieWithoutHttpOnly.go:15:20:15:21 | &... [pointer] : Cookie | semmle.label | &... [pointer] : Cookie | -| CookieWithoutHttpOnly.go:15:21:15:21 | c : Cookie | semmle.label | c : Cookie | -| CookieWithoutHttpOnly.go:20:13:20:21 | "session" : string | semmle.label | "session" : string | -| CookieWithoutHttpOnly.go:22:13:22:17 | false : bool | semmle.label | false : bool | +| CookieWithoutHttpOnly.go:15:20:15:21 | &... | semmle.label | &... | +| CookieWithoutHttpOnly.go:15:20:15:21 | &... [pointer] | semmle.label | &... [pointer] | +| CookieWithoutHttpOnly.go:15:21:15:21 | c | semmle.label | c | +| CookieWithoutHttpOnly.go:20:13:20:21 | "session" | semmle.label | "session" | +| CookieWithoutHttpOnly.go:22:13:22:17 | false | semmle.label | false | | CookieWithoutHttpOnly.go:24:20:24:21 | &... | semmle.label | &... | | CookieWithoutHttpOnly.go:24:20:24:21 | &... | semmle.label | &... | -| CookieWithoutHttpOnly.go:24:20:24:21 | &... : pointer type | semmle.label | &... : pointer type | -| CookieWithoutHttpOnly.go:24:20:24:21 | &... : pointer type | semmle.label | &... : pointer type | -| CookieWithoutHttpOnly.go:24:20:24:21 | &... [pointer] : Cookie | semmle.label | &... [pointer] : Cookie | -| CookieWithoutHttpOnly.go:24:20:24:21 | &... [pointer] : Cookie | semmle.label | &... [pointer] : Cookie | -| CookieWithoutHttpOnly.go:24:21:24:21 | c : Cookie | semmle.label | c : Cookie | -| CookieWithoutHttpOnly.go:24:21:24:21 | c : Cookie | semmle.label | c : Cookie | -| CookieWithoutHttpOnly.go:29:13:29:21 | "session" : string | semmle.label | "session" : string | -| CookieWithoutHttpOnly.go:31:13:31:16 | true : bool | semmle.label | true : bool | +| CookieWithoutHttpOnly.go:24:20:24:21 | &... | semmle.label | &... | +| CookieWithoutHttpOnly.go:24:20:24:21 | &... | semmle.label | &... | +| CookieWithoutHttpOnly.go:24:20:24:21 | &... [pointer] | semmle.label | &... [pointer] | +| CookieWithoutHttpOnly.go:24:20:24:21 | &... [pointer] | semmle.label | &... [pointer] | +| CookieWithoutHttpOnly.go:24:21:24:21 | c | semmle.label | c | +| CookieWithoutHttpOnly.go:24:21:24:21 | c | semmle.label | c | +| CookieWithoutHttpOnly.go:29:13:29:21 | "session" | semmle.label | "session" | +| CookieWithoutHttpOnly.go:31:13:31:16 | true | semmle.label | true | | CookieWithoutHttpOnly.go:33:20:33:21 | &... | semmle.label | &... | | CookieWithoutHttpOnly.go:33:20:33:21 | &... | semmle.label | &... | -| CookieWithoutHttpOnly.go:33:20:33:21 | &... : pointer type | semmle.label | &... : pointer type | -| CookieWithoutHttpOnly.go:33:20:33:21 | &... : pointer type | semmle.label | &... : pointer type | -| CookieWithoutHttpOnly.go:33:20:33:21 | &... [pointer] : Cookie | semmle.label | &... [pointer] : Cookie | -| CookieWithoutHttpOnly.go:33:20:33:21 | &... [pointer] : Cookie | semmle.label | &... [pointer] : Cookie | -| CookieWithoutHttpOnly.go:33:21:33:21 | c : Cookie | semmle.label | c : Cookie | -| CookieWithoutHttpOnly.go:33:21:33:21 | c : Cookie | semmle.label | c : Cookie | -| CookieWithoutHttpOnly.go:38:10:38:18 | "session" : string | semmle.label | "session" : string | -| CookieWithoutHttpOnly.go:41:15:41:18 | true : bool | semmle.label | true : bool | +| CookieWithoutHttpOnly.go:33:20:33:21 | &... | semmle.label | &... | +| CookieWithoutHttpOnly.go:33:20:33:21 | &... | semmle.label | &... | +| CookieWithoutHttpOnly.go:33:20:33:21 | &... [pointer] | semmle.label | &... [pointer] | +| CookieWithoutHttpOnly.go:33:20:33:21 | &... [pointer] | semmle.label | &... [pointer] | +| CookieWithoutHttpOnly.go:33:21:33:21 | c | semmle.label | c | +| CookieWithoutHttpOnly.go:33:21:33:21 | c | semmle.label | c | +| CookieWithoutHttpOnly.go:38:10:38:18 | "session" | semmle.label | "session" | +| CookieWithoutHttpOnly.go:41:15:41:18 | true | semmle.label | true | | CookieWithoutHttpOnly.go:42:20:42:21 | &... | semmle.label | &... | | CookieWithoutHttpOnly.go:42:20:42:21 | &... | semmle.label | &... | -| CookieWithoutHttpOnly.go:42:20:42:21 | &... : pointer type | semmle.label | &... : pointer type | -| CookieWithoutHttpOnly.go:42:20:42:21 | &... : pointer type | semmle.label | &... : pointer type | -| CookieWithoutHttpOnly.go:42:20:42:21 | &... [pointer] : Cookie | semmle.label | &... [pointer] : Cookie | -| CookieWithoutHttpOnly.go:42:20:42:21 | &... [pointer] : Cookie | semmle.label | &... [pointer] : Cookie | -| CookieWithoutHttpOnly.go:42:21:42:21 | c : Cookie | semmle.label | c : Cookie | -| CookieWithoutHttpOnly.go:42:21:42:21 | c : Cookie | semmle.label | c : Cookie | -| CookieWithoutHttpOnly.go:47:10:47:18 | "session" : string | semmle.label | "session" : string | -| CookieWithoutHttpOnly.go:50:15:50:19 | false : bool | semmle.label | false : bool | +| CookieWithoutHttpOnly.go:42:20:42:21 | &... | semmle.label | &... | +| CookieWithoutHttpOnly.go:42:20:42:21 | &... | semmle.label | &... | +| CookieWithoutHttpOnly.go:42:20:42:21 | &... [pointer] | semmle.label | &... [pointer] | +| CookieWithoutHttpOnly.go:42:20:42:21 | &... [pointer] | semmle.label | &... [pointer] | +| CookieWithoutHttpOnly.go:42:21:42:21 | c | semmle.label | c | +| CookieWithoutHttpOnly.go:42:21:42:21 | c | semmle.label | c | +| CookieWithoutHttpOnly.go:47:10:47:18 | "session" | semmle.label | "session" | +| CookieWithoutHttpOnly.go:50:15:50:19 | false | semmle.label | false | | CookieWithoutHttpOnly.go:51:20:51:21 | &... | semmle.label | &... | | CookieWithoutHttpOnly.go:51:20:51:21 | &... | semmle.label | &... | -| CookieWithoutHttpOnly.go:51:20:51:21 | &... : pointer type | semmle.label | &... : pointer type | -| CookieWithoutHttpOnly.go:51:20:51:21 | &... : pointer type | semmle.label | &... : pointer type | -| CookieWithoutHttpOnly.go:51:20:51:21 | &... [pointer] : Cookie | semmle.label | &... [pointer] : Cookie | -| CookieWithoutHttpOnly.go:51:20:51:21 | &... [pointer] : Cookie | semmle.label | &... [pointer] : Cookie | -| CookieWithoutHttpOnly.go:51:21:51:21 | c : Cookie | semmle.label | c : Cookie | -| CookieWithoutHttpOnly.go:51:21:51:21 | c : Cookie | semmle.label | c : Cookie | -| CookieWithoutHttpOnly.go:55:2:55:4 | definition of val : bool | semmle.label | definition of val : bool | -| CookieWithoutHttpOnly.go:55:9:55:13 | false : bool | semmle.label | false : bool | -| CookieWithoutHttpOnly.go:57:13:57:21 | "session" : string | semmle.label | "session" : string | -| CookieWithoutHttpOnly.go:59:13:59:15 | val : bool | semmle.label | val : bool | +| CookieWithoutHttpOnly.go:51:20:51:21 | &... | semmle.label | &... | +| CookieWithoutHttpOnly.go:51:20:51:21 | &... | semmle.label | &... | +| CookieWithoutHttpOnly.go:51:20:51:21 | &... [pointer] | semmle.label | &... [pointer] | +| CookieWithoutHttpOnly.go:51:20:51:21 | &... [pointer] | semmle.label | &... [pointer] | +| CookieWithoutHttpOnly.go:51:21:51:21 | c | semmle.label | c | +| CookieWithoutHttpOnly.go:51:21:51:21 | c | semmle.label | c | +| CookieWithoutHttpOnly.go:55:2:55:4 | definition of val | semmle.label | definition of val | +| CookieWithoutHttpOnly.go:55:9:55:13 | false | semmle.label | false | +| CookieWithoutHttpOnly.go:57:13:57:21 | "session" | semmle.label | "session" | +| CookieWithoutHttpOnly.go:59:13:59:15 | val | semmle.label | val | | CookieWithoutHttpOnly.go:61:20:61:21 | &... | semmle.label | &... | | CookieWithoutHttpOnly.go:61:20:61:21 | &... | semmle.label | &... | -| CookieWithoutHttpOnly.go:61:20:61:21 | &... : pointer type | semmle.label | &... : pointer type | -| CookieWithoutHttpOnly.go:61:20:61:21 | &... : pointer type | semmle.label | &... : pointer type | -| CookieWithoutHttpOnly.go:61:20:61:21 | &... [pointer] : Cookie | semmle.label | &... [pointer] : Cookie | -| CookieWithoutHttpOnly.go:61:20:61:21 | &... [pointer] : Cookie | semmle.label | &... [pointer] : Cookie | -| CookieWithoutHttpOnly.go:61:21:61:21 | c : Cookie | semmle.label | c : Cookie | -| CookieWithoutHttpOnly.go:61:21:61:21 | c : Cookie | semmle.label | c : Cookie | -| CookieWithoutHttpOnly.go:65:2:65:4 | definition of val : bool | semmle.label | definition of val : bool | -| CookieWithoutHttpOnly.go:65:9:65:12 | true : bool | semmle.label | true : bool | -| CookieWithoutHttpOnly.go:67:13:67:21 | "session" : string | semmle.label | "session" : string | -| CookieWithoutHttpOnly.go:69:13:69:15 | val : bool | semmle.label | val : bool | +| CookieWithoutHttpOnly.go:61:20:61:21 | &... | semmle.label | &... | +| CookieWithoutHttpOnly.go:61:20:61:21 | &... | semmle.label | &... | +| CookieWithoutHttpOnly.go:61:20:61:21 | &... [pointer] | semmle.label | &... [pointer] | +| CookieWithoutHttpOnly.go:61:20:61:21 | &... [pointer] | semmle.label | &... [pointer] | +| CookieWithoutHttpOnly.go:61:21:61:21 | c | semmle.label | c | +| CookieWithoutHttpOnly.go:61:21:61:21 | c | semmle.label | c | +| CookieWithoutHttpOnly.go:65:2:65:4 | definition of val | semmle.label | definition of val | +| CookieWithoutHttpOnly.go:65:9:65:12 | true | semmle.label | true | +| CookieWithoutHttpOnly.go:67:13:67:21 | "session" | semmle.label | "session" | +| CookieWithoutHttpOnly.go:69:13:69:15 | val | semmle.label | val | | CookieWithoutHttpOnly.go:71:20:71:21 | &... | semmle.label | &... | | CookieWithoutHttpOnly.go:71:20:71:21 | &... | semmle.label | &... | -| CookieWithoutHttpOnly.go:71:20:71:21 | &... : pointer type | semmle.label | &... : pointer type | -| CookieWithoutHttpOnly.go:71:20:71:21 | &... : pointer type | semmle.label | &... : pointer type | -| CookieWithoutHttpOnly.go:71:20:71:21 | &... [pointer] : Cookie | semmle.label | &... [pointer] : Cookie | -| CookieWithoutHttpOnly.go:71:20:71:21 | &... [pointer] : Cookie | semmle.label | &... [pointer] : Cookie | -| CookieWithoutHttpOnly.go:71:21:71:21 | c : Cookie | semmle.label | c : Cookie | -| CookieWithoutHttpOnly.go:71:21:71:21 | c : Cookie | semmle.label | c : Cookie | -| CookieWithoutHttpOnly.go:75:2:75:4 | definition of val : bool | semmle.label | definition of val : bool | -| CookieWithoutHttpOnly.go:75:9:75:12 | true : bool | semmle.label | true : bool | -| CookieWithoutHttpOnly.go:77:10:77:18 | "session" : string | semmle.label | "session" : string | -| CookieWithoutHttpOnly.go:80:15:80:17 | val : bool | semmle.label | val : bool | +| CookieWithoutHttpOnly.go:71:20:71:21 | &... | semmle.label | &... | +| CookieWithoutHttpOnly.go:71:20:71:21 | &... | semmle.label | &... | +| CookieWithoutHttpOnly.go:71:20:71:21 | &... [pointer] | semmle.label | &... [pointer] | +| CookieWithoutHttpOnly.go:71:20:71:21 | &... [pointer] | semmle.label | &... [pointer] | +| CookieWithoutHttpOnly.go:71:21:71:21 | c | semmle.label | c | +| CookieWithoutHttpOnly.go:71:21:71:21 | c | semmle.label | c | +| CookieWithoutHttpOnly.go:75:2:75:4 | definition of val | semmle.label | definition of val | +| CookieWithoutHttpOnly.go:75:9:75:12 | true | semmle.label | true | +| CookieWithoutHttpOnly.go:77:10:77:18 | "session" | semmle.label | "session" | +| CookieWithoutHttpOnly.go:80:15:80:17 | val | semmle.label | val | | CookieWithoutHttpOnly.go:81:20:81:21 | &... | semmle.label | &... | | CookieWithoutHttpOnly.go:81:20:81:21 | &... | semmle.label | &... | -| CookieWithoutHttpOnly.go:81:20:81:21 | &... : pointer type | semmle.label | &... : pointer type | -| CookieWithoutHttpOnly.go:81:20:81:21 | &... : pointer type | semmle.label | &... : pointer type | -| CookieWithoutHttpOnly.go:81:20:81:21 | &... [pointer] : Cookie | semmle.label | &... [pointer] : Cookie | -| CookieWithoutHttpOnly.go:81:20:81:21 | &... [pointer] : Cookie | semmle.label | &... [pointer] : Cookie | -| CookieWithoutHttpOnly.go:81:21:81:21 | c : Cookie | semmle.label | c : Cookie | -| CookieWithoutHttpOnly.go:81:21:81:21 | c : Cookie | semmle.label | c : Cookie | -| CookieWithoutHttpOnly.go:85:2:85:4 | definition of val : bool | semmle.label | definition of val : bool | -| CookieWithoutHttpOnly.go:85:9:85:13 | false : bool | semmle.label | false : bool | -| CookieWithoutHttpOnly.go:87:10:87:18 | "session" : string | semmle.label | "session" : string | -| CookieWithoutHttpOnly.go:90:15:90:17 | val : bool | semmle.label | val : bool | +| CookieWithoutHttpOnly.go:81:20:81:21 | &... | semmle.label | &... | +| CookieWithoutHttpOnly.go:81:20:81:21 | &... | semmle.label | &... | +| CookieWithoutHttpOnly.go:81:20:81:21 | &... [pointer] | semmle.label | &... [pointer] | +| CookieWithoutHttpOnly.go:81:20:81:21 | &... [pointer] | semmle.label | &... [pointer] | +| CookieWithoutHttpOnly.go:81:21:81:21 | c | semmle.label | c | +| CookieWithoutHttpOnly.go:81:21:81:21 | c | semmle.label | c | +| CookieWithoutHttpOnly.go:85:2:85:4 | definition of val | semmle.label | definition of val | +| CookieWithoutHttpOnly.go:85:9:85:13 | false | semmle.label | false | +| CookieWithoutHttpOnly.go:87:10:87:18 | "session" | semmle.label | "session" | +| CookieWithoutHttpOnly.go:90:15:90:17 | val | semmle.label | val | | CookieWithoutHttpOnly.go:91:20:91:21 | &... | semmle.label | &... | | CookieWithoutHttpOnly.go:91:20:91:21 | &... | semmle.label | &... | -| CookieWithoutHttpOnly.go:91:20:91:21 | &... : pointer type | semmle.label | &... : pointer type | -| CookieWithoutHttpOnly.go:91:20:91:21 | &... : pointer type | semmle.label | &... : pointer type | -| CookieWithoutHttpOnly.go:91:20:91:21 | &... [pointer] : Cookie | semmle.label | &... [pointer] : Cookie | -| CookieWithoutHttpOnly.go:91:20:91:21 | &... [pointer] : Cookie | semmle.label | &... [pointer] : Cookie | -| CookieWithoutHttpOnly.go:91:21:91:21 | c : Cookie | semmle.label | c : Cookie | -| CookieWithoutHttpOnly.go:91:21:91:21 | c : Cookie | semmle.label | c : Cookie | -| CookieWithoutHttpOnly.go:99:15:99:19 | false : bool | semmle.label | false : bool | +| CookieWithoutHttpOnly.go:91:20:91:21 | &... | semmle.label | &... | +| CookieWithoutHttpOnly.go:91:20:91:21 | &... | semmle.label | &... | +| CookieWithoutHttpOnly.go:91:20:91:21 | &... [pointer] | semmle.label | &... [pointer] | +| CookieWithoutHttpOnly.go:91:20:91:21 | &... [pointer] | semmle.label | &... [pointer] | +| CookieWithoutHttpOnly.go:91:21:91:21 | c | semmle.label | c | +| CookieWithoutHttpOnly.go:91:21:91:21 | c | semmle.label | c | +| CookieWithoutHttpOnly.go:99:15:99:19 | false | semmle.label | false | | CookieWithoutHttpOnly.go:100:20:100:21 | &... | semmle.label | &... | -| CookieWithoutHttpOnly.go:100:20:100:21 | &... : pointer type | semmle.label | &... : pointer type | -| CookieWithoutHttpOnly.go:100:20:100:21 | &... [pointer] : Cookie | semmle.label | &... [pointer] : Cookie | -| CookieWithoutHttpOnly.go:100:21:100:21 | c : Cookie | semmle.label | c : Cookie | -| CookieWithoutHttpOnly.go:104:10:104:18 | "session" : string | semmle.label | "session" : string | -| CookieWithoutHttpOnly.go:109:15:109:19 | false : bool | semmle.label | false : bool | +| CookieWithoutHttpOnly.go:100:20:100:21 | &... | semmle.label | &... | +| CookieWithoutHttpOnly.go:100:20:100:21 | &... [pointer] | semmle.label | &... [pointer] | +| CookieWithoutHttpOnly.go:100:21:100:21 | c | semmle.label | c | +| CookieWithoutHttpOnly.go:104:10:104:18 | "session" | semmle.label | "session" | +| CookieWithoutHttpOnly.go:109:15:109:19 | false | semmle.label | false | | CookieWithoutHttpOnly.go:110:20:110:21 | &... | semmle.label | &... | | CookieWithoutHttpOnly.go:110:20:110:21 | &... | semmle.label | &... | -| CookieWithoutHttpOnly.go:110:20:110:21 | &... : pointer type | semmle.label | &... : pointer type | -| CookieWithoutHttpOnly.go:110:20:110:21 | &... : pointer type | semmle.label | &... : pointer type | -| CookieWithoutHttpOnly.go:110:20:110:21 | &... [pointer] : Cookie | semmle.label | &... [pointer] : Cookie | -| CookieWithoutHttpOnly.go:110:20:110:21 | &... [pointer] : Cookie | semmle.label | &... [pointer] : Cookie | -| CookieWithoutHttpOnly.go:110:21:110:21 | c : Cookie | semmle.label | c : Cookie | -| CookieWithoutHttpOnly.go:110:21:110:21 | c : Cookie | semmle.label | c : Cookie | -| CookieWithoutHttpOnly.go:114:13:114:24 | "login_name" : string | semmle.label | "login_name" : string | -| CookieWithoutHttpOnly.go:116:10:116:16 | session : string | semmle.label | session : string | -| CookieWithoutHttpOnly.go:119:15:119:19 | false : bool | semmle.label | false : bool | +| CookieWithoutHttpOnly.go:110:20:110:21 | &... | semmle.label | &... | +| CookieWithoutHttpOnly.go:110:20:110:21 | &... | semmle.label | &... | +| CookieWithoutHttpOnly.go:110:20:110:21 | &... [pointer] | semmle.label | &... [pointer] | +| CookieWithoutHttpOnly.go:110:20:110:21 | &... [pointer] | semmle.label | &... [pointer] | +| CookieWithoutHttpOnly.go:110:21:110:21 | c | semmle.label | c | +| CookieWithoutHttpOnly.go:110:21:110:21 | c | semmle.label | c | +| CookieWithoutHttpOnly.go:114:13:114:24 | "login_name" | semmle.label | "login_name" | +| CookieWithoutHttpOnly.go:116:10:116:16 | session | semmle.label | session | +| CookieWithoutHttpOnly.go:119:15:119:19 | false | semmle.label | false | | CookieWithoutHttpOnly.go:120:20:120:21 | &... | semmle.label | &... | | CookieWithoutHttpOnly.go:120:20:120:21 | &... | semmle.label | &... | -| CookieWithoutHttpOnly.go:120:20:120:21 | &... : pointer type | semmle.label | &... : pointer type | -| CookieWithoutHttpOnly.go:120:20:120:21 | &... : pointer type | semmle.label | &... : pointer type | -| CookieWithoutHttpOnly.go:120:20:120:21 | &... [pointer] : Cookie | semmle.label | &... [pointer] : Cookie | -| CookieWithoutHttpOnly.go:120:20:120:21 | &... [pointer] : Cookie | semmle.label | &... [pointer] : Cookie | -| CookieWithoutHttpOnly.go:120:21:120:21 | c : Cookie | semmle.label | c : Cookie | -| CookieWithoutHttpOnly.go:120:21:120:21 | c : Cookie | semmle.label | c : Cookie | -| CookieWithoutHttpOnly.go:123:13:123:49 | call to NewCookieStore : pointer type | semmle.label | call to NewCookieStore : pointer type | -| CookieWithoutHttpOnly.go:126:16:126:20 | store : pointer type | semmle.label | store : pointer type | +| CookieWithoutHttpOnly.go:120:20:120:21 | &... | semmle.label | &... | +| CookieWithoutHttpOnly.go:120:20:120:21 | &... | semmle.label | &... | +| CookieWithoutHttpOnly.go:120:20:120:21 | &... [pointer] | semmle.label | &... [pointer] | +| CookieWithoutHttpOnly.go:120:20:120:21 | &... [pointer] | semmle.label | &... [pointer] | +| CookieWithoutHttpOnly.go:120:21:120:21 | c | semmle.label | c | +| CookieWithoutHttpOnly.go:120:21:120:21 | c | semmle.label | c | +| CookieWithoutHttpOnly.go:123:13:123:49 | call to NewCookieStore | semmle.label | call to NewCookieStore | +| CookieWithoutHttpOnly.go:126:16:126:20 | store | semmle.label | store | | CookieWithoutHttpOnly.go:129:2:129:8 | session | semmle.label | session | -| CookieWithoutHttpOnly.go:133:2:133:9 | definition of httpOnly : bool | semmle.label | definition of httpOnly : bool | -| CookieWithoutHttpOnly.go:133:14:133:18 | false : bool | semmle.label | false : bool | -| CookieWithoutHttpOnly.go:134:2:134:8 | definition of session [pointer] : Session | semmle.label | definition of session [pointer] : Session | -| CookieWithoutHttpOnly.go:134:2:134:8 | definition of session [pointer] : Session | semmle.label | definition of session [pointer] : Session | -| CookieWithoutHttpOnly.go:134:16:134:20 | store : pointer type | semmle.label | store : pointer type | -| CookieWithoutHttpOnly.go:135:2:135:8 | implicit dereference : Session | semmle.label | implicit dereference : Session | -| CookieWithoutHttpOnly.go:135:2:135:8 | implicit dereference : Session | semmle.label | implicit dereference : Session | -| CookieWithoutHttpOnly.go:135:2:135:8 | session [pointer] : Session | semmle.label | session [pointer] : Session | -| CookieWithoutHttpOnly.go:135:2:135:8 | session [pointer] : Session | semmle.label | session [pointer] : Session | -| CookieWithoutHttpOnly.go:137:2:137:8 | implicit dereference : Session | semmle.label | implicit dereference : Session | -| CookieWithoutHttpOnly.go:137:2:137:8 | implicit dereference : Session | semmle.label | implicit dereference : Session | -| CookieWithoutHttpOnly.go:137:2:137:8 | session [pointer] : Session | semmle.label | session [pointer] : Session | -| CookieWithoutHttpOnly.go:137:2:137:8 | session [pointer] : Session | semmle.label | session [pointer] : Session | -| CookieWithoutHttpOnly.go:137:21:140:2 | struct literal : Options | semmle.label | struct literal : Options | -| CookieWithoutHttpOnly.go:139:13:139:20 | httpOnly : bool | semmle.label | httpOnly : bool | +| CookieWithoutHttpOnly.go:133:2:133:9 | definition of httpOnly | semmle.label | definition of httpOnly | +| CookieWithoutHttpOnly.go:133:14:133:18 | false | semmle.label | false | +| CookieWithoutHttpOnly.go:134:2:134:8 | definition of session [pointer] | semmle.label | definition of session [pointer] | +| CookieWithoutHttpOnly.go:134:2:134:8 | definition of session [pointer] | semmle.label | definition of session [pointer] | +| CookieWithoutHttpOnly.go:134:16:134:20 | store | semmle.label | store | +| CookieWithoutHttpOnly.go:135:2:135:8 | implicit dereference | semmle.label | implicit dereference | +| CookieWithoutHttpOnly.go:135:2:135:8 | implicit dereference | semmle.label | implicit dereference | +| CookieWithoutHttpOnly.go:135:2:135:8 | session [pointer] | semmle.label | session [pointer] | +| CookieWithoutHttpOnly.go:135:2:135:8 | session [pointer] | semmle.label | session [pointer] | +| CookieWithoutHttpOnly.go:137:2:137:8 | implicit dereference | semmle.label | implicit dereference | +| CookieWithoutHttpOnly.go:137:2:137:8 | implicit dereference | semmle.label | implicit dereference | +| CookieWithoutHttpOnly.go:137:2:137:8 | session [pointer] | semmle.label | session [pointer] | +| CookieWithoutHttpOnly.go:137:2:137:8 | session [pointer] | semmle.label | session [pointer] | +| CookieWithoutHttpOnly.go:137:21:140:2 | struct literal | semmle.label | struct literal | +| CookieWithoutHttpOnly.go:139:13:139:20 | httpOnly | semmle.label | httpOnly | | CookieWithoutHttpOnly.go:142:2:142:8 | session | semmle.label | session | | CookieWithoutHttpOnly.go:142:2:142:8 | session | semmle.label | session | | CookieWithoutHttpOnly.go:142:2:142:8 | session | semmle.label | session | -| CookieWithoutHttpOnly.go:146:2:146:8 | definition of session [pointer] : Session | semmle.label | definition of session [pointer] : Session | -| CookieWithoutHttpOnly.go:146:16:146:20 | store : pointer type | semmle.label | store : pointer type | -| CookieWithoutHttpOnly.go:147:2:147:8 | implicit dereference : Session | semmle.label | implicit dereference : Session | -| CookieWithoutHttpOnly.go:147:2:147:8 | session [pointer] : Session | semmle.label | session [pointer] : Session | -| CookieWithoutHttpOnly.go:149:2:149:8 | implicit dereference : Session | semmle.label | implicit dereference : Session | -| CookieWithoutHttpOnly.go:149:2:149:8 | session [pointer] : Session | semmle.label | session [pointer] : Session | -| CookieWithoutHttpOnly.go:149:21:151:2 | struct literal : Options | semmle.label | struct literal : Options | +| CookieWithoutHttpOnly.go:146:2:146:8 | definition of session [pointer] | semmle.label | definition of session [pointer] | +| CookieWithoutHttpOnly.go:146:16:146:20 | store | semmle.label | store | +| CookieWithoutHttpOnly.go:147:2:147:8 | implicit dereference | semmle.label | implicit dereference | +| CookieWithoutHttpOnly.go:147:2:147:8 | session [pointer] | semmle.label | session [pointer] | +| CookieWithoutHttpOnly.go:149:2:149:8 | implicit dereference | semmle.label | implicit dereference | +| CookieWithoutHttpOnly.go:149:2:149:8 | session [pointer] | semmle.label | session [pointer] | +| CookieWithoutHttpOnly.go:149:21:151:2 | struct literal | semmle.label | struct literal | | CookieWithoutHttpOnly.go:153:2:153:8 | session | semmle.label | session | | CookieWithoutHttpOnly.go:153:2:153:8 | session | semmle.label | session | -| CookieWithoutHttpOnly.go:157:2:157:9 | definition of httpOnly : bool | semmle.label | definition of httpOnly : bool | -| CookieWithoutHttpOnly.go:157:14:157:17 | true : bool | semmle.label | true : bool | -| CookieWithoutHttpOnly.go:158:2:158:8 | definition of session [pointer] : Session | semmle.label | definition of session [pointer] : Session | -| CookieWithoutHttpOnly.go:158:2:158:8 | definition of session [pointer] : Session | semmle.label | definition of session [pointer] : Session | -| CookieWithoutHttpOnly.go:158:16:158:20 | store : pointer type | semmle.label | store : pointer type | -| CookieWithoutHttpOnly.go:159:2:159:8 | implicit dereference : Session | semmle.label | implicit dereference : Session | -| CookieWithoutHttpOnly.go:159:2:159:8 | implicit dereference : Session | semmle.label | implicit dereference : Session | -| CookieWithoutHttpOnly.go:159:2:159:8 | session [pointer] : Session | semmle.label | session [pointer] : Session | -| CookieWithoutHttpOnly.go:159:2:159:8 | session [pointer] : Session | semmle.label | session [pointer] : Session | -| CookieWithoutHttpOnly.go:161:2:161:8 | implicit dereference : Session | semmle.label | implicit dereference : Session | -| CookieWithoutHttpOnly.go:161:2:161:8 | implicit dereference : Session | semmle.label | implicit dereference : Session | -| CookieWithoutHttpOnly.go:161:2:161:8 | session [pointer] : Session | semmle.label | session [pointer] : Session | -| CookieWithoutHttpOnly.go:161:2:161:8 | session [pointer] : Session | semmle.label | session [pointer] : Session | -| CookieWithoutHttpOnly.go:161:21:164:2 | struct literal : Options | semmle.label | struct literal : Options | -| CookieWithoutHttpOnly.go:163:13:163:20 | httpOnly : bool | semmle.label | httpOnly : bool | +| CookieWithoutHttpOnly.go:157:2:157:9 | definition of httpOnly | semmle.label | definition of httpOnly | +| CookieWithoutHttpOnly.go:157:14:157:17 | true | semmle.label | true | +| CookieWithoutHttpOnly.go:158:2:158:8 | definition of session [pointer] | semmle.label | definition of session [pointer] | +| CookieWithoutHttpOnly.go:158:2:158:8 | definition of session [pointer] | semmle.label | definition of session [pointer] | +| CookieWithoutHttpOnly.go:158:16:158:20 | store | semmle.label | store | +| CookieWithoutHttpOnly.go:159:2:159:8 | implicit dereference | semmle.label | implicit dereference | +| CookieWithoutHttpOnly.go:159:2:159:8 | implicit dereference | semmle.label | implicit dereference | +| CookieWithoutHttpOnly.go:159:2:159:8 | session [pointer] | semmle.label | session [pointer] | +| CookieWithoutHttpOnly.go:159:2:159:8 | session [pointer] | semmle.label | session [pointer] | +| CookieWithoutHttpOnly.go:161:2:161:8 | implicit dereference | semmle.label | implicit dereference | +| CookieWithoutHttpOnly.go:161:2:161:8 | implicit dereference | semmle.label | implicit dereference | +| CookieWithoutHttpOnly.go:161:2:161:8 | session [pointer] | semmle.label | session [pointer] | +| CookieWithoutHttpOnly.go:161:2:161:8 | session [pointer] | semmle.label | session [pointer] | +| CookieWithoutHttpOnly.go:161:21:164:2 | struct literal | semmle.label | struct literal | +| CookieWithoutHttpOnly.go:163:13:163:20 | httpOnly | semmle.label | httpOnly | | CookieWithoutHttpOnly.go:166:2:166:8 | session | semmle.label | session | | CookieWithoutHttpOnly.go:166:2:166:8 | session | semmle.label | session | | CookieWithoutHttpOnly.go:166:2:166:8 | session | semmle.label | session | -| CookieWithoutHttpOnly.go:169:56:169:63 | argument corresponding to httpOnly : bool | semmle.label | argument corresponding to httpOnly : bool | -| CookieWithoutHttpOnly.go:169:56:169:63 | definition of httpOnly : bool | semmle.label | definition of httpOnly : bool | -| CookieWithoutHttpOnly.go:170:2:170:8 | definition of session [pointer] : Session | semmle.label | definition of session [pointer] : Session | -| CookieWithoutHttpOnly.go:170:2:170:8 | definition of session [pointer] : Session | semmle.label | definition of session [pointer] : Session | -| CookieWithoutHttpOnly.go:170:16:170:20 | store : pointer type | semmle.label | store : pointer type | -| CookieWithoutHttpOnly.go:171:2:171:8 | implicit dereference : Session | semmle.label | implicit dereference : Session | -| CookieWithoutHttpOnly.go:171:2:171:8 | implicit dereference : Session | semmle.label | implicit dereference : Session | -| CookieWithoutHttpOnly.go:171:2:171:8 | session [pointer] : Session | semmle.label | session [pointer] : Session | -| CookieWithoutHttpOnly.go:171:2:171:8 | session [pointer] : Session | semmle.label | session [pointer] : Session | -| CookieWithoutHttpOnly.go:173:2:173:8 | implicit dereference : Session | semmle.label | implicit dereference : Session | -| CookieWithoutHttpOnly.go:173:2:173:8 | implicit dereference : Session | semmle.label | implicit dereference : Session | -| CookieWithoutHttpOnly.go:173:2:173:8 | session [pointer] : Session | semmle.label | session [pointer] : Session | -| CookieWithoutHttpOnly.go:173:2:173:8 | session [pointer] : Session | semmle.label | session [pointer] : Session | -| CookieWithoutHttpOnly.go:173:21:176:2 | struct literal : Options | semmle.label | struct literal : Options | -| CookieWithoutHttpOnly.go:175:13:175:20 | httpOnly : bool | semmle.label | httpOnly : bool | +| CookieWithoutHttpOnly.go:169:56:169:63 | argument corresponding to httpOnly | semmle.label | argument corresponding to httpOnly | +| CookieWithoutHttpOnly.go:169:56:169:63 | definition of httpOnly | semmle.label | definition of httpOnly | +| CookieWithoutHttpOnly.go:170:2:170:8 | definition of session [pointer] | semmle.label | definition of session [pointer] | +| CookieWithoutHttpOnly.go:170:2:170:8 | definition of session [pointer] | semmle.label | definition of session [pointer] | +| CookieWithoutHttpOnly.go:170:16:170:20 | store | semmle.label | store | +| CookieWithoutHttpOnly.go:171:2:171:8 | implicit dereference | semmle.label | implicit dereference | +| CookieWithoutHttpOnly.go:171:2:171:8 | implicit dereference | semmle.label | implicit dereference | +| CookieWithoutHttpOnly.go:171:2:171:8 | session [pointer] | semmle.label | session [pointer] | +| CookieWithoutHttpOnly.go:171:2:171:8 | session [pointer] | semmle.label | session [pointer] | +| CookieWithoutHttpOnly.go:173:2:173:8 | implicit dereference | semmle.label | implicit dereference | +| CookieWithoutHttpOnly.go:173:2:173:8 | implicit dereference | semmle.label | implicit dereference | +| CookieWithoutHttpOnly.go:173:2:173:8 | session [pointer] | semmle.label | session [pointer] | +| CookieWithoutHttpOnly.go:173:2:173:8 | session [pointer] | semmle.label | session [pointer] | +| CookieWithoutHttpOnly.go:173:21:176:2 | struct literal | semmle.label | struct literal | +| CookieWithoutHttpOnly.go:175:13:175:20 | httpOnly | semmle.label | httpOnly | | CookieWithoutHttpOnly.go:178:2:178:8 | session | semmle.label | session | | CookieWithoutHttpOnly.go:178:2:178:8 | session | semmle.label | session | | CookieWithoutHttpOnly.go:178:2:178:8 | session | semmle.label | session | -| CookieWithoutHttpOnly.go:183:16:183:20 | store : pointer type | semmle.label | store : pointer type | +| CookieWithoutHttpOnly.go:183:16:183:20 | store | semmle.label | store | | CookieWithoutHttpOnly.go:191:19:191:25 | session | semmle.label | session | -| CookieWithoutHttpOnly.go:195:16:195:20 | store : pointer type | semmle.label | store : pointer type | +| CookieWithoutHttpOnly.go:195:16:195:20 | store | semmle.label | store | | CookieWithoutHttpOnly.go:202:19:202:25 | session | semmle.label | session | | CookieWithoutHttpOnly.go:214:66:214:70 | false | semmle.label | false | subpaths #select -| CookieWithoutHttpOnly.go:15:20:15:21 | &... | CookieWithoutHttpOnly.go:12:10:12:18 | "session" : string | CookieWithoutHttpOnly.go:15:20:15:21 | &... | Cookie attribute 'HttpOnly' is not set to true. | -| CookieWithoutHttpOnly.go:24:20:24:21 | &... | CookieWithoutHttpOnly.go:22:13:22:17 | false : bool | CookieWithoutHttpOnly.go:24:20:24:21 | &... | Cookie attribute 'HttpOnly' is not set to true. | -| CookieWithoutHttpOnly.go:51:20:51:21 | &... | CookieWithoutHttpOnly.go:50:15:50:19 | false : bool | CookieWithoutHttpOnly.go:51:20:51:21 | &... | Cookie attribute 'HttpOnly' is not set to true. | -| CookieWithoutHttpOnly.go:61:20:61:21 | &... | CookieWithoutHttpOnly.go:55:9:55:13 | false : bool | CookieWithoutHttpOnly.go:61:20:61:21 | &... | Cookie attribute 'HttpOnly' is not set to true. | -| CookieWithoutHttpOnly.go:91:20:91:21 | &... | CookieWithoutHttpOnly.go:85:9:85:13 | false : bool | CookieWithoutHttpOnly.go:91:20:91:21 | &... | Cookie attribute 'HttpOnly' is not set to true. | -| CookieWithoutHttpOnly.go:110:20:110:21 | &... | CookieWithoutHttpOnly.go:109:15:109:19 | false : bool | CookieWithoutHttpOnly.go:110:20:110:21 | &... | Cookie attribute 'HttpOnly' is not set to true. | -| CookieWithoutHttpOnly.go:120:20:120:21 | &... | CookieWithoutHttpOnly.go:119:15:119:19 | false : bool | CookieWithoutHttpOnly.go:120:20:120:21 | &... | Cookie attribute 'HttpOnly' is not set to true. | -| CookieWithoutHttpOnly.go:129:2:129:8 | session | CookieWithoutHttpOnly.go:123:13:123:49 | call to NewCookieStore : pointer type | CookieWithoutHttpOnly.go:129:2:129:8 | session | Cookie attribute 'HttpOnly' is not set to true. | -| CookieWithoutHttpOnly.go:142:2:142:8 | session | CookieWithoutHttpOnly.go:133:14:133:18 | false : bool | CookieWithoutHttpOnly.go:142:2:142:8 | session | Cookie attribute 'HttpOnly' is not set to true. | -| CookieWithoutHttpOnly.go:153:2:153:8 | session | CookieWithoutHttpOnly.go:149:21:151:2 | struct literal : Options | CookieWithoutHttpOnly.go:153:2:153:8 | session | Cookie attribute 'HttpOnly' is not set to true. | -| CookieWithoutHttpOnly.go:191:19:191:25 | session | CookieWithoutHttpOnly.go:123:13:123:49 | call to NewCookieStore : pointer type | CookieWithoutHttpOnly.go:191:19:191:25 | session | Cookie attribute 'HttpOnly' is not set to true. | -| CookieWithoutHttpOnly.go:202:19:202:25 | session | CookieWithoutHttpOnly.go:123:13:123:49 | call to NewCookieStore : pointer type | CookieWithoutHttpOnly.go:202:19:202:25 | session | Cookie attribute 'HttpOnly' is not set to true. | +| CookieWithoutHttpOnly.go:15:20:15:21 | &... | CookieWithoutHttpOnly.go:12:10:12:18 | "session" | CookieWithoutHttpOnly.go:15:20:15:21 | &... | Cookie attribute 'HttpOnly' is not set to true. | +| CookieWithoutHttpOnly.go:24:20:24:21 | &... | CookieWithoutHttpOnly.go:22:13:22:17 | false | CookieWithoutHttpOnly.go:24:20:24:21 | &... | Cookie attribute 'HttpOnly' is not set to true. | +| CookieWithoutHttpOnly.go:51:20:51:21 | &... | CookieWithoutHttpOnly.go:50:15:50:19 | false | CookieWithoutHttpOnly.go:51:20:51:21 | &... | Cookie attribute 'HttpOnly' is not set to true. | +| CookieWithoutHttpOnly.go:61:20:61:21 | &... | CookieWithoutHttpOnly.go:55:9:55:13 | false | CookieWithoutHttpOnly.go:61:20:61:21 | &... | Cookie attribute 'HttpOnly' is not set to true. | +| CookieWithoutHttpOnly.go:91:20:91:21 | &... | CookieWithoutHttpOnly.go:85:9:85:13 | false | CookieWithoutHttpOnly.go:91:20:91:21 | &... | Cookie attribute 'HttpOnly' is not set to true. | +| CookieWithoutHttpOnly.go:110:20:110:21 | &... | CookieWithoutHttpOnly.go:109:15:109:19 | false | CookieWithoutHttpOnly.go:110:20:110:21 | &... | Cookie attribute 'HttpOnly' is not set to true. | +| CookieWithoutHttpOnly.go:120:20:120:21 | &... | CookieWithoutHttpOnly.go:119:15:119:19 | false | CookieWithoutHttpOnly.go:120:20:120:21 | &... | Cookie attribute 'HttpOnly' is not set to true. | +| CookieWithoutHttpOnly.go:129:2:129:8 | session | CookieWithoutHttpOnly.go:123:13:123:49 | call to NewCookieStore | CookieWithoutHttpOnly.go:129:2:129:8 | session | Cookie attribute 'HttpOnly' is not set to true. | +| CookieWithoutHttpOnly.go:142:2:142:8 | session | CookieWithoutHttpOnly.go:133:14:133:18 | false | CookieWithoutHttpOnly.go:142:2:142:8 | session | Cookie attribute 'HttpOnly' is not set to true. | +| CookieWithoutHttpOnly.go:153:2:153:8 | session | CookieWithoutHttpOnly.go:149:21:151:2 | struct literal | CookieWithoutHttpOnly.go:153:2:153:8 | session | Cookie attribute 'HttpOnly' is not set to true. | +| CookieWithoutHttpOnly.go:191:19:191:25 | session | CookieWithoutHttpOnly.go:123:13:123:49 | call to NewCookieStore | CookieWithoutHttpOnly.go:191:19:191:25 | session | Cookie attribute 'HttpOnly' is not set to true. | +| CookieWithoutHttpOnly.go:202:19:202:25 | session | CookieWithoutHttpOnly.go:123:13:123:49 | call to NewCookieStore | CookieWithoutHttpOnly.go:202:19:202:25 | session | Cookie attribute 'HttpOnly' is not set to true. | | CookieWithoutHttpOnly.go:214:66:214:70 | false | CookieWithoutHttpOnly.go:214:66:214:70 | false | CookieWithoutHttpOnly.go:214:66:214:70 | false | Cookie attribute 'HttpOnly' is not set to true. | diff --git a/go/ql/test/experimental/CWE-321/HardcodedKeys.expected b/go/ql/test/experimental/CWE-321/HardcodedKeys.expected index 23b79ccb2a9..fe0fb2d238d 100644 --- a/go/ql/test/experimental/CWE-321/HardcodedKeys.expected +++ b/go/ql/test/experimental/CWE-321/HardcodedKeys.expected @@ -1,74 +1,74 @@ edges -| HardcodedKeysBad.go:11:18:11:38 | type conversion : string | HardcodedKeysBad.go:19:28:19:39 | mySigningKey | -| HardcodedKeysBad.go:11:25:11:37 | "AllYourBase" : string | HardcodedKeysBad.go:11:18:11:38 | type conversion : string | -| main.go:25:18:25:31 | type conversion : string | main.go:34:28:34:39 | mySigningKey | -| main.go:25:25:25:30 | "key1" : string | main.go:25:18:25:31 | type conversion : string | -| main.go:42:23:42:28 | "key2" : string | main.go:42:16:42:29 | type conversion | -| main.go:60:9:60:22 | type conversion : string | main.go:61:44:61:46 | key | -| main.go:60:16:60:21 | `key3` : string | main.go:60:9:60:22 | type conversion : string | -| main.go:65:9:65:22 | type conversion : string | main.go:66:66:66:68 | key | -| main.go:65:16:65:21 | "key4" : string | main.go:65:9:65:22 | type conversion : string | -| main.go:69:10:69:23 | type conversion : string | main.go:74:15:74:18 | key2 | -| main.go:69:17:69:22 | "key5" : string | main.go:69:10:69:23 | type conversion : string | -| main.go:80:9:80:22 | type conversion : string | main.go:84:41:84:43 | key | -| main.go:80:16:80:21 | "key6" : string | main.go:80:9:80:22 | type conversion : string | -| main.go:89:10:89:23 | type conversion : string | main.go:91:66:91:69 | key2 | -| main.go:89:17:89:22 | "key7" : string | main.go:89:10:89:23 | type conversion : string | -| main.go:97:9:97:22 | type conversion : string | main.go:102:30:102:32 | key | -| main.go:97:16:97:21 | "key8" : string | main.go:97:9:97:22 | type conversion : string | -| main.go:106:15:106:28 | type conversion : string | main.go:107:16:107:24 | sharedKey | -| main.go:106:22:106:27 | "key9" : string | main.go:106:15:106:28 | type conversion : string | -| main.go:110:23:110:37 | type conversion : string | main.go:113:16:113:30 | sharedKeyglobal | -| main.go:110:30:110:36 | "key10" : string | main.go:110:23:110:37 | type conversion : string | -| sanitizer.go:17:9:17:21 | type conversion : string | sanitizer.go:18:44:18:46 | key | -| sanitizer.go:17:16:17:20 | `key` : string | sanitizer.go:17:9:17:21 | type conversion : string | +| HardcodedKeysBad.go:11:18:11:38 | type conversion | HardcodedKeysBad.go:19:28:19:39 | mySigningKey | +| HardcodedKeysBad.go:11:25:11:37 | "AllYourBase" | HardcodedKeysBad.go:11:18:11:38 | type conversion | +| main.go:25:18:25:31 | type conversion | main.go:34:28:34:39 | mySigningKey | +| main.go:25:25:25:30 | "key1" | main.go:25:18:25:31 | type conversion | +| main.go:42:23:42:28 | "key2" | main.go:42:16:42:29 | type conversion | +| main.go:60:9:60:22 | type conversion | main.go:61:44:61:46 | key | +| main.go:60:16:60:21 | `key3` | main.go:60:9:60:22 | type conversion | +| main.go:65:9:65:22 | type conversion | main.go:66:66:66:68 | key | +| main.go:65:16:65:21 | "key4" | main.go:65:9:65:22 | type conversion | +| main.go:69:10:69:23 | type conversion | main.go:74:15:74:18 | key2 | +| main.go:69:17:69:22 | "key5" | main.go:69:10:69:23 | type conversion | +| main.go:80:9:80:22 | type conversion | main.go:84:41:84:43 | key | +| main.go:80:16:80:21 | "key6" | main.go:80:9:80:22 | type conversion | +| main.go:89:10:89:23 | type conversion | main.go:91:66:91:69 | key2 | +| main.go:89:17:89:22 | "key7" | main.go:89:10:89:23 | type conversion | +| main.go:97:9:97:22 | type conversion | main.go:102:30:102:32 | key | +| main.go:97:16:97:21 | "key8" | main.go:97:9:97:22 | type conversion | +| main.go:106:15:106:28 | type conversion | main.go:107:16:107:24 | sharedKey | +| main.go:106:22:106:27 | "key9" | main.go:106:15:106:28 | type conversion | +| main.go:110:23:110:37 | type conversion | main.go:113:16:113:30 | sharedKeyglobal | +| main.go:110:30:110:36 | "key10" | main.go:110:23:110:37 | type conversion | +| sanitizer.go:17:9:17:21 | type conversion | sanitizer.go:18:44:18:46 | key | +| sanitizer.go:17:16:17:20 | `key` | sanitizer.go:17:9:17:21 | type conversion | nodes -| HardcodedKeysBad.go:11:18:11:38 | type conversion : string | semmle.label | type conversion : string | -| HardcodedKeysBad.go:11:25:11:37 | "AllYourBase" : string | semmle.label | "AllYourBase" : string | +| HardcodedKeysBad.go:11:18:11:38 | type conversion | semmle.label | type conversion | +| HardcodedKeysBad.go:11:25:11:37 | "AllYourBase" | semmle.label | "AllYourBase" | | HardcodedKeysBad.go:19:28:19:39 | mySigningKey | semmle.label | mySigningKey | -| main.go:25:18:25:31 | type conversion : string | semmle.label | type conversion : string | -| main.go:25:25:25:30 | "key1" : string | semmle.label | "key1" : string | +| main.go:25:18:25:31 | type conversion | semmle.label | type conversion | +| main.go:25:25:25:30 | "key1" | semmle.label | "key1" | | main.go:34:28:34:39 | mySigningKey | semmle.label | mySigningKey | | main.go:42:16:42:29 | type conversion | semmle.label | type conversion | -| main.go:42:23:42:28 | "key2" : string | semmle.label | "key2" : string | -| main.go:60:9:60:22 | type conversion : string | semmle.label | type conversion : string | -| main.go:60:16:60:21 | `key3` : string | semmle.label | `key3` : string | +| main.go:42:23:42:28 | "key2" | semmle.label | "key2" | +| main.go:60:9:60:22 | type conversion | semmle.label | type conversion | +| main.go:60:16:60:21 | `key3` | semmle.label | `key3` | | main.go:61:44:61:46 | key | semmle.label | key | -| main.go:65:9:65:22 | type conversion : string | semmle.label | type conversion : string | -| main.go:65:16:65:21 | "key4" : string | semmle.label | "key4" : string | +| main.go:65:9:65:22 | type conversion | semmle.label | type conversion | +| main.go:65:16:65:21 | "key4" | semmle.label | "key4" | | main.go:66:66:66:68 | key | semmle.label | key | -| main.go:69:10:69:23 | type conversion : string | semmle.label | type conversion : string | -| main.go:69:17:69:22 | "key5" : string | semmle.label | "key5" : string | +| main.go:69:10:69:23 | type conversion | semmle.label | type conversion | +| main.go:69:17:69:22 | "key5" | semmle.label | "key5" | | main.go:74:15:74:18 | key2 | semmle.label | key2 | -| main.go:80:9:80:22 | type conversion : string | semmle.label | type conversion : string | -| main.go:80:16:80:21 | "key6" : string | semmle.label | "key6" : string | +| main.go:80:9:80:22 | type conversion | semmle.label | type conversion | +| main.go:80:16:80:21 | "key6" | semmle.label | "key6" | | main.go:84:41:84:43 | key | semmle.label | key | -| main.go:89:10:89:23 | type conversion : string | semmle.label | type conversion : string | -| main.go:89:17:89:22 | "key7" : string | semmle.label | "key7" : string | +| main.go:89:10:89:23 | type conversion | semmle.label | type conversion | +| main.go:89:17:89:22 | "key7" | semmle.label | "key7" | | main.go:91:66:91:69 | key2 | semmle.label | key2 | -| main.go:97:9:97:22 | type conversion : string | semmle.label | type conversion : string | -| main.go:97:16:97:21 | "key8" : string | semmle.label | "key8" : string | +| main.go:97:9:97:22 | type conversion | semmle.label | type conversion | +| main.go:97:16:97:21 | "key8" | semmle.label | "key8" | | main.go:102:30:102:32 | key | semmle.label | key | -| main.go:106:15:106:28 | type conversion : string | semmle.label | type conversion : string | -| main.go:106:22:106:27 | "key9" : string | semmle.label | "key9" : string | +| main.go:106:15:106:28 | type conversion | semmle.label | type conversion | +| main.go:106:22:106:27 | "key9" | semmle.label | "key9" | | main.go:107:16:107:24 | sharedKey | semmle.label | sharedKey | -| main.go:110:23:110:37 | type conversion : string | semmle.label | type conversion : string | -| main.go:110:30:110:36 | "key10" : string | semmle.label | "key10" : string | +| main.go:110:23:110:37 | type conversion | semmle.label | type conversion | +| main.go:110:30:110:36 | "key10" | semmle.label | "key10" | | main.go:113:16:113:30 | sharedKeyglobal | semmle.label | sharedKeyglobal | -| sanitizer.go:17:9:17:21 | type conversion : string | semmle.label | type conversion : string | -| sanitizer.go:17:16:17:20 | `key` : string | semmle.label | `key` : string | +| sanitizer.go:17:9:17:21 | type conversion | semmle.label | type conversion | +| sanitizer.go:17:16:17:20 | `key` | semmle.label | `key` | | sanitizer.go:18:44:18:46 | key | semmle.label | key | subpaths #select -| HardcodedKeysBad.go:19:28:19:39 | mySigningKey | HardcodedKeysBad.go:11:25:11:37 | "AllYourBase" : string | HardcodedKeysBad.go:19:28:19:39 | mySigningKey | $@ is used to sign a JWT token. | HardcodedKeysBad.go:11:25:11:37 | "AllYourBase" | Hardcoded String | -| main.go:34:28:34:39 | mySigningKey | main.go:25:25:25:30 | "key1" : string | main.go:34:28:34:39 | mySigningKey | $@ is used to sign a JWT token. | main.go:25:25:25:30 | "key1" | Hardcoded String | -| main.go:42:16:42:29 | type conversion | main.go:42:23:42:28 | "key2" : string | main.go:42:16:42:29 | type conversion | $@ is used to sign a JWT token. | main.go:42:23:42:28 | "key2" | Hardcoded String | -| main.go:61:44:61:46 | key | main.go:60:16:60:21 | `key3` : string | main.go:61:44:61:46 | key | $@ is used to sign a JWT token. | main.go:60:16:60:21 | `key3` | Hardcoded String | -| main.go:66:66:66:68 | key | main.go:65:16:65:21 | "key4" : string | main.go:66:66:66:68 | key | $@ is used to sign a JWT token. | main.go:65:16:65:21 | "key4" | Hardcoded String | -| main.go:74:15:74:18 | key2 | main.go:69:17:69:22 | "key5" : string | main.go:74:15:74:18 | key2 | $@ is used to sign a JWT token. | main.go:69:17:69:22 | "key5" | Hardcoded String | -| main.go:84:41:84:43 | key | main.go:80:16:80:21 | "key6" : string | main.go:84:41:84:43 | key | $@ is used to sign a JWT token. | main.go:80:16:80:21 | "key6" | Hardcoded String | -| main.go:91:66:91:69 | key2 | main.go:89:17:89:22 | "key7" : string | main.go:91:66:91:69 | key2 | $@ is used to sign a JWT token. | main.go:89:17:89:22 | "key7" | Hardcoded String | -| main.go:102:30:102:32 | key | main.go:97:16:97:21 | "key8" : string | main.go:102:30:102:32 | key | $@ is used to sign a JWT token. | main.go:97:16:97:21 | "key8" | Hardcoded String | -| main.go:107:16:107:24 | sharedKey | main.go:106:22:106:27 | "key9" : string | main.go:107:16:107:24 | sharedKey | $@ is used to sign a JWT token. | main.go:106:22:106:27 | "key9" | Hardcoded String | -| main.go:113:16:113:30 | sharedKeyglobal | main.go:110:30:110:36 | "key10" : string | main.go:113:16:113:30 | sharedKeyglobal | $@ is used to sign a JWT token. | main.go:110:30:110:36 | "key10" | Hardcoded String | -| sanitizer.go:18:44:18:46 | key | sanitizer.go:17:16:17:20 | `key` : string | sanitizer.go:18:44:18:46 | key | $@ is used to sign a JWT token. | sanitizer.go:17:16:17:20 | `key` | Hardcoded String | +| HardcodedKeysBad.go:19:28:19:39 | mySigningKey | HardcodedKeysBad.go:11:25:11:37 | "AllYourBase" | HardcodedKeysBad.go:19:28:19:39 | mySigningKey | $@ is used to sign a JWT token. | HardcodedKeysBad.go:11:25:11:37 | "AllYourBase" | Hardcoded String | +| main.go:34:28:34:39 | mySigningKey | main.go:25:25:25:30 | "key1" | main.go:34:28:34:39 | mySigningKey | $@ is used to sign a JWT token. | main.go:25:25:25:30 | "key1" | Hardcoded String | +| main.go:42:16:42:29 | type conversion | main.go:42:23:42:28 | "key2" | main.go:42:16:42:29 | type conversion | $@ is used to sign a JWT token. | main.go:42:23:42:28 | "key2" | Hardcoded String | +| main.go:61:44:61:46 | key | main.go:60:16:60:21 | `key3` | main.go:61:44:61:46 | key | $@ is used to sign a JWT token. | main.go:60:16:60:21 | `key3` | Hardcoded String | +| main.go:66:66:66:68 | key | main.go:65:16:65:21 | "key4" | main.go:66:66:66:68 | key | $@ is used to sign a JWT token. | main.go:65:16:65:21 | "key4" | Hardcoded String | +| main.go:74:15:74:18 | key2 | main.go:69:17:69:22 | "key5" | main.go:74:15:74:18 | key2 | $@ is used to sign a JWT token. | main.go:69:17:69:22 | "key5" | Hardcoded String | +| main.go:84:41:84:43 | key | main.go:80:16:80:21 | "key6" | main.go:84:41:84:43 | key | $@ is used to sign a JWT token. | main.go:80:16:80:21 | "key6" | Hardcoded String | +| main.go:91:66:91:69 | key2 | main.go:89:17:89:22 | "key7" | main.go:91:66:91:69 | key2 | $@ is used to sign a JWT token. | main.go:89:17:89:22 | "key7" | Hardcoded String | +| main.go:102:30:102:32 | key | main.go:97:16:97:21 | "key8" | main.go:102:30:102:32 | key | $@ is used to sign a JWT token. | main.go:97:16:97:21 | "key8" | Hardcoded String | +| main.go:107:16:107:24 | sharedKey | main.go:106:22:106:27 | "key9" | main.go:107:16:107:24 | sharedKey | $@ is used to sign a JWT token. | main.go:106:22:106:27 | "key9" | Hardcoded String | +| main.go:113:16:113:30 | sharedKeyglobal | main.go:110:30:110:36 | "key10" | main.go:113:16:113:30 | sharedKeyglobal | $@ is used to sign a JWT token. | main.go:110:30:110:36 | "key10" | Hardcoded String | +| sanitizer.go:18:44:18:46 | key | sanitizer.go:17:16:17:20 | `key` | sanitizer.go:18:44:18:46 | key | $@ is used to sign a JWT token. | sanitizer.go:17:16:17:20 | `key` | Hardcoded String | diff --git a/go/ql/test/experimental/CWE-369/DivideByZero.expected b/go/ql/test/experimental/CWE-369/DivideByZero.expected index e80e3295c22..081dac5ec37 100644 --- a/go/ql/test/experimental/CWE-369/DivideByZero.expected +++ b/go/ql/test/experimental/CWE-369/DivideByZero.expected @@ -1,32 +1,32 @@ edges -| DivideByZero.go:10:12:10:16 | selection of URL : pointer type | DivideByZero.go:12:16:12:20 | value | -| DivideByZero.go:17:12:17:16 | selection of URL : pointer type | DivideByZero.go:18:11:18:24 | type conversion : uint8 | -| DivideByZero.go:18:11:18:24 | type conversion : uint8 | DivideByZero.go:19:16:19:20 | value | -| DivideByZero.go:24:12:24:16 | selection of URL : pointer type | DivideByZero.go:26:16:26:20 | value | -| DivideByZero.go:31:12:31:16 | selection of URL : pointer type | DivideByZero.go:33:16:33:20 | value | -| DivideByZero.go:38:12:38:16 | selection of URL : pointer type | DivideByZero.go:40:16:40:20 | value | -| DivideByZero.go:54:12:54:16 | selection of URL : pointer type | DivideByZero.go:55:11:55:24 | type conversion : uint8 | -| DivideByZero.go:55:11:55:24 | type conversion : uint8 | DivideByZero.go:57:17:57:21 | value | +| DivideByZero.go:10:12:10:16 | selection of URL | DivideByZero.go:12:16:12:20 | value | +| DivideByZero.go:17:12:17:16 | selection of URL | DivideByZero.go:18:11:18:24 | type conversion | +| DivideByZero.go:18:11:18:24 | type conversion | DivideByZero.go:19:16:19:20 | value | +| DivideByZero.go:24:12:24:16 | selection of URL | DivideByZero.go:26:16:26:20 | value | +| DivideByZero.go:31:12:31:16 | selection of URL | DivideByZero.go:33:16:33:20 | value | +| DivideByZero.go:38:12:38:16 | selection of URL | DivideByZero.go:40:16:40:20 | value | +| DivideByZero.go:54:12:54:16 | selection of URL | DivideByZero.go:55:11:55:24 | type conversion | +| DivideByZero.go:55:11:55:24 | type conversion | DivideByZero.go:57:17:57:21 | value | nodes -| DivideByZero.go:10:12:10:16 | selection of URL : pointer type | semmle.label | selection of URL : pointer type | +| DivideByZero.go:10:12:10:16 | selection of URL | semmle.label | selection of URL | | DivideByZero.go:12:16:12:20 | value | semmle.label | value | -| DivideByZero.go:17:12:17:16 | selection of URL : pointer type | semmle.label | selection of URL : pointer type | -| DivideByZero.go:18:11:18:24 | type conversion : uint8 | semmle.label | type conversion : uint8 | +| DivideByZero.go:17:12:17:16 | selection of URL | semmle.label | selection of URL | +| DivideByZero.go:18:11:18:24 | type conversion | semmle.label | type conversion | | DivideByZero.go:19:16:19:20 | value | semmle.label | value | -| DivideByZero.go:24:12:24:16 | selection of URL : pointer type | semmle.label | selection of URL : pointer type | +| DivideByZero.go:24:12:24:16 | selection of URL | semmle.label | selection of URL | | DivideByZero.go:26:16:26:20 | value | semmle.label | value | -| DivideByZero.go:31:12:31:16 | selection of URL : pointer type | semmle.label | selection of URL : pointer type | +| DivideByZero.go:31:12:31:16 | selection of URL | semmle.label | selection of URL | | DivideByZero.go:33:16:33:20 | value | semmle.label | value | -| DivideByZero.go:38:12:38:16 | selection of URL : pointer type | semmle.label | selection of URL : pointer type | +| DivideByZero.go:38:12:38:16 | selection of URL | semmle.label | selection of URL | | DivideByZero.go:40:16:40:20 | value | semmle.label | value | -| DivideByZero.go:54:12:54:16 | selection of URL : pointer type | semmle.label | selection of URL : pointer type | -| DivideByZero.go:55:11:55:24 | type conversion : uint8 | semmle.label | type conversion : uint8 | +| DivideByZero.go:54:12:54:16 | selection of URL | semmle.label | selection of URL | +| DivideByZero.go:55:11:55:24 | type conversion | semmle.label | type conversion | | DivideByZero.go:57:17:57:21 | value | semmle.label | value | subpaths #select -| DivideByZero.go:12:16:12:20 | value | DivideByZero.go:10:12:10:16 | selection of URL : pointer type | DivideByZero.go:12:16:12:20 | value | This variable might be zero leading to a division-by-zero panic. | -| DivideByZero.go:19:16:19:20 | value | DivideByZero.go:17:12:17:16 | selection of URL : pointer type | DivideByZero.go:19:16:19:20 | value | This variable might be zero leading to a division-by-zero panic. | -| DivideByZero.go:26:16:26:20 | value | DivideByZero.go:24:12:24:16 | selection of URL : pointer type | DivideByZero.go:26:16:26:20 | value | This variable might be zero leading to a division-by-zero panic. | -| DivideByZero.go:33:16:33:20 | value | DivideByZero.go:31:12:31:16 | selection of URL : pointer type | DivideByZero.go:33:16:33:20 | value | This variable might be zero leading to a division-by-zero panic. | -| DivideByZero.go:40:16:40:20 | value | DivideByZero.go:38:12:38:16 | selection of URL : pointer type | DivideByZero.go:40:16:40:20 | value | This variable might be zero leading to a division-by-zero panic. | -| DivideByZero.go:57:17:57:21 | value | DivideByZero.go:54:12:54:16 | selection of URL : pointer type | DivideByZero.go:57:17:57:21 | value | This variable might be zero leading to a division-by-zero panic. | +| DivideByZero.go:12:16:12:20 | value | DivideByZero.go:10:12:10:16 | selection of URL | DivideByZero.go:12:16:12:20 | value | This variable might be zero leading to a division-by-zero panic. | +| DivideByZero.go:19:16:19:20 | value | DivideByZero.go:17:12:17:16 | selection of URL | DivideByZero.go:19:16:19:20 | value | This variable might be zero leading to a division-by-zero panic. | +| DivideByZero.go:26:16:26:20 | value | DivideByZero.go:24:12:24:16 | selection of URL | DivideByZero.go:26:16:26:20 | value | This variable might be zero leading to a division-by-zero panic. | +| DivideByZero.go:33:16:33:20 | value | DivideByZero.go:31:12:31:16 | selection of URL | DivideByZero.go:33:16:33:20 | value | This variable might be zero leading to a division-by-zero panic. | +| DivideByZero.go:40:16:40:20 | value | DivideByZero.go:38:12:38:16 | selection of URL | DivideByZero.go:40:16:40:20 | value | This variable might be zero leading to a division-by-zero panic. | +| DivideByZero.go:57:17:57:21 | value | DivideByZero.go:54:12:54:16 | selection of URL | DivideByZero.go:57:17:57:21 | value | This variable might be zero leading to a division-by-zero panic. | diff --git a/go/ql/test/experimental/CWE-79/HTMLTemplateEscapingPassthrough.expected b/go/ql/test/experimental/CWE-79/HTMLTemplateEscapingPassthrough.expected index ff2053dd942..77cd46d64e6 100644 --- a/go/ql/test/experimental/CWE-79/HTMLTemplateEscapingPassthrough.expected +++ b/go/ql/test/experimental/CWE-79/HTMLTemplateEscapingPassthrough.expected @@ -1,117 +1,117 @@ edges -| HTMLTemplateEscapingPassthrough.go:28:12:28:41 | type conversion : HTML | HTMLTemplateEscapingPassthrough.go:29:39:29:39 | a | -| HTMLTemplateEscapingPassthrough.go:28:12:28:41 | type conversion : HTML | HTMLTemplateEscapingPassthrough.go:29:39:29:39 | a | -| HTMLTemplateEscapingPassthrough.go:28:12:28:41 | type conversion : HTML | HTMLTemplateEscapingPassthrough.go:29:39:29:39 | a | -| HTMLTemplateEscapingPassthrough.go:28:12:28:41 | type conversion : HTML | HTMLTemplateEscapingPassthrough.go:29:39:29:39 | a | -| HTMLTemplateEscapingPassthrough.go:28:12:28:41 | type conversion : HTML | HTMLTemplateEscapingPassthrough.go:29:39:29:39 | a | -| HTMLTemplateEscapingPassthrough.go:28:12:28:41 | type conversion : HTML | HTMLTemplateEscapingPassthrough.go:29:39:29:39 | a | -| HTMLTemplateEscapingPassthrough.go:28:12:28:41 | type conversion : HTML | HTMLTemplateEscapingPassthrough.go:29:39:29:39 | a | -| HTMLTemplateEscapingPassthrough.go:28:12:28:41 | type conversion : string | HTMLTemplateEscapingPassthrough.go:29:39:29:39 | a | -| HTMLTemplateEscapingPassthrough.go:28:26:28:40 | call to UserAgent : string | HTMLTemplateEscapingPassthrough.go:28:12:28:41 | type conversion | -| HTMLTemplateEscapingPassthrough.go:28:26:28:40 | call to UserAgent : string | HTMLTemplateEscapingPassthrough.go:28:12:28:41 | type conversion : string | -| HTMLTemplateEscapingPassthrough.go:34:9:34:38 | type conversion : HTML | HTMLTemplateEscapingPassthrough.go:35:40:35:40 | a | -| HTMLTemplateEscapingPassthrough.go:34:9:34:38 | type conversion : HTML | HTMLTemplateEscapingPassthrough.go:35:40:35:40 | a | -| HTMLTemplateEscapingPassthrough.go:34:9:34:38 | type conversion : HTML | HTMLTemplateEscapingPassthrough.go:35:40:35:40 | a | -| HTMLTemplateEscapingPassthrough.go:34:9:34:38 | type conversion : HTML | HTMLTemplateEscapingPassthrough.go:35:40:35:40 | a | -| HTMLTemplateEscapingPassthrough.go:34:9:34:38 | type conversion : HTML | HTMLTemplateEscapingPassthrough.go:35:40:35:40 | a | -| HTMLTemplateEscapingPassthrough.go:34:9:34:38 | type conversion : HTML | HTMLTemplateEscapingPassthrough.go:35:40:35:40 | a | -| HTMLTemplateEscapingPassthrough.go:34:9:34:38 | type conversion : HTML | HTMLTemplateEscapingPassthrough.go:35:40:35:40 | a | -| HTMLTemplateEscapingPassthrough.go:34:9:34:38 | type conversion : string | HTMLTemplateEscapingPassthrough.go:35:40:35:40 | a | -| HTMLTemplateEscapingPassthrough.go:34:23:34:37 | call to UserAgent : string | HTMLTemplateEscapingPassthrough.go:34:9:34:38 | type conversion | -| HTMLTemplateEscapingPassthrough.go:34:23:34:37 | call to UserAgent : string | HTMLTemplateEscapingPassthrough.go:34:9:34:38 | type conversion : string | -| HTMLTemplateEscapingPassthrough.go:39:9:39:34 | type conversion : HTML | HTMLTemplateEscapingPassthrough.go:40:40:40:40 | a | -| HTMLTemplateEscapingPassthrough.go:39:9:39:34 | type conversion : HTML | HTMLTemplateEscapingPassthrough.go:40:40:40:40 | a | -| HTMLTemplateEscapingPassthrough.go:39:9:39:34 | type conversion : HTML | HTMLTemplateEscapingPassthrough.go:40:40:40:40 | a | -| HTMLTemplateEscapingPassthrough.go:39:9:39:34 | type conversion : HTML | HTMLTemplateEscapingPassthrough.go:40:40:40:40 | a | -| HTMLTemplateEscapingPassthrough.go:39:9:39:34 | type conversion : HTML | HTMLTemplateEscapingPassthrough.go:40:40:40:40 | a | -| HTMLTemplateEscapingPassthrough.go:39:9:39:34 | type conversion : HTML | HTMLTemplateEscapingPassthrough.go:40:40:40:40 | a | -| HTMLTemplateEscapingPassthrough.go:39:9:39:34 | type conversion : HTML | HTMLTemplateEscapingPassthrough.go:40:40:40:40 | a | -| HTMLTemplateEscapingPassthrough.go:39:9:39:34 | type conversion : string | HTMLTemplateEscapingPassthrough.go:40:40:40:40 | a | -| HTMLTemplateEscapingPassthrough.go:39:19:39:33 | call to UserAgent : string | HTMLTemplateEscapingPassthrough.go:39:9:39:34 | type conversion | -| HTMLTemplateEscapingPassthrough.go:39:19:39:33 | call to UserAgent : string | HTMLTemplateEscapingPassthrough.go:39:9:39:34 | type conversion : string | -| HTMLTemplateEscapingPassthrough.go:45:11:45:44 | type conversion : HTMLAttr | HTMLTemplateEscapingPassthrough.go:46:41:46:41 | c | -| HTMLTemplateEscapingPassthrough.go:45:11:45:44 | type conversion : HTMLAttr | HTMLTemplateEscapingPassthrough.go:46:41:46:41 | c | -| HTMLTemplateEscapingPassthrough.go:45:11:45:44 | type conversion : HTMLAttr | HTMLTemplateEscapingPassthrough.go:46:41:46:41 | c | -| HTMLTemplateEscapingPassthrough.go:45:11:45:44 | type conversion : HTMLAttr | HTMLTemplateEscapingPassthrough.go:46:41:46:41 | c | -| HTMLTemplateEscapingPassthrough.go:45:11:45:44 | type conversion : HTMLAttr | HTMLTemplateEscapingPassthrough.go:46:41:46:41 | c | -| HTMLTemplateEscapingPassthrough.go:45:11:45:44 | type conversion : HTMLAttr | HTMLTemplateEscapingPassthrough.go:46:41:46:41 | c | -| HTMLTemplateEscapingPassthrough.go:45:11:45:44 | type conversion : HTMLAttr | HTMLTemplateEscapingPassthrough.go:46:41:46:41 | c | -| HTMLTemplateEscapingPassthrough.go:45:11:45:44 | type conversion : string | HTMLTemplateEscapingPassthrough.go:46:41:46:41 | c | -| HTMLTemplateEscapingPassthrough.go:45:29:45:43 | call to UserAgent : string | HTMLTemplateEscapingPassthrough.go:45:11:45:44 | type conversion | -| HTMLTemplateEscapingPassthrough.go:45:29:45:43 | call to UserAgent : string | HTMLTemplateEscapingPassthrough.go:45:11:45:44 | type conversion : string | -| HTMLTemplateEscapingPassthrough.go:49:11:49:38 | type conversion : JS | HTMLTemplateEscapingPassthrough.go:50:44:50:44 | d | -| HTMLTemplateEscapingPassthrough.go:49:11:49:38 | type conversion : JS | HTMLTemplateEscapingPassthrough.go:50:44:50:44 | d | -| HTMLTemplateEscapingPassthrough.go:49:11:49:38 | type conversion : JS | HTMLTemplateEscapingPassthrough.go:50:44:50:44 | d | -| HTMLTemplateEscapingPassthrough.go:49:11:49:38 | type conversion : JS | HTMLTemplateEscapingPassthrough.go:50:44:50:44 | d | -| HTMLTemplateEscapingPassthrough.go:49:11:49:38 | type conversion : JS | HTMLTemplateEscapingPassthrough.go:50:44:50:44 | d | -| HTMLTemplateEscapingPassthrough.go:49:11:49:38 | type conversion : JS | HTMLTemplateEscapingPassthrough.go:50:44:50:44 | d | -| HTMLTemplateEscapingPassthrough.go:49:11:49:38 | type conversion : JS | HTMLTemplateEscapingPassthrough.go:50:44:50:44 | d | -| HTMLTemplateEscapingPassthrough.go:49:11:49:38 | type conversion : string | HTMLTemplateEscapingPassthrough.go:50:44:50:44 | d | -| HTMLTemplateEscapingPassthrough.go:49:23:49:37 | call to UserAgent : string | HTMLTemplateEscapingPassthrough.go:49:11:49:38 | type conversion | -| HTMLTemplateEscapingPassthrough.go:49:23:49:37 | call to UserAgent : string | HTMLTemplateEscapingPassthrough.go:49:11:49:38 | type conversion : string | -| HTMLTemplateEscapingPassthrough.go:53:11:53:41 | type conversion : JSStr | HTMLTemplateEscapingPassthrough.go:54:44:54:44 | e | -| HTMLTemplateEscapingPassthrough.go:53:11:53:41 | type conversion : JSStr | HTMLTemplateEscapingPassthrough.go:54:44:54:44 | e | -| HTMLTemplateEscapingPassthrough.go:53:11:53:41 | type conversion : JSStr | HTMLTemplateEscapingPassthrough.go:54:44:54:44 | e | -| HTMLTemplateEscapingPassthrough.go:53:11:53:41 | type conversion : JSStr | HTMLTemplateEscapingPassthrough.go:54:44:54:44 | e | -| HTMLTemplateEscapingPassthrough.go:53:11:53:41 | type conversion : JSStr | HTMLTemplateEscapingPassthrough.go:54:44:54:44 | e | -| HTMLTemplateEscapingPassthrough.go:53:11:53:41 | type conversion : JSStr | HTMLTemplateEscapingPassthrough.go:54:44:54:44 | e | -| HTMLTemplateEscapingPassthrough.go:53:11:53:41 | type conversion : JSStr | HTMLTemplateEscapingPassthrough.go:54:44:54:44 | e | -| HTMLTemplateEscapingPassthrough.go:53:11:53:41 | type conversion : string | HTMLTemplateEscapingPassthrough.go:54:44:54:44 | e | -| HTMLTemplateEscapingPassthrough.go:53:26:53:40 | call to UserAgent : string | HTMLTemplateEscapingPassthrough.go:53:11:53:41 | type conversion | -| HTMLTemplateEscapingPassthrough.go:53:26:53:40 | call to UserAgent : string | HTMLTemplateEscapingPassthrough.go:53:11:53:41 | type conversion : string | -| HTMLTemplateEscapingPassthrough.go:57:11:57:39 | type conversion : CSS | HTMLTemplateEscapingPassthrough.go:58:38:58:38 | b | -| HTMLTemplateEscapingPassthrough.go:57:11:57:39 | type conversion : CSS | HTMLTemplateEscapingPassthrough.go:58:38:58:38 | b | -| HTMLTemplateEscapingPassthrough.go:57:11:57:39 | type conversion : CSS | HTMLTemplateEscapingPassthrough.go:58:38:58:38 | b | -| HTMLTemplateEscapingPassthrough.go:57:11:57:39 | type conversion : CSS | HTMLTemplateEscapingPassthrough.go:58:38:58:38 | b | -| HTMLTemplateEscapingPassthrough.go:57:11:57:39 | type conversion : CSS | HTMLTemplateEscapingPassthrough.go:58:38:58:38 | b | -| HTMLTemplateEscapingPassthrough.go:57:11:57:39 | type conversion : CSS | HTMLTemplateEscapingPassthrough.go:58:38:58:38 | b | -| HTMLTemplateEscapingPassthrough.go:57:11:57:39 | type conversion : CSS | HTMLTemplateEscapingPassthrough.go:58:38:58:38 | b | -| HTMLTemplateEscapingPassthrough.go:57:11:57:39 | type conversion : string | HTMLTemplateEscapingPassthrough.go:58:38:58:38 | b | -| HTMLTemplateEscapingPassthrough.go:57:24:57:38 | call to UserAgent : string | HTMLTemplateEscapingPassthrough.go:57:11:57:39 | type conversion | -| HTMLTemplateEscapingPassthrough.go:57:24:57:38 | call to UserAgent : string | HTMLTemplateEscapingPassthrough.go:57:11:57:39 | type conversion : string | -| HTMLTemplateEscapingPassthrough.go:61:11:61:42 | type conversion : Srcset | HTMLTemplateEscapingPassthrough.go:62:44:62:44 | f | -| HTMLTemplateEscapingPassthrough.go:61:11:61:42 | type conversion : Srcset | HTMLTemplateEscapingPassthrough.go:62:44:62:44 | f | -| HTMLTemplateEscapingPassthrough.go:61:11:61:42 | type conversion : Srcset | HTMLTemplateEscapingPassthrough.go:62:44:62:44 | f | -| HTMLTemplateEscapingPassthrough.go:61:11:61:42 | type conversion : Srcset | HTMLTemplateEscapingPassthrough.go:62:44:62:44 | f | -| HTMLTemplateEscapingPassthrough.go:61:11:61:42 | type conversion : Srcset | HTMLTemplateEscapingPassthrough.go:62:44:62:44 | f | -| HTMLTemplateEscapingPassthrough.go:61:11:61:42 | type conversion : Srcset | HTMLTemplateEscapingPassthrough.go:62:44:62:44 | f | -| HTMLTemplateEscapingPassthrough.go:61:11:61:42 | type conversion : Srcset | HTMLTemplateEscapingPassthrough.go:62:44:62:44 | f | -| HTMLTemplateEscapingPassthrough.go:61:11:61:42 | type conversion : string | HTMLTemplateEscapingPassthrough.go:62:44:62:44 | f | -| HTMLTemplateEscapingPassthrough.go:61:27:61:41 | call to UserAgent : string | HTMLTemplateEscapingPassthrough.go:61:11:61:42 | type conversion | -| HTMLTemplateEscapingPassthrough.go:61:27:61:41 | call to UserAgent : string | HTMLTemplateEscapingPassthrough.go:61:11:61:42 | type conversion : string | -| HTMLTemplateEscapingPassthrough.go:65:11:65:39 | type conversion : URL | HTMLTemplateEscapingPassthrough.go:66:38:66:38 | g | -| HTMLTemplateEscapingPassthrough.go:65:11:65:39 | type conversion : URL | HTMLTemplateEscapingPassthrough.go:66:38:66:38 | g | -| HTMLTemplateEscapingPassthrough.go:65:11:65:39 | type conversion : URL | HTMLTemplateEscapingPassthrough.go:66:38:66:38 | g | -| HTMLTemplateEscapingPassthrough.go:65:11:65:39 | type conversion : URL | HTMLTemplateEscapingPassthrough.go:66:38:66:38 | g | -| HTMLTemplateEscapingPassthrough.go:65:11:65:39 | type conversion : URL | HTMLTemplateEscapingPassthrough.go:66:38:66:38 | g | -| HTMLTemplateEscapingPassthrough.go:65:11:65:39 | type conversion : URL | HTMLTemplateEscapingPassthrough.go:66:38:66:38 | g | -| HTMLTemplateEscapingPassthrough.go:65:11:65:39 | type conversion : URL | HTMLTemplateEscapingPassthrough.go:66:38:66:38 | g | -| HTMLTemplateEscapingPassthrough.go:65:11:65:39 | type conversion : string | HTMLTemplateEscapingPassthrough.go:66:38:66:38 | g | -| HTMLTemplateEscapingPassthrough.go:65:24:65:38 | call to UserAgent : string | HTMLTemplateEscapingPassthrough.go:65:11:65:39 | type conversion | -| HTMLTemplateEscapingPassthrough.go:65:24:65:38 | call to UserAgent : string | HTMLTemplateEscapingPassthrough.go:65:11:65:39 | type conversion : string | -| HTMLTemplateEscapingPassthrough.go:74:17:74:31 | call to UserAgent : string | HTMLTemplateEscapingPassthrough.go:75:38:75:44 | escaped | -| HTMLTemplateEscapingPassthrough.go:80:10:80:24 | call to UserAgent : string | HTMLTemplateEscapingPassthrough.go:81:16:81:33 | type conversion | -| HTMLTemplateEscapingPassthrough.go:80:10:80:24 | call to UserAgent : string | HTMLTemplateEscapingPassthrough.go:83:38:83:40 | src | -| HTMLTemplateEscapingPassthrough.go:88:10:88:24 | call to UserAgent : string | HTMLTemplateEscapingPassthrough.go:90:16:90:77 | type conversion | -| HTMLTemplateEscapingPassthrough.go:90:16:90:77 | type conversion : HTML | HTMLTemplateEscapingPassthrough.go:91:38:91:46 | converted | -| HTMLTemplateEscapingPassthrough.go:90:16:90:77 | type conversion : HTML | HTMLTemplateEscapingPassthrough.go:91:38:91:46 | converted | -| HTMLTemplateEscapingPassthrough.go:90:16:90:77 | type conversion : HTML | HTMLTemplateEscapingPassthrough.go:91:38:91:46 | converted | -| HTMLTemplateEscapingPassthrough.go:90:16:90:77 | type conversion : HTML | HTMLTemplateEscapingPassthrough.go:91:38:91:46 | converted | -| HTMLTemplateEscapingPassthrough.go:90:16:90:77 | type conversion : HTML | HTMLTemplateEscapingPassthrough.go:91:38:91:46 | converted | -| HTMLTemplateEscapingPassthrough.go:90:16:90:77 | type conversion : HTML | HTMLTemplateEscapingPassthrough.go:91:38:91:46 | converted | -| HTMLTemplateEscapingPassthrough.go:90:16:90:77 | type conversion : HTML | HTMLTemplateEscapingPassthrough.go:91:38:91:46 | converted | +| HTMLTemplateEscapingPassthrough.go:28:12:28:41 | type conversion | HTMLTemplateEscapingPassthrough.go:29:39:29:39 | a | +| HTMLTemplateEscapingPassthrough.go:28:12:28:41 | type conversion | HTMLTemplateEscapingPassthrough.go:29:39:29:39 | a | +| HTMLTemplateEscapingPassthrough.go:28:12:28:41 | type conversion | HTMLTemplateEscapingPassthrough.go:29:39:29:39 | a | +| HTMLTemplateEscapingPassthrough.go:28:12:28:41 | type conversion | HTMLTemplateEscapingPassthrough.go:29:39:29:39 | a | +| HTMLTemplateEscapingPassthrough.go:28:12:28:41 | type conversion | HTMLTemplateEscapingPassthrough.go:29:39:29:39 | a | +| HTMLTemplateEscapingPassthrough.go:28:12:28:41 | type conversion | HTMLTemplateEscapingPassthrough.go:29:39:29:39 | a | +| HTMLTemplateEscapingPassthrough.go:28:12:28:41 | type conversion | HTMLTemplateEscapingPassthrough.go:29:39:29:39 | a | +| HTMLTemplateEscapingPassthrough.go:28:12:28:41 | type conversion | HTMLTemplateEscapingPassthrough.go:29:39:29:39 | a | +| HTMLTemplateEscapingPassthrough.go:28:26:28:40 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:28:12:28:41 | type conversion | +| HTMLTemplateEscapingPassthrough.go:28:26:28:40 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:28:12:28:41 | type conversion | +| HTMLTemplateEscapingPassthrough.go:34:9:34:38 | type conversion | HTMLTemplateEscapingPassthrough.go:35:40:35:40 | a | +| HTMLTemplateEscapingPassthrough.go:34:9:34:38 | type conversion | HTMLTemplateEscapingPassthrough.go:35:40:35:40 | a | +| HTMLTemplateEscapingPassthrough.go:34:9:34:38 | type conversion | HTMLTemplateEscapingPassthrough.go:35:40:35:40 | a | +| HTMLTemplateEscapingPassthrough.go:34:9:34:38 | type conversion | HTMLTemplateEscapingPassthrough.go:35:40:35:40 | a | +| HTMLTemplateEscapingPassthrough.go:34:9:34:38 | type conversion | HTMLTemplateEscapingPassthrough.go:35:40:35:40 | a | +| HTMLTemplateEscapingPassthrough.go:34:9:34:38 | type conversion | HTMLTemplateEscapingPassthrough.go:35:40:35:40 | a | +| HTMLTemplateEscapingPassthrough.go:34:9:34:38 | type conversion | HTMLTemplateEscapingPassthrough.go:35:40:35:40 | a | +| HTMLTemplateEscapingPassthrough.go:34:9:34:38 | type conversion | HTMLTemplateEscapingPassthrough.go:35:40:35:40 | a | +| HTMLTemplateEscapingPassthrough.go:34:23:34:37 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:34:9:34:38 | type conversion | +| HTMLTemplateEscapingPassthrough.go:34:23:34:37 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:34:9:34:38 | type conversion | +| HTMLTemplateEscapingPassthrough.go:39:9:39:34 | type conversion | HTMLTemplateEscapingPassthrough.go:40:40:40:40 | a | +| HTMLTemplateEscapingPassthrough.go:39:9:39:34 | type conversion | HTMLTemplateEscapingPassthrough.go:40:40:40:40 | a | +| HTMLTemplateEscapingPassthrough.go:39:9:39:34 | type conversion | HTMLTemplateEscapingPassthrough.go:40:40:40:40 | a | +| HTMLTemplateEscapingPassthrough.go:39:9:39:34 | type conversion | HTMLTemplateEscapingPassthrough.go:40:40:40:40 | a | +| HTMLTemplateEscapingPassthrough.go:39:9:39:34 | type conversion | HTMLTemplateEscapingPassthrough.go:40:40:40:40 | a | +| HTMLTemplateEscapingPassthrough.go:39:9:39:34 | type conversion | HTMLTemplateEscapingPassthrough.go:40:40:40:40 | a | +| HTMLTemplateEscapingPassthrough.go:39:9:39:34 | type conversion | HTMLTemplateEscapingPassthrough.go:40:40:40:40 | a | +| HTMLTemplateEscapingPassthrough.go:39:9:39:34 | type conversion | HTMLTemplateEscapingPassthrough.go:40:40:40:40 | a | +| HTMLTemplateEscapingPassthrough.go:39:19:39:33 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:39:9:39:34 | type conversion | +| HTMLTemplateEscapingPassthrough.go:39:19:39:33 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:39:9:39:34 | type conversion | +| HTMLTemplateEscapingPassthrough.go:45:11:45:44 | type conversion | HTMLTemplateEscapingPassthrough.go:46:41:46:41 | c | +| HTMLTemplateEscapingPassthrough.go:45:11:45:44 | type conversion | HTMLTemplateEscapingPassthrough.go:46:41:46:41 | c | +| HTMLTemplateEscapingPassthrough.go:45:11:45:44 | type conversion | HTMLTemplateEscapingPassthrough.go:46:41:46:41 | c | +| HTMLTemplateEscapingPassthrough.go:45:11:45:44 | type conversion | HTMLTemplateEscapingPassthrough.go:46:41:46:41 | c | +| HTMLTemplateEscapingPassthrough.go:45:11:45:44 | type conversion | HTMLTemplateEscapingPassthrough.go:46:41:46:41 | c | +| HTMLTemplateEscapingPassthrough.go:45:11:45:44 | type conversion | HTMLTemplateEscapingPassthrough.go:46:41:46:41 | c | +| HTMLTemplateEscapingPassthrough.go:45:11:45:44 | type conversion | HTMLTemplateEscapingPassthrough.go:46:41:46:41 | c | +| HTMLTemplateEscapingPassthrough.go:45:11:45:44 | type conversion | HTMLTemplateEscapingPassthrough.go:46:41:46:41 | c | +| HTMLTemplateEscapingPassthrough.go:45:29:45:43 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:45:11:45:44 | type conversion | +| HTMLTemplateEscapingPassthrough.go:45:29:45:43 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:45:11:45:44 | type conversion | +| HTMLTemplateEscapingPassthrough.go:49:11:49:38 | type conversion | HTMLTemplateEscapingPassthrough.go:50:44:50:44 | d | +| HTMLTemplateEscapingPassthrough.go:49:11:49:38 | type conversion | HTMLTemplateEscapingPassthrough.go:50:44:50:44 | d | +| HTMLTemplateEscapingPassthrough.go:49:11:49:38 | type conversion | HTMLTemplateEscapingPassthrough.go:50:44:50:44 | d | +| HTMLTemplateEscapingPassthrough.go:49:11:49:38 | type conversion | HTMLTemplateEscapingPassthrough.go:50:44:50:44 | d | +| HTMLTemplateEscapingPassthrough.go:49:11:49:38 | type conversion | HTMLTemplateEscapingPassthrough.go:50:44:50:44 | d | +| HTMLTemplateEscapingPassthrough.go:49:11:49:38 | type conversion | HTMLTemplateEscapingPassthrough.go:50:44:50:44 | d | +| HTMLTemplateEscapingPassthrough.go:49:11:49:38 | type conversion | HTMLTemplateEscapingPassthrough.go:50:44:50:44 | d | +| HTMLTemplateEscapingPassthrough.go:49:11:49:38 | type conversion | HTMLTemplateEscapingPassthrough.go:50:44:50:44 | d | +| HTMLTemplateEscapingPassthrough.go:49:23:49:37 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:49:11:49:38 | type conversion | +| HTMLTemplateEscapingPassthrough.go:49:23:49:37 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:49:11:49:38 | type conversion | +| HTMLTemplateEscapingPassthrough.go:53:11:53:41 | type conversion | HTMLTemplateEscapingPassthrough.go:54:44:54:44 | e | +| HTMLTemplateEscapingPassthrough.go:53:11:53:41 | type conversion | HTMLTemplateEscapingPassthrough.go:54:44:54:44 | e | +| HTMLTemplateEscapingPassthrough.go:53:11:53:41 | type conversion | HTMLTemplateEscapingPassthrough.go:54:44:54:44 | e | +| HTMLTemplateEscapingPassthrough.go:53:11:53:41 | type conversion | HTMLTemplateEscapingPassthrough.go:54:44:54:44 | e | +| HTMLTemplateEscapingPassthrough.go:53:11:53:41 | type conversion | HTMLTemplateEscapingPassthrough.go:54:44:54:44 | e | +| HTMLTemplateEscapingPassthrough.go:53:11:53:41 | type conversion | HTMLTemplateEscapingPassthrough.go:54:44:54:44 | e | +| HTMLTemplateEscapingPassthrough.go:53:11:53:41 | type conversion | HTMLTemplateEscapingPassthrough.go:54:44:54:44 | e | +| HTMLTemplateEscapingPassthrough.go:53:11:53:41 | type conversion | HTMLTemplateEscapingPassthrough.go:54:44:54:44 | e | +| HTMLTemplateEscapingPassthrough.go:53:26:53:40 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:53:11:53:41 | type conversion | +| HTMLTemplateEscapingPassthrough.go:53:26:53:40 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:53:11:53:41 | type conversion | +| HTMLTemplateEscapingPassthrough.go:57:11:57:39 | type conversion | HTMLTemplateEscapingPassthrough.go:58:38:58:38 | b | +| HTMLTemplateEscapingPassthrough.go:57:11:57:39 | type conversion | HTMLTemplateEscapingPassthrough.go:58:38:58:38 | b | +| HTMLTemplateEscapingPassthrough.go:57:11:57:39 | type conversion | HTMLTemplateEscapingPassthrough.go:58:38:58:38 | b | +| HTMLTemplateEscapingPassthrough.go:57:11:57:39 | type conversion | HTMLTemplateEscapingPassthrough.go:58:38:58:38 | b | +| HTMLTemplateEscapingPassthrough.go:57:11:57:39 | type conversion | HTMLTemplateEscapingPassthrough.go:58:38:58:38 | b | +| HTMLTemplateEscapingPassthrough.go:57:11:57:39 | type conversion | HTMLTemplateEscapingPassthrough.go:58:38:58:38 | b | +| HTMLTemplateEscapingPassthrough.go:57:11:57:39 | type conversion | HTMLTemplateEscapingPassthrough.go:58:38:58:38 | b | +| HTMLTemplateEscapingPassthrough.go:57:11:57:39 | type conversion | HTMLTemplateEscapingPassthrough.go:58:38:58:38 | b | +| HTMLTemplateEscapingPassthrough.go:57:24:57:38 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:57:11:57:39 | type conversion | +| HTMLTemplateEscapingPassthrough.go:57:24:57:38 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:57:11:57:39 | type conversion | +| HTMLTemplateEscapingPassthrough.go:61:11:61:42 | type conversion | HTMLTemplateEscapingPassthrough.go:62:44:62:44 | f | +| HTMLTemplateEscapingPassthrough.go:61:11:61:42 | type conversion | HTMLTemplateEscapingPassthrough.go:62:44:62:44 | f | +| HTMLTemplateEscapingPassthrough.go:61:11:61:42 | type conversion | HTMLTemplateEscapingPassthrough.go:62:44:62:44 | f | +| HTMLTemplateEscapingPassthrough.go:61:11:61:42 | type conversion | HTMLTemplateEscapingPassthrough.go:62:44:62:44 | f | +| HTMLTemplateEscapingPassthrough.go:61:11:61:42 | type conversion | HTMLTemplateEscapingPassthrough.go:62:44:62:44 | f | +| HTMLTemplateEscapingPassthrough.go:61:11:61:42 | type conversion | HTMLTemplateEscapingPassthrough.go:62:44:62:44 | f | +| HTMLTemplateEscapingPassthrough.go:61:11:61:42 | type conversion | HTMLTemplateEscapingPassthrough.go:62:44:62:44 | f | +| HTMLTemplateEscapingPassthrough.go:61:11:61:42 | type conversion | HTMLTemplateEscapingPassthrough.go:62:44:62:44 | f | +| HTMLTemplateEscapingPassthrough.go:61:27:61:41 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:61:11:61:42 | type conversion | +| HTMLTemplateEscapingPassthrough.go:61:27:61:41 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:61:11:61:42 | type conversion | +| HTMLTemplateEscapingPassthrough.go:65:11:65:39 | type conversion | HTMLTemplateEscapingPassthrough.go:66:38:66:38 | g | +| HTMLTemplateEscapingPassthrough.go:65:11:65:39 | type conversion | HTMLTemplateEscapingPassthrough.go:66:38:66:38 | g | +| HTMLTemplateEscapingPassthrough.go:65:11:65:39 | type conversion | HTMLTemplateEscapingPassthrough.go:66:38:66:38 | g | +| HTMLTemplateEscapingPassthrough.go:65:11:65:39 | type conversion | HTMLTemplateEscapingPassthrough.go:66:38:66:38 | g | +| HTMLTemplateEscapingPassthrough.go:65:11:65:39 | type conversion | HTMLTemplateEscapingPassthrough.go:66:38:66:38 | g | +| HTMLTemplateEscapingPassthrough.go:65:11:65:39 | type conversion | HTMLTemplateEscapingPassthrough.go:66:38:66:38 | g | +| HTMLTemplateEscapingPassthrough.go:65:11:65:39 | type conversion | HTMLTemplateEscapingPassthrough.go:66:38:66:38 | g | +| HTMLTemplateEscapingPassthrough.go:65:11:65:39 | type conversion | HTMLTemplateEscapingPassthrough.go:66:38:66:38 | g | +| HTMLTemplateEscapingPassthrough.go:65:24:65:38 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:65:11:65:39 | type conversion | +| HTMLTemplateEscapingPassthrough.go:65:24:65:38 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:65:11:65:39 | type conversion | +| HTMLTemplateEscapingPassthrough.go:74:17:74:31 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:75:38:75:44 | escaped | +| HTMLTemplateEscapingPassthrough.go:80:10:80:24 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:81:16:81:33 | type conversion | +| HTMLTemplateEscapingPassthrough.go:80:10:80:24 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:83:38:83:40 | src | +| HTMLTemplateEscapingPassthrough.go:88:10:88:24 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:90:16:90:77 | type conversion | +| HTMLTemplateEscapingPassthrough.go:90:16:90:77 | type conversion | HTMLTemplateEscapingPassthrough.go:91:38:91:46 | converted | +| HTMLTemplateEscapingPassthrough.go:90:16:90:77 | type conversion | HTMLTemplateEscapingPassthrough.go:91:38:91:46 | converted | +| HTMLTemplateEscapingPassthrough.go:90:16:90:77 | type conversion | HTMLTemplateEscapingPassthrough.go:91:38:91:46 | converted | +| HTMLTemplateEscapingPassthrough.go:90:16:90:77 | type conversion | HTMLTemplateEscapingPassthrough.go:91:38:91:46 | converted | +| HTMLTemplateEscapingPassthrough.go:90:16:90:77 | type conversion | HTMLTemplateEscapingPassthrough.go:91:38:91:46 | converted | +| HTMLTemplateEscapingPassthrough.go:90:16:90:77 | type conversion | HTMLTemplateEscapingPassthrough.go:91:38:91:46 | converted | +| HTMLTemplateEscapingPassthrough.go:90:16:90:77 | type conversion | HTMLTemplateEscapingPassthrough.go:91:38:91:46 | converted | nodes | HTMLTemplateEscapingPassthrough.go:28:12:28:41 | type conversion | semmle.label | type conversion | -| HTMLTemplateEscapingPassthrough.go:28:12:28:41 | type conversion : HTML | semmle.label | type conversion : HTML | -| HTMLTemplateEscapingPassthrough.go:28:12:28:41 | type conversion : HTML | semmle.label | type conversion : HTML | -| HTMLTemplateEscapingPassthrough.go:28:12:28:41 | type conversion : HTML | semmle.label | type conversion : HTML | -| HTMLTemplateEscapingPassthrough.go:28:12:28:41 | type conversion : HTML | semmle.label | type conversion : HTML | -| HTMLTemplateEscapingPassthrough.go:28:12:28:41 | type conversion : HTML | semmle.label | type conversion : HTML | -| HTMLTemplateEscapingPassthrough.go:28:12:28:41 | type conversion : HTML | semmle.label | type conversion : HTML | -| HTMLTemplateEscapingPassthrough.go:28:12:28:41 | type conversion : HTML | semmle.label | type conversion : HTML | -| HTMLTemplateEscapingPassthrough.go:28:12:28:41 | type conversion : string | semmle.label | type conversion : string | -| HTMLTemplateEscapingPassthrough.go:28:26:28:40 | call to UserAgent : string | semmle.label | call to UserAgent : string | -| HTMLTemplateEscapingPassthrough.go:28:26:28:40 | call to UserAgent : string | semmle.label | call to UserAgent : string | +| HTMLTemplateEscapingPassthrough.go:28:12:28:41 | type conversion | semmle.label | type conversion | +| HTMLTemplateEscapingPassthrough.go:28:12:28:41 | type conversion | semmle.label | type conversion | +| HTMLTemplateEscapingPassthrough.go:28:12:28:41 | type conversion | semmle.label | type conversion | +| HTMLTemplateEscapingPassthrough.go:28:12:28:41 | type conversion | semmle.label | type conversion | +| HTMLTemplateEscapingPassthrough.go:28:12:28:41 | type conversion | semmle.label | type conversion | +| HTMLTemplateEscapingPassthrough.go:28:12:28:41 | type conversion | semmle.label | type conversion | +| HTMLTemplateEscapingPassthrough.go:28:12:28:41 | type conversion | semmle.label | type conversion | +| HTMLTemplateEscapingPassthrough.go:28:12:28:41 | type conversion | semmle.label | type conversion | +| HTMLTemplateEscapingPassthrough.go:28:26:28:40 | call to UserAgent | semmle.label | call to UserAgent | +| HTMLTemplateEscapingPassthrough.go:28:26:28:40 | call to UserAgent | semmle.label | call to UserAgent | | HTMLTemplateEscapingPassthrough.go:29:39:29:39 | a | semmle.label | a | | HTMLTemplateEscapingPassthrough.go:29:39:29:39 | a | semmle.label | a | | HTMLTemplateEscapingPassthrough.go:29:39:29:39 | a | semmle.label | a | @@ -121,16 +121,16 @@ nodes | HTMLTemplateEscapingPassthrough.go:29:39:29:39 | a | semmle.label | a | | HTMLTemplateEscapingPassthrough.go:29:39:29:39 | a | semmle.label | a | | HTMLTemplateEscapingPassthrough.go:34:9:34:38 | type conversion | semmle.label | type conversion | -| HTMLTemplateEscapingPassthrough.go:34:9:34:38 | type conversion : HTML | semmle.label | type conversion : HTML | -| HTMLTemplateEscapingPassthrough.go:34:9:34:38 | type conversion : HTML | semmle.label | type conversion : HTML | -| HTMLTemplateEscapingPassthrough.go:34:9:34:38 | type conversion : HTML | semmle.label | type conversion : HTML | -| HTMLTemplateEscapingPassthrough.go:34:9:34:38 | type conversion : HTML | semmle.label | type conversion : HTML | -| HTMLTemplateEscapingPassthrough.go:34:9:34:38 | type conversion : HTML | semmle.label | type conversion : HTML | -| HTMLTemplateEscapingPassthrough.go:34:9:34:38 | type conversion : HTML | semmle.label | type conversion : HTML | -| HTMLTemplateEscapingPassthrough.go:34:9:34:38 | type conversion : HTML | semmle.label | type conversion : HTML | -| HTMLTemplateEscapingPassthrough.go:34:9:34:38 | type conversion : string | semmle.label | type conversion : string | -| HTMLTemplateEscapingPassthrough.go:34:23:34:37 | call to UserAgent : string | semmle.label | call to UserAgent : string | -| HTMLTemplateEscapingPassthrough.go:34:23:34:37 | call to UserAgent : string | semmle.label | call to UserAgent : string | +| HTMLTemplateEscapingPassthrough.go:34:9:34:38 | type conversion | semmle.label | type conversion | +| HTMLTemplateEscapingPassthrough.go:34:9:34:38 | type conversion | semmle.label | type conversion | +| HTMLTemplateEscapingPassthrough.go:34:9:34:38 | type conversion | semmle.label | type conversion | +| HTMLTemplateEscapingPassthrough.go:34:9:34:38 | type conversion | semmle.label | type conversion | +| HTMLTemplateEscapingPassthrough.go:34:9:34:38 | type conversion | semmle.label | type conversion | +| HTMLTemplateEscapingPassthrough.go:34:9:34:38 | type conversion | semmle.label | type conversion | +| HTMLTemplateEscapingPassthrough.go:34:9:34:38 | type conversion | semmle.label | type conversion | +| HTMLTemplateEscapingPassthrough.go:34:9:34:38 | type conversion | semmle.label | type conversion | +| HTMLTemplateEscapingPassthrough.go:34:23:34:37 | call to UserAgent | semmle.label | call to UserAgent | +| HTMLTemplateEscapingPassthrough.go:34:23:34:37 | call to UserAgent | semmle.label | call to UserAgent | | HTMLTemplateEscapingPassthrough.go:35:40:35:40 | a | semmle.label | a | | HTMLTemplateEscapingPassthrough.go:35:40:35:40 | a | semmle.label | a | | HTMLTemplateEscapingPassthrough.go:35:40:35:40 | a | semmle.label | a | @@ -140,16 +140,16 @@ nodes | HTMLTemplateEscapingPassthrough.go:35:40:35:40 | a | semmle.label | a | | HTMLTemplateEscapingPassthrough.go:35:40:35:40 | a | semmle.label | a | | HTMLTemplateEscapingPassthrough.go:39:9:39:34 | type conversion | semmle.label | type conversion | -| HTMLTemplateEscapingPassthrough.go:39:9:39:34 | type conversion : HTML | semmle.label | type conversion : HTML | -| HTMLTemplateEscapingPassthrough.go:39:9:39:34 | type conversion : HTML | semmle.label | type conversion : HTML | -| HTMLTemplateEscapingPassthrough.go:39:9:39:34 | type conversion : HTML | semmle.label | type conversion : HTML | -| HTMLTemplateEscapingPassthrough.go:39:9:39:34 | type conversion : HTML | semmle.label | type conversion : HTML | -| HTMLTemplateEscapingPassthrough.go:39:9:39:34 | type conversion : HTML | semmle.label | type conversion : HTML | -| HTMLTemplateEscapingPassthrough.go:39:9:39:34 | type conversion : HTML | semmle.label | type conversion : HTML | -| HTMLTemplateEscapingPassthrough.go:39:9:39:34 | type conversion : HTML | semmle.label | type conversion : HTML | -| HTMLTemplateEscapingPassthrough.go:39:9:39:34 | type conversion : string | semmle.label | type conversion : string | -| HTMLTemplateEscapingPassthrough.go:39:19:39:33 | call to UserAgent : string | semmle.label | call to UserAgent : string | -| HTMLTemplateEscapingPassthrough.go:39:19:39:33 | call to UserAgent : string | semmle.label | call to UserAgent : string | +| HTMLTemplateEscapingPassthrough.go:39:9:39:34 | type conversion | semmle.label | type conversion | +| HTMLTemplateEscapingPassthrough.go:39:9:39:34 | type conversion | semmle.label | type conversion | +| HTMLTemplateEscapingPassthrough.go:39:9:39:34 | type conversion | semmle.label | type conversion | +| HTMLTemplateEscapingPassthrough.go:39:9:39:34 | type conversion | semmle.label | type conversion | +| HTMLTemplateEscapingPassthrough.go:39:9:39:34 | type conversion | semmle.label | type conversion | +| HTMLTemplateEscapingPassthrough.go:39:9:39:34 | type conversion | semmle.label | type conversion | +| HTMLTemplateEscapingPassthrough.go:39:9:39:34 | type conversion | semmle.label | type conversion | +| HTMLTemplateEscapingPassthrough.go:39:9:39:34 | type conversion | semmle.label | type conversion | +| HTMLTemplateEscapingPassthrough.go:39:19:39:33 | call to UserAgent | semmle.label | call to UserAgent | +| HTMLTemplateEscapingPassthrough.go:39:19:39:33 | call to UserAgent | semmle.label | call to UserAgent | | HTMLTemplateEscapingPassthrough.go:40:40:40:40 | a | semmle.label | a | | HTMLTemplateEscapingPassthrough.go:40:40:40:40 | a | semmle.label | a | | HTMLTemplateEscapingPassthrough.go:40:40:40:40 | a | semmle.label | a | @@ -159,16 +159,16 @@ nodes | HTMLTemplateEscapingPassthrough.go:40:40:40:40 | a | semmle.label | a | | HTMLTemplateEscapingPassthrough.go:40:40:40:40 | a | semmle.label | a | | HTMLTemplateEscapingPassthrough.go:45:11:45:44 | type conversion | semmle.label | type conversion | -| HTMLTemplateEscapingPassthrough.go:45:11:45:44 | type conversion : HTMLAttr | semmle.label | type conversion : HTMLAttr | -| HTMLTemplateEscapingPassthrough.go:45:11:45:44 | type conversion : HTMLAttr | semmle.label | type conversion : HTMLAttr | -| HTMLTemplateEscapingPassthrough.go:45:11:45:44 | type conversion : HTMLAttr | semmle.label | type conversion : HTMLAttr | -| HTMLTemplateEscapingPassthrough.go:45:11:45:44 | type conversion : HTMLAttr | semmle.label | type conversion : HTMLAttr | -| HTMLTemplateEscapingPassthrough.go:45:11:45:44 | type conversion : HTMLAttr | semmle.label | type conversion : HTMLAttr | -| HTMLTemplateEscapingPassthrough.go:45:11:45:44 | type conversion : HTMLAttr | semmle.label | type conversion : HTMLAttr | -| HTMLTemplateEscapingPassthrough.go:45:11:45:44 | type conversion : HTMLAttr | semmle.label | type conversion : HTMLAttr | -| HTMLTemplateEscapingPassthrough.go:45:11:45:44 | type conversion : string | semmle.label | type conversion : string | -| HTMLTemplateEscapingPassthrough.go:45:29:45:43 | call to UserAgent : string | semmle.label | call to UserAgent : string | -| HTMLTemplateEscapingPassthrough.go:45:29:45:43 | call to UserAgent : string | semmle.label | call to UserAgent : string | +| HTMLTemplateEscapingPassthrough.go:45:11:45:44 | type conversion | semmle.label | type conversion | +| HTMLTemplateEscapingPassthrough.go:45:11:45:44 | type conversion | semmle.label | type conversion | +| HTMLTemplateEscapingPassthrough.go:45:11:45:44 | type conversion | semmle.label | type conversion | +| HTMLTemplateEscapingPassthrough.go:45:11:45:44 | type conversion | semmle.label | type conversion | +| HTMLTemplateEscapingPassthrough.go:45:11:45:44 | type conversion | semmle.label | type conversion | +| HTMLTemplateEscapingPassthrough.go:45:11:45:44 | type conversion | semmle.label | type conversion | +| HTMLTemplateEscapingPassthrough.go:45:11:45:44 | type conversion | semmle.label | type conversion | +| HTMLTemplateEscapingPassthrough.go:45:11:45:44 | type conversion | semmle.label | type conversion | +| HTMLTemplateEscapingPassthrough.go:45:29:45:43 | call to UserAgent | semmle.label | call to UserAgent | +| HTMLTemplateEscapingPassthrough.go:45:29:45:43 | call to UserAgent | semmle.label | call to UserAgent | | HTMLTemplateEscapingPassthrough.go:46:41:46:41 | c | semmle.label | c | | HTMLTemplateEscapingPassthrough.go:46:41:46:41 | c | semmle.label | c | | HTMLTemplateEscapingPassthrough.go:46:41:46:41 | c | semmle.label | c | @@ -178,16 +178,16 @@ nodes | HTMLTemplateEscapingPassthrough.go:46:41:46:41 | c | semmle.label | c | | HTMLTemplateEscapingPassthrough.go:46:41:46:41 | c | semmle.label | c | | HTMLTemplateEscapingPassthrough.go:49:11:49:38 | type conversion | semmle.label | type conversion | -| HTMLTemplateEscapingPassthrough.go:49:11:49:38 | type conversion : JS | semmle.label | type conversion : JS | -| HTMLTemplateEscapingPassthrough.go:49:11:49:38 | type conversion : JS | semmle.label | type conversion : JS | -| HTMLTemplateEscapingPassthrough.go:49:11:49:38 | type conversion : JS | semmle.label | type conversion : JS | -| HTMLTemplateEscapingPassthrough.go:49:11:49:38 | type conversion : JS | semmle.label | type conversion : JS | -| HTMLTemplateEscapingPassthrough.go:49:11:49:38 | type conversion : JS | semmle.label | type conversion : JS | -| HTMLTemplateEscapingPassthrough.go:49:11:49:38 | type conversion : JS | semmle.label | type conversion : JS | -| HTMLTemplateEscapingPassthrough.go:49:11:49:38 | type conversion : JS | semmle.label | type conversion : JS | -| HTMLTemplateEscapingPassthrough.go:49:11:49:38 | type conversion : string | semmle.label | type conversion : string | -| HTMLTemplateEscapingPassthrough.go:49:23:49:37 | call to UserAgent : string | semmle.label | call to UserAgent : string | -| HTMLTemplateEscapingPassthrough.go:49:23:49:37 | call to UserAgent : string | semmle.label | call to UserAgent : string | +| HTMLTemplateEscapingPassthrough.go:49:11:49:38 | type conversion | semmle.label | type conversion | +| HTMLTemplateEscapingPassthrough.go:49:11:49:38 | type conversion | semmle.label | type conversion | +| HTMLTemplateEscapingPassthrough.go:49:11:49:38 | type conversion | semmle.label | type conversion | +| HTMLTemplateEscapingPassthrough.go:49:11:49:38 | type conversion | semmle.label | type conversion | +| HTMLTemplateEscapingPassthrough.go:49:11:49:38 | type conversion | semmle.label | type conversion | +| HTMLTemplateEscapingPassthrough.go:49:11:49:38 | type conversion | semmle.label | type conversion | +| HTMLTemplateEscapingPassthrough.go:49:11:49:38 | type conversion | semmle.label | type conversion | +| HTMLTemplateEscapingPassthrough.go:49:11:49:38 | type conversion | semmle.label | type conversion | +| HTMLTemplateEscapingPassthrough.go:49:23:49:37 | call to UserAgent | semmle.label | call to UserAgent | +| HTMLTemplateEscapingPassthrough.go:49:23:49:37 | call to UserAgent | semmle.label | call to UserAgent | | HTMLTemplateEscapingPassthrough.go:50:44:50:44 | d | semmle.label | d | | HTMLTemplateEscapingPassthrough.go:50:44:50:44 | d | semmle.label | d | | HTMLTemplateEscapingPassthrough.go:50:44:50:44 | d | semmle.label | d | @@ -197,16 +197,16 @@ nodes | HTMLTemplateEscapingPassthrough.go:50:44:50:44 | d | semmle.label | d | | HTMLTemplateEscapingPassthrough.go:50:44:50:44 | d | semmle.label | d | | HTMLTemplateEscapingPassthrough.go:53:11:53:41 | type conversion | semmle.label | type conversion | -| HTMLTemplateEscapingPassthrough.go:53:11:53:41 | type conversion : JSStr | semmle.label | type conversion : JSStr | -| HTMLTemplateEscapingPassthrough.go:53:11:53:41 | type conversion : JSStr | semmle.label | type conversion : JSStr | -| HTMLTemplateEscapingPassthrough.go:53:11:53:41 | type conversion : JSStr | semmle.label | type conversion : JSStr | -| HTMLTemplateEscapingPassthrough.go:53:11:53:41 | type conversion : JSStr | semmle.label | type conversion : JSStr | -| HTMLTemplateEscapingPassthrough.go:53:11:53:41 | type conversion : JSStr | semmle.label | type conversion : JSStr | -| HTMLTemplateEscapingPassthrough.go:53:11:53:41 | type conversion : JSStr | semmle.label | type conversion : JSStr | -| HTMLTemplateEscapingPassthrough.go:53:11:53:41 | type conversion : JSStr | semmle.label | type conversion : JSStr | -| HTMLTemplateEscapingPassthrough.go:53:11:53:41 | type conversion : string | semmle.label | type conversion : string | -| HTMLTemplateEscapingPassthrough.go:53:26:53:40 | call to UserAgent : string | semmle.label | call to UserAgent : string | -| HTMLTemplateEscapingPassthrough.go:53:26:53:40 | call to UserAgent : string | semmle.label | call to UserAgent : string | +| HTMLTemplateEscapingPassthrough.go:53:11:53:41 | type conversion | semmle.label | type conversion | +| HTMLTemplateEscapingPassthrough.go:53:11:53:41 | type conversion | semmle.label | type conversion | +| HTMLTemplateEscapingPassthrough.go:53:11:53:41 | type conversion | semmle.label | type conversion | +| HTMLTemplateEscapingPassthrough.go:53:11:53:41 | type conversion | semmle.label | type conversion | +| HTMLTemplateEscapingPassthrough.go:53:11:53:41 | type conversion | semmle.label | type conversion | +| HTMLTemplateEscapingPassthrough.go:53:11:53:41 | type conversion | semmle.label | type conversion | +| HTMLTemplateEscapingPassthrough.go:53:11:53:41 | type conversion | semmle.label | type conversion | +| HTMLTemplateEscapingPassthrough.go:53:11:53:41 | type conversion | semmle.label | type conversion | +| HTMLTemplateEscapingPassthrough.go:53:26:53:40 | call to UserAgent | semmle.label | call to UserAgent | +| HTMLTemplateEscapingPassthrough.go:53:26:53:40 | call to UserAgent | semmle.label | call to UserAgent | | HTMLTemplateEscapingPassthrough.go:54:44:54:44 | e | semmle.label | e | | HTMLTemplateEscapingPassthrough.go:54:44:54:44 | e | semmle.label | e | | HTMLTemplateEscapingPassthrough.go:54:44:54:44 | e | semmle.label | e | @@ -216,16 +216,16 @@ nodes | HTMLTemplateEscapingPassthrough.go:54:44:54:44 | e | semmle.label | e | | HTMLTemplateEscapingPassthrough.go:54:44:54:44 | e | semmle.label | e | | HTMLTemplateEscapingPassthrough.go:57:11:57:39 | type conversion | semmle.label | type conversion | -| HTMLTemplateEscapingPassthrough.go:57:11:57:39 | type conversion : CSS | semmle.label | type conversion : CSS | -| HTMLTemplateEscapingPassthrough.go:57:11:57:39 | type conversion : CSS | semmle.label | type conversion : CSS | -| HTMLTemplateEscapingPassthrough.go:57:11:57:39 | type conversion : CSS | semmle.label | type conversion : CSS | -| HTMLTemplateEscapingPassthrough.go:57:11:57:39 | type conversion : CSS | semmle.label | type conversion : CSS | -| HTMLTemplateEscapingPassthrough.go:57:11:57:39 | type conversion : CSS | semmle.label | type conversion : CSS | -| HTMLTemplateEscapingPassthrough.go:57:11:57:39 | type conversion : CSS | semmle.label | type conversion : CSS | -| HTMLTemplateEscapingPassthrough.go:57:11:57:39 | type conversion : CSS | semmle.label | type conversion : CSS | -| HTMLTemplateEscapingPassthrough.go:57:11:57:39 | type conversion : string | semmle.label | type conversion : string | -| HTMLTemplateEscapingPassthrough.go:57:24:57:38 | call to UserAgent : string | semmle.label | call to UserAgent : string | -| HTMLTemplateEscapingPassthrough.go:57:24:57:38 | call to UserAgent : string | semmle.label | call to UserAgent : string | +| HTMLTemplateEscapingPassthrough.go:57:11:57:39 | type conversion | semmle.label | type conversion | +| HTMLTemplateEscapingPassthrough.go:57:11:57:39 | type conversion | semmle.label | type conversion | +| HTMLTemplateEscapingPassthrough.go:57:11:57:39 | type conversion | semmle.label | type conversion | +| HTMLTemplateEscapingPassthrough.go:57:11:57:39 | type conversion | semmle.label | type conversion | +| HTMLTemplateEscapingPassthrough.go:57:11:57:39 | type conversion | semmle.label | type conversion | +| HTMLTemplateEscapingPassthrough.go:57:11:57:39 | type conversion | semmle.label | type conversion | +| HTMLTemplateEscapingPassthrough.go:57:11:57:39 | type conversion | semmle.label | type conversion | +| HTMLTemplateEscapingPassthrough.go:57:11:57:39 | type conversion | semmle.label | type conversion | +| HTMLTemplateEscapingPassthrough.go:57:24:57:38 | call to UserAgent | semmle.label | call to UserAgent | +| HTMLTemplateEscapingPassthrough.go:57:24:57:38 | call to UserAgent | semmle.label | call to UserAgent | | HTMLTemplateEscapingPassthrough.go:58:38:58:38 | b | semmle.label | b | | HTMLTemplateEscapingPassthrough.go:58:38:58:38 | b | semmle.label | b | | HTMLTemplateEscapingPassthrough.go:58:38:58:38 | b | semmle.label | b | @@ -235,16 +235,16 @@ nodes | HTMLTemplateEscapingPassthrough.go:58:38:58:38 | b | semmle.label | b | | HTMLTemplateEscapingPassthrough.go:58:38:58:38 | b | semmle.label | b | | HTMLTemplateEscapingPassthrough.go:61:11:61:42 | type conversion | semmle.label | type conversion | -| HTMLTemplateEscapingPassthrough.go:61:11:61:42 | type conversion : Srcset | semmle.label | type conversion : Srcset | -| HTMLTemplateEscapingPassthrough.go:61:11:61:42 | type conversion : Srcset | semmle.label | type conversion : Srcset | -| HTMLTemplateEscapingPassthrough.go:61:11:61:42 | type conversion : Srcset | semmle.label | type conversion : Srcset | -| HTMLTemplateEscapingPassthrough.go:61:11:61:42 | type conversion : Srcset | semmle.label | type conversion : Srcset | -| HTMLTemplateEscapingPassthrough.go:61:11:61:42 | type conversion : Srcset | semmle.label | type conversion : Srcset | -| HTMLTemplateEscapingPassthrough.go:61:11:61:42 | type conversion : Srcset | semmle.label | type conversion : Srcset | -| HTMLTemplateEscapingPassthrough.go:61:11:61:42 | type conversion : Srcset | semmle.label | type conversion : Srcset | -| HTMLTemplateEscapingPassthrough.go:61:11:61:42 | type conversion : string | semmle.label | type conversion : string | -| HTMLTemplateEscapingPassthrough.go:61:27:61:41 | call to UserAgent : string | semmle.label | call to UserAgent : string | -| HTMLTemplateEscapingPassthrough.go:61:27:61:41 | call to UserAgent : string | semmle.label | call to UserAgent : string | +| HTMLTemplateEscapingPassthrough.go:61:11:61:42 | type conversion | semmle.label | type conversion | +| HTMLTemplateEscapingPassthrough.go:61:11:61:42 | type conversion | semmle.label | type conversion | +| HTMLTemplateEscapingPassthrough.go:61:11:61:42 | type conversion | semmle.label | type conversion | +| HTMLTemplateEscapingPassthrough.go:61:11:61:42 | type conversion | semmle.label | type conversion | +| HTMLTemplateEscapingPassthrough.go:61:11:61:42 | type conversion | semmle.label | type conversion | +| HTMLTemplateEscapingPassthrough.go:61:11:61:42 | type conversion | semmle.label | type conversion | +| HTMLTemplateEscapingPassthrough.go:61:11:61:42 | type conversion | semmle.label | type conversion | +| HTMLTemplateEscapingPassthrough.go:61:11:61:42 | type conversion | semmle.label | type conversion | +| HTMLTemplateEscapingPassthrough.go:61:27:61:41 | call to UserAgent | semmle.label | call to UserAgent | +| HTMLTemplateEscapingPassthrough.go:61:27:61:41 | call to UserAgent | semmle.label | call to UserAgent | | HTMLTemplateEscapingPassthrough.go:62:44:62:44 | f | semmle.label | f | | HTMLTemplateEscapingPassthrough.go:62:44:62:44 | f | semmle.label | f | | HTMLTemplateEscapingPassthrough.go:62:44:62:44 | f | semmle.label | f | @@ -254,16 +254,16 @@ nodes | HTMLTemplateEscapingPassthrough.go:62:44:62:44 | f | semmle.label | f | | HTMLTemplateEscapingPassthrough.go:62:44:62:44 | f | semmle.label | f | | HTMLTemplateEscapingPassthrough.go:65:11:65:39 | type conversion | semmle.label | type conversion | -| HTMLTemplateEscapingPassthrough.go:65:11:65:39 | type conversion : URL | semmle.label | type conversion : URL | -| HTMLTemplateEscapingPassthrough.go:65:11:65:39 | type conversion : URL | semmle.label | type conversion : URL | -| HTMLTemplateEscapingPassthrough.go:65:11:65:39 | type conversion : URL | semmle.label | type conversion : URL | -| HTMLTemplateEscapingPassthrough.go:65:11:65:39 | type conversion : URL | semmle.label | type conversion : URL | -| HTMLTemplateEscapingPassthrough.go:65:11:65:39 | type conversion : URL | semmle.label | type conversion : URL | -| HTMLTemplateEscapingPassthrough.go:65:11:65:39 | type conversion : URL | semmle.label | type conversion : URL | -| HTMLTemplateEscapingPassthrough.go:65:11:65:39 | type conversion : URL | semmle.label | type conversion : URL | -| HTMLTemplateEscapingPassthrough.go:65:11:65:39 | type conversion : string | semmle.label | type conversion : string | -| HTMLTemplateEscapingPassthrough.go:65:24:65:38 | call to UserAgent : string | semmle.label | call to UserAgent : string | -| HTMLTemplateEscapingPassthrough.go:65:24:65:38 | call to UserAgent : string | semmle.label | call to UserAgent : string | +| HTMLTemplateEscapingPassthrough.go:65:11:65:39 | type conversion | semmle.label | type conversion | +| HTMLTemplateEscapingPassthrough.go:65:11:65:39 | type conversion | semmle.label | type conversion | +| HTMLTemplateEscapingPassthrough.go:65:11:65:39 | type conversion | semmle.label | type conversion | +| HTMLTemplateEscapingPassthrough.go:65:11:65:39 | type conversion | semmle.label | type conversion | +| HTMLTemplateEscapingPassthrough.go:65:11:65:39 | type conversion | semmle.label | type conversion | +| HTMLTemplateEscapingPassthrough.go:65:11:65:39 | type conversion | semmle.label | type conversion | +| HTMLTemplateEscapingPassthrough.go:65:11:65:39 | type conversion | semmle.label | type conversion | +| HTMLTemplateEscapingPassthrough.go:65:11:65:39 | type conversion | semmle.label | type conversion | +| HTMLTemplateEscapingPassthrough.go:65:24:65:38 | call to UserAgent | semmle.label | call to UserAgent | +| HTMLTemplateEscapingPassthrough.go:65:24:65:38 | call to UserAgent | semmle.label | call to UserAgent | | HTMLTemplateEscapingPassthrough.go:66:38:66:38 | g | semmle.label | g | | HTMLTemplateEscapingPassthrough.go:66:38:66:38 | g | semmle.label | g | | HTMLTemplateEscapingPassthrough.go:66:38:66:38 | g | semmle.label | g | @@ -272,21 +272,21 @@ nodes | HTMLTemplateEscapingPassthrough.go:66:38:66:38 | g | semmle.label | g | | HTMLTemplateEscapingPassthrough.go:66:38:66:38 | g | semmle.label | g | | HTMLTemplateEscapingPassthrough.go:66:38:66:38 | g | semmle.label | g | -| HTMLTemplateEscapingPassthrough.go:74:17:74:31 | call to UserAgent : string | semmle.label | call to UserAgent : string | +| HTMLTemplateEscapingPassthrough.go:74:17:74:31 | call to UserAgent | semmle.label | call to UserAgent | | HTMLTemplateEscapingPassthrough.go:75:38:75:44 | escaped | semmle.label | escaped | -| HTMLTemplateEscapingPassthrough.go:80:10:80:24 | call to UserAgent : string | semmle.label | call to UserAgent : string | -| HTMLTemplateEscapingPassthrough.go:80:10:80:24 | call to UserAgent : string | semmle.label | call to UserAgent : string | +| HTMLTemplateEscapingPassthrough.go:80:10:80:24 | call to UserAgent | semmle.label | call to UserAgent | +| HTMLTemplateEscapingPassthrough.go:80:10:80:24 | call to UserAgent | semmle.label | call to UserAgent | | HTMLTemplateEscapingPassthrough.go:81:16:81:33 | type conversion | semmle.label | type conversion | | HTMLTemplateEscapingPassthrough.go:83:38:83:40 | src | semmle.label | src | -| HTMLTemplateEscapingPassthrough.go:88:10:88:24 | call to UserAgent : string | semmle.label | call to UserAgent : string | +| HTMLTemplateEscapingPassthrough.go:88:10:88:24 | call to UserAgent | semmle.label | call to UserAgent | +| HTMLTemplateEscapingPassthrough.go:90:16:90:77 | type conversion | semmle.label | type conversion | +| HTMLTemplateEscapingPassthrough.go:90:16:90:77 | type conversion | semmle.label | type conversion | +| HTMLTemplateEscapingPassthrough.go:90:16:90:77 | type conversion | semmle.label | type conversion | +| HTMLTemplateEscapingPassthrough.go:90:16:90:77 | type conversion | semmle.label | type conversion | +| HTMLTemplateEscapingPassthrough.go:90:16:90:77 | type conversion | semmle.label | type conversion | +| HTMLTemplateEscapingPassthrough.go:90:16:90:77 | type conversion | semmle.label | type conversion | +| HTMLTemplateEscapingPassthrough.go:90:16:90:77 | type conversion | semmle.label | type conversion | | HTMLTemplateEscapingPassthrough.go:90:16:90:77 | type conversion | semmle.label | type conversion | -| HTMLTemplateEscapingPassthrough.go:90:16:90:77 | type conversion : HTML | semmle.label | type conversion : HTML | -| HTMLTemplateEscapingPassthrough.go:90:16:90:77 | type conversion : HTML | semmle.label | type conversion : HTML | -| HTMLTemplateEscapingPassthrough.go:90:16:90:77 | type conversion : HTML | semmle.label | type conversion : HTML | -| HTMLTemplateEscapingPassthrough.go:90:16:90:77 | type conversion : HTML | semmle.label | type conversion : HTML | -| HTMLTemplateEscapingPassthrough.go:90:16:90:77 | type conversion : HTML | semmle.label | type conversion : HTML | -| HTMLTemplateEscapingPassthrough.go:90:16:90:77 | type conversion : HTML | semmle.label | type conversion : HTML | -| HTMLTemplateEscapingPassthrough.go:90:16:90:77 | type conversion : HTML | semmle.label | type conversion : HTML | | HTMLTemplateEscapingPassthrough.go:91:38:91:46 | converted | semmle.label | converted | | HTMLTemplateEscapingPassthrough.go:91:38:91:46 | converted | semmle.label | converted | | HTMLTemplateEscapingPassthrough.go:91:38:91:46 | converted | semmle.label | converted | @@ -296,12 +296,12 @@ nodes | HTMLTemplateEscapingPassthrough.go:91:38:91:46 | converted | semmle.label | converted | subpaths #select -| HTMLTemplateEscapingPassthrough.go:29:39:29:39 | a | HTMLTemplateEscapingPassthrough.go:28:26:28:40 | call to UserAgent : string | HTMLTemplateEscapingPassthrough.go:29:39:29:39 | a | Data from an $@ will not be auto-escaped because it was $@ to template.HTML | HTMLTemplateEscapingPassthrough.go:28:26:28:40 | call to UserAgent | untrusted source | HTMLTemplateEscapingPassthrough.go:28:12:28:41 | type conversion | converted | -| HTMLTemplateEscapingPassthrough.go:35:40:35:40 | a | HTMLTemplateEscapingPassthrough.go:34:23:34:37 | call to UserAgent : string | HTMLTemplateEscapingPassthrough.go:35:40:35:40 | a | Data from an $@ will not be auto-escaped because it was $@ to template.HTML | HTMLTemplateEscapingPassthrough.go:34:23:34:37 | call to UserAgent | untrusted source | HTMLTemplateEscapingPassthrough.go:34:9:34:38 | type conversion | converted | -| HTMLTemplateEscapingPassthrough.go:40:40:40:40 | a | HTMLTemplateEscapingPassthrough.go:39:19:39:33 | call to UserAgent : string | HTMLTemplateEscapingPassthrough.go:40:40:40:40 | a | Data from an $@ will not be auto-escaped because it was $@ to template.HTML | HTMLTemplateEscapingPassthrough.go:39:19:39:33 | call to UserAgent | untrusted source | HTMLTemplateEscapingPassthrough.go:39:9:39:34 | type conversion | converted | -| HTMLTemplateEscapingPassthrough.go:46:41:46:41 | c | HTMLTemplateEscapingPassthrough.go:45:29:45:43 | call to UserAgent : string | HTMLTemplateEscapingPassthrough.go:46:41:46:41 | c | Data from an $@ will not be auto-escaped because it was $@ to template.HTMLAttr | HTMLTemplateEscapingPassthrough.go:45:29:45:43 | call to UserAgent | untrusted source | HTMLTemplateEscapingPassthrough.go:45:11:45:44 | type conversion | converted | -| HTMLTemplateEscapingPassthrough.go:50:44:50:44 | d | HTMLTemplateEscapingPassthrough.go:49:23:49:37 | call to UserAgent : string | HTMLTemplateEscapingPassthrough.go:50:44:50:44 | d | Data from an $@ will not be auto-escaped because it was $@ to template.JS | HTMLTemplateEscapingPassthrough.go:49:23:49:37 | call to UserAgent | untrusted source | HTMLTemplateEscapingPassthrough.go:49:11:49:38 | type conversion | converted | -| HTMLTemplateEscapingPassthrough.go:54:44:54:44 | e | HTMLTemplateEscapingPassthrough.go:53:26:53:40 | call to UserAgent : string | HTMLTemplateEscapingPassthrough.go:54:44:54:44 | e | Data from an $@ will not be auto-escaped because it was $@ to template.JSStr | HTMLTemplateEscapingPassthrough.go:53:26:53:40 | call to UserAgent | untrusted source | HTMLTemplateEscapingPassthrough.go:53:11:53:41 | type conversion | converted | -| HTMLTemplateEscapingPassthrough.go:58:38:58:38 | b | HTMLTemplateEscapingPassthrough.go:57:24:57:38 | call to UserAgent : string | HTMLTemplateEscapingPassthrough.go:58:38:58:38 | b | Data from an $@ will not be auto-escaped because it was $@ to template.CSS | HTMLTemplateEscapingPassthrough.go:57:24:57:38 | call to UserAgent | untrusted source | HTMLTemplateEscapingPassthrough.go:57:11:57:39 | type conversion | converted | -| HTMLTemplateEscapingPassthrough.go:62:44:62:44 | f | HTMLTemplateEscapingPassthrough.go:61:27:61:41 | call to UserAgent : string | HTMLTemplateEscapingPassthrough.go:62:44:62:44 | f | Data from an $@ will not be auto-escaped because it was $@ to template.Srcset | HTMLTemplateEscapingPassthrough.go:61:27:61:41 | call to UserAgent | untrusted source | HTMLTemplateEscapingPassthrough.go:61:11:61:42 | type conversion | converted | -| HTMLTemplateEscapingPassthrough.go:66:38:66:38 | g | HTMLTemplateEscapingPassthrough.go:65:24:65:38 | call to UserAgent : string | HTMLTemplateEscapingPassthrough.go:66:38:66:38 | g | Data from an $@ will not be auto-escaped because it was $@ to template.URL | HTMLTemplateEscapingPassthrough.go:65:24:65:38 | call to UserAgent | untrusted source | HTMLTemplateEscapingPassthrough.go:65:11:65:39 | type conversion | converted | +| HTMLTemplateEscapingPassthrough.go:29:39:29:39 | a | HTMLTemplateEscapingPassthrough.go:28:26:28:40 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:29:39:29:39 | a | Data from an $@ will not be auto-escaped because it was $@ to template.HTML | HTMLTemplateEscapingPassthrough.go:28:26:28:40 | call to UserAgent | untrusted source | HTMLTemplateEscapingPassthrough.go:28:12:28:41 | type conversion | converted | +| HTMLTemplateEscapingPassthrough.go:35:40:35:40 | a | HTMLTemplateEscapingPassthrough.go:34:23:34:37 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:35:40:35:40 | a | Data from an $@ will not be auto-escaped because it was $@ to template.HTML | HTMLTemplateEscapingPassthrough.go:34:23:34:37 | call to UserAgent | untrusted source | HTMLTemplateEscapingPassthrough.go:34:9:34:38 | type conversion | converted | +| HTMLTemplateEscapingPassthrough.go:40:40:40:40 | a | HTMLTemplateEscapingPassthrough.go:39:19:39:33 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:40:40:40:40 | a | Data from an $@ will not be auto-escaped because it was $@ to template.HTML | HTMLTemplateEscapingPassthrough.go:39:19:39:33 | call to UserAgent | untrusted source | HTMLTemplateEscapingPassthrough.go:39:9:39:34 | type conversion | converted | +| HTMLTemplateEscapingPassthrough.go:46:41:46:41 | c | HTMLTemplateEscapingPassthrough.go:45:29:45:43 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:46:41:46:41 | c | Data from an $@ will not be auto-escaped because it was $@ to template.HTMLAttr | HTMLTemplateEscapingPassthrough.go:45:29:45:43 | call to UserAgent | untrusted source | HTMLTemplateEscapingPassthrough.go:45:11:45:44 | type conversion | converted | +| HTMLTemplateEscapingPassthrough.go:50:44:50:44 | d | HTMLTemplateEscapingPassthrough.go:49:23:49:37 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:50:44:50:44 | d | Data from an $@ will not be auto-escaped because it was $@ to template.JS | HTMLTemplateEscapingPassthrough.go:49:23:49:37 | call to UserAgent | untrusted source | HTMLTemplateEscapingPassthrough.go:49:11:49:38 | type conversion | converted | +| HTMLTemplateEscapingPassthrough.go:54:44:54:44 | e | HTMLTemplateEscapingPassthrough.go:53:26:53:40 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:54:44:54:44 | e | Data from an $@ will not be auto-escaped because it was $@ to template.JSStr | HTMLTemplateEscapingPassthrough.go:53:26:53:40 | call to UserAgent | untrusted source | HTMLTemplateEscapingPassthrough.go:53:11:53:41 | type conversion | converted | +| HTMLTemplateEscapingPassthrough.go:58:38:58:38 | b | HTMLTemplateEscapingPassthrough.go:57:24:57:38 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:58:38:58:38 | b | Data from an $@ will not be auto-escaped because it was $@ to template.CSS | HTMLTemplateEscapingPassthrough.go:57:24:57:38 | call to UserAgent | untrusted source | HTMLTemplateEscapingPassthrough.go:57:11:57:39 | type conversion | converted | +| HTMLTemplateEscapingPassthrough.go:62:44:62:44 | f | HTMLTemplateEscapingPassthrough.go:61:27:61:41 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:62:44:62:44 | f | Data from an $@ will not be auto-escaped because it was $@ to template.Srcset | HTMLTemplateEscapingPassthrough.go:61:27:61:41 | call to UserAgent | untrusted source | HTMLTemplateEscapingPassthrough.go:61:11:61:42 | type conversion | converted | +| HTMLTemplateEscapingPassthrough.go:66:38:66:38 | g | HTMLTemplateEscapingPassthrough.go:65:24:65:38 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:66:38:66:38 | g | Data from an $@ will not be auto-escaped because it was $@ to template.URL | HTMLTemplateEscapingPassthrough.go:65:24:65:38 | call to UserAgent | untrusted source | HTMLTemplateEscapingPassthrough.go:65:11:65:39 | type conversion | converted | diff --git a/go/ql/test/experimental/CWE-918/SSRF.expected b/go/ql/test/experimental/CWE-918/SSRF.expected index 31b9e81ff89..6617c2ee474 100644 --- a/go/ql/test/experimental/CWE-918/SSRF.expected +++ b/go/ql/test/experimental/CWE-918/SSRF.expected @@ -1,68 +1,68 @@ edges -| builtin.go:19:12:19:34 | call to FormValue : string | builtin.go:22:21:22:62 | ...+... | -| builtin.go:83:21:83:31 | call to Referer : string | builtin.go:88:27:88:40 | untrustedInput | -| builtin.go:97:21:97:31 | call to Referer : string | builtin.go:101:36:101:49 | untrustedInput | -| builtin.go:111:21:111:31 | call to Referer : string | builtin.go:114:15:114:28 | untrustedInput | -| builtin.go:129:21:129:31 | call to Referer : string | builtin.go:132:38:132:51 | untrustedInput | -| new-tests.go:26:26:26:30 | &... : pointer type | new-tests.go:31:11:31:57 | call to Sprintf | -| new-tests.go:26:26:26:30 | &... : pointer type | new-tests.go:32:11:32:57 | call to Sprintf | -| new-tests.go:26:26:26:30 | &... : pointer type | new-tests.go:35:12:35:58 | call to Sprintf | -| new-tests.go:39:18:39:30 | call to Param : string | new-tests.go:47:11:47:46 | ...+... | -| new-tests.go:49:18:49:30 | call to Query : string | new-tests.go:50:11:50:46 | ...+... | -| new-tests.go:62:31:62:38 | selection of Body : ReadCloser | new-tests.go:68:11:68:57 | call to Sprintf | -| new-tests.go:62:31:62:38 | selection of Body : ReadCloser | new-tests.go:69:11:69:57 | call to Sprintf | -| new-tests.go:62:31:62:38 | selection of Body : ReadCloser | new-tests.go:74:12:74:58 | call to Sprintf | -| new-tests.go:78:18:78:24 | selection of URL : pointer type | new-tests.go:79:11:79:46 | ...+... | -| new-tests.go:81:37:81:43 | selection of URL : pointer type | new-tests.go:82:11:82:46 | ...+... | -| new-tests.go:86:10:86:20 | call to Vars : map type | new-tests.go:88:11:88:46 | ...+... | -| new-tests.go:95:18:95:45 | call to URLParam : string | new-tests.go:96:11:96:46 | ...+... | +| builtin.go:19:12:19:34 | call to FormValue | builtin.go:22:21:22:62 | ...+... | +| builtin.go:83:21:83:31 | call to Referer | builtin.go:88:27:88:40 | untrustedInput | +| builtin.go:97:21:97:31 | call to Referer | builtin.go:101:36:101:49 | untrustedInput | +| builtin.go:111:21:111:31 | call to Referer | builtin.go:114:15:114:28 | untrustedInput | +| builtin.go:129:21:129:31 | call to Referer | builtin.go:132:38:132:51 | untrustedInput | +| new-tests.go:26:26:26:30 | &... | new-tests.go:31:11:31:57 | call to Sprintf | +| new-tests.go:26:26:26:30 | &... | new-tests.go:32:11:32:57 | call to Sprintf | +| new-tests.go:26:26:26:30 | &... | new-tests.go:35:12:35:58 | call to Sprintf | +| new-tests.go:39:18:39:30 | call to Param | new-tests.go:47:11:47:46 | ...+... | +| new-tests.go:49:18:49:30 | call to Query | new-tests.go:50:11:50:46 | ...+... | +| new-tests.go:62:31:62:38 | selection of Body | new-tests.go:68:11:68:57 | call to Sprintf | +| new-tests.go:62:31:62:38 | selection of Body | new-tests.go:69:11:69:57 | call to Sprintf | +| new-tests.go:62:31:62:38 | selection of Body | new-tests.go:74:12:74:58 | call to Sprintf | +| new-tests.go:78:18:78:24 | selection of URL | new-tests.go:79:11:79:46 | ...+... | +| new-tests.go:81:37:81:43 | selection of URL | new-tests.go:82:11:82:46 | ...+... | +| new-tests.go:86:10:86:20 | call to Vars | new-tests.go:88:11:88:46 | ...+... | +| new-tests.go:95:18:95:45 | call to URLParam | new-tests.go:96:11:96:46 | ...+... | nodes -| builtin.go:19:12:19:34 | call to FormValue : string | semmle.label | call to FormValue : string | +| builtin.go:19:12:19:34 | call to FormValue | semmle.label | call to FormValue | | builtin.go:22:21:22:62 | ...+... | semmle.label | ...+... | -| builtin.go:83:21:83:31 | call to Referer : string | semmle.label | call to Referer : string | +| builtin.go:83:21:83:31 | call to Referer | semmle.label | call to Referer | | builtin.go:88:27:88:40 | untrustedInput | semmle.label | untrustedInput | -| builtin.go:97:21:97:31 | call to Referer : string | semmle.label | call to Referer : string | +| builtin.go:97:21:97:31 | call to Referer | semmle.label | call to Referer | | builtin.go:101:36:101:49 | untrustedInput | semmle.label | untrustedInput | -| builtin.go:111:21:111:31 | call to Referer : string | semmle.label | call to Referer : string | +| builtin.go:111:21:111:31 | call to Referer | semmle.label | call to Referer | | builtin.go:114:15:114:28 | untrustedInput | semmle.label | untrustedInput | -| builtin.go:129:21:129:31 | call to Referer : string | semmle.label | call to Referer : string | +| builtin.go:129:21:129:31 | call to Referer | semmle.label | call to Referer | | builtin.go:132:38:132:51 | untrustedInput | semmle.label | untrustedInput | -| new-tests.go:26:26:26:30 | &... : pointer type | semmle.label | &... : pointer type | +| new-tests.go:26:26:26:30 | &... | semmle.label | &... | | new-tests.go:31:11:31:57 | call to Sprintf | semmle.label | call to Sprintf | | new-tests.go:32:11:32:57 | call to Sprintf | semmle.label | call to Sprintf | | new-tests.go:35:12:35:58 | call to Sprintf | semmle.label | call to Sprintf | -| new-tests.go:39:18:39:30 | call to Param : string | semmle.label | call to Param : string | +| new-tests.go:39:18:39:30 | call to Param | semmle.label | call to Param | | new-tests.go:47:11:47:46 | ...+... | semmle.label | ...+... | -| new-tests.go:49:18:49:30 | call to Query : string | semmle.label | call to Query : string | +| new-tests.go:49:18:49:30 | call to Query | semmle.label | call to Query | | new-tests.go:50:11:50:46 | ...+... | semmle.label | ...+... | -| new-tests.go:62:31:62:38 | selection of Body : ReadCloser | semmle.label | selection of Body : ReadCloser | +| new-tests.go:62:31:62:38 | selection of Body | semmle.label | selection of Body | | new-tests.go:68:11:68:57 | call to Sprintf | semmle.label | call to Sprintf | | new-tests.go:69:11:69:57 | call to Sprintf | semmle.label | call to Sprintf | | new-tests.go:74:12:74:58 | call to Sprintf | semmle.label | call to Sprintf | -| new-tests.go:78:18:78:24 | selection of URL : pointer type | semmle.label | selection of URL : pointer type | +| new-tests.go:78:18:78:24 | selection of URL | semmle.label | selection of URL | | new-tests.go:79:11:79:46 | ...+... | semmle.label | ...+... | -| new-tests.go:81:37:81:43 | selection of URL : pointer type | semmle.label | selection of URL : pointer type | +| new-tests.go:81:37:81:43 | selection of URL | semmle.label | selection of URL | | new-tests.go:82:11:82:46 | ...+... | semmle.label | ...+... | -| new-tests.go:86:10:86:20 | call to Vars : map type | semmle.label | call to Vars : map type | +| new-tests.go:86:10:86:20 | call to Vars | semmle.label | call to Vars | | new-tests.go:88:11:88:46 | ...+... | semmle.label | ...+... | -| new-tests.go:95:18:95:45 | call to URLParam : string | semmle.label | call to URLParam : string | +| new-tests.go:95:18:95:45 | call to URLParam | semmle.label | call to URLParam | | new-tests.go:96:11:96:46 | ...+... | semmle.label | ...+... | subpaths #select -| builtin.go:22:12:22:63 | call to Get | builtin.go:19:12:19:34 | call to FormValue : string | builtin.go:22:21:22:62 | ...+... | The URL of this request depends on a user-provided value. | -| builtin.go:88:12:88:53 | call to Dial | builtin.go:83:21:83:31 | call to Referer : string | builtin.go:88:27:88:40 | untrustedInput | The URL of this request depends on a user-provided value. | -| builtin.go:102:13:102:40 | call to DialConfig | builtin.go:97:21:97:31 | call to Referer : string | builtin.go:101:36:101:49 | untrustedInput | The URL of this request depends on a user-provided value. | -| builtin.go:114:3:114:39 | call to Dial | builtin.go:111:21:111:31 | call to Referer : string | builtin.go:114:15:114:28 | untrustedInput | The URL of this request depends on a user-provided value. | -| builtin.go:132:3:132:62 | call to DialContext | builtin.go:129:21:129:31 | call to Referer : string | builtin.go:132:38:132:51 | untrustedInput | The URL of this request depends on a user-provided value. | -| new-tests.go:31:2:31:58 | call to Get | new-tests.go:26:26:26:30 | &... : pointer type | new-tests.go:31:11:31:57 | call to Sprintf | The URL of this request depends on a user-provided value. | -| new-tests.go:32:2:32:58 | call to Get | new-tests.go:26:26:26:30 | &... : pointer type | new-tests.go:32:11:32:57 | call to Sprintf | The URL of this request depends on a user-provided value. | -| new-tests.go:35:3:35:59 | call to Get | new-tests.go:26:26:26:30 | &... : pointer type | new-tests.go:35:12:35:58 | call to Sprintf | The URL of this request depends on a user-provided value. | -| new-tests.go:47:2:47:47 | call to Get | new-tests.go:39:18:39:30 | call to Param : string | new-tests.go:47:11:47:46 | ...+... | The URL of this request depends on a user-provided value. | -| new-tests.go:50:2:50:47 | call to Get | new-tests.go:49:18:49:30 | call to Query : string | new-tests.go:50:11:50:46 | ...+... | The URL of this request depends on a user-provided value. | -| new-tests.go:68:2:68:58 | call to Get | new-tests.go:62:31:62:38 | selection of Body : ReadCloser | new-tests.go:68:11:68:57 | call to Sprintf | The URL of this request depends on a user-provided value. | -| new-tests.go:69:2:69:58 | call to Get | new-tests.go:62:31:62:38 | selection of Body : ReadCloser | new-tests.go:69:11:69:57 | call to Sprintf | The URL of this request depends on a user-provided value. | -| new-tests.go:74:3:74:59 | call to Get | new-tests.go:62:31:62:38 | selection of Body : ReadCloser | new-tests.go:74:12:74:58 | call to Sprintf | The URL of this request depends on a user-provided value. | -| new-tests.go:79:2:79:47 | call to Get | new-tests.go:78:18:78:24 | selection of URL : pointer type | new-tests.go:79:11:79:46 | ...+... | The URL of this request depends on a user-provided value. | -| new-tests.go:82:2:82:47 | call to Get | new-tests.go:81:37:81:43 | selection of URL : pointer type | new-tests.go:82:11:82:46 | ...+... | The URL of this request depends on a user-provided value. | -| new-tests.go:88:2:88:47 | call to Get | new-tests.go:86:10:86:20 | call to Vars : map type | new-tests.go:88:11:88:46 | ...+... | The URL of this request depends on a user-provided value. | -| new-tests.go:96:2:96:47 | call to Get | new-tests.go:95:18:95:45 | call to URLParam : string | new-tests.go:96:11:96:46 | ...+... | The URL of this request depends on a user-provided value. | +| builtin.go:22:12:22:63 | call to Get | builtin.go:19:12:19:34 | call to FormValue | builtin.go:22:21:22:62 | ...+... | The URL of this request depends on a user-provided value. | +| builtin.go:88:12:88:53 | call to Dial | builtin.go:83:21:83:31 | call to Referer | builtin.go:88:27:88:40 | untrustedInput | The URL of this request depends on a user-provided value. | +| builtin.go:102:13:102:40 | call to DialConfig | builtin.go:97:21:97:31 | call to Referer | builtin.go:101:36:101:49 | untrustedInput | The URL of this request depends on a user-provided value. | +| builtin.go:114:3:114:39 | call to Dial | builtin.go:111:21:111:31 | call to Referer | builtin.go:114:15:114:28 | untrustedInput | The URL of this request depends on a user-provided value. | +| builtin.go:132:3:132:62 | call to DialContext | builtin.go:129:21:129:31 | call to Referer | builtin.go:132:38:132:51 | untrustedInput | The URL of this request depends on a user-provided value. | +| new-tests.go:31:2:31:58 | call to Get | new-tests.go:26:26:26:30 | &... | new-tests.go:31:11:31:57 | call to Sprintf | The URL of this request depends on a user-provided value. | +| new-tests.go:32:2:32:58 | call to Get | new-tests.go:26:26:26:30 | &... | new-tests.go:32:11:32:57 | call to Sprintf | The URL of this request depends on a user-provided value. | +| new-tests.go:35:3:35:59 | call to Get | new-tests.go:26:26:26:30 | &... | new-tests.go:35:12:35:58 | call to Sprintf | The URL of this request depends on a user-provided value. | +| new-tests.go:47:2:47:47 | call to Get | new-tests.go:39:18:39:30 | call to Param | new-tests.go:47:11:47:46 | ...+... | The URL of this request depends on a user-provided value. | +| new-tests.go:50:2:50:47 | call to Get | new-tests.go:49:18:49:30 | call to Query | new-tests.go:50:11:50:46 | ...+... | The URL of this request depends on a user-provided value. | +| new-tests.go:68:2:68:58 | call to Get | new-tests.go:62:31:62:38 | selection of Body | new-tests.go:68:11:68:57 | call to Sprintf | The URL of this request depends on a user-provided value. | +| new-tests.go:69:2:69:58 | call to Get | new-tests.go:62:31:62:38 | selection of Body | new-tests.go:69:11:69:57 | call to Sprintf | The URL of this request depends on a user-provided value. | +| new-tests.go:74:3:74:59 | call to Get | new-tests.go:62:31:62:38 | selection of Body | new-tests.go:74:12:74:58 | call to Sprintf | The URL of this request depends on a user-provided value. | +| new-tests.go:79:2:79:47 | call to Get | new-tests.go:78:18:78:24 | selection of URL | new-tests.go:79:11:79:46 | ...+... | The URL of this request depends on a user-provided value. | +| new-tests.go:82:2:82:47 | call to Get | new-tests.go:81:37:81:43 | selection of URL | new-tests.go:82:11:82:46 | ...+... | The URL of this request depends on a user-provided value. | +| new-tests.go:88:2:88:47 | call to Get | new-tests.go:86:10:86:20 | call to Vars | new-tests.go:88:11:88:46 | ...+... | The URL of this request depends on a user-provided value. | +| new-tests.go:96:2:96:47 | call to Get | new-tests.go:95:18:95:45 | call to URLParam | new-tests.go:96:11:96:46 | ...+... | The URL of this request depends on a user-provided value. | diff --git a/go/ql/test/experimental/Unsafe/WrongUsageOfUnsafe.expected b/go/ql/test/experimental/Unsafe/WrongUsageOfUnsafe.expected index 277a4b6df90..612c6ef1e51 100644 --- a/go/ql/test/experimental/Unsafe/WrongUsageOfUnsafe.expected +++ b/go/ql/test/experimental/Unsafe/WrongUsageOfUnsafe.expected @@ -1,62 +1,62 @@ edges -| WrongUsageOfUnsafe.go:17:24:17:48 | type conversion : unsafe.Pointer | WrongUsageOfUnsafe.go:17:13:17:49 | type conversion | -| WrongUsageOfUnsafe.go:34:24:34:51 | type conversion : unsafe.Pointer | WrongUsageOfUnsafe.go:34:13:34:52 | type conversion | -| WrongUsageOfUnsafe.go:55:24:55:51 | type conversion : unsafe.Pointer | WrongUsageOfUnsafe.go:55:13:55:52 | type conversion | -| WrongUsageOfUnsafe.go:77:27:77:54 | type conversion : unsafe.Pointer | WrongUsageOfUnsafe.go:77:16:77:55 | type conversion | -| WrongUsageOfUnsafe.go:93:20:93:44 | type conversion : unsafe.Pointer | WrongUsageOfUnsafe.go:93:13:93:45 | type conversion | -| WrongUsageOfUnsafe.go:111:31:111:58 | type conversion : unsafe.Pointer | WrongUsageOfUnsafe.go:111:16:111:59 | type conversion | -| WrongUsageOfUnsafe.go:129:31:129:55 | type conversion : unsafe.Pointer | WrongUsageOfUnsafe.go:129:16:129:56 | type conversion | -| WrongUsageOfUnsafe.go:149:31:149:55 | type conversion : unsafe.Pointer | WrongUsageOfUnsafe.go:149:16:149:56 | type conversion | -| WrongUsageOfUnsafe.go:166:33:166:57 | type conversion : unsafe.Pointer | WrongUsageOfUnsafe.go:166:16:166:58 | type conversion | -| WrongUsageOfUnsafe.go:189:31:189:55 | type conversion : unsafe.Pointer | WrongUsageOfUnsafe.go:189:16:189:56 | type conversion | -| WrongUsageOfUnsafe.go:211:31:211:60 | type conversion : unsafe.Pointer | WrongUsageOfUnsafe.go:211:16:211:61 | type conversion | -| WrongUsageOfUnsafe.go:227:31:227:55 | type conversion : unsafe.Pointer | WrongUsageOfUnsafe.go:236:21:236:23 | definition of req : unsafe.Pointer | -| WrongUsageOfUnsafe.go:236:21:236:23 | definition of req : unsafe.Pointer | WrongUsageOfUnsafe.go:243:9:243:27 | type conversion | -| WrongUsageOfUnsafe.go:256:28:256:52 | type conversion : unsafe.Pointer | WrongUsageOfUnsafe.go:256:16:256:53 | type conversion | -| WrongUsageOfUnsafe.go:274:25:274:49 | type conversion : unsafe.Pointer | WrongUsageOfUnsafe.go:274:16:274:50 | type conversion | -| WrongUsageOfUnsafe.go:292:23:292:47 | type conversion : unsafe.Pointer | WrongUsageOfUnsafe.go:292:16:292:48 | type conversion | +| WrongUsageOfUnsafe.go:17:24:17:48 | type conversion | WrongUsageOfUnsafe.go:17:13:17:49 | type conversion | +| WrongUsageOfUnsafe.go:34:24:34:51 | type conversion | WrongUsageOfUnsafe.go:34:13:34:52 | type conversion | +| WrongUsageOfUnsafe.go:55:24:55:51 | type conversion | WrongUsageOfUnsafe.go:55:13:55:52 | type conversion | +| WrongUsageOfUnsafe.go:77:27:77:54 | type conversion | WrongUsageOfUnsafe.go:77:16:77:55 | type conversion | +| WrongUsageOfUnsafe.go:93:20:93:44 | type conversion | WrongUsageOfUnsafe.go:93:13:93:45 | type conversion | +| WrongUsageOfUnsafe.go:111:31:111:58 | type conversion | WrongUsageOfUnsafe.go:111:16:111:59 | type conversion | +| WrongUsageOfUnsafe.go:129:31:129:55 | type conversion | WrongUsageOfUnsafe.go:129:16:129:56 | type conversion | +| WrongUsageOfUnsafe.go:149:31:149:55 | type conversion | WrongUsageOfUnsafe.go:149:16:149:56 | type conversion | +| WrongUsageOfUnsafe.go:166:33:166:57 | type conversion | WrongUsageOfUnsafe.go:166:16:166:58 | type conversion | +| WrongUsageOfUnsafe.go:189:31:189:55 | type conversion | WrongUsageOfUnsafe.go:189:16:189:56 | type conversion | +| WrongUsageOfUnsafe.go:211:31:211:60 | type conversion | WrongUsageOfUnsafe.go:211:16:211:61 | type conversion | +| WrongUsageOfUnsafe.go:227:31:227:55 | type conversion | WrongUsageOfUnsafe.go:236:21:236:23 | definition of req | +| WrongUsageOfUnsafe.go:236:21:236:23 | definition of req | WrongUsageOfUnsafe.go:243:9:243:27 | type conversion | +| WrongUsageOfUnsafe.go:256:28:256:52 | type conversion | WrongUsageOfUnsafe.go:256:16:256:53 | type conversion | +| WrongUsageOfUnsafe.go:274:25:274:49 | type conversion | WrongUsageOfUnsafe.go:274:16:274:50 | type conversion | +| WrongUsageOfUnsafe.go:292:23:292:47 | type conversion | WrongUsageOfUnsafe.go:292:16:292:48 | type conversion | nodes | WrongUsageOfUnsafe.go:17:13:17:49 | type conversion | semmle.label | type conversion | -| WrongUsageOfUnsafe.go:17:24:17:48 | type conversion : unsafe.Pointer | semmle.label | type conversion : unsafe.Pointer | +| WrongUsageOfUnsafe.go:17:24:17:48 | type conversion | semmle.label | type conversion | | WrongUsageOfUnsafe.go:34:13:34:52 | type conversion | semmle.label | type conversion | -| WrongUsageOfUnsafe.go:34:24:34:51 | type conversion : unsafe.Pointer | semmle.label | type conversion : unsafe.Pointer | +| WrongUsageOfUnsafe.go:34:24:34:51 | type conversion | semmle.label | type conversion | | WrongUsageOfUnsafe.go:55:13:55:52 | type conversion | semmle.label | type conversion | -| WrongUsageOfUnsafe.go:55:24:55:51 | type conversion : unsafe.Pointer | semmle.label | type conversion : unsafe.Pointer | +| WrongUsageOfUnsafe.go:55:24:55:51 | type conversion | semmle.label | type conversion | | WrongUsageOfUnsafe.go:77:16:77:55 | type conversion | semmle.label | type conversion | -| WrongUsageOfUnsafe.go:77:27:77:54 | type conversion : unsafe.Pointer | semmle.label | type conversion : unsafe.Pointer | +| WrongUsageOfUnsafe.go:77:27:77:54 | type conversion | semmle.label | type conversion | | WrongUsageOfUnsafe.go:93:13:93:45 | type conversion | semmle.label | type conversion | -| WrongUsageOfUnsafe.go:93:20:93:44 | type conversion : unsafe.Pointer | semmle.label | type conversion : unsafe.Pointer | +| WrongUsageOfUnsafe.go:93:20:93:44 | type conversion | semmle.label | type conversion | | WrongUsageOfUnsafe.go:111:16:111:59 | type conversion | semmle.label | type conversion | -| WrongUsageOfUnsafe.go:111:31:111:58 | type conversion : unsafe.Pointer | semmle.label | type conversion : unsafe.Pointer | +| WrongUsageOfUnsafe.go:111:31:111:58 | type conversion | semmle.label | type conversion | | WrongUsageOfUnsafe.go:129:16:129:56 | type conversion | semmle.label | type conversion | -| WrongUsageOfUnsafe.go:129:31:129:55 | type conversion : unsafe.Pointer | semmle.label | type conversion : unsafe.Pointer | +| WrongUsageOfUnsafe.go:129:31:129:55 | type conversion | semmle.label | type conversion | | WrongUsageOfUnsafe.go:149:16:149:56 | type conversion | semmle.label | type conversion | -| WrongUsageOfUnsafe.go:149:31:149:55 | type conversion : unsafe.Pointer | semmle.label | type conversion : unsafe.Pointer | +| WrongUsageOfUnsafe.go:149:31:149:55 | type conversion | semmle.label | type conversion | | WrongUsageOfUnsafe.go:166:16:166:58 | type conversion | semmle.label | type conversion | -| WrongUsageOfUnsafe.go:166:33:166:57 | type conversion : unsafe.Pointer | semmle.label | type conversion : unsafe.Pointer | +| WrongUsageOfUnsafe.go:166:33:166:57 | type conversion | semmle.label | type conversion | | WrongUsageOfUnsafe.go:189:16:189:56 | type conversion | semmle.label | type conversion | -| WrongUsageOfUnsafe.go:189:31:189:55 | type conversion : unsafe.Pointer | semmle.label | type conversion : unsafe.Pointer | +| WrongUsageOfUnsafe.go:189:31:189:55 | type conversion | semmle.label | type conversion | | WrongUsageOfUnsafe.go:211:16:211:61 | type conversion | semmle.label | type conversion | -| WrongUsageOfUnsafe.go:211:31:211:60 | type conversion : unsafe.Pointer | semmle.label | type conversion : unsafe.Pointer | -| WrongUsageOfUnsafe.go:227:31:227:55 | type conversion : unsafe.Pointer | semmle.label | type conversion : unsafe.Pointer | -| WrongUsageOfUnsafe.go:236:21:236:23 | definition of req : unsafe.Pointer | semmle.label | definition of req : unsafe.Pointer | +| WrongUsageOfUnsafe.go:211:31:211:60 | type conversion | semmle.label | type conversion | +| WrongUsageOfUnsafe.go:227:31:227:55 | type conversion | semmle.label | type conversion | +| WrongUsageOfUnsafe.go:236:21:236:23 | definition of req | semmle.label | definition of req | | WrongUsageOfUnsafe.go:243:9:243:27 | type conversion | semmle.label | type conversion | | WrongUsageOfUnsafe.go:256:16:256:53 | type conversion | semmle.label | type conversion | -| WrongUsageOfUnsafe.go:256:28:256:52 | type conversion : unsafe.Pointer | semmle.label | type conversion : unsafe.Pointer | +| WrongUsageOfUnsafe.go:256:28:256:52 | type conversion | semmle.label | type conversion | | WrongUsageOfUnsafe.go:274:16:274:50 | type conversion | semmle.label | type conversion | -| WrongUsageOfUnsafe.go:274:25:274:49 | type conversion : unsafe.Pointer | semmle.label | type conversion : unsafe.Pointer | +| WrongUsageOfUnsafe.go:274:25:274:49 | type conversion | semmle.label | type conversion | | WrongUsageOfUnsafe.go:292:16:292:48 | type conversion | semmle.label | type conversion | -| WrongUsageOfUnsafe.go:292:23:292:47 | type conversion : unsafe.Pointer | semmle.label | type conversion : unsafe.Pointer | +| WrongUsageOfUnsafe.go:292:23:292:47 | type conversion | semmle.label | type conversion | subpaths #select -| WrongUsageOfUnsafe.go:77:16:77:55 | type conversion | WrongUsageOfUnsafe.go:77:27:77:54 | type conversion : unsafe.Pointer | WrongUsageOfUnsafe.go:77:16:77:55 | type conversion | $@. | WrongUsageOfUnsafe.go:77:27:77:54 | type conversion | Dangerous array type casting to [8]uint8 from an index expression ([8]uint8)[2] (the destination type is 2 elements longer) | -| WrongUsageOfUnsafe.go:111:16:111:59 | type conversion | WrongUsageOfUnsafe.go:111:31:111:58 | type conversion : unsafe.Pointer | WrongUsageOfUnsafe.go:111:16:111:59 | type conversion | $@. | WrongUsageOfUnsafe.go:111:31:111:58 | type conversion | Dangerous array type casting to [17]uint8 from an index expression ([8]uint8)[0] (the destination type is 9 elements longer) | -| WrongUsageOfUnsafe.go:129:16:129:56 | type conversion | WrongUsageOfUnsafe.go:129:31:129:55 | type conversion : unsafe.Pointer | WrongUsageOfUnsafe.go:129:16:129:56 | type conversion | $@. | WrongUsageOfUnsafe.go:129:31:129:55 | type conversion | Dangerous array type casting to [17]uint8 from [8]uint8 | -| WrongUsageOfUnsafe.go:149:16:149:56 | type conversion | WrongUsageOfUnsafe.go:149:31:149:55 | type conversion : unsafe.Pointer | WrongUsageOfUnsafe.go:149:16:149:56 | type conversion | $@. | WrongUsageOfUnsafe.go:149:31:149:55 | type conversion | Dangerous array type casting to [17]uint8 from [8]uint8 | -| WrongUsageOfUnsafe.go:166:16:166:58 | type conversion | WrongUsageOfUnsafe.go:166:33:166:57 | type conversion : unsafe.Pointer | WrongUsageOfUnsafe.go:166:16:166:58 | type conversion | $@. | WrongUsageOfUnsafe.go:166:33:166:57 | type conversion | Dangerous array type casting to [17]string from [8]string | -| WrongUsageOfUnsafe.go:189:16:189:56 | type conversion | WrongUsageOfUnsafe.go:189:31:189:55 | type conversion : unsafe.Pointer | WrongUsageOfUnsafe.go:189:16:189:56 | type conversion | $@. | WrongUsageOfUnsafe.go:189:31:189:55 | type conversion | Dangerous type up-casting to [17]uint8 from struct type | -| WrongUsageOfUnsafe.go:211:16:211:61 | type conversion | WrongUsageOfUnsafe.go:211:31:211:60 | type conversion : unsafe.Pointer | WrongUsageOfUnsafe.go:211:16:211:61 | type conversion | $@. | WrongUsageOfUnsafe.go:211:31:211:60 | type conversion | Dangerous array type casting to [17]uint8 from [8]uint8 | -| WrongUsageOfUnsafe.go:243:9:243:27 | type conversion | WrongUsageOfUnsafe.go:227:31:227:55 | type conversion : unsafe.Pointer | WrongUsageOfUnsafe.go:243:9:243:27 | type conversion | $@. | WrongUsageOfUnsafe.go:227:31:227:55 | type conversion | Dangerous array type casting to [17]uint8 from [8]uint8 | -| WrongUsageOfUnsafe.go:256:16:256:53 | type conversion | WrongUsageOfUnsafe.go:256:28:256:52 | type conversion : unsafe.Pointer | WrongUsageOfUnsafe.go:256:16:256:53 | type conversion | $@. | WrongUsageOfUnsafe.go:256:28:256:52 | type conversion | Dangerous array type casting to [4]int64 from [1]int64 | -| WrongUsageOfUnsafe.go:274:16:274:50 | type conversion | WrongUsageOfUnsafe.go:274:25:274:49 | type conversion : unsafe.Pointer | WrongUsageOfUnsafe.go:274:16:274:50 | type conversion | $@. | WrongUsageOfUnsafe.go:274:25:274:49 | type conversion | Dangerous numeric type casting to int64 from int8 | -| WrongUsageOfUnsafe.go:292:16:292:48 | type conversion | WrongUsageOfUnsafe.go:292:23:292:47 | type conversion : unsafe.Pointer | WrongUsageOfUnsafe.go:292:16:292:48 | type conversion | $@. | WrongUsageOfUnsafe.go:292:23:292:47 | type conversion | Dangerous numeric type casting to int from int8 | +| WrongUsageOfUnsafe.go:77:16:77:55 | type conversion | WrongUsageOfUnsafe.go:77:27:77:54 | type conversion | WrongUsageOfUnsafe.go:77:16:77:55 | type conversion | $@. | WrongUsageOfUnsafe.go:77:27:77:54 | type conversion | Dangerous array type casting to [8]uint8 from an index expression ([8]uint8)[2] (the destination type is 2 elements longer) | +| WrongUsageOfUnsafe.go:111:16:111:59 | type conversion | WrongUsageOfUnsafe.go:111:31:111:58 | type conversion | WrongUsageOfUnsafe.go:111:16:111:59 | type conversion | $@. | WrongUsageOfUnsafe.go:111:31:111:58 | type conversion | Dangerous array type casting to [17]uint8 from an index expression ([8]uint8)[0] (the destination type is 9 elements longer) | +| WrongUsageOfUnsafe.go:129:16:129:56 | type conversion | WrongUsageOfUnsafe.go:129:31:129:55 | type conversion | WrongUsageOfUnsafe.go:129:16:129:56 | type conversion | $@. | WrongUsageOfUnsafe.go:129:31:129:55 | type conversion | Dangerous array type casting to [17]uint8 from [8]uint8 | +| WrongUsageOfUnsafe.go:149:16:149:56 | type conversion | WrongUsageOfUnsafe.go:149:31:149:55 | type conversion | WrongUsageOfUnsafe.go:149:16:149:56 | type conversion | $@. | WrongUsageOfUnsafe.go:149:31:149:55 | type conversion | Dangerous array type casting to [17]uint8 from [8]uint8 | +| WrongUsageOfUnsafe.go:166:16:166:58 | type conversion | WrongUsageOfUnsafe.go:166:33:166:57 | type conversion | WrongUsageOfUnsafe.go:166:16:166:58 | type conversion | $@. | WrongUsageOfUnsafe.go:166:33:166:57 | type conversion | Dangerous array type casting to [17]string from [8]string | +| WrongUsageOfUnsafe.go:189:16:189:56 | type conversion | WrongUsageOfUnsafe.go:189:31:189:55 | type conversion | WrongUsageOfUnsafe.go:189:16:189:56 | type conversion | $@. | WrongUsageOfUnsafe.go:189:31:189:55 | type conversion | Dangerous type up-casting to [17]uint8 from struct type | +| WrongUsageOfUnsafe.go:211:16:211:61 | type conversion | WrongUsageOfUnsafe.go:211:31:211:60 | type conversion | WrongUsageOfUnsafe.go:211:16:211:61 | type conversion | $@. | WrongUsageOfUnsafe.go:211:31:211:60 | type conversion | Dangerous array type casting to [17]uint8 from [8]uint8 | +| WrongUsageOfUnsafe.go:243:9:243:27 | type conversion | WrongUsageOfUnsafe.go:227:31:227:55 | type conversion | WrongUsageOfUnsafe.go:243:9:243:27 | type conversion | $@. | WrongUsageOfUnsafe.go:227:31:227:55 | type conversion | Dangerous array type casting to [17]uint8 from [8]uint8 | +| WrongUsageOfUnsafe.go:256:16:256:53 | type conversion | WrongUsageOfUnsafe.go:256:28:256:52 | type conversion | WrongUsageOfUnsafe.go:256:16:256:53 | type conversion | $@. | WrongUsageOfUnsafe.go:256:28:256:52 | type conversion | Dangerous array type casting to [4]int64 from [1]int64 | +| WrongUsageOfUnsafe.go:274:16:274:50 | type conversion | WrongUsageOfUnsafe.go:274:25:274:49 | type conversion | WrongUsageOfUnsafe.go:274:16:274:50 | type conversion | $@. | WrongUsageOfUnsafe.go:274:25:274:49 | type conversion | Dangerous numeric type casting to int64 from int8 | +| WrongUsageOfUnsafe.go:292:16:292:48 | type conversion | WrongUsageOfUnsafe.go:292:23:292:47 | type conversion | WrongUsageOfUnsafe.go:292:16:292:48 | type conversion | $@. | WrongUsageOfUnsafe.go:292:23:292:47 | type conversion | Dangerous numeric type casting to int from int8 | diff --git a/go/ql/test/library-tests/semmle/go/Types/Method_hasQualifiedName2.expected b/go/ql/test/library-tests/semmle/go/Types/Method_hasQualifiedName2.expected index 24eac7cebc1..bf1bd76aa33 100644 --- a/go/ql/test/library-tests/semmle/go/Types/Method_hasQualifiedName2.expected +++ b/go/ql/test/library-tests/semmle/go/Types/Method_hasQualifiedName2.expected @@ -1,59 +1,59 @@ -| generic.go:33:2:33:5 | GetT | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types | GenericInterface | GetT | -| generic.go:48:2:48:6 | clone | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types | MyInterface | clone | -| generic.go:49:2:49:7 | dummy1 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types | MyInterface | dummy1 | -| generic.go:50:2:50:7 | dummy2 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types | MyInterface | dummy2 | -| generic.go:51:2:51:7 | dummy3 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types | MyInterface | dummy3 | -| generic.go:52:2:52:7 | dummy4 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types | MyInterface | dummy4 | -| generic.go:53:2:53:7 | dummy5 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types | MyInterface | dummy5 | -| generic.go:54:2:54:7 | dummy6 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types | MyInterface | dummy6 | -| generic.go:55:2:55:7 | dummy7 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types | MyInterface | dummy7 | -| generic.go:56:2:56:8 | dummy11 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types | MyInterface | dummy11 | -| generic.go:57:2:57:8 | dummy12 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types | MyInterface | dummy12 | -| generic.go:58:2:58:8 | dummy13 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types | MyInterface | dummy13 | -| generic.go:59:2:59:8 | dummy14 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types | MyInterface | dummy14 | -| generic.go:60:2:60:8 | dummy15 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types | MyInterface | dummy15 | -| generic.go:61:2:61:8 | dummy17 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types | MyInterface | dummy17 | -| generic.go:62:2:62:8 | dummy18 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types | MyInterface | dummy18 | -| generic.go:63:2:63:8 | dummy19 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types | MyInterface | dummy19 | -| generic.go:64:2:64:8 | dummy20 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types | MyInterface | dummy20 | -| interface.go:30:2:30:7 | String | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types | i6 | String | -| interface.go:30:2:30:7 | String | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types | i8 | String | -| interface.go:30:2:30:7 | String | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types | i9 | String | -| interface.go:30:2:30:7 | String | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types | i14 | String | -| interface.go:30:2:30:7 | String | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types | i15 | String | -| interface.go:37:2:37:7 | String | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types | i7 | String | -| interface.go:43:2:43:8 | StringA | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types | i8 | StringA | -| interface.go:43:2:43:8 | StringA | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types | i14 | StringA | -| interface.go:49:2:49:8 | StringB | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types | i9 | StringB | -| interface.go:49:2:49:8 | StringB | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types | i15 | StringB | -| interface.go:92:2:92:8 | StringA | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types | i17 | StringA | -| interface.go:97:2:97:8 | StringA | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types | i18 | StringA | -| interface.go:102:2:102:8 | StringB | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types | i19 | StringB | -| interface.go:107:2:107:8 | StringB | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types | i20 | StringB | -| pkg1/embedding.go:10:13:10:13 | f | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | base | f | -| pkg1/embedding.go:10:13:10:13 | f | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | embedder | f | -| pkg1/embedding.go:10:13:10:13 | f | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | embedder2 | f | -| pkg1/embedding.go:10:13:10:13 | f | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | ptrembedder | f | -| pkg1/embedding.go:14:14:14:14 | g | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | base | g | -| pkg1/embedding.go:14:14:14:14 | g | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | embedder | g | -| pkg1/embedding.go:14:14:14:14 | g | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | embedder2 | g | -| pkg1/embedding.go:14:14:14:14 | g | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | embedder3 | g | -| pkg1/embedding.go:14:14:14:14 | g | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | embedder4 | g | -| pkg1/embedding.go:14:14:14:14 | g | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | ptrembedder | g | -| pkg1/embedding.go:30:18:30:18 | f | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | embedder3 | f | -| pkg1/interfaces.go:4:2:4:2 | m | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | A | m | -| pkg1/interfaces.go:4:2:4:2 | m | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | AC | m | -| pkg1/interfaces.go:4:2:4:2 | m | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | AEmbedded | m | -| pkg1/interfaces.go:4:2:4:2 | m | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | AExtended | m | -| pkg1/interfaces.go:8:2:8:2 | m | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | B | m | -| pkg1/interfaces.go:9:2:9:2 | n | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | B | n | -| pkg1/interfaces.go:13:2:13:2 | n | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | AC | n | -| pkg1/interfaces.go:13:2:13:2 | n | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | C | n | -| pkg1/interfaces.go:14:2:14:2 | o | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | AC | o | -| pkg1/interfaces.go:14:2:14:2 | o | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | C | o | -| pkg1/interfaces.go:28:2:28:2 | n | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | AExtended | n | -| pkg1/interfaces.go:32:2:32:2 | m | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | A2 | m | -| pkg1/tst.go:33:16:33:19 | half | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | Foo | half | -| pkg1/tst.go:33:16:33:19 | half | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | T | half | -| pkg1/tst.go:33:16:33:19 | half | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | T3 | half | -| pkg1/tst.go:33:16:33:19 | half | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | T4 | half | +| generic.go:33:2:33:5 | GetT | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.GenericInterface | GetT | +| generic.go:48:2:48:6 | clone | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.MyInterface | clone | +| generic.go:49:2:49:7 | dummy1 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.MyInterface | dummy1 | +| generic.go:50:2:50:7 | dummy2 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.MyInterface | dummy2 | +| generic.go:51:2:51:7 | dummy3 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.MyInterface | dummy3 | +| generic.go:52:2:52:7 | dummy4 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.MyInterface | dummy4 | +| generic.go:53:2:53:7 | dummy5 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.MyInterface | dummy5 | +| generic.go:54:2:54:7 | dummy6 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.MyInterface | dummy6 | +| generic.go:55:2:55:7 | dummy7 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.MyInterface | dummy7 | +| generic.go:56:2:56:8 | dummy11 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.MyInterface | dummy11 | +| generic.go:57:2:57:8 | dummy12 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.MyInterface | dummy12 | +| generic.go:58:2:58:8 | dummy13 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.MyInterface | dummy13 | +| generic.go:59:2:59:8 | dummy14 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.MyInterface | dummy14 | +| generic.go:60:2:60:8 | dummy15 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.MyInterface | dummy15 | +| generic.go:61:2:61:8 | dummy17 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.MyInterface | dummy17 | +| generic.go:62:2:62:8 | dummy18 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.MyInterface | dummy18 | +| generic.go:63:2:63:8 | dummy19 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.MyInterface | dummy19 | +| generic.go:64:2:64:8 | dummy20 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.MyInterface | dummy20 | +| interface.go:30:2:30:7 | String | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.i6 | String | +| interface.go:30:2:30:7 | String | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.i8 | String | +| interface.go:30:2:30:7 | String | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.i9 | String | +| interface.go:30:2:30:7 | String | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.i14 | String | +| interface.go:30:2:30:7 | String | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.i15 | String | +| interface.go:37:2:37:7 | String | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.i7 | String | +| interface.go:43:2:43:8 | StringA | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.i8 | StringA | +| interface.go:43:2:43:8 | StringA | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.i14 | StringA | +| interface.go:49:2:49:8 | StringB | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.i9 | StringB | +| interface.go:49:2:49:8 | StringB | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.i15 | StringB | +| interface.go:92:2:92:8 | StringA | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.i17 | StringA | +| interface.go:97:2:97:8 | StringA | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.i18 | StringA | +| interface.go:102:2:102:8 | StringB | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.i19 | StringB | +| interface.go:107:2:107:8 | StringB | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.i20 | StringB | +| pkg1/embedding.go:10:13:10:13 | f | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1.base | f | +| pkg1/embedding.go:10:13:10:13 | f | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1.embedder | f | +| pkg1/embedding.go:10:13:10:13 | f | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1.embedder2 | f | +| pkg1/embedding.go:10:13:10:13 | f | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1.ptrembedder | f | +| pkg1/embedding.go:14:14:14:14 | g | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1.base | g | +| pkg1/embedding.go:14:14:14:14 | g | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1.embedder | g | +| pkg1/embedding.go:14:14:14:14 | g | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1.embedder2 | g | +| pkg1/embedding.go:14:14:14:14 | g | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1.embedder3 | g | +| pkg1/embedding.go:14:14:14:14 | g | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1.embedder4 | g | +| pkg1/embedding.go:14:14:14:14 | g | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1.ptrembedder | g | +| pkg1/embedding.go:30:18:30:18 | f | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1.embedder3 | f | +| pkg1/interfaces.go:4:2:4:2 | m | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1.A | m | +| pkg1/interfaces.go:4:2:4:2 | m | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1.AC | m | +| pkg1/interfaces.go:4:2:4:2 | m | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1.AEmbedded | m | +| pkg1/interfaces.go:4:2:4:2 | m | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1.AExtended | m | +| pkg1/interfaces.go:8:2:8:2 | m | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1.B | m | +| pkg1/interfaces.go:9:2:9:2 | n | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1.B | n | +| pkg1/interfaces.go:13:2:13:2 | n | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1.AC | n | +| pkg1/interfaces.go:13:2:13:2 | n | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1.C | n | +| pkg1/interfaces.go:14:2:14:2 | o | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1.AC | o | +| pkg1/interfaces.go:14:2:14:2 | o | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1.C | o | +| pkg1/interfaces.go:28:2:28:2 | n | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1.AExtended | n | +| pkg1/interfaces.go:32:2:32:2 | m | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1.A2 | m | +| pkg1/tst.go:33:16:33:19 | half | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1.Foo | half | +| pkg1/tst.go:33:16:33:19 | half | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1.T | half | +| pkg1/tst.go:33:16:33:19 | half | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1.T3 | half | +| pkg1/tst.go:33:16:33:19 | half | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1.T4 | half | diff --git a/go/ql/test/library-tests/semmle/go/Types/Method_hasQualifiedName2.ql b/go/ql/test/library-tests/semmle/go/Types/Method_hasQualifiedName2.ql index b8df1364fc1..e6700d82e47 100644 --- a/go/ql/test/library-tests/semmle/go/Types/Method_hasQualifiedName2.ql +++ b/go/ql/test/library-tests/semmle/go/Types/Method_hasQualifiedName2.ql @@ -1,5 +1,5 @@ import go -from Method meth, string pkg, string tp, string m -where meth.hasQualifiedName(pkg, tp, m) -select meth.getDeclaration(), pkg, tp, m +from Method meth, string tp, string m +where meth.hasQualifiedName(tp, m) +select meth.getDeclaration(), tp, m diff --git a/go/ql/test/library-tests/semmle/go/dataflow/ChannelField/test.expected b/go/ql/test/library-tests/semmle/go/dataflow/ChannelField/test.expected index f8721f61972..523d27be250 100644 --- a/go/ql/test/library-tests/semmle/go/dataflow/ChannelField/test.expected +++ b/go/ql/test/library-tests/semmle/go/dataflow/ChannelField/test.expected @@ -1,22 +1,22 @@ edges -| test.go:9:9:9:11 | selection of c [collection] : string | test.go:9:7:9:11 | <-... | -| test.go:13:16:13:16 | definition of s [pointer, c, collection] : string | test.go:16:2:16:2 | s [pointer, c, collection] : string | -| test.go:15:10:15:17 | call to source : string | test.go:16:9:16:12 | data : string | -| test.go:16:2:16:2 | implicit dereference [c, collection] : string | test.go:13:16:13:16 | definition of s [pointer, c, collection] : string | -| test.go:16:2:16:2 | implicit dereference [c, collection] : string | test.go:16:2:16:4 | selection of c [collection] : string | -| test.go:16:2:16:2 | s [pointer, c, collection] : string | test.go:16:2:16:2 | implicit dereference [c, collection] : string | -| test.go:16:2:16:4 | selection of c [collection] : string | test.go:9:9:9:11 | selection of c [collection] : string | -| test.go:16:2:16:4 | selection of c [collection] : string | test.go:16:2:16:2 | implicit dereference [c, collection] : string | -| test.go:16:9:16:12 | data : string | test.go:16:2:16:4 | selection of c [collection] : string | +| test.go:9:9:9:11 | selection of c [collection] | test.go:9:7:9:11 | <-... | +| test.go:13:16:13:16 | definition of s [pointer, c, collection] | test.go:16:2:16:2 | s [pointer, c, collection] | +| test.go:15:10:15:17 | call to source | test.go:16:9:16:12 | data | +| test.go:16:2:16:2 | implicit dereference [c, collection] | test.go:13:16:13:16 | definition of s [pointer, c, collection] | +| test.go:16:2:16:2 | implicit dereference [c, collection] | test.go:16:2:16:4 | selection of c [collection] | +| test.go:16:2:16:2 | s [pointer, c, collection] | test.go:16:2:16:2 | implicit dereference [c, collection] | +| test.go:16:2:16:4 | selection of c [collection] | test.go:9:9:9:11 | selection of c [collection] | +| test.go:16:2:16:4 | selection of c [collection] | test.go:16:2:16:2 | implicit dereference [c, collection] | +| test.go:16:9:16:12 | data | test.go:16:2:16:4 | selection of c [collection] | nodes | test.go:9:7:9:11 | <-... | semmle.label | <-... | -| test.go:9:9:9:11 | selection of c [collection] : string | semmle.label | selection of c [collection] : string | -| test.go:13:16:13:16 | definition of s [pointer, c, collection] : string | semmle.label | definition of s [pointer, c, collection] : string | -| test.go:15:10:15:17 | call to source : string | semmle.label | call to source : string | -| test.go:16:2:16:2 | implicit dereference [c, collection] : string | semmle.label | implicit dereference [c, collection] : string | -| test.go:16:2:16:2 | s [pointer, c, collection] : string | semmle.label | s [pointer, c, collection] : string | -| test.go:16:2:16:4 | selection of c [collection] : string | semmle.label | selection of c [collection] : string | -| test.go:16:9:16:12 | data : string | semmle.label | data : string | +| test.go:9:9:9:11 | selection of c [collection] | semmle.label | selection of c [collection] | +| test.go:13:16:13:16 | definition of s [pointer, c, collection] | semmle.label | definition of s [pointer, c, collection] | +| test.go:15:10:15:17 | call to source | semmle.label | call to source | +| test.go:16:2:16:2 | implicit dereference [c, collection] | semmle.label | implicit dereference [c, collection] | +| test.go:16:2:16:2 | s [pointer, c, collection] | semmle.label | s [pointer, c, collection] | +| test.go:16:2:16:4 | selection of c [collection] | semmle.label | selection of c [collection] | +| test.go:16:9:16:12 | data | semmle.label | data | subpaths #select -| test.go:15:10:15:17 | call to source : string | test.go:15:10:15:17 | call to source : string | test.go:9:7:9:11 | <-... | path | +| test.go:15:10:15:17 | call to source | test.go:15:10:15:17 | call to source | test.go:9:7:9:11 | <-... | path | diff --git a/go/ql/test/library-tests/semmle/go/frameworks/Beego/ReflectedXss.expected b/go/ql/test/library-tests/semmle/go/frameworks/Beego/ReflectedXss.expected index 6af1a75cbbd..37feb5ef6f5 100644 --- a/go/ql/test/library-tests/semmle/go/frameworks/Beego/ReflectedXss.expected +++ b/go/ql/test/library-tests/semmle/go/frameworks/Beego/ReflectedXss.expected @@ -1,123 +1,123 @@ edges -| test.go:27:6:27:10 | definition of bound : bindMe | test.go:29:13:29:30 | type conversion | -| test.go:27:6:27:10 | definition of bound : bindMe | test.go:30:13:30:27 | type conversion | -| test.go:27:6:27:10 | definition of bound : bindMe | test.go:31:13:31:29 | type conversion | -| test.go:36:20:36:42 | call to Cookie : string | test.go:36:13:36:43 | type conversion | -| test.go:41:20:41:31 | call to Data : map type | test.go:41:13:41:52 | type conversion | -| test.go:46:20:46:43 | call to GetData : basic interface type | test.go:46:13:46:53 | type conversion | -| test.go:51:20:51:42 | call to Header : string | test.go:51:13:51:43 | type conversion | -| test.go:56:20:56:41 | call to Param : string | test.go:56:13:56:42 | type conversion | -| test.go:61:20:61:33 | call to Params : map type | test.go:61:13:61:45 | type conversion | -| test.go:66:20:66:41 | call to Query : string | test.go:66:13:66:42 | type conversion | -| test.go:71:20:71:32 | call to Refer : string | test.go:71:13:71:33 | type conversion | -| test.go:76:20:76:34 | call to Referer : string | test.go:76:13:76:35 | type conversion | -| test.go:81:20:81:30 | call to URI : string | test.go:81:13:81:31 | type conversion | -| test.go:86:20:86:30 | call to URL : string | test.go:86:13:86:31 | type conversion | -| test.go:91:20:91:36 | call to UserAgent : string | test.go:91:13:91:37 | type conversion | -| test.go:96:14:96:25 | call to Data : map type | test.go:96:14:96:45 | type assertion | -| test.go:108:14:108:25 | call to Data : map type | test.go:108:14:108:45 | type assertion | -| test.go:120:14:120:25 | call to Data : map type | test.go:120:14:120:45 | type assertion | -| test.go:137:23:137:42 | call to Data : map type | test.go:137:23:137:62 | type assertion | -| test.go:193:15:193:26 | call to Data : map type | test.go:194:14:194:55 | type conversion | -| test.go:193:15:193:26 | call to Data : map type | test.go:195:14:195:58 | type conversion | -| test.go:193:15:193:26 | call to Data : map type | test.go:197:14:197:28 | type assertion | -| test.go:193:15:193:26 | call to Data : map type | test.go:198:14:198:55 | type conversion | -| test.go:193:15:193:26 | call to Data : map type | test.go:199:14:199:59 | type conversion | -| test.go:202:18:202:33 | selection of Form : Values | test.go:203:14:203:28 | type conversion | -| test.go:217:2:217:34 | ... := ...[0] : File | test.go:220:14:220:20 | content | -| test.go:217:2:217:34 | ... := ...[1] : pointer type | test.go:218:14:218:32 | type conversion | -| test.go:222:2:222:40 | ... := ...[0] : slice type | test.go:223:14:223:38 | type conversion | -| test.go:225:7:225:28 | call to GetString : string | test.go:226:14:226:22 | type conversion | -| test.go:228:8:228:35 | call to GetStrings : slice type | test.go:229:14:229:26 | type conversion | -| test.go:231:9:231:17 | call to Input : Values | test.go:232:14:232:27 | type conversion | -| test.go:234:6:234:8 | definition of str : myStruct | test.go:236:14:236:30 | type conversion | -| test.go:240:15:240:36 | call to GetString : string | test.go:243:21:243:29 | untrusted | -| test.go:253:23:253:44 | call to GetCookie : string | test.go:253:16:253:45 | type conversion | -| test.go:264:62:264:83 | call to GetCookie : string | test.go:264:55:264:84 | type conversion | -| test.go:269:2:269:40 | ... := ...[0] : slice type | test.go:277:21:277:61 | call to GetDisplayString | -| test.go:269:2:269:40 | ... := ...[0] : slice type | test.go:278:21:278:92 | selection of Filename | -| test.go:269:2:269:40 | ... := ...[0] : slice type | test.go:279:21:279:96 | selection of Filename | -| test.go:269:2:269:40 | ... := ...[0] : slice type | test.go:284:3:286:80 | selection of Filename | -| test.go:269:2:269:40 | ... := ...[0] : slice type | test.go:287:21:287:101 | selection of Filename | -| test.go:269:2:269:40 | ... := ...[0] : slice type | test.go:288:21:288:101 | selection of Filename | -| test.go:269:2:269:40 | ... := ...[0] : slice type | test.go:289:21:289:97 | selection of Filename | -| test.go:269:2:269:40 | ... := ...[0] : slice type | test.go:290:21:290:97 | selection of Filename | -| test.go:269:2:269:40 | ... := ...[0] : slice type | test.go:291:21:291:102 | selection of Filename | -| test.go:269:2:269:40 | ... := ...[0] : slice type | test.go:292:21:292:102 | selection of Filename | -| test.go:269:2:269:40 | ... := ...[0] : slice type | test.go:293:21:293:82 | selection of Filename | -| test.go:269:2:269:40 | ... := ...[0] : slice type | test.go:295:21:295:133 | selection of Filename | -| test.go:269:2:269:40 | ... := ...[0] : slice type | test.go:296:21:296:88 | selection of Filename | -| test.go:269:2:269:40 | ... := ...[0] : slice type | test.go:297:21:297:87 | selection of Filename | -| test.go:303:15:303:36 | call to GetString : string | test.go:305:21:305:48 | type assertion | -| test.go:303:15:303:36 | call to GetString : string | test.go:306:21:306:52 | type assertion | +| test.go:27:6:27:10 | definition of bound | test.go:29:13:29:30 | type conversion | +| test.go:27:6:27:10 | definition of bound | test.go:30:13:30:27 | type conversion | +| test.go:27:6:27:10 | definition of bound | test.go:31:13:31:29 | type conversion | +| test.go:36:20:36:42 | call to Cookie | test.go:36:13:36:43 | type conversion | +| test.go:41:20:41:31 | call to Data | test.go:41:13:41:52 | type conversion | +| test.go:46:20:46:43 | call to GetData | test.go:46:13:46:53 | type conversion | +| test.go:51:20:51:42 | call to Header | test.go:51:13:51:43 | type conversion | +| test.go:56:20:56:41 | call to Param | test.go:56:13:56:42 | type conversion | +| test.go:61:20:61:33 | call to Params | test.go:61:13:61:45 | type conversion | +| test.go:66:20:66:41 | call to Query | test.go:66:13:66:42 | type conversion | +| test.go:71:20:71:32 | call to Refer | test.go:71:13:71:33 | type conversion | +| test.go:76:20:76:34 | call to Referer | test.go:76:13:76:35 | type conversion | +| test.go:81:20:81:30 | call to URI | test.go:81:13:81:31 | type conversion | +| test.go:86:20:86:30 | call to URL | test.go:86:13:86:31 | type conversion | +| test.go:91:20:91:36 | call to UserAgent | test.go:91:13:91:37 | type conversion | +| test.go:96:14:96:25 | call to Data | test.go:96:14:96:45 | type assertion | +| test.go:108:14:108:25 | call to Data | test.go:108:14:108:45 | type assertion | +| test.go:120:14:120:25 | call to Data | test.go:120:14:120:45 | type assertion | +| test.go:137:23:137:42 | call to Data | test.go:137:23:137:62 | type assertion | +| test.go:193:15:193:26 | call to Data | test.go:194:14:194:55 | type conversion | +| test.go:193:15:193:26 | call to Data | test.go:195:14:195:58 | type conversion | +| test.go:193:15:193:26 | call to Data | test.go:197:14:197:28 | type assertion | +| test.go:193:15:193:26 | call to Data | test.go:198:14:198:55 | type conversion | +| test.go:193:15:193:26 | call to Data | test.go:199:14:199:59 | type conversion | +| test.go:202:18:202:33 | selection of Form | test.go:203:14:203:28 | type conversion | +| test.go:217:2:217:34 | ... := ...[0] | test.go:220:14:220:20 | content | +| test.go:217:2:217:34 | ... := ...[1] | test.go:218:14:218:32 | type conversion | +| test.go:222:2:222:40 | ... := ...[0] | test.go:223:14:223:38 | type conversion | +| test.go:225:7:225:28 | call to GetString | test.go:226:14:226:22 | type conversion | +| test.go:228:8:228:35 | call to GetStrings | test.go:229:14:229:26 | type conversion | +| test.go:231:9:231:17 | call to Input | test.go:232:14:232:27 | type conversion | +| test.go:234:6:234:8 | definition of str | test.go:236:14:236:30 | type conversion | +| test.go:240:15:240:36 | call to GetString | test.go:243:21:243:29 | untrusted | +| test.go:253:23:253:44 | call to GetCookie | test.go:253:16:253:45 | type conversion | +| test.go:264:62:264:83 | call to GetCookie | test.go:264:55:264:84 | type conversion | +| test.go:269:2:269:40 | ... := ...[0] | test.go:277:21:277:61 | call to GetDisplayString | +| test.go:269:2:269:40 | ... := ...[0] | test.go:278:21:278:92 | selection of Filename | +| test.go:269:2:269:40 | ... := ...[0] | test.go:279:21:279:96 | selection of Filename | +| test.go:269:2:269:40 | ... := ...[0] | test.go:284:3:286:80 | selection of Filename | +| test.go:269:2:269:40 | ... := ...[0] | test.go:287:21:287:101 | selection of Filename | +| test.go:269:2:269:40 | ... := ...[0] | test.go:288:21:288:101 | selection of Filename | +| test.go:269:2:269:40 | ... := ...[0] | test.go:289:21:289:97 | selection of Filename | +| test.go:269:2:269:40 | ... := ...[0] | test.go:290:21:290:97 | selection of Filename | +| test.go:269:2:269:40 | ... := ...[0] | test.go:291:21:291:102 | selection of Filename | +| test.go:269:2:269:40 | ... := ...[0] | test.go:292:21:292:102 | selection of Filename | +| test.go:269:2:269:40 | ... := ...[0] | test.go:293:21:293:82 | selection of Filename | +| test.go:269:2:269:40 | ... := ...[0] | test.go:295:21:295:133 | selection of Filename | +| test.go:269:2:269:40 | ... := ...[0] | test.go:296:21:296:88 | selection of Filename | +| test.go:269:2:269:40 | ... := ...[0] | test.go:297:21:297:87 | selection of Filename | +| test.go:303:15:303:36 | call to GetString | test.go:305:21:305:48 | type assertion | +| test.go:303:15:303:36 | call to GetString | test.go:306:21:306:52 | type assertion | nodes -| test.go:27:6:27:10 | definition of bound : bindMe | semmle.label | definition of bound : bindMe | +| test.go:27:6:27:10 | definition of bound | semmle.label | definition of bound | | test.go:29:13:29:30 | type conversion | semmle.label | type conversion | | test.go:30:13:30:27 | type conversion | semmle.label | type conversion | | test.go:31:13:31:29 | type conversion | semmle.label | type conversion | | test.go:36:13:36:43 | type conversion | semmle.label | type conversion | -| test.go:36:20:36:42 | call to Cookie : string | semmle.label | call to Cookie : string | +| test.go:36:20:36:42 | call to Cookie | semmle.label | call to Cookie | | test.go:41:13:41:52 | type conversion | semmle.label | type conversion | -| test.go:41:20:41:31 | call to Data : map type | semmle.label | call to Data : map type | +| test.go:41:20:41:31 | call to Data | semmle.label | call to Data | | test.go:46:13:46:53 | type conversion | semmle.label | type conversion | -| test.go:46:20:46:43 | call to GetData : basic interface type | semmle.label | call to GetData : basic interface type | +| test.go:46:20:46:43 | call to GetData | semmle.label | call to GetData | | test.go:51:13:51:43 | type conversion | semmle.label | type conversion | -| test.go:51:20:51:42 | call to Header : string | semmle.label | call to Header : string | +| test.go:51:20:51:42 | call to Header | semmle.label | call to Header | | test.go:56:13:56:42 | type conversion | semmle.label | type conversion | -| test.go:56:20:56:41 | call to Param : string | semmle.label | call to Param : string | +| test.go:56:20:56:41 | call to Param | semmle.label | call to Param | | test.go:61:13:61:45 | type conversion | semmle.label | type conversion | -| test.go:61:20:61:33 | call to Params : map type | semmle.label | call to Params : map type | +| test.go:61:20:61:33 | call to Params | semmle.label | call to Params | | test.go:66:13:66:42 | type conversion | semmle.label | type conversion | -| test.go:66:20:66:41 | call to Query : string | semmle.label | call to Query : string | +| test.go:66:20:66:41 | call to Query | semmle.label | call to Query | | test.go:71:13:71:33 | type conversion | semmle.label | type conversion | -| test.go:71:20:71:32 | call to Refer : string | semmle.label | call to Refer : string | +| test.go:71:20:71:32 | call to Refer | semmle.label | call to Refer | | test.go:76:13:76:35 | type conversion | semmle.label | type conversion | -| test.go:76:20:76:34 | call to Referer : string | semmle.label | call to Referer : string | +| test.go:76:20:76:34 | call to Referer | semmle.label | call to Referer | | test.go:81:13:81:31 | type conversion | semmle.label | type conversion | -| test.go:81:20:81:30 | call to URI : string | semmle.label | call to URI : string | +| test.go:81:20:81:30 | call to URI | semmle.label | call to URI | | test.go:86:13:86:31 | type conversion | semmle.label | type conversion | -| test.go:86:20:86:30 | call to URL : string | semmle.label | call to URL : string | +| test.go:86:20:86:30 | call to URL | semmle.label | call to URL | | test.go:91:13:91:37 | type conversion | semmle.label | type conversion | -| test.go:91:20:91:36 | call to UserAgent : string | semmle.label | call to UserAgent : string | -| test.go:96:14:96:25 | call to Data : map type | semmle.label | call to Data : map type | +| test.go:91:20:91:36 | call to UserAgent | semmle.label | call to UserAgent | +| test.go:96:14:96:25 | call to Data | semmle.label | call to Data | | test.go:96:14:96:45 | type assertion | semmle.label | type assertion | -| test.go:108:14:108:25 | call to Data : map type | semmle.label | call to Data : map type | +| test.go:108:14:108:25 | call to Data | semmle.label | call to Data | | test.go:108:14:108:45 | type assertion | semmle.label | type assertion | -| test.go:120:14:120:25 | call to Data : map type | semmle.label | call to Data : map type | +| test.go:120:14:120:25 | call to Data | semmle.label | call to Data | | test.go:120:14:120:45 | type assertion | semmle.label | type assertion | -| test.go:137:23:137:42 | call to Data : map type | semmle.label | call to Data : map type | +| test.go:137:23:137:42 | call to Data | semmle.label | call to Data | | test.go:137:23:137:62 | type assertion | semmle.label | type assertion | -| test.go:193:15:193:26 | call to Data : map type | semmle.label | call to Data : map type | +| test.go:193:15:193:26 | call to Data | semmle.label | call to Data | | test.go:194:14:194:55 | type conversion | semmle.label | type conversion | | test.go:195:14:195:58 | type conversion | semmle.label | type conversion | | test.go:197:14:197:28 | type assertion | semmle.label | type assertion | | test.go:198:14:198:55 | type conversion | semmle.label | type conversion | | test.go:199:14:199:59 | type conversion | semmle.label | type conversion | -| test.go:202:18:202:33 | selection of Form : Values | semmle.label | selection of Form : Values | +| test.go:202:18:202:33 | selection of Form | semmle.label | selection of Form | | test.go:203:14:203:28 | type conversion | semmle.label | type conversion | -| test.go:217:2:217:34 | ... := ...[0] : File | semmle.label | ... := ...[0] : File | -| test.go:217:2:217:34 | ... := ...[1] : pointer type | semmle.label | ... := ...[1] : pointer type | +| test.go:217:2:217:34 | ... := ...[0] | semmle.label | ... := ...[0] | +| test.go:217:2:217:34 | ... := ...[1] | semmle.label | ... := ...[1] | | test.go:218:14:218:32 | type conversion | semmle.label | type conversion | | test.go:220:14:220:20 | content | semmle.label | content | -| test.go:222:2:222:40 | ... := ...[0] : slice type | semmle.label | ... := ...[0] : slice type | +| test.go:222:2:222:40 | ... := ...[0] | semmle.label | ... := ...[0] | | test.go:223:14:223:38 | type conversion | semmle.label | type conversion | -| test.go:225:7:225:28 | call to GetString : string | semmle.label | call to GetString : string | +| test.go:225:7:225:28 | call to GetString | semmle.label | call to GetString | | test.go:226:14:226:22 | type conversion | semmle.label | type conversion | -| test.go:228:8:228:35 | call to GetStrings : slice type | semmle.label | call to GetStrings : slice type | +| test.go:228:8:228:35 | call to GetStrings | semmle.label | call to GetStrings | | test.go:229:14:229:26 | type conversion | semmle.label | type conversion | -| test.go:231:9:231:17 | call to Input : Values | semmle.label | call to Input : Values | +| test.go:231:9:231:17 | call to Input | semmle.label | call to Input | | test.go:232:14:232:27 | type conversion | semmle.label | type conversion | -| test.go:234:6:234:8 | definition of str : myStruct | semmle.label | definition of str : myStruct | +| test.go:234:6:234:8 | definition of str | semmle.label | definition of str | | test.go:236:14:236:30 | type conversion | semmle.label | type conversion | -| test.go:240:15:240:36 | call to GetString : string | semmle.label | call to GetString : string | +| test.go:240:15:240:36 | call to GetString | semmle.label | call to GetString | | test.go:243:21:243:29 | untrusted | semmle.label | untrusted | | test.go:253:16:253:45 | type conversion | semmle.label | type conversion | -| test.go:253:23:253:44 | call to GetCookie : string | semmle.label | call to GetCookie : string | +| test.go:253:23:253:44 | call to GetCookie | semmle.label | call to GetCookie | | test.go:258:16:258:37 | call to GetCookie | semmle.label | call to GetCookie | | test.go:259:15:259:41 | call to GetCookie | semmle.label | call to GetCookie | | test.go:264:55:264:84 | type conversion | semmle.label | type conversion | -| test.go:264:62:264:83 | call to GetCookie : string | semmle.label | call to GetCookie : string | -| test.go:269:2:269:40 | ... := ...[0] : slice type | semmle.label | ... := ...[0] : slice type | +| test.go:264:62:264:83 | call to GetCookie | semmle.label | call to GetCookie | +| test.go:269:2:269:40 | ... := ...[0] | semmle.label | ... := ...[0] | | test.go:277:21:277:61 | call to GetDisplayString | semmle.label | call to GetDisplayString | | test.go:278:21:278:92 | selection of Filename | semmle.label | selection of Filename | | test.go:279:21:279:96 | selection of Filename | semmle.label | selection of Filename | @@ -132,61 +132,61 @@ nodes | test.go:295:21:295:133 | selection of Filename | semmle.label | selection of Filename | | test.go:296:21:296:88 | selection of Filename | semmle.label | selection of Filename | | test.go:297:21:297:87 | selection of Filename | semmle.label | selection of Filename | -| test.go:303:15:303:36 | call to GetString : string | semmle.label | call to GetString : string | +| test.go:303:15:303:36 | call to GetString | semmle.label | call to GetString | | test.go:305:21:305:48 | type assertion | semmle.label | type assertion | | test.go:306:21:306:52 | type assertion | semmle.label | type assertion | subpaths #select -| test.go:29:13:29:30 | type conversion | test.go:27:6:27:10 | definition of bound : bindMe | test.go:29:13:29:30 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:27:6:27:10 | definition of bound | user-provided value | test.go:0:0:0:0 | test.go | | -| test.go:30:13:30:27 | type conversion | test.go:27:6:27:10 | definition of bound : bindMe | test.go:30:13:30:27 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:27:6:27:10 | definition of bound | user-provided value | test.go:0:0:0:0 | test.go | | -| test.go:31:13:31:29 | type conversion | test.go:27:6:27:10 | definition of bound : bindMe | test.go:31:13:31:29 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:27:6:27:10 | definition of bound | user-provided value | test.go:0:0:0:0 | test.go | | -| test.go:36:13:36:43 | type conversion | test.go:36:20:36:42 | call to Cookie : string | test.go:36:13:36:43 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:36:20:36:42 | call to Cookie | user-provided value | test.go:0:0:0:0 | test.go | | -| test.go:41:13:41:52 | type conversion | test.go:41:20:41:31 | call to Data : map type | test.go:41:13:41:52 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:41:20:41:31 | call to Data | user-provided value | test.go:0:0:0:0 | test.go | | -| test.go:46:13:46:53 | type conversion | test.go:46:20:46:43 | call to GetData : basic interface type | test.go:46:13:46:53 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:46:20:46:43 | call to GetData | user-provided value | test.go:0:0:0:0 | test.go | | -| test.go:51:13:51:43 | type conversion | test.go:51:20:51:42 | call to Header : string | test.go:51:13:51:43 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:51:20:51:42 | call to Header | user-provided value | test.go:0:0:0:0 | test.go | | -| test.go:56:13:56:42 | type conversion | test.go:56:20:56:41 | call to Param : string | test.go:56:13:56:42 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:56:20:56:41 | call to Param | user-provided value | test.go:0:0:0:0 | test.go | | -| test.go:61:13:61:45 | type conversion | test.go:61:20:61:33 | call to Params : map type | test.go:61:13:61:45 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:61:20:61:33 | call to Params | user-provided value | test.go:0:0:0:0 | test.go | | -| test.go:66:13:66:42 | type conversion | test.go:66:20:66:41 | call to Query : string | test.go:66:13:66:42 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:66:20:66:41 | call to Query | user-provided value | test.go:0:0:0:0 | test.go | | -| test.go:71:13:71:33 | type conversion | test.go:71:20:71:32 | call to Refer : string | test.go:71:13:71:33 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:71:20:71:32 | call to Refer | user-provided value | test.go:0:0:0:0 | test.go | | -| test.go:76:13:76:35 | type conversion | test.go:76:20:76:34 | call to Referer : string | test.go:76:13:76:35 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:76:20:76:34 | call to Referer | user-provided value | test.go:0:0:0:0 | test.go | | -| test.go:81:13:81:31 | type conversion | test.go:81:20:81:30 | call to URI : string | test.go:81:13:81:31 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:81:20:81:30 | call to URI | user-provided value | test.go:0:0:0:0 | test.go | | -| test.go:86:13:86:31 | type conversion | test.go:86:20:86:30 | call to URL : string | test.go:86:13:86:31 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:86:20:86:30 | call to URL | user-provided value | test.go:0:0:0:0 | test.go | | -| test.go:91:13:91:37 | type conversion | test.go:91:20:91:36 | call to UserAgent : string | test.go:91:13:91:37 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:91:20:91:36 | call to UserAgent | user-provided value | test.go:0:0:0:0 | test.go | | -| test.go:96:14:96:45 | type assertion | test.go:96:14:96:25 | call to Data : map type | test.go:96:14:96:45 | type assertion | Cross-site scripting vulnerability due to $@. | test.go:96:14:96:25 | call to Data | user-provided value | test.go:0:0:0:0 | test.go | | -| test.go:108:14:108:45 | type assertion | test.go:108:14:108:25 | call to Data : map type | test.go:108:14:108:45 | type assertion | Cross-site scripting vulnerability due to $@. | test.go:108:14:108:25 | call to Data | user-provided value | test.go:0:0:0:0 | test.go | | -| test.go:120:14:120:45 | type assertion | test.go:120:14:120:25 | call to Data : map type | test.go:120:14:120:45 | type assertion | Cross-site scripting vulnerability due to $@. | test.go:120:14:120:25 | call to Data | user-provided value | test.go:0:0:0:0 | test.go | | -| test.go:137:23:137:62 | type assertion | test.go:137:23:137:42 | call to Data : map type | test.go:137:23:137:62 | type assertion | Cross-site scripting vulnerability due to $@. | test.go:137:23:137:42 | call to Data | user-provided value | test.go:0:0:0:0 | test.go | | -| test.go:194:14:194:55 | type conversion | test.go:193:15:193:26 | call to Data : map type | test.go:194:14:194:55 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:193:15:193:26 | call to Data | user-provided value | test.go:0:0:0:0 | test.go | | -| test.go:195:14:195:58 | type conversion | test.go:193:15:193:26 | call to Data : map type | test.go:195:14:195:58 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:193:15:193:26 | call to Data | user-provided value | test.go:0:0:0:0 | test.go | | -| test.go:197:14:197:28 | type assertion | test.go:193:15:193:26 | call to Data : map type | test.go:197:14:197:28 | type assertion | Cross-site scripting vulnerability due to $@. | test.go:193:15:193:26 | call to Data | user-provided value | test.go:0:0:0:0 | test.go | | -| test.go:198:14:198:55 | type conversion | test.go:193:15:193:26 | call to Data : map type | test.go:198:14:198:55 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:193:15:193:26 | call to Data | user-provided value | test.go:0:0:0:0 | test.go | | -| test.go:199:14:199:59 | type conversion | test.go:193:15:193:26 | call to Data : map type | test.go:199:14:199:59 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:193:15:193:26 | call to Data | user-provided value | test.go:0:0:0:0 | test.go | | -| test.go:203:14:203:28 | type conversion | test.go:202:18:202:33 | selection of Form : Values | test.go:203:14:203:28 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:202:18:202:33 | selection of Form | user-provided value | test.go:0:0:0:0 | test.go | | -| test.go:218:14:218:32 | type conversion | test.go:217:2:217:34 | ... := ...[1] : pointer type | test.go:218:14:218:32 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:217:2:217:34 | ... := ...[1] | user-provided value | test.go:0:0:0:0 | test.go | | -| test.go:220:14:220:20 | content | test.go:217:2:217:34 | ... := ...[0] : File | test.go:220:14:220:20 | content | Cross-site scripting vulnerability due to $@. | test.go:217:2:217:34 | ... := ...[0] | user-provided value | test.go:0:0:0:0 | test.go | | -| test.go:223:14:223:38 | type conversion | test.go:222:2:222:40 | ... := ...[0] : slice type | test.go:223:14:223:38 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:222:2:222:40 | ... := ...[0] | user-provided value | test.go:0:0:0:0 | test.go | | -| test.go:226:14:226:22 | type conversion | test.go:225:7:225:28 | call to GetString : string | test.go:226:14:226:22 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:225:7:225:28 | call to GetString | user-provided value | test.go:0:0:0:0 | test.go | | -| test.go:229:14:229:26 | type conversion | test.go:228:8:228:35 | call to GetStrings : slice type | test.go:229:14:229:26 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:228:8:228:35 | call to GetStrings | user-provided value | test.go:0:0:0:0 | test.go | | -| test.go:232:14:232:27 | type conversion | test.go:231:9:231:17 | call to Input : Values | test.go:232:14:232:27 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:231:9:231:17 | call to Input | user-provided value | test.go:0:0:0:0 | test.go | | -| test.go:236:14:236:30 | type conversion | test.go:234:6:234:8 | definition of str : myStruct | test.go:236:14:236:30 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:234:6:234:8 | definition of str | user-provided value | test.go:0:0:0:0 | test.go | | -| test.go:243:21:243:29 | untrusted | test.go:240:15:240:36 | call to GetString : string | test.go:243:21:243:29 | untrusted | Cross-site scripting vulnerability due to $@. | test.go:240:15:240:36 | call to GetString | user-provided value | test.go:0:0:0:0 | test.go | | -| test.go:253:16:253:45 | type conversion | test.go:253:23:253:44 | call to GetCookie : string | test.go:253:16:253:45 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:253:23:253:44 | call to GetCookie | user-provided value | test.go:0:0:0:0 | test.go | | +| test.go:29:13:29:30 | type conversion | test.go:27:6:27:10 | definition of bound | test.go:29:13:29:30 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:27:6:27:10 | definition of bound | user-provided value | test.go:0:0:0:0 | test.go | | +| test.go:30:13:30:27 | type conversion | test.go:27:6:27:10 | definition of bound | test.go:30:13:30:27 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:27:6:27:10 | definition of bound | user-provided value | test.go:0:0:0:0 | test.go | | +| test.go:31:13:31:29 | type conversion | test.go:27:6:27:10 | definition of bound | test.go:31:13:31:29 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:27:6:27:10 | definition of bound | user-provided value | test.go:0:0:0:0 | test.go | | +| test.go:36:13:36:43 | type conversion | test.go:36:20:36:42 | call to Cookie | test.go:36:13:36:43 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:36:20:36:42 | call to Cookie | user-provided value | test.go:0:0:0:0 | test.go | | +| test.go:41:13:41:52 | type conversion | test.go:41:20:41:31 | call to Data | test.go:41:13:41:52 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:41:20:41:31 | call to Data | user-provided value | test.go:0:0:0:0 | test.go | | +| test.go:46:13:46:53 | type conversion | test.go:46:20:46:43 | call to GetData | test.go:46:13:46:53 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:46:20:46:43 | call to GetData | user-provided value | test.go:0:0:0:0 | test.go | | +| test.go:51:13:51:43 | type conversion | test.go:51:20:51:42 | call to Header | test.go:51:13:51:43 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:51:20:51:42 | call to Header | user-provided value | test.go:0:0:0:0 | test.go | | +| test.go:56:13:56:42 | type conversion | test.go:56:20:56:41 | call to Param | test.go:56:13:56:42 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:56:20:56:41 | call to Param | user-provided value | test.go:0:0:0:0 | test.go | | +| test.go:61:13:61:45 | type conversion | test.go:61:20:61:33 | call to Params | test.go:61:13:61:45 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:61:20:61:33 | call to Params | user-provided value | test.go:0:0:0:0 | test.go | | +| test.go:66:13:66:42 | type conversion | test.go:66:20:66:41 | call to Query | test.go:66:13:66:42 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:66:20:66:41 | call to Query | user-provided value | test.go:0:0:0:0 | test.go | | +| test.go:71:13:71:33 | type conversion | test.go:71:20:71:32 | call to Refer | test.go:71:13:71:33 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:71:20:71:32 | call to Refer | user-provided value | test.go:0:0:0:0 | test.go | | +| test.go:76:13:76:35 | type conversion | test.go:76:20:76:34 | call to Referer | test.go:76:13:76:35 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:76:20:76:34 | call to Referer | user-provided value | test.go:0:0:0:0 | test.go | | +| test.go:81:13:81:31 | type conversion | test.go:81:20:81:30 | call to URI | test.go:81:13:81:31 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:81:20:81:30 | call to URI | user-provided value | test.go:0:0:0:0 | test.go | | +| test.go:86:13:86:31 | type conversion | test.go:86:20:86:30 | call to URL | test.go:86:13:86:31 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:86:20:86:30 | call to URL | user-provided value | test.go:0:0:0:0 | test.go | | +| test.go:91:13:91:37 | type conversion | test.go:91:20:91:36 | call to UserAgent | test.go:91:13:91:37 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:91:20:91:36 | call to UserAgent | user-provided value | test.go:0:0:0:0 | test.go | | +| test.go:96:14:96:45 | type assertion | test.go:96:14:96:25 | call to Data | test.go:96:14:96:45 | type assertion | Cross-site scripting vulnerability due to $@. | test.go:96:14:96:25 | call to Data | user-provided value | test.go:0:0:0:0 | test.go | | +| test.go:108:14:108:45 | type assertion | test.go:108:14:108:25 | call to Data | test.go:108:14:108:45 | type assertion | Cross-site scripting vulnerability due to $@. | test.go:108:14:108:25 | call to Data | user-provided value | test.go:0:0:0:0 | test.go | | +| test.go:120:14:120:45 | type assertion | test.go:120:14:120:25 | call to Data | test.go:120:14:120:45 | type assertion | Cross-site scripting vulnerability due to $@. | test.go:120:14:120:25 | call to Data | user-provided value | test.go:0:0:0:0 | test.go | | +| test.go:137:23:137:62 | type assertion | test.go:137:23:137:42 | call to Data | test.go:137:23:137:62 | type assertion | Cross-site scripting vulnerability due to $@. | test.go:137:23:137:42 | call to Data | user-provided value | test.go:0:0:0:0 | test.go | | +| test.go:194:14:194:55 | type conversion | test.go:193:15:193:26 | call to Data | test.go:194:14:194:55 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:193:15:193:26 | call to Data | user-provided value | test.go:0:0:0:0 | test.go | | +| test.go:195:14:195:58 | type conversion | test.go:193:15:193:26 | call to Data | test.go:195:14:195:58 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:193:15:193:26 | call to Data | user-provided value | test.go:0:0:0:0 | test.go | | +| test.go:197:14:197:28 | type assertion | test.go:193:15:193:26 | call to Data | test.go:197:14:197:28 | type assertion | Cross-site scripting vulnerability due to $@. | test.go:193:15:193:26 | call to Data | user-provided value | test.go:0:0:0:0 | test.go | | +| test.go:198:14:198:55 | type conversion | test.go:193:15:193:26 | call to Data | test.go:198:14:198:55 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:193:15:193:26 | call to Data | user-provided value | test.go:0:0:0:0 | test.go | | +| test.go:199:14:199:59 | type conversion | test.go:193:15:193:26 | call to Data | test.go:199:14:199:59 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:193:15:193:26 | call to Data | user-provided value | test.go:0:0:0:0 | test.go | | +| test.go:203:14:203:28 | type conversion | test.go:202:18:202:33 | selection of Form | test.go:203:14:203:28 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:202:18:202:33 | selection of Form | user-provided value | test.go:0:0:0:0 | test.go | | +| test.go:218:14:218:32 | type conversion | test.go:217:2:217:34 | ... := ...[1] | test.go:218:14:218:32 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:217:2:217:34 | ... := ...[1] | user-provided value | test.go:0:0:0:0 | test.go | | +| test.go:220:14:220:20 | content | test.go:217:2:217:34 | ... := ...[0] | test.go:220:14:220:20 | content | Cross-site scripting vulnerability due to $@. | test.go:217:2:217:34 | ... := ...[0] | user-provided value | test.go:0:0:0:0 | test.go | | +| test.go:223:14:223:38 | type conversion | test.go:222:2:222:40 | ... := ...[0] | test.go:223:14:223:38 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:222:2:222:40 | ... := ...[0] | user-provided value | test.go:0:0:0:0 | test.go | | +| test.go:226:14:226:22 | type conversion | test.go:225:7:225:28 | call to GetString | test.go:226:14:226:22 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:225:7:225:28 | call to GetString | user-provided value | test.go:0:0:0:0 | test.go | | +| test.go:229:14:229:26 | type conversion | test.go:228:8:228:35 | call to GetStrings | test.go:229:14:229:26 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:228:8:228:35 | call to GetStrings | user-provided value | test.go:0:0:0:0 | test.go | | +| test.go:232:14:232:27 | type conversion | test.go:231:9:231:17 | call to Input | test.go:232:14:232:27 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:231:9:231:17 | call to Input | user-provided value | test.go:0:0:0:0 | test.go | | +| test.go:236:14:236:30 | type conversion | test.go:234:6:234:8 | definition of str | test.go:236:14:236:30 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:234:6:234:8 | definition of str | user-provided value | test.go:0:0:0:0 | test.go | | +| test.go:243:21:243:29 | untrusted | test.go:240:15:240:36 | call to GetString | test.go:243:21:243:29 | untrusted | Cross-site scripting vulnerability due to $@. | test.go:240:15:240:36 | call to GetString | user-provided value | test.go:0:0:0:0 | test.go | | +| test.go:253:16:253:45 | type conversion | test.go:253:23:253:44 | call to GetCookie | test.go:253:16:253:45 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:253:23:253:44 | call to GetCookie | user-provided value | test.go:0:0:0:0 | test.go | | | test.go:258:16:258:37 | call to GetCookie | test.go:258:16:258:37 | call to GetCookie | test.go:258:16:258:37 | call to GetCookie | Cross-site scripting vulnerability due to $@. | test.go:258:16:258:37 | call to GetCookie | user-provided value | test.go:0:0:0:0 | test.go | | | test.go:259:15:259:41 | call to GetCookie | test.go:259:15:259:41 | call to GetCookie | test.go:259:15:259:41 | call to GetCookie | Cross-site scripting vulnerability due to $@. | test.go:259:15:259:41 | call to GetCookie | user-provided value | test.go:0:0:0:0 | test.go | | -| test.go:264:55:264:84 | type conversion | test.go:264:62:264:83 | call to GetCookie : string | test.go:264:55:264:84 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:264:62:264:83 | call to GetCookie | user-provided value | test.go:0:0:0:0 | test.go | | -| test.go:277:21:277:61 | call to GetDisplayString | test.go:269:2:269:40 | ... := ...[0] : slice type | test.go:277:21:277:61 | call to GetDisplayString | Cross-site scripting vulnerability due to $@. | test.go:269:2:269:40 | ... := ...[0] | user-provided value | test.go:0:0:0:0 | test.go | | -| test.go:278:21:278:92 | selection of Filename | test.go:269:2:269:40 | ... := ...[0] : slice type | test.go:278:21:278:92 | selection of Filename | Cross-site scripting vulnerability due to $@. | test.go:269:2:269:40 | ... := ...[0] | user-provided value | test.go:0:0:0:0 | test.go | | -| test.go:279:21:279:96 | selection of Filename | test.go:269:2:269:40 | ... := ...[0] : slice type | test.go:279:21:279:96 | selection of Filename | Cross-site scripting vulnerability due to $@. | test.go:269:2:269:40 | ... := ...[0] | user-provided value | test.go:0:0:0:0 | test.go | | -| test.go:284:3:286:80 | selection of Filename | test.go:269:2:269:40 | ... := ...[0] : slice type | test.go:284:3:286:80 | selection of Filename | Cross-site scripting vulnerability due to $@. | test.go:269:2:269:40 | ... := ...[0] | user-provided value | test.go:0:0:0:0 | test.go | | -| test.go:287:21:287:101 | selection of Filename | test.go:269:2:269:40 | ... := ...[0] : slice type | test.go:287:21:287:101 | selection of Filename | Cross-site scripting vulnerability due to $@. | test.go:269:2:269:40 | ... := ...[0] | user-provided value | test.go:0:0:0:0 | test.go | | -| test.go:288:21:288:101 | selection of Filename | test.go:269:2:269:40 | ... := ...[0] : slice type | test.go:288:21:288:101 | selection of Filename | Cross-site scripting vulnerability due to $@. | test.go:269:2:269:40 | ... := ...[0] | user-provided value | test.go:0:0:0:0 | test.go | | -| test.go:289:21:289:97 | selection of Filename | test.go:269:2:269:40 | ... := ...[0] : slice type | test.go:289:21:289:97 | selection of Filename | Cross-site scripting vulnerability due to $@. | test.go:269:2:269:40 | ... := ...[0] | user-provided value | test.go:0:0:0:0 | test.go | | -| test.go:290:21:290:97 | selection of Filename | test.go:269:2:269:40 | ... := ...[0] : slice type | test.go:290:21:290:97 | selection of Filename | Cross-site scripting vulnerability due to $@. | test.go:269:2:269:40 | ... := ...[0] | user-provided value | test.go:0:0:0:0 | test.go | | -| test.go:291:21:291:102 | selection of Filename | test.go:269:2:269:40 | ... := ...[0] : slice type | test.go:291:21:291:102 | selection of Filename | Cross-site scripting vulnerability due to $@. | test.go:269:2:269:40 | ... := ...[0] | user-provided value | test.go:0:0:0:0 | test.go | | -| test.go:292:21:292:102 | selection of Filename | test.go:269:2:269:40 | ... := ...[0] : slice type | test.go:292:21:292:102 | selection of Filename | Cross-site scripting vulnerability due to $@. | test.go:269:2:269:40 | ... := ...[0] | user-provided value | test.go:0:0:0:0 | test.go | | -| test.go:293:21:293:82 | selection of Filename | test.go:269:2:269:40 | ... := ...[0] : slice type | test.go:293:21:293:82 | selection of Filename | Cross-site scripting vulnerability due to $@. | test.go:269:2:269:40 | ... := ...[0] | user-provided value | test.go:0:0:0:0 | test.go | | -| test.go:295:21:295:133 | selection of Filename | test.go:269:2:269:40 | ... := ...[0] : slice type | test.go:295:21:295:133 | selection of Filename | Cross-site scripting vulnerability due to $@. | test.go:269:2:269:40 | ... := ...[0] | user-provided value | test.go:0:0:0:0 | test.go | | -| test.go:296:21:296:88 | selection of Filename | test.go:269:2:269:40 | ... := ...[0] : slice type | test.go:296:21:296:88 | selection of Filename | Cross-site scripting vulnerability due to $@. | test.go:269:2:269:40 | ... := ...[0] | user-provided value | test.go:0:0:0:0 | test.go | | -| test.go:297:21:297:87 | selection of Filename | test.go:269:2:269:40 | ... := ...[0] : slice type | test.go:297:21:297:87 | selection of Filename | Cross-site scripting vulnerability due to $@. | test.go:269:2:269:40 | ... := ...[0] | user-provided value | test.go:0:0:0:0 | test.go | | -| test.go:305:21:305:48 | type assertion | test.go:303:15:303:36 | call to GetString : string | test.go:305:21:305:48 | type assertion | Cross-site scripting vulnerability due to $@. | test.go:303:15:303:36 | call to GetString | user-provided value | test.go:0:0:0:0 | test.go | | -| test.go:306:21:306:52 | type assertion | test.go:303:15:303:36 | call to GetString : string | test.go:306:21:306:52 | type assertion | Cross-site scripting vulnerability due to $@. | test.go:303:15:303:36 | call to GetString | user-provided value | test.go:0:0:0:0 | test.go | | +| test.go:264:55:264:84 | type conversion | test.go:264:62:264:83 | call to GetCookie | test.go:264:55:264:84 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:264:62:264:83 | call to GetCookie | user-provided value | test.go:0:0:0:0 | test.go | | +| test.go:277:21:277:61 | call to GetDisplayString | test.go:269:2:269:40 | ... := ...[0] | test.go:277:21:277:61 | call to GetDisplayString | Cross-site scripting vulnerability due to $@. | test.go:269:2:269:40 | ... := ...[0] | user-provided value | test.go:0:0:0:0 | test.go | | +| test.go:278:21:278:92 | selection of Filename | test.go:269:2:269:40 | ... := ...[0] | test.go:278:21:278:92 | selection of Filename | Cross-site scripting vulnerability due to $@. | test.go:269:2:269:40 | ... := ...[0] | user-provided value | test.go:0:0:0:0 | test.go | | +| test.go:279:21:279:96 | selection of Filename | test.go:269:2:269:40 | ... := ...[0] | test.go:279:21:279:96 | selection of Filename | Cross-site scripting vulnerability due to $@. | test.go:269:2:269:40 | ... := ...[0] | user-provided value | test.go:0:0:0:0 | test.go | | +| test.go:284:3:286:80 | selection of Filename | test.go:269:2:269:40 | ... := ...[0] | test.go:284:3:286:80 | selection of Filename | Cross-site scripting vulnerability due to $@. | test.go:269:2:269:40 | ... := ...[0] | user-provided value | test.go:0:0:0:0 | test.go | | +| test.go:287:21:287:101 | selection of Filename | test.go:269:2:269:40 | ... := ...[0] | test.go:287:21:287:101 | selection of Filename | Cross-site scripting vulnerability due to $@. | test.go:269:2:269:40 | ... := ...[0] | user-provided value | test.go:0:0:0:0 | test.go | | +| test.go:288:21:288:101 | selection of Filename | test.go:269:2:269:40 | ... := ...[0] | test.go:288:21:288:101 | selection of Filename | Cross-site scripting vulnerability due to $@. | test.go:269:2:269:40 | ... := ...[0] | user-provided value | test.go:0:0:0:0 | test.go | | +| test.go:289:21:289:97 | selection of Filename | test.go:269:2:269:40 | ... := ...[0] | test.go:289:21:289:97 | selection of Filename | Cross-site scripting vulnerability due to $@. | test.go:269:2:269:40 | ... := ...[0] | user-provided value | test.go:0:0:0:0 | test.go | | +| test.go:290:21:290:97 | selection of Filename | test.go:269:2:269:40 | ... := ...[0] | test.go:290:21:290:97 | selection of Filename | Cross-site scripting vulnerability due to $@. | test.go:269:2:269:40 | ... := ...[0] | user-provided value | test.go:0:0:0:0 | test.go | | +| test.go:291:21:291:102 | selection of Filename | test.go:269:2:269:40 | ... := ...[0] | test.go:291:21:291:102 | selection of Filename | Cross-site scripting vulnerability due to $@. | test.go:269:2:269:40 | ... := ...[0] | user-provided value | test.go:0:0:0:0 | test.go | | +| test.go:292:21:292:102 | selection of Filename | test.go:269:2:269:40 | ... := ...[0] | test.go:292:21:292:102 | selection of Filename | Cross-site scripting vulnerability due to $@. | test.go:269:2:269:40 | ... := ...[0] | user-provided value | test.go:0:0:0:0 | test.go | | +| test.go:293:21:293:82 | selection of Filename | test.go:269:2:269:40 | ... := ...[0] | test.go:293:21:293:82 | selection of Filename | Cross-site scripting vulnerability due to $@. | test.go:269:2:269:40 | ... := ...[0] | user-provided value | test.go:0:0:0:0 | test.go | | +| test.go:295:21:295:133 | selection of Filename | test.go:269:2:269:40 | ... := ...[0] | test.go:295:21:295:133 | selection of Filename | Cross-site scripting vulnerability due to $@. | test.go:269:2:269:40 | ... := ...[0] | user-provided value | test.go:0:0:0:0 | test.go | | +| test.go:296:21:296:88 | selection of Filename | test.go:269:2:269:40 | ... := ...[0] | test.go:296:21:296:88 | selection of Filename | Cross-site scripting vulnerability due to $@. | test.go:269:2:269:40 | ... := ...[0] | user-provided value | test.go:0:0:0:0 | test.go | | +| test.go:297:21:297:87 | selection of Filename | test.go:269:2:269:40 | ... := ...[0] | test.go:297:21:297:87 | selection of Filename | Cross-site scripting vulnerability due to $@. | test.go:269:2:269:40 | ... := ...[0] | user-provided value | test.go:0:0:0:0 | test.go | | +| test.go:305:21:305:48 | type assertion | test.go:303:15:303:36 | call to GetString | test.go:305:21:305:48 | type assertion | Cross-site scripting vulnerability due to $@. | test.go:303:15:303:36 | call to GetString | user-provided value | test.go:0:0:0:0 | test.go | | +| test.go:306:21:306:52 | type assertion | test.go:303:15:303:36 | call to GetString | test.go:306:21:306:52 | type assertion | Cross-site scripting vulnerability due to $@. | test.go:303:15:303:36 | call to GetString | user-provided value | test.go:0:0:0:0 | test.go | | diff --git a/go/ql/test/library-tests/semmle/go/frameworks/Beego/TaintedPath.expected b/go/ql/test/library-tests/semmle/go/frameworks/Beego/TaintedPath.expected index 116d5d44a6d..a84489df5bc 100644 --- a/go/ql/test/library-tests/semmle/go/frameworks/Beego/TaintedPath.expected +++ b/go/ql/test/library-tests/semmle/go/frameworks/Beego/TaintedPath.expected @@ -1,18 +1,18 @@ edges -| test.go:209:15:209:26 | call to Data : map type | test.go:210:18:210:26 | untrusted | -| test.go:209:15:209:26 | call to Data : map type | test.go:211:10:211:18 | untrusted | -| test.go:209:15:209:26 | call to Data : map type | test.go:212:35:212:43 | untrusted | -| test.go:318:17:318:37 | selection of RequestBody : slice type | test.go:320:35:320:43 | untrusted | +| test.go:209:15:209:26 | call to Data | test.go:210:18:210:26 | untrusted | +| test.go:209:15:209:26 | call to Data | test.go:211:10:211:18 | untrusted | +| test.go:209:15:209:26 | call to Data | test.go:212:35:212:43 | untrusted | +| test.go:318:17:318:37 | selection of RequestBody | test.go:320:35:320:43 | untrusted | nodes -| test.go:209:15:209:26 | call to Data : map type | semmle.label | call to Data : map type | +| test.go:209:15:209:26 | call to Data | semmle.label | call to Data | | test.go:210:18:210:26 | untrusted | semmle.label | untrusted | | test.go:211:10:211:18 | untrusted | semmle.label | untrusted | | test.go:212:35:212:43 | untrusted | semmle.label | untrusted | -| test.go:318:17:318:37 | selection of RequestBody : slice type | semmle.label | selection of RequestBody : slice type | +| test.go:318:17:318:37 | selection of RequestBody | semmle.label | selection of RequestBody | | test.go:320:35:320:43 | untrusted | semmle.label | untrusted | subpaths #select -| test.go:210:18:210:26 | untrusted | test.go:209:15:209:26 | call to Data : map type | test.go:210:18:210:26 | untrusted | This path depends on a $@. | test.go:209:15:209:26 | call to Data | user-provided value | -| test.go:211:10:211:18 | untrusted | test.go:209:15:209:26 | call to Data : map type | test.go:211:10:211:18 | untrusted | This path depends on a $@. | test.go:209:15:209:26 | call to Data | user-provided value | -| test.go:212:35:212:43 | untrusted | test.go:209:15:209:26 | call to Data : map type | test.go:212:35:212:43 | untrusted | This path depends on a $@. | test.go:209:15:209:26 | call to Data | user-provided value | -| test.go:320:35:320:43 | untrusted | test.go:318:17:318:37 | selection of RequestBody : slice type | test.go:320:35:320:43 | untrusted | This path depends on a $@. | test.go:318:17:318:37 | selection of RequestBody | user-provided value | +| test.go:210:18:210:26 | untrusted | test.go:209:15:209:26 | call to Data | test.go:210:18:210:26 | untrusted | This path depends on a $@. | test.go:209:15:209:26 | call to Data | user-provided value | +| test.go:211:10:211:18 | untrusted | test.go:209:15:209:26 | call to Data | test.go:211:10:211:18 | untrusted | This path depends on a $@. | test.go:209:15:209:26 | call to Data | user-provided value | +| test.go:212:35:212:43 | untrusted | test.go:209:15:209:26 | call to Data | test.go:212:35:212:43 | untrusted | This path depends on a $@. | test.go:209:15:209:26 | call to Data | user-provided value | +| test.go:320:35:320:43 | untrusted | test.go:318:17:318:37 | selection of RequestBody | test.go:320:35:320:43 | untrusted | This path depends on a $@. | test.go:318:17:318:37 | selection of RequestBody | user-provided value | diff --git a/go/ql/test/library-tests/semmle/go/frameworks/BeegoOrm/SqlInjection.expected b/go/ql/test/library-tests/semmle/go/frameworks/BeegoOrm/SqlInjection.expected index 873eed34f41..f9668a6f723 100644 --- a/go/ql/test/library-tests/semmle/go/frameworks/BeegoOrm/SqlInjection.expected +++ b/go/ql/test/library-tests/semmle/go/frameworks/BeegoOrm/SqlInjection.expected @@ -1,38 +1,38 @@ edges -| test.go:10:15:10:41 | call to UserAgent : string | test.go:12:11:12:19 | untrusted | -| test.go:10:15:10:41 | call to UserAgent : string | test.go:13:23:13:31 | untrusted | -| test.go:10:15:10:41 | call to UserAgent : string | test.go:14:14:14:22 | untrusted | -| test.go:10:15:10:41 | call to UserAgent : string | test.go:15:26:15:34 | untrusted | -| test.go:10:15:10:41 | call to UserAgent : string | test.go:16:12:16:20 | untrusted | -| test.go:10:15:10:41 | call to UserAgent : string | test.go:17:24:17:32 | untrusted | -| test.go:10:15:10:41 | call to UserAgent : string | test.go:18:15:18:23 | untrusted | -| test.go:10:15:10:41 | call to UserAgent : string | test.go:19:27:19:35 | untrusted | -| test.go:24:15:24:41 | call to UserAgent : string | test.go:26:12:26:20 | untrusted | -| test.go:24:15:24:41 | call to UserAgent : string | test.go:27:10:27:18 | untrusted | -| test.go:24:15:24:41 | call to UserAgent : string | test.go:28:15:28:23 | untrusted | -| test.go:24:15:24:41 | call to UserAgent : string | test.go:29:14:29:22 | untrusted | -| test.go:24:15:24:41 | call to UserAgent : string | test.go:30:15:30:23 | untrusted | -| test.go:24:15:24:41 | call to UserAgent : string | test.go:31:8:31:16 | untrusted | -| test.go:24:15:24:41 | call to UserAgent : string | test.go:32:11:32:19 | untrusted | -| test.go:24:15:24:41 | call to UserAgent : string | test.go:33:9:33:17 | untrusted | -| test.go:24:15:24:41 | call to UserAgent : string | test.go:34:8:34:16 | untrusted | -| test.go:24:15:24:41 | call to UserAgent : string | test.go:35:8:35:16 | untrusted | -| test.go:24:15:24:41 | call to UserAgent : string | test.go:36:13:36:21 | untrusted | -| test.go:24:15:24:41 | call to UserAgent : string | test.go:37:13:37:21 | untrusted | -| test.go:24:15:24:41 | call to UserAgent : string | test.go:38:12:38:20 | untrusted | -| test.go:24:15:24:41 | call to UserAgent : string | test.go:39:12:39:20 | untrusted | -| test.go:24:15:24:41 | call to UserAgent : string | test.go:40:9:40:17 | untrusted | -| test.go:24:15:24:41 | call to UserAgent : string | test.go:41:12:41:20 | untrusted | -| test.go:24:15:24:41 | call to UserAgent : string | test.go:42:16:42:24 | untrusted | -| test.go:24:15:24:41 | call to UserAgent : string | test.go:42:27:42:35 | untrusted | -| test.go:24:15:24:41 | call to UserAgent : string | test.go:43:12:43:20 | untrusted | -| test.go:24:15:24:41 | call to UserAgent : string | test.go:44:14:44:22 | untrusted | -| test.go:24:15:24:41 | call to UserAgent : string | test.go:44:25:44:33 | untrusted | -| test.go:48:15:48:41 | call to UserAgent : string | test.go:49:12:49:20 | untrusted | -| test.go:54:15:54:41 | call to UserAgent : string | test.go:56:31:56:39 | untrusted | -| test.go:60:15:60:41 | call to UserAgent : string | test.go:62:19:62:27 | untrusted | +| test.go:10:15:10:41 | call to UserAgent | test.go:12:11:12:19 | untrusted | +| test.go:10:15:10:41 | call to UserAgent | test.go:13:23:13:31 | untrusted | +| test.go:10:15:10:41 | call to UserAgent | test.go:14:14:14:22 | untrusted | +| test.go:10:15:10:41 | call to UserAgent | test.go:15:26:15:34 | untrusted | +| test.go:10:15:10:41 | call to UserAgent | test.go:16:12:16:20 | untrusted | +| test.go:10:15:10:41 | call to UserAgent | test.go:17:24:17:32 | untrusted | +| test.go:10:15:10:41 | call to UserAgent | test.go:18:15:18:23 | untrusted | +| test.go:10:15:10:41 | call to UserAgent | test.go:19:27:19:35 | untrusted | +| test.go:24:15:24:41 | call to UserAgent | test.go:26:12:26:20 | untrusted | +| test.go:24:15:24:41 | call to UserAgent | test.go:27:10:27:18 | untrusted | +| test.go:24:15:24:41 | call to UserAgent | test.go:28:15:28:23 | untrusted | +| test.go:24:15:24:41 | call to UserAgent | test.go:29:14:29:22 | untrusted | +| test.go:24:15:24:41 | call to UserAgent | test.go:30:15:30:23 | untrusted | +| test.go:24:15:24:41 | call to UserAgent | test.go:31:8:31:16 | untrusted | +| test.go:24:15:24:41 | call to UserAgent | test.go:32:11:32:19 | untrusted | +| test.go:24:15:24:41 | call to UserAgent | test.go:33:9:33:17 | untrusted | +| test.go:24:15:24:41 | call to UserAgent | test.go:34:8:34:16 | untrusted | +| test.go:24:15:24:41 | call to UserAgent | test.go:35:8:35:16 | untrusted | +| test.go:24:15:24:41 | call to UserAgent | test.go:36:13:36:21 | untrusted | +| test.go:24:15:24:41 | call to UserAgent | test.go:37:13:37:21 | untrusted | +| test.go:24:15:24:41 | call to UserAgent | test.go:38:12:38:20 | untrusted | +| test.go:24:15:24:41 | call to UserAgent | test.go:39:12:39:20 | untrusted | +| test.go:24:15:24:41 | call to UserAgent | test.go:40:9:40:17 | untrusted | +| test.go:24:15:24:41 | call to UserAgent | test.go:41:12:41:20 | untrusted | +| test.go:24:15:24:41 | call to UserAgent | test.go:42:16:42:24 | untrusted | +| test.go:24:15:24:41 | call to UserAgent | test.go:42:27:42:35 | untrusted | +| test.go:24:15:24:41 | call to UserAgent | test.go:43:12:43:20 | untrusted | +| test.go:24:15:24:41 | call to UserAgent | test.go:44:14:44:22 | untrusted | +| test.go:24:15:24:41 | call to UserAgent | test.go:44:25:44:33 | untrusted | +| test.go:48:15:48:41 | call to UserAgent | test.go:49:12:49:20 | untrusted | +| test.go:54:15:54:41 | call to UserAgent | test.go:56:31:56:39 | untrusted | +| test.go:60:15:60:41 | call to UserAgent | test.go:62:19:62:27 | untrusted | nodes -| test.go:10:15:10:41 | call to UserAgent : string | semmle.label | call to UserAgent : string | +| test.go:10:15:10:41 | call to UserAgent | semmle.label | call to UserAgent | | test.go:12:11:12:19 | untrusted | semmle.label | untrusted | | test.go:13:23:13:31 | untrusted | semmle.label | untrusted | | test.go:14:14:14:22 | untrusted | semmle.label | untrusted | @@ -41,7 +41,7 @@ nodes | test.go:17:24:17:32 | untrusted | semmle.label | untrusted | | test.go:18:15:18:23 | untrusted | semmle.label | untrusted | | test.go:19:27:19:35 | untrusted | semmle.label | untrusted | -| test.go:24:15:24:41 | call to UserAgent : string | semmle.label | call to UserAgent : string | +| test.go:24:15:24:41 | call to UserAgent | semmle.label | call to UserAgent | | test.go:26:12:26:20 | untrusted | semmle.label | untrusted | | test.go:27:10:27:18 | untrusted | semmle.label | untrusted | | test.go:28:15:28:23 | untrusted | semmle.label | untrusted | @@ -63,43 +63,43 @@ nodes | test.go:43:12:43:20 | untrusted | semmle.label | untrusted | | test.go:44:14:44:22 | untrusted | semmle.label | untrusted | | test.go:44:25:44:33 | untrusted | semmle.label | untrusted | -| test.go:48:15:48:41 | call to UserAgent : string | semmle.label | call to UserAgent : string | +| test.go:48:15:48:41 | call to UserAgent | semmle.label | call to UserAgent | | test.go:49:12:49:20 | untrusted | semmle.label | untrusted | -| test.go:54:15:54:41 | call to UserAgent : string | semmle.label | call to UserAgent : string | +| test.go:54:15:54:41 | call to UserAgent | semmle.label | call to UserAgent | | test.go:56:31:56:39 | untrusted | semmle.label | untrusted | -| test.go:60:15:60:41 | call to UserAgent : string | semmle.label | call to UserAgent : string | +| test.go:60:15:60:41 | call to UserAgent | semmle.label | call to UserAgent | | test.go:62:19:62:27 | untrusted | semmle.label | untrusted | subpaths #select -| test.go:12:11:12:19 | untrusted | test.go:10:15:10:41 | call to UserAgent : string | test.go:12:11:12:19 | untrusted | This query depends on a $@. | test.go:10:15:10:41 | call to UserAgent | user-provided value | -| test.go:13:23:13:31 | untrusted | test.go:10:15:10:41 | call to UserAgent : string | test.go:13:23:13:31 | untrusted | This query depends on a $@. | test.go:10:15:10:41 | call to UserAgent | user-provided value | -| test.go:14:14:14:22 | untrusted | test.go:10:15:10:41 | call to UserAgent : string | test.go:14:14:14:22 | untrusted | This query depends on a $@. | test.go:10:15:10:41 | call to UserAgent | user-provided value | -| test.go:15:26:15:34 | untrusted | test.go:10:15:10:41 | call to UserAgent : string | test.go:15:26:15:34 | untrusted | This query depends on a $@. | test.go:10:15:10:41 | call to UserAgent | user-provided value | -| test.go:16:12:16:20 | untrusted | test.go:10:15:10:41 | call to UserAgent : string | test.go:16:12:16:20 | untrusted | This query depends on a $@. | test.go:10:15:10:41 | call to UserAgent | user-provided value | -| test.go:17:24:17:32 | untrusted | test.go:10:15:10:41 | call to UserAgent : string | test.go:17:24:17:32 | untrusted | This query depends on a $@. | test.go:10:15:10:41 | call to UserAgent | user-provided value | -| test.go:18:15:18:23 | untrusted | test.go:10:15:10:41 | call to UserAgent : string | test.go:18:15:18:23 | untrusted | This query depends on a $@. | test.go:10:15:10:41 | call to UserAgent | user-provided value | -| test.go:19:27:19:35 | untrusted | test.go:10:15:10:41 | call to UserAgent : string | test.go:19:27:19:35 | untrusted | This query depends on a $@. | test.go:10:15:10:41 | call to UserAgent | user-provided value | -| test.go:26:12:26:20 | untrusted | test.go:24:15:24:41 | call to UserAgent : string | test.go:26:12:26:20 | untrusted | This query depends on a $@. | test.go:24:15:24:41 | call to UserAgent | user-provided value | -| test.go:27:10:27:18 | untrusted | test.go:24:15:24:41 | call to UserAgent : string | test.go:27:10:27:18 | untrusted | This query depends on a $@. | test.go:24:15:24:41 | call to UserAgent | user-provided value | -| test.go:28:15:28:23 | untrusted | test.go:24:15:24:41 | call to UserAgent : string | test.go:28:15:28:23 | untrusted | This query depends on a $@. | test.go:24:15:24:41 | call to UserAgent | user-provided value | -| test.go:29:14:29:22 | untrusted | test.go:24:15:24:41 | call to UserAgent : string | test.go:29:14:29:22 | untrusted | This query depends on a $@. | test.go:24:15:24:41 | call to UserAgent | user-provided value | -| test.go:30:15:30:23 | untrusted | test.go:24:15:24:41 | call to UserAgent : string | test.go:30:15:30:23 | untrusted | This query depends on a $@. | test.go:24:15:24:41 | call to UserAgent | user-provided value | -| test.go:31:8:31:16 | untrusted | test.go:24:15:24:41 | call to UserAgent : string | test.go:31:8:31:16 | untrusted | This query depends on a $@. | test.go:24:15:24:41 | call to UserAgent | user-provided value | -| test.go:32:11:32:19 | untrusted | test.go:24:15:24:41 | call to UserAgent : string | test.go:32:11:32:19 | untrusted | This query depends on a $@. | test.go:24:15:24:41 | call to UserAgent | user-provided value | -| test.go:33:9:33:17 | untrusted | test.go:24:15:24:41 | call to UserAgent : string | test.go:33:9:33:17 | untrusted | This query depends on a $@. | test.go:24:15:24:41 | call to UserAgent | user-provided value | -| test.go:34:8:34:16 | untrusted | test.go:24:15:24:41 | call to UserAgent : string | test.go:34:8:34:16 | untrusted | This query depends on a $@. | test.go:24:15:24:41 | call to UserAgent | user-provided value | -| test.go:35:8:35:16 | untrusted | test.go:24:15:24:41 | call to UserAgent : string | test.go:35:8:35:16 | untrusted | This query depends on a $@. | test.go:24:15:24:41 | call to UserAgent | user-provided value | -| test.go:36:13:36:21 | untrusted | test.go:24:15:24:41 | call to UserAgent : string | test.go:36:13:36:21 | untrusted | This query depends on a $@. | test.go:24:15:24:41 | call to UserAgent | user-provided value | -| test.go:37:13:37:21 | untrusted | test.go:24:15:24:41 | call to UserAgent : string | test.go:37:13:37:21 | untrusted | This query depends on a $@. | test.go:24:15:24:41 | call to UserAgent | user-provided value | -| test.go:38:12:38:20 | untrusted | test.go:24:15:24:41 | call to UserAgent : string | test.go:38:12:38:20 | untrusted | This query depends on a $@. | test.go:24:15:24:41 | call to UserAgent | user-provided value | -| test.go:39:12:39:20 | untrusted | test.go:24:15:24:41 | call to UserAgent : string | test.go:39:12:39:20 | untrusted | This query depends on a $@. | test.go:24:15:24:41 | call to UserAgent | user-provided value | -| test.go:40:9:40:17 | untrusted | test.go:24:15:24:41 | call to UserAgent : string | test.go:40:9:40:17 | untrusted | This query depends on a $@. | test.go:24:15:24:41 | call to UserAgent | user-provided value | -| test.go:41:12:41:20 | untrusted | test.go:24:15:24:41 | call to UserAgent : string | test.go:41:12:41:20 | untrusted | This query depends on a $@. | test.go:24:15:24:41 | call to UserAgent | user-provided value | -| test.go:42:16:42:24 | untrusted | test.go:24:15:24:41 | call to UserAgent : string | test.go:42:16:42:24 | untrusted | This query depends on a $@. | test.go:24:15:24:41 | call to UserAgent | user-provided value | -| test.go:42:27:42:35 | untrusted | test.go:24:15:24:41 | call to UserAgent : string | test.go:42:27:42:35 | untrusted | This query depends on a $@. | test.go:24:15:24:41 | call to UserAgent | user-provided value | -| test.go:43:12:43:20 | untrusted | test.go:24:15:24:41 | call to UserAgent : string | test.go:43:12:43:20 | untrusted | This query depends on a $@. | test.go:24:15:24:41 | call to UserAgent | user-provided value | -| test.go:44:14:44:22 | untrusted | test.go:24:15:24:41 | call to UserAgent : string | test.go:44:14:44:22 | untrusted | This query depends on a $@. | test.go:24:15:24:41 | call to UserAgent | user-provided value | -| test.go:44:25:44:33 | untrusted | test.go:24:15:24:41 | call to UserAgent : string | test.go:44:25:44:33 | untrusted | This query depends on a $@. | test.go:24:15:24:41 | call to UserAgent | user-provided value | -| test.go:49:12:49:20 | untrusted | test.go:48:15:48:41 | call to UserAgent : string | test.go:49:12:49:20 | untrusted | This query depends on a $@. | test.go:48:15:48:41 | call to UserAgent | user-provided value | -| test.go:56:31:56:39 | untrusted | test.go:54:15:54:41 | call to UserAgent : string | test.go:56:31:56:39 | untrusted | This query depends on a $@. | test.go:54:15:54:41 | call to UserAgent | user-provided value | -| test.go:62:19:62:27 | untrusted | test.go:60:15:60:41 | call to UserAgent : string | test.go:62:19:62:27 | untrusted | This query depends on a $@. | test.go:60:15:60:41 | call to UserAgent | user-provided value | +| test.go:12:11:12:19 | untrusted | test.go:10:15:10:41 | call to UserAgent | test.go:12:11:12:19 | untrusted | This query depends on a $@. | test.go:10:15:10:41 | call to UserAgent | user-provided value | +| test.go:13:23:13:31 | untrusted | test.go:10:15:10:41 | call to UserAgent | test.go:13:23:13:31 | untrusted | This query depends on a $@. | test.go:10:15:10:41 | call to UserAgent | user-provided value | +| test.go:14:14:14:22 | untrusted | test.go:10:15:10:41 | call to UserAgent | test.go:14:14:14:22 | untrusted | This query depends on a $@. | test.go:10:15:10:41 | call to UserAgent | user-provided value | +| test.go:15:26:15:34 | untrusted | test.go:10:15:10:41 | call to UserAgent | test.go:15:26:15:34 | untrusted | This query depends on a $@. | test.go:10:15:10:41 | call to UserAgent | user-provided value | +| test.go:16:12:16:20 | untrusted | test.go:10:15:10:41 | call to UserAgent | test.go:16:12:16:20 | untrusted | This query depends on a $@. | test.go:10:15:10:41 | call to UserAgent | user-provided value | +| test.go:17:24:17:32 | untrusted | test.go:10:15:10:41 | call to UserAgent | test.go:17:24:17:32 | untrusted | This query depends on a $@. | test.go:10:15:10:41 | call to UserAgent | user-provided value | +| test.go:18:15:18:23 | untrusted | test.go:10:15:10:41 | call to UserAgent | test.go:18:15:18:23 | untrusted | This query depends on a $@. | test.go:10:15:10:41 | call to UserAgent | user-provided value | +| test.go:19:27:19:35 | untrusted | test.go:10:15:10:41 | call to UserAgent | test.go:19:27:19:35 | untrusted | This query depends on a $@. | test.go:10:15:10:41 | call to UserAgent | user-provided value | +| test.go:26:12:26:20 | untrusted | test.go:24:15:24:41 | call to UserAgent | test.go:26:12:26:20 | untrusted | This query depends on a $@. | test.go:24:15:24:41 | call to UserAgent | user-provided value | +| test.go:27:10:27:18 | untrusted | test.go:24:15:24:41 | call to UserAgent | test.go:27:10:27:18 | untrusted | This query depends on a $@. | test.go:24:15:24:41 | call to UserAgent | user-provided value | +| test.go:28:15:28:23 | untrusted | test.go:24:15:24:41 | call to UserAgent | test.go:28:15:28:23 | untrusted | This query depends on a $@. | test.go:24:15:24:41 | call to UserAgent | user-provided value | +| test.go:29:14:29:22 | untrusted | test.go:24:15:24:41 | call to UserAgent | test.go:29:14:29:22 | untrusted | This query depends on a $@. | test.go:24:15:24:41 | call to UserAgent | user-provided value | +| test.go:30:15:30:23 | untrusted | test.go:24:15:24:41 | call to UserAgent | test.go:30:15:30:23 | untrusted | This query depends on a $@. | test.go:24:15:24:41 | call to UserAgent | user-provided value | +| test.go:31:8:31:16 | untrusted | test.go:24:15:24:41 | call to UserAgent | test.go:31:8:31:16 | untrusted | This query depends on a $@. | test.go:24:15:24:41 | call to UserAgent | user-provided value | +| test.go:32:11:32:19 | untrusted | test.go:24:15:24:41 | call to UserAgent | test.go:32:11:32:19 | untrusted | This query depends on a $@. | test.go:24:15:24:41 | call to UserAgent | user-provided value | +| test.go:33:9:33:17 | untrusted | test.go:24:15:24:41 | call to UserAgent | test.go:33:9:33:17 | untrusted | This query depends on a $@. | test.go:24:15:24:41 | call to UserAgent | user-provided value | +| test.go:34:8:34:16 | untrusted | test.go:24:15:24:41 | call to UserAgent | test.go:34:8:34:16 | untrusted | This query depends on a $@. | test.go:24:15:24:41 | call to UserAgent | user-provided value | +| test.go:35:8:35:16 | untrusted | test.go:24:15:24:41 | call to UserAgent | test.go:35:8:35:16 | untrusted | This query depends on a $@. | test.go:24:15:24:41 | call to UserAgent | user-provided value | +| test.go:36:13:36:21 | untrusted | test.go:24:15:24:41 | call to UserAgent | test.go:36:13:36:21 | untrusted | This query depends on a $@. | test.go:24:15:24:41 | call to UserAgent | user-provided value | +| test.go:37:13:37:21 | untrusted | test.go:24:15:24:41 | call to UserAgent | test.go:37:13:37:21 | untrusted | This query depends on a $@. | test.go:24:15:24:41 | call to UserAgent | user-provided value | +| test.go:38:12:38:20 | untrusted | test.go:24:15:24:41 | call to UserAgent | test.go:38:12:38:20 | untrusted | This query depends on a $@. | test.go:24:15:24:41 | call to UserAgent | user-provided value | +| test.go:39:12:39:20 | untrusted | test.go:24:15:24:41 | call to UserAgent | test.go:39:12:39:20 | untrusted | This query depends on a $@. | test.go:24:15:24:41 | call to UserAgent | user-provided value | +| test.go:40:9:40:17 | untrusted | test.go:24:15:24:41 | call to UserAgent | test.go:40:9:40:17 | untrusted | This query depends on a $@. | test.go:24:15:24:41 | call to UserAgent | user-provided value | +| test.go:41:12:41:20 | untrusted | test.go:24:15:24:41 | call to UserAgent | test.go:41:12:41:20 | untrusted | This query depends on a $@. | test.go:24:15:24:41 | call to UserAgent | user-provided value | +| test.go:42:16:42:24 | untrusted | test.go:24:15:24:41 | call to UserAgent | test.go:42:16:42:24 | untrusted | This query depends on a $@. | test.go:24:15:24:41 | call to UserAgent | user-provided value | +| test.go:42:27:42:35 | untrusted | test.go:24:15:24:41 | call to UserAgent | test.go:42:27:42:35 | untrusted | This query depends on a $@. | test.go:24:15:24:41 | call to UserAgent | user-provided value | +| test.go:43:12:43:20 | untrusted | test.go:24:15:24:41 | call to UserAgent | test.go:43:12:43:20 | untrusted | This query depends on a $@. | test.go:24:15:24:41 | call to UserAgent | user-provided value | +| test.go:44:14:44:22 | untrusted | test.go:24:15:24:41 | call to UserAgent | test.go:44:14:44:22 | untrusted | This query depends on a $@. | test.go:24:15:24:41 | call to UserAgent | user-provided value | +| test.go:44:25:44:33 | untrusted | test.go:24:15:24:41 | call to UserAgent | test.go:44:25:44:33 | untrusted | This query depends on a $@. | test.go:24:15:24:41 | call to UserAgent | user-provided value | +| test.go:49:12:49:20 | untrusted | test.go:48:15:48:41 | call to UserAgent | test.go:49:12:49:20 | untrusted | This query depends on a $@. | test.go:48:15:48:41 | call to UserAgent | user-provided value | +| test.go:56:31:56:39 | untrusted | test.go:54:15:54:41 | call to UserAgent | test.go:56:31:56:39 | untrusted | This query depends on a $@. | test.go:54:15:54:41 | call to UserAgent | user-provided value | +| test.go:62:19:62:27 | untrusted | test.go:60:15:60:41 | call to UserAgent | test.go:62:19:62:27 | untrusted | This query depends on a $@. | test.go:60:15:60:41 | call to UserAgent | user-provided value | diff --git a/go/ql/test/library-tests/semmle/go/frameworks/BeegoOrm/StoredXss.expected b/go/ql/test/library-tests/semmle/go/frameworks/BeegoOrm/StoredXss.expected index 502de21a22e..09a41c42fb2 100644 --- a/go/ql/test/library-tests/semmle/go/frameworks/BeegoOrm/StoredXss.expected +++ b/go/ql/test/library-tests/semmle/go/frameworks/BeegoOrm/StoredXss.expected @@ -1,111 +1,111 @@ edges -| test.go:77:13:77:16 | &... : pointer type | test.go:78:13:78:29 | type conversion | -| test.go:77:13:77:16 | &... : pointer type | test.go:79:13:79:43 | type conversion | -| test.go:82:22:82:26 | &... : pointer type | test.go:83:13:83:30 | type conversion | -| test.go:86:21:86:25 | &... : pointer type | test.go:87:13:87:30 | type conversion | -| test.go:92:20:92:36 | call to Value : string | test.go:92:13:92:37 | type conversion | -| test.go:93:20:93:39 | call to RawValue : basic interface type | test.go:93:13:93:49 | type conversion | -| test.go:94:20:94:37 | call to String : string | test.go:94:13:94:38 | type conversion | -| test.go:95:20:95:36 | call to Value : string | test.go:95:13:95:37 | type conversion | -| test.go:96:20:96:39 | call to RawValue : basic interface type | test.go:96:13:96:49 | type conversion | -| test.go:97:20:97:37 | call to String : string | test.go:97:13:97:38 | type conversion | -| test.go:98:20:98:37 | call to Value : string | test.go:98:13:98:38 | type conversion | -| test.go:99:20:99:40 | call to RawValue : basic interface type | test.go:99:13:99:50 | type conversion | -| test.go:100:20:100:38 | call to String : string | test.go:100:13:100:39 | type conversion | -| test.go:106:9:106:13 | &... : pointer type | test.go:107:13:107:33 | type conversion | -| test.go:110:9:110:12 | &... : pointer type | test.go:111:13:111:29 | type conversion | -| test.go:114:12:114:19 | &... : pointer type | test.go:115:13:115:48 | type conversion | -| test.go:118:16:118:24 | &... : pointer type | test.go:119:13:119:43 | type conversion | -| test.go:122:16:122:23 | &... : pointer type | test.go:123:13:123:39 | type conversion | -| test.go:126:15:126:24 | &... : pointer type | test.go:127:13:127:47 | type conversion | -| test.go:130:18:130:30 | &... : pointer type | test.go:131:13:131:38 | type conversion | -| test.go:137:12:137:19 | &... : pointer type | test.go:138:13:138:48 | type conversion | -| test.go:141:16:141:24 | &... : pointer type | test.go:142:13:142:43 | type conversion | -| test.go:145:16:145:23 | &... : pointer type | test.go:146:13:146:39 | type conversion | -| test.go:149:15:149:24 | &... : pointer type | test.go:150:13:150:47 | type conversion | -| test.go:153:18:153:30 | &... : pointer type | test.go:154:13:154:38 | type conversion | -| test.go:157:14:157:22 | &... : pointer type | test.go:158:13:158:28 | type conversion | -| test.go:161:15:161:24 | &... : pointer type | test.go:162:13:162:32 | type conversion | +| test.go:77:13:77:16 | &... | test.go:78:13:78:29 | type conversion | +| test.go:77:13:77:16 | &... | test.go:79:13:79:43 | type conversion | +| test.go:82:22:82:26 | &... | test.go:83:13:83:30 | type conversion | +| test.go:86:21:86:25 | &... | test.go:87:13:87:30 | type conversion | +| test.go:92:20:92:36 | call to Value | test.go:92:13:92:37 | type conversion | +| test.go:93:20:93:39 | call to RawValue | test.go:93:13:93:49 | type conversion | +| test.go:94:20:94:37 | call to String | test.go:94:13:94:38 | type conversion | +| test.go:95:20:95:36 | call to Value | test.go:95:13:95:37 | type conversion | +| test.go:96:20:96:39 | call to RawValue | test.go:96:13:96:49 | type conversion | +| test.go:97:20:97:37 | call to String | test.go:97:13:97:38 | type conversion | +| test.go:98:20:98:37 | call to Value | test.go:98:13:98:38 | type conversion | +| test.go:99:20:99:40 | call to RawValue | test.go:99:13:99:50 | type conversion | +| test.go:100:20:100:38 | call to String | test.go:100:13:100:39 | type conversion | +| test.go:106:9:106:13 | &... | test.go:107:13:107:33 | type conversion | +| test.go:110:9:110:12 | &... | test.go:111:13:111:29 | type conversion | +| test.go:114:12:114:19 | &... | test.go:115:13:115:48 | type conversion | +| test.go:118:16:118:24 | &... | test.go:119:13:119:43 | type conversion | +| test.go:122:16:122:23 | &... | test.go:123:13:123:39 | type conversion | +| test.go:126:15:126:24 | &... | test.go:127:13:127:47 | type conversion | +| test.go:130:18:130:30 | &... | test.go:131:13:131:38 | type conversion | +| test.go:137:12:137:19 | &... | test.go:138:13:138:48 | type conversion | +| test.go:141:16:141:24 | &... | test.go:142:13:142:43 | type conversion | +| test.go:145:16:145:23 | &... | test.go:146:13:146:39 | type conversion | +| test.go:149:15:149:24 | &... | test.go:150:13:150:47 | type conversion | +| test.go:153:18:153:30 | &... | test.go:154:13:154:38 | type conversion | +| test.go:157:14:157:22 | &... | test.go:158:13:158:28 | type conversion | +| test.go:161:15:161:24 | &... | test.go:162:13:162:32 | type conversion | nodes -| test.go:77:13:77:16 | &... : pointer type | semmle.label | &... : pointer type | +| test.go:77:13:77:16 | &... | semmle.label | &... | | test.go:78:13:78:29 | type conversion | semmle.label | type conversion | | test.go:79:13:79:43 | type conversion | semmle.label | type conversion | -| test.go:82:22:82:26 | &... : pointer type | semmle.label | &... : pointer type | +| test.go:82:22:82:26 | &... | semmle.label | &... | | test.go:83:13:83:30 | type conversion | semmle.label | type conversion | -| test.go:86:21:86:25 | &... : pointer type | semmle.label | &... : pointer type | +| test.go:86:21:86:25 | &... | semmle.label | &... | | test.go:87:13:87:30 | type conversion | semmle.label | type conversion | | test.go:92:13:92:37 | type conversion | semmle.label | type conversion | -| test.go:92:20:92:36 | call to Value : string | semmle.label | call to Value : string | +| test.go:92:20:92:36 | call to Value | semmle.label | call to Value | | test.go:93:13:93:49 | type conversion | semmle.label | type conversion | -| test.go:93:20:93:39 | call to RawValue : basic interface type | semmle.label | call to RawValue : basic interface type | +| test.go:93:20:93:39 | call to RawValue | semmle.label | call to RawValue | | test.go:94:13:94:38 | type conversion | semmle.label | type conversion | -| test.go:94:20:94:37 | call to String : string | semmle.label | call to String : string | +| test.go:94:20:94:37 | call to String | semmle.label | call to String | | test.go:95:13:95:37 | type conversion | semmle.label | type conversion | -| test.go:95:20:95:36 | call to Value : string | semmle.label | call to Value : string | +| test.go:95:20:95:36 | call to Value | semmle.label | call to Value | | test.go:96:13:96:49 | type conversion | semmle.label | type conversion | -| test.go:96:20:96:39 | call to RawValue : basic interface type | semmle.label | call to RawValue : basic interface type | +| test.go:96:20:96:39 | call to RawValue | semmle.label | call to RawValue | | test.go:97:13:97:38 | type conversion | semmle.label | type conversion | -| test.go:97:20:97:37 | call to String : string | semmle.label | call to String : string | +| test.go:97:20:97:37 | call to String | semmle.label | call to String | | test.go:98:13:98:38 | type conversion | semmle.label | type conversion | -| test.go:98:20:98:37 | call to Value : string | semmle.label | call to Value : string | +| test.go:98:20:98:37 | call to Value | semmle.label | call to Value | | test.go:99:13:99:50 | type conversion | semmle.label | type conversion | -| test.go:99:20:99:40 | call to RawValue : basic interface type | semmle.label | call to RawValue : basic interface type | +| test.go:99:20:99:40 | call to RawValue | semmle.label | call to RawValue | | test.go:100:13:100:39 | type conversion | semmle.label | type conversion | -| test.go:100:20:100:38 | call to String : string | semmle.label | call to String : string | -| test.go:106:9:106:13 | &... : pointer type | semmle.label | &... : pointer type | +| test.go:100:20:100:38 | call to String | semmle.label | call to String | +| test.go:106:9:106:13 | &... | semmle.label | &... | | test.go:107:13:107:33 | type conversion | semmle.label | type conversion | -| test.go:110:9:110:12 | &... : pointer type | semmle.label | &... : pointer type | +| test.go:110:9:110:12 | &... | semmle.label | &... | | test.go:111:13:111:29 | type conversion | semmle.label | type conversion | -| test.go:114:12:114:19 | &... : pointer type | semmle.label | &... : pointer type | +| test.go:114:12:114:19 | &... | semmle.label | &... | | test.go:115:13:115:48 | type conversion | semmle.label | type conversion | -| test.go:118:16:118:24 | &... : pointer type | semmle.label | &... : pointer type | +| test.go:118:16:118:24 | &... | semmle.label | &... | | test.go:119:13:119:43 | type conversion | semmle.label | type conversion | -| test.go:122:16:122:23 | &... : pointer type | semmle.label | &... : pointer type | +| test.go:122:16:122:23 | &... | semmle.label | &... | | test.go:123:13:123:39 | type conversion | semmle.label | type conversion | -| test.go:126:15:126:24 | &... : pointer type | semmle.label | &... : pointer type | +| test.go:126:15:126:24 | &... | semmle.label | &... | | test.go:127:13:127:47 | type conversion | semmle.label | type conversion | -| test.go:130:18:130:30 | &... : pointer type | semmle.label | &... : pointer type | +| test.go:130:18:130:30 | &... | semmle.label | &... | | test.go:131:13:131:38 | type conversion | semmle.label | type conversion | -| test.go:137:12:137:19 | &... : pointer type | semmle.label | &... : pointer type | +| test.go:137:12:137:19 | &... | semmle.label | &... | | test.go:138:13:138:48 | type conversion | semmle.label | type conversion | -| test.go:141:16:141:24 | &... : pointer type | semmle.label | &... : pointer type | +| test.go:141:16:141:24 | &... | semmle.label | &... | | test.go:142:13:142:43 | type conversion | semmle.label | type conversion | -| test.go:145:16:145:23 | &... : pointer type | semmle.label | &... : pointer type | +| test.go:145:16:145:23 | &... | semmle.label | &... | | test.go:146:13:146:39 | type conversion | semmle.label | type conversion | -| test.go:149:15:149:24 | &... : pointer type | semmle.label | &... : pointer type | +| test.go:149:15:149:24 | &... | semmle.label | &... | | test.go:150:13:150:47 | type conversion | semmle.label | type conversion | -| test.go:153:18:153:30 | &... : pointer type | semmle.label | &... : pointer type | +| test.go:153:18:153:30 | &... | semmle.label | &... | | test.go:154:13:154:38 | type conversion | semmle.label | type conversion | -| test.go:157:14:157:22 | &... : pointer type | semmle.label | &... : pointer type | +| test.go:157:14:157:22 | &... | semmle.label | &... | | test.go:158:13:158:28 | type conversion | semmle.label | type conversion | -| test.go:161:15:161:24 | &... : pointer type | semmle.label | &... : pointer type | +| test.go:161:15:161:24 | &... | semmle.label | &... | | test.go:162:13:162:32 | type conversion | semmle.label | type conversion | subpaths #select -| test.go:78:13:78:29 | type conversion | test.go:77:13:77:16 | &... : pointer type | test.go:78:13:78:29 | type conversion | Stored cross-site scripting vulnerability due to $@. | test.go:77:13:77:16 | &... | stored value | -| test.go:79:13:79:43 | type conversion | test.go:77:13:77:16 | &... : pointer type | test.go:79:13:79:43 | type conversion | Stored cross-site scripting vulnerability due to $@. | test.go:77:13:77:16 | &... | stored value | -| test.go:83:13:83:30 | type conversion | test.go:82:22:82:26 | &... : pointer type | test.go:83:13:83:30 | type conversion | Stored cross-site scripting vulnerability due to $@. | test.go:82:22:82:26 | &... | stored value | -| test.go:87:13:87:30 | type conversion | test.go:86:21:86:25 | &... : pointer type | test.go:87:13:87:30 | type conversion | Stored cross-site scripting vulnerability due to $@. | test.go:86:21:86:25 | &... | stored value | -| test.go:92:13:92:37 | type conversion | test.go:92:20:92:36 | call to Value : string | test.go:92:13:92:37 | type conversion | Stored cross-site scripting vulnerability due to $@. | test.go:92:20:92:36 | call to Value | stored value | -| test.go:93:13:93:49 | type conversion | test.go:93:20:93:39 | call to RawValue : basic interface type | test.go:93:13:93:49 | type conversion | Stored cross-site scripting vulnerability due to $@. | test.go:93:20:93:39 | call to RawValue | stored value | -| test.go:94:13:94:38 | type conversion | test.go:94:20:94:37 | call to String : string | test.go:94:13:94:38 | type conversion | Stored cross-site scripting vulnerability due to $@. | test.go:94:20:94:37 | call to String | stored value | -| test.go:95:13:95:37 | type conversion | test.go:95:20:95:36 | call to Value : string | test.go:95:13:95:37 | type conversion | Stored cross-site scripting vulnerability due to $@. | test.go:95:20:95:36 | call to Value | stored value | -| test.go:96:13:96:49 | type conversion | test.go:96:20:96:39 | call to RawValue : basic interface type | test.go:96:13:96:49 | type conversion | Stored cross-site scripting vulnerability due to $@. | test.go:96:20:96:39 | call to RawValue | stored value | -| test.go:97:13:97:38 | type conversion | test.go:97:20:97:37 | call to String : string | test.go:97:13:97:38 | type conversion | Stored cross-site scripting vulnerability due to $@. | test.go:97:20:97:37 | call to String | stored value | -| test.go:98:13:98:38 | type conversion | test.go:98:20:98:37 | call to Value : string | test.go:98:13:98:38 | type conversion | Stored cross-site scripting vulnerability due to $@. | test.go:98:20:98:37 | call to Value | stored value | -| test.go:99:13:99:50 | type conversion | test.go:99:20:99:40 | call to RawValue : basic interface type | test.go:99:13:99:50 | type conversion | Stored cross-site scripting vulnerability due to $@. | test.go:99:20:99:40 | call to RawValue | stored value | -| test.go:100:13:100:39 | type conversion | test.go:100:20:100:38 | call to String : string | test.go:100:13:100:39 | type conversion | Stored cross-site scripting vulnerability due to $@. | test.go:100:20:100:38 | call to String | stored value | -| test.go:107:13:107:33 | type conversion | test.go:106:9:106:13 | &... : pointer type | test.go:107:13:107:33 | type conversion | Stored cross-site scripting vulnerability due to $@. | test.go:106:9:106:13 | &... | stored value | -| test.go:111:13:111:29 | type conversion | test.go:110:9:110:12 | &... : pointer type | test.go:111:13:111:29 | type conversion | Stored cross-site scripting vulnerability due to $@. | test.go:110:9:110:12 | &... | stored value | -| test.go:115:13:115:48 | type conversion | test.go:114:12:114:19 | &... : pointer type | test.go:115:13:115:48 | type conversion | Stored cross-site scripting vulnerability due to $@. | test.go:114:12:114:19 | &... | stored value | -| test.go:119:13:119:43 | type conversion | test.go:118:16:118:24 | &... : pointer type | test.go:119:13:119:43 | type conversion | Stored cross-site scripting vulnerability due to $@. | test.go:118:16:118:24 | &... | stored value | -| test.go:123:13:123:39 | type conversion | test.go:122:16:122:23 | &... : pointer type | test.go:123:13:123:39 | type conversion | Stored cross-site scripting vulnerability due to $@. | test.go:122:16:122:23 | &... | stored value | -| test.go:127:13:127:47 | type conversion | test.go:126:15:126:24 | &... : pointer type | test.go:127:13:127:47 | type conversion | Stored cross-site scripting vulnerability due to $@. | test.go:126:15:126:24 | &... | stored value | -| test.go:131:13:131:38 | type conversion | test.go:130:18:130:30 | &... : pointer type | test.go:131:13:131:38 | type conversion | Stored cross-site scripting vulnerability due to $@. | test.go:130:18:130:30 | &... | stored value | -| test.go:138:13:138:48 | type conversion | test.go:137:12:137:19 | &... : pointer type | test.go:138:13:138:48 | type conversion | Stored cross-site scripting vulnerability due to $@. | test.go:137:12:137:19 | &... | stored value | -| test.go:142:13:142:43 | type conversion | test.go:141:16:141:24 | &... : pointer type | test.go:142:13:142:43 | type conversion | Stored cross-site scripting vulnerability due to $@. | test.go:141:16:141:24 | &... | stored value | -| test.go:146:13:146:39 | type conversion | test.go:145:16:145:23 | &... : pointer type | test.go:146:13:146:39 | type conversion | Stored cross-site scripting vulnerability due to $@. | test.go:145:16:145:23 | &... | stored value | -| test.go:150:13:150:47 | type conversion | test.go:149:15:149:24 | &... : pointer type | test.go:150:13:150:47 | type conversion | Stored cross-site scripting vulnerability due to $@. | test.go:149:15:149:24 | &... | stored value | -| test.go:154:13:154:38 | type conversion | test.go:153:18:153:30 | &... : pointer type | test.go:154:13:154:38 | type conversion | Stored cross-site scripting vulnerability due to $@. | test.go:153:18:153:30 | &... | stored value | -| test.go:158:13:158:28 | type conversion | test.go:157:14:157:22 | &... : pointer type | test.go:158:13:158:28 | type conversion | Stored cross-site scripting vulnerability due to $@. | test.go:157:14:157:22 | &... | stored value | -| test.go:162:13:162:32 | type conversion | test.go:161:15:161:24 | &... : pointer type | test.go:162:13:162:32 | type conversion | Stored cross-site scripting vulnerability due to $@. | test.go:161:15:161:24 | &... | stored value | +| test.go:78:13:78:29 | type conversion | test.go:77:13:77:16 | &... | test.go:78:13:78:29 | type conversion | Stored cross-site scripting vulnerability due to $@. | test.go:77:13:77:16 | &... | stored value | +| test.go:79:13:79:43 | type conversion | test.go:77:13:77:16 | &... | test.go:79:13:79:43 | type conversion | Stored cross-site scripting vulnerability due to $@. | test.go:77:13:77:16 | &... | stored value | +| test.go:83:13:83:30 | type conversion | test.go:82:22:82:26 | &... | test.go:83:13:83:30 | type conversion | Stored cross-site scripting vulnerability due to $@. | test.go:82:22:82:26 | &... | stored value | +| test.go:87:13:87:30 | type conversion | test.go:86:21:86:25 | &... | test.go:87:13:87:30 | type conversion | Stored cross-site scripting vulnerability due to $@. | test.go:86:21:86:25 | &... | stored value | +| test.go:92:13:92:37 | type conversion | test.go:92:20:92:36 | call to Value | test.go:92:13:92:37 | type conversion | Stored cross-site scripting vulnerability due to $@. | test.go:92:20:92:36 | call to Value | stored value | +| test.go:93:13:93:49 | type conversion | test.go:93:20:93:39 | call to RawValue | test.go:93:13:93:49 | type conversion | Stored cross-site scripting vulnerability due to $@. | test.go:93:20:93:39 | call to RawValue | stored value | +| test.go:94:13:94:38 | type conversion | test.go:94:20:94:37 | call to String | test.go:94:13:94:38 | type conversion | Stored cross-site scripting vulnerability due to $@. | test.go:94:20:94:37 | call to String | stored value | +| test.go:95:13:95:37 | type conversion | test.go:95:20:95:36 | call to Value | test.go:95:13:95:37 | type conversion | Stored cross-site scripting vulnerability due to $@. | test.go:95:20:95:36 | call to Value | stored value | +| test.go:96:13:96:49 | type conversion | test.go:96:20:96:39 | call to RawValue | test.go:96:13:96:49 | type conversion | Stored cross-site scripting vulnerability due to $@. | test.go:96:20:96:39 | call to RawValue | stored value | +| test.go:97:13:97:38 | type conversion | test.go:97:20:97:37 | call to String | test.go:97:13:97:38 | type conversion | Stored cross-site scripting vulnerability due to $@. | test.go:97:20:97:37 | call to String | stored value | +| test.go:98:13:98:38 | type conversion | test.go:98:20:98:37 | call to Value | test.go:98:13:98:38 | type conversion | Stored cross-site scripting vulnerability due to $@. | test.go:98:20:98:37 | call to Value | stored value | +| test.go:99:13:99:50 | type conversion | test.go:99:20:99:40 | call to RawValue | test.go:99:13:99:50 | type conversion | Stored cross-site scripting vulnerability due to $@. | test.go:99:20:99:40 | call to RawValue | stored value | +| test.go:100:13:100:39 | type conversion | test.go:100:20:100:38 | call to String | test.go:100:13:100:39 | type conversion | Stored cross-site scripting vulnerability due to $@. | test.go:100:20:100:38 | call to String | stored value | +| test.go:107:13:107:33 | type conversion | test.go:106:9:106:13 | &... | test.go:107:13:107:33 | type conversion | Stored cross-site scripting vulnerability due to $@. | test.go:106:9:106:13 | &... | stored value | +| test.go:111:13:111:29 | type conversion | test.go:110:9:110:12 | &... | test.go:111:13:111:29 | type conversion | Stored cross-site scripting vulnerability due to $@. | test.go:110:9:110:12 | &... | stored value | +| test.go:115:13:115:48 | type conversion | test.go:114:12:114:19 | &... | test.go:115:13:115:48 | type conversion | Stored cross-site scripting vulnerability due to $@. | test.go:114:12:114:19 | &... | stored value | +| test.go:119:13:119:43 | type conversion | test.go:118:16:118:24 | &... | test.go:119:13:119:43 | type conversion | Stored cross-site scripting vulnerability due to $@. | test.go:118:16:118:24 | &... | stored value | +| test.go:123:13:123:39 | type conversion | test.go:122:16:122:23 | &... | test.go:123:13:123:39 | type conversion | Stored cross-site scripting vulnerability due to $@. | test.go:122:16:122:23 | &... | stored value | +| test.go:127:13:127:47 | type conversion | test.go:126:15:126:24 | &... | test.go:127:13:127:47 | type conversion | Stored cross-site scripting vulnerability due to $@. | test.go:126:15:126:24 | &... | stored value | +| test.go:131:13:131:38 | type conversion | test.go:130:18:130:30 | &... | test.go:131:13:131:38 | type conversion | Stored cross-site scripting vulnerability due to $@. | test.go:130:18:130:30 | &... | stored value | +| test.go:138:13:138:48 | type conversion | test.go:137:12:137:19 | &... | test.go:138:13:138:48 | type conversion | Stored cross-site scripting vulnerability due to $@. | test.go:137:12:137:19 | &... | stored value | +| test.go:142:13:142:43 | type conversion | test.go:141:16:141:24 | &... | test.go:142:13:142:43 | type conversion | Stored cross-site scripting vulnerability due to $@. | test.go:141:16:141:24 | &... | stored value | +| test.go:146:13:146:39 | type conversion | test.go:145:16:145:23 | &... | test.go:146:13:146:39 | type conversion | Stored cross-site scripting vulnerability due to $@. | test.go:145:16:145:23 | &... | stored value | +| test.go:150:13:150:47 | type conversion | test.go:149:15:149:24 | &... | test.go:150:13:150:47 | type conversion | Stored cross-site scripting vulnerability due to $@. | test.go:149:15:149:24 | &... | stored value | +| test.go:154:13:154:38 | type conversion | test.go:153:18:153:30 | &... | test.go:154:13:154:38 | type conversion | Stored cross-site scripting vulnerability due to $@. | test.go:153:18:153:30 | &... | stored value | +| test.go:158:13:158:28 | type conversion | test.go:157:14:157:22 | &... | test.go:158:13:158:28 | type conversion | Stored cross-site scripting vulnerability due to $@. | test.go:157:14:157:22 | &... | stored value | +| test.go:162:13:162:32 | type conversion | test.go:161:15:161:24 | &... | test.go:162:13:162:32 | type conversion | Stored cross-site scripting vulnerability due to $@. | test.go:161:15:161:24 | &... | stored value | diff --git a/go/ql/test/library-tests/semmle/go/frameworks/Chi/ReflectedXss.expected b/go/ql/test/library-tests/semmle/go/frameworks/Chi/ReflectedXss.expected index 3c2812ee51a..cc6d95f8717 100644 --- a/go/ql/test/library-tests/semmle/go/frameworks/Chi/ReflectedXss.expected +++ b/go/ql/test/library-tests/semmle/go/frameworks/Chi/ReflectedXss.expected @@ -1,24 +1,24 @@ edges -| test.go:13:12:13:16 | selection of URL : pointer type | test.go:13:12:13:21 | selection of Path : string | -| test.go:13:12:13:21 | selection of Path : string | test.go:21:18:21:23 | hidden : string | -| test.go:21:18:21:23 | hidden : string | test.go:21:11:21:24 | type conversion | -| test.go:22:18:22:45 | call to URLParam : string | test.go:22:11:22:46 | type conversion | -| test.go:23:18:23:60 | call to URLParamFromCtx : string | test.go:23:11:23:61 | type conversion | -| test.go:24:18:24:71 | call to URLParam : string | test.go:24:11:24:72 | type conversion | +| test.go:13:12:13:16 | selection of URL | test.go:13:12:13:21 | selection of Path | +| test.go:13:12:13:21 | selection of Path | test.go:21:18:21:23 | hidden | +| test.go:21:18:21:23 | hidden | test.go:21:11:21:24 | type conversion | +| test.go:22:18:22:45 | call to URLParam | test.go:22:11:22:46 | type conversion | +| test.go:23:18:23:60 | call to URLParamFromCtx | test.go:23:11:23:61 | type conversion | +| test.go:24:18:24:71 | call to URLParam | test.go:24:11:24:72 | type conversion | nodes -| test.go:13:12:13:16 | selection of URL : pointer type | semmle.label | selection of URL : pointer type | -| test.go:13:12:13:21 | selection of Path : string | semmle.label | selection of Path : string | +| test.go:13:12:13:16 | selection of URL | semmle.label | selection of URL | +| test.go:13:12:13:21 | selection of Path | semmle.label | selection of Path | | test.go:21:11:21:24 | type conversion | semmle.label | type conversion | -| test.go:21:18:21:23 | hidden : string | semmle.label | hidden : string | +| test.go:21:18:21:23 | hidden | semmle.label | hidden | | test.go:22:11:22:46 | type conversion | semmle.label | type conversion | -| test.go:22:18:22:45 | call to URLParam : string | semmle.label | call to URLParam : string | +| test.go:22:18:22:45 | call to URLParam | semmle.label | call to URLParam | | test.go:23:11:23:61 | type conversion | semmle.label | type conversion | -| test.go:23:18:23:60 | call to URLParamFromCtx : string | semmle.label | call to URLParamFromCtx : string | +| test.go:23:18:23:60 | call to URLParamFromCtx | semmle.label | call to URLParamFromCtx | | test.go:24:11:24:72 | type conversion | semmle.label | type conversion | -| test.go:24:18:24:71 | call to URLParam : string | semmle.label | call to URLParam : string | +| test.go:24:18:24:71 | call to URLParam | semmle.label | call to URLParam | subpaths #select -| test.go:21:11:21:24 | type conversion | test.go:13:12:13:16 | selection of URL : pointer type | test.go:21:11:21:24 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:13:12:13:16 | selection of URL | user-provided value | test.go:0:0:0:0 | test.go | | -| test.go:22:11:22:46 | type conversion | test.go:22:18:22:45 | call to URLParam : string | test.go:22:11:22:46 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:22:18:22:45 | call to URLParam | user-provided value | test.go:0:0:0:0 | test.go | | -| test.go:23:11:23:61 | type conversion | test.go:23:18:23:60 | call to URLParamFromCtx : string | test.go:23:11:23:61 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:23:18:23:60 | call to URLParamFromCtx | user-provided value | test.go:0:0:0:0 | test.go | | -| test.go:24:11:24:72 | type conversion | test.go:24:18:24:71 | call to URLParam : string | test.go:24:11:24:72 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:24:18:24:71 | call to URLParam | user-provided value | test.go:0:0:0:0 | test.go | | +| test.go:21:11:21:24 | type conversion | test.go:13:12:13:16 | selection of URL | test.go:21:11:21:24 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:13:12:13:16 | selection of URL | user-provided value | test.go:0:0:0:0 | test.go | | +| test.go:22:11:22:46 | type conversion | test.go:22:18:22:45 | call to URLParam | test.go:22:11:22:46 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:22:18:22:45 | call to URLParam | user-provided value | test.go:0:0:0:0 | test.go | | +| test.go:23:11:23:61 | type conversion | test.go:23:18:23:60 | call to URLParamFromCtx | test.go:23:11:23:61 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:23:18:23:60 | call to URLParamFromCtx | user-provided value | test.go:0:0:0:0 | test.go | | +| test.go:24:11:24:72 | type conversion | test.go:24:18:24:71 | call to URLParam | test.go:24:11:24:72 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:24:18:24:71 | call to URLParam | user-provided value | test.go:0:0:0:0 | test.go | | diff --git a/go/ql/test/library-tests/semmle/go/frameworks/Echo/OpenRedirect.expected b/go/ql/test/library-tests/semmle/go/frameworks/Echo/OpenRedirect.expected index a51104dfa47..10ad0046423 100644 --- a/go/ql/test/library-tests/semmle/go/frameworks/Echo/OpenRedirect.expected +++ b/go/ql/test/library-tests/semmle/go/frameworks/Echo/OpenRedirect.expected @@ -1,18 +1,18 @@ edges -| test.go:170:11:170:32 | call to Param : string | test.go:171:20:171:24 | param | -| test.go:176:11:176:32 | call to Param : string | test.go:180:20:180:28 | ...+... | -| test.go:188:10:188:26 | selection of URL : pointer type | test.go:191:21:191:32 | call to String | -| test.go:188:10:188:26 | selection of URL : pointer type | test.go:191:21:191:32 | call to String | +| test.go:170:11:170:32 | call to Param | test.go:171:20:171:24 | param | +| test.go:176:11:176:32 | call to Param | test.go:180:20:180:28 | ...+... | +| test.go:188:10:188:26 | selection of URL | test.go:191:21:191:32 | call to String | +| test.go:188:10:188:26 | selection of URL | test.go:191:21:191:32 | call to String | nodes -| test.go:170:11:170:32 | call to Param : string | semmle.label | call to Param : string | +| test.go:170:11:170:32 | call to Param | semmle.label | call to Param | | test.go:171:20:171:24 | param | semmle.label | param | -| test.go:176:11:176:32 | call to Param : string | semmle.label | call to Param : string | +| test.go:176:11:176:32 | call to Param | semmle.label | call to Param | | test.go:180:20:180:28 | ...+... | semmle.label | ...+... | -| test.go:188:10:188:26 | selection of URL : pointer type | semmle.label | selection of URL : pointer type | -| test.go:188:10:188:26 | selection of URL : pointer type | semmle.label | selection of URL : pointer type | +| test.go:188:10:188:26 | selection of URL | semmle.label | selection of URL | +| test.go:188:10:188:26 | selection of URL | semmle.label | selection of URL | | test.go:191:21:191:32 | call to String | semmle.label | call to String | | test.go:191:21:191:32 | call to String | semmle.label | call to String | subpaths #select -| test.go:171:20:171:24 | param | test.go:170:11:170:32 | call to Param : string | test.go:171:20:171:24 | param | Untrusted URL redirection depends on a $@. | test.go:170:11:170:32 | call to Param | user-provided value | -| test.go:180:20:180:28 | ...+... | test.go:176:11:176:32 | call to Param : string | test.go:180:20:180:28 | ...+... | Untrusted URL redirection depends on a $@. | test.go:176:11:176:32 | call to Param | user-provided value | +| test.go:171:20:171:24 | param | test.go:170:11:170:32 | call to Param | test.go:171:20:171:24 | param | Untrusted URL redirection depends on a $@. | test.go:170:11:170:32 | call to Param | user-provided value | +| test.go:180:20:180:28 | ...+... | test.go:176:11:176:32 | call to Param | test.go:180:20:180:28 | ...+... | Untrusted URL redirection depends on a $@. | test.go:176:11:176:32 | call to Param | user-provided value | diff --git a/go/ql/test/library-tests/semmle/go/frameworks/Echo/ReflectedXss.expected b/go/ql/test/library-tests/semmle/go/frameworks/Echo/ReflectedXss.expected index 1e7a86c70cd..641ceddb08f 100644 --- a/go/ql/test/library-tests/semmle/go/frameworks/Echo/ReflectedXss.expected +++ b/go/ql/test/library-tests/semmle/go/frameworks/Echo/ReflectedXss.expected @@ -1,80 +1,80 @@ edges -| test.go:13:11:13:32 | call to Param : string | test.go:14:16:14:20 | param | -| test.go:19:11:19:27 | call to ParamValues : slice type | test.go:20:16:20:20 | param | -| test.go:25:11:25:37 | call to QueryParam : string | test.go:26:16:26:20 | param | -| test.go:31:11:31:27 | call to QueryParams : Values | test.go:32:16:32:20 | param | -| test.go:37:10:37:26 | call to QueryString : string | test.go:38:16:38:19 | qstr | -| test.go:43:9:43:34 | call to FormValue : string | test.go:44:16:44:18 | val | -| test.go:49:2:49:30 | ... := ...[0] : Values | test.go:50:16:50:37 | index expression | -| test.go:55:2:55:46 | ... := ...[0] : pointer type | test.go:59:20:59:25 | buffer | -| test.go:64:2:64:31 | ... := ...[0] : pointer type | test.go:65:16:65:41 | index expression | -| test.go:70:2:70:31 | ... := ...[0] : pointer type | test.go:75:20:75:25 | buffer | -| test.go:80:2:80:32 | ... := ...[0] : pointer type | test.go:81:16:81:24 | selection of Value | -| test.go:86:13:86:25 | call to Cookies : slice type | test.go:87:16:87:31 | selection of Value | -| test.go:97:11:97:15 | &... : pointer type | test.go:98:16:98:21 | selection of s | -| test.go:111:21:111:42 | call to Param : string | test.go:112:16:112:42 | type assertion | -| test.go:122:11:122:32 | call to Param : string | test.go:123:16:123:20 | param | -| test.go:128:11:128:32 | call to Param : string | test.go:129:20:129:32 | type conversion | -| test.go:134:11:134:32 | call to Param : string | test.go:135:29:135:41 | type conversion | -| test.go:146:11:146:32 | call to Param : string | test.go:148:31:148:36 | reader | -| test.go:162:11:162:32 | call to Param : string | test.go:163:23:163:35 | type conversion | +| test.go:13:11:13:32 | call to Param | test.go:14:16:14:20 | param | +| test.go:19:11:19:27 | call to ParamValues | test.go:20:16:20:20 | param | +| test.go:25:11:25:37 | call to QueryParam | test.go:26:16:26:20 | param | +| test.go:31:11:31:27 | call to QueryParams | test.go:32:16:32:20 | param | +| test.go:37:10:37:26 | call to QueryString | test.go:38:16:38:19 | qstr | +| test.go:43:9:43:34 | call to FormValue | test.go:44:16:44:18 | val | +| test.go:49:2:49:30 | ... := ...[0] | test.go:50:16:50:37 | index expression | +| test.go:55:2:55:46 | ... := ...[0] | test.go:59:20:59:25 | buffer | +| test.go:64:2:64:31 | ... := ...[0] | test.go:65:16:65:41 | index expression | +| test.go:70:2:70:31 | ... := ...[0] | test.go:75:20:75:25 | buffer | +| test.go:80:2:80:32 | ... := ...[0] | test.go:81:16:81:24 | selection of Value | +| test.go:86:13:86:25 | call to Cookies | test.go:87:16:87:31 | selection of Value | +| test.go:97:11:97:15 | &... | test.go:98:16:98:21 | selection of s | +| test.go:111:21:111:42 | call to Param | test.go:112:16:112:42 | type assertion | +| test.go:122:11:122:32 | call to Param | test.go:123:16:123:20 | param | +| test.go:128:11:128:32 | call to Param | test.go:129:20:129:32 | type conversion | +| test.go:134:11:134:32 | call to Param | test.go:135:29:135:41 | type conversion | +| test.go:146:11:146:32 | call to Param | test.go:148:31:148:36 | reader | +| test.go:162:11:162:32 | call to Param | test.go:163:23:163:35 | type conversion | nodes -| test.go:13:11:13:32 | call to Param : string | semmle.label | call to Param : string | +| test.go:13:11:13:32 | call to Param | semmle.label | call to Param | | test.go:14:16:14:20 | param | semmle.label | param | -| test.go:19:11:19:27 | call to ParamValues : slice type | semmle.label | call to ParamValues : slice type | +| test.go:19:11:19:27 | call to ParamValues | semmle.label | call to ParamValues | | test.go:20:16:20:20 | param | semmle.label | param | -| test.go:25:11:25:37 | call to QueryParam : string | semmle.label | call to QueryParam : string | +| test.go:25:11:25:37 | call to QueryParam | semmle.label | call to QueryParam | | test.go:26:16:26:20 | param | semmle.label | param | -| test.go:31:11:31:27 | call to QueryParams : Values | semmle.label | call to QueryParams : Values | +| test.go:31:11:31:27 | call to QueryParams | semmle.label | call to QueryParams | | test.go:32:16:32:20 | param | semmle.label | param | -| test.go:37:10:37:26 | call to QueryString : string | semmle.label | call to QueryString : string | +| test.go:37:10:37:26 | call to QueryString | semmle.label | call to QueryString | | test.go:38:16:38:19 | qstr | semmle.label | qstr | -| test.go:43:9:43:34 | call to FormValue : string | semmle.label | call to FormValue : string | +| test.go:43:9:43:34 | call to FormValue | semmle.label | call to FormValue | | test.go:44:16:44:18 | val | semmle.label | val | -| test.go:49:2:49:30 | ... := ...[0] : Values | semmle.label | ... := ...[0] : Values | +| test.go:49:2:49:30 | ... := ...[0] | semmle.label | ... := ...[0] | | test.go:50:16:50:37 | index expression | semmle.label | index expression | -| test.go:55:2:55:46 | ... := ...[0] : pointer type | semmle.label | ... := ...[0] : pointer type | +| test.go:55:2:55:46 | ... := ...[0] | semmle.label | ... := ...[0] | | test.go:59:20:59:25 | buffer | semmle.label | buffer | -| test.go:64:2:64:31 | ... := ...[0] : pointer type | semmle.label | ... := ...[0] : pointer type | +| test.go:64:2:64:31 | ... := ...[0] | semmle.label | ... := ...[0] | | test.go:65:16:65:41 | index expression | semmle.label | index expression | -| test.go:70:2:70:31 | ... := ...[0] : pointer type | semmle.label | ... := ...[0] : pointer type | +| test.go:70:2:70:31 | ... := ...[0] | semmle.label | ... := ...[0] | | test.go:75:20:75:25 | buffer | semmle.label | buffer | -| test.go:80:2:80:32 | ... := ...[0] : pointer type | semmle.label | ... := ...[0] : pointer type | +| test.go:80:2:80:32 | ... := ...[0] | semmle.label | ... := ...[0] | | test.go:81:16:81:24 | selection of Value | semmle.label | selection of Value | -| test.go:86:13:86:25 | call to Cookies : slice type | semmle.label | call to Cookies : slice type | +| test.go:86:13:86:25 | call to Cookies | semmle.label | call to Cookies | | test.go:87:16:87:31 | selection of Value | semmle.label | selection of Value | -| test.go:97:11:97:15 | &... : pointer type | semmle.label | &... : pointer type | +| test.go:97:11:97:15 | &... | semmle.label | &... | | test.go:98:16:98:21 | selection of s | semmle.label | selection of s | -| test.go:111:21:111:42 | call to Param : string | semmle.label | call to Param : string | +| test.go:111:21:111:42 | call to Param | semmle.label | call to Param | | test.go:112:16:112:42 | type assertion | semmle.label | type assertion | -| test.go:122:11:122:32 | call to Param : string | semmle.label | call to Param : string | +| test.go:122:11:122:32 | call to Param | semmle.label | call to Param | | test.go:123:16:123:20 | param | semmle.label | param | -| test.go:128:11:128:32 | call to Param : string | semmle.label | call to Param : string | +| test.go:128:11:128:32 | call to Param | semmle.label | call to Param | | test.go:129:20:129:32 | type conversion | semmle.label | type conversion | -| test.go:134:11:134:32 | call to Param : string | semmle.label | call to Param : string | +| test.go:134:11:134:32 | call to Param | semmle.label | call to Param | | test.go:135:29:135:41 | type conversion | semmle.label | type conversion | -| test.go:146:11:146:32 | call to Param : string | semmle.label | call to Param : string | +| test.go:146:11:146:32 | call to Param | semmle.label | call to Param | | test.go:148:31:148:36 | reader | semmle.label | reader | -| test.go:162:11:162:32 | call to Param : string | semmle.label | call to Param : string | +| test.go:162:11:162:32 | call to Param | semmle.label | call to Param | | test.go:163:23:163:35 | type conversion | semmle.label | type conversion | subpaths #select -| test.go:14:16:14:20 | param | test.go:13:11:13:32 | call to Param : string | test.go:14:16:14:20 | param | Cross-site scripting vulnerability due to $@. | test.go:13:11:13:32 | call to Param | user-provided value | test.go:0:0:0:0 | test.go | | -| test.go:20:16:20:20 | param | test.go:19:11:19:27 | call to ParamValues : slice type | test.go:20:16:20:20 | param | Cross-site scripting vulnerability due to $@. | test.go:19:11:19:27 | call to ParamValues | user-provided value | test.go:0:0:0:0 | test.go | | -| test.go:26:16:26:20 | param | test.go:25:11:25:37 | call to QueryParam : string | test.go:26:16:26:20 | param | Cross-site scripting vulnerability due to $@. | test.go:25:11:25:37 | call to QueryParam | user-provided value | test.go:0:0:0:0 | test.go | | -| test.go:32:16:32:20 | param | test.go:31:11:31:27 | call to QueryParams : Values | test.go:32:16:32:20 | param | Cross-site scripting vulnerability due to $@. | test.go:31:11:31:27 | call to QueryParams | user-provided value | test.go:0:0:0:0 | test.go | | -| test.go:38:16:38:19 | qstr | test.go:37:10:37:26 | call to QueryString : string | test.go:38:16:38:19 | qstr | Cross-site scripting vulnerability due to $@. | test.go:37:10:37:26 | call to QueryString | user-provided value | test.go:0:0:0:0 | test.go | | -| test.go:44:16:44:18 | val | test.go:43:9:43:34 | call to FormValue : string | test.go:44:16:44:18 | val | Cross-site scripting vulnerability due to $@. | test.go:43:9:43:34 | call to FormValue | user-provided value | test.go:0:0:0:0 | test.go | | -| test.go:50:16:50:37 | index expression | test.go:49:2:49:30 | ... := ...[0] : Values | test.go:50:16:50:37 | index expression | Cross-site scripting vulnerability due to $@. | test.go:49:2:49:30 | ... := ...[0] | user-provided value | test.go:0:0:0:0 | test.go | | -| test.go:59:20:59:25 | buffer | test.go:55:2:55:46 | ... := ...[0] : pointer type | test.go:59:20:59:25 | buffer | Cross-site scripting vulnerability due to $@. | test.go:55:2:55:46 | ... := ...[0] | user-provided value | test.go:0:0:0:0 | test.go | | -| test.go:65:16:65:41 | index expression | test.go:64:2:64:31 | ... := ...[0] : pointer type | test.go:65:16:65:41 | index expression | Cross-site scripting vulnerability due to $@. | test.go:64:2:64:31 | ... := ...[0] | user-provided value | test.go:0:0:0:0 | test.go | | -| test.go:75:20:75:25 | buffer | test.go:70:2:70:31 | ... := ...[0] : pointer type | test.go:75:20:75:25 | buffer | Cross-site scripting vulnerability due to $@. | test.go:70:2:70:31 | ... := ...[0] | user-provided value | test.go:0:0:0:0 | test.go | | -| test.go:81:16:81:24 | selection of Value | test.go:80:2:80:32 | ... := ...[0] : pointer type | test.go:81:16:81:24 | selection of Value | Cross-site scripting vulnerability due to $@. | test.go:80:2:80:32 | ... := ...[0] | user-provided value | test.go:0:0:0:0 | test.go | | -| test.go:87:16:87:31 | selection of Value | test.go:86:13:86:25 | call to Cookies : slice type | test.go:87:16:87:31 | selection of Value | Cross-site scripting vulnerability due to $@. | test.go:86:13:86:25 | call to Cookies | user-provided value | test.go:0:0:0:0 | test.go | | -| test.go:98:16:98:21 | selection of s | test.go:97:11:97:15 | &... : pointer type | test.go:98:16:98:21 | selection of s | Cross-site scripting vulnerability due to $@. | test.go:97:11:97:15 | &... | user-provided value | test.go:0:0:0:0 | test.go | | -| test.go:112:16:112:42 | type assertion | test.go:111:21:111:42 | call to Param : string | test.go:112:16:112:42 | type assertion | Cross-site scripting vulnerability due to $@. | test.go:111:21:111:42 | call to Param | user-provided value | test.go:0:0:0:0 | test.go | | -| test.go:123:16:123:20 | param | test.go:122:11:122:32 | call to Param : string | test.go:123:16:123:20 | param | Cross-site scripting vulnerability due to $@. | test.go:122:11:122:32 | call to Param | user-provided value | test.go:0:0:0:0 | test.go | | -| test.go:129:20:129:32 | type conversion | test.go:128:11:128:32 | call to Param : string | test.go:129:20:129:32 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:128:11:128:32 | call to Param | user-provided value | test.go:0:0:0:0 | test.go | | -| test.go:135:29:135:41 | type conversion | test.go:134:11:134:32 | call to Param : string | test.go:135:29:135:41 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:134:11:134:32 | call to Param | user-provided value | test.go:0:0:0:0 | test.go | | -| test.go:148:31:148:36 | reader | test.go:146:11:146:32 | call to Param : string | test.go:148:31:148:36 | reader | Cross-site scripting vulnerability due to $@. | test.go:146:11:146:32 | call to Param | user-provided value | test.go:0:0:0:0 | test.go | | -| test.go:163:23:163:35 | type conversion | test.go:162:11:162:32 | call to Param : string | test.go:163:23:163:35 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:162:11:162:32 | call to Param | user-provided value | test.go:0:0:0:0 | test.go | | +| test.go:14:16:14:20 | param | test.go:13:11:13:32 | call to Param | test.go:14:16:14:20 | param | Cross-site scripting vulnerability due to $@. | test.go:13:11:13:32 | call to Param | user-provided value | test.go:0:0:0:0 | test.go | | +| test.go:20:16:20:20 | param | test.go:19:11:19:27 | call to ParamValues | test.go:20:16:20:20 | param | Cross-site scripting vulnerability due to $@. | test.go:19:11:19:27 | call to ParamValues | user-provided value | test.go:0:0:0:0 | test.go | | +| test.go:26:16:26:20 | param | test.go:25:11:25:37 | call to QueryParam | test.go:26:16:26:20 | param | Cross-site scripting vulnerability due to $@. | test.go:25:11:25:37 | call to QueryParam | user-provided value | test.go:0:0:0:0 | test.go | | +| test.go:32:16:32:20 | param | test.go:31:11:31:27 | call to QueryParams | test.go:32:16:32:20 | param | Cross-site scripting vulnerability due to $@. | test.go:31:11:31:27 | call to QueryParams | user-provided value | test.go:0:0:0:0 | test.go | | +| test.go:38:16:38:19 | qstr | test.go:37:10:37:26 | call to QueryString | test.go:38:16:38:19 | qstr | Cross-site scripting vulnerability due to $@. | test.go:37:10:37:26 | call to QueryString | user-provided value | test.go:0:0:0:0 | test.go | | +| test.go:44:16:44:18 | val | test.go:43:9:43:34 | call to FormValue | test.go:44:16:44:18 | val | Cross-site scripting vulnerability due to $@. | test.go:43:9:43:34 | call to FormValue | user-provided value | test.go:0:0:0:0 | test.go | | +| test.go:50:16:50:37 | index expression | test.go:49:2:49:30 | ... := ...[0] | test.go:50:16:50:37 | index expression | Cross-site scripting vulnerability due to $@. | test.go:49:2:49:30 | ... := ...[0] | user-provided value | test.go:0:0:0:0 | test.go | | +| test.go:59:20:59:25 | buffer | test.go:55:2:55:46 | ... := ...[0] | test.go:59:20:59:25 | buffer | Cross-site scripting vulnerability due to $@. | test.go:55:2:55:46 | ... := ...[0] | user-provided value | test.go:0:0:0:0 | test.go | | +| test.go:65:16:65:41 | index expression | test.go:64:2:64:31 | ... := ...[0] | test.go:65:16:65:41 | index expression | Cross-site scripting vulnerability due to $@. | test.go:64:2:64:31 | ... := ...[0] | user-provided value | test.go:0:0:0:0 | test.go | | +| test.go:75:20:75:25 | buffer | test.go:70:2:70:31 | ... := ...[0] | test.go:75:20:75:25 | buffer | Cross-site scripting vulnerability due to $@. | test.go:70:2:70:31 | ... := ...[0] | user-provided value | test.go:0:0:0:0 | test.go | | +| test.go:81:16:81:24 | selection of Value | test.go:80:2:80:32 | ... := ...[0] | test.go:81:16:81:24 | selection of Value | Cross-site scripting vulnerability due to $@. | test.go:80:2:80:32 | ... := ...[0] | user-provided value | test.go:0:0:0:0 | test.go | | +| test.go:87:16:87:31 | selection of Value | test.go:86:13:86:25 | call to Cookies | test.go:87:16:87:31 | selection of Value | Cross-site scripting vulnerability due to $@. | test.go:86:13:86:25 | call to Cookies | user-provided value | test.go:0:0:0:0 | test.go | | +| test.go:98:16:98:21 | selection of s | test.go:97:11:97:15 | &... | test.go:98:16:98:21 | selection of s | Cross-site scripting vulnerability due to $@. | test.go:97:11:97:15 | &... | user-provided value | test.go:0:0:0:0 | test.go | | +| test.go:112:16:112:42 | type assertion | test.go:111:21:111:42 | call to Param | test.go:112:16:112:42 | type assertion | Cross-site scripting vulnerability due to $@. | test.go:111:21:111:42 | call to Param | user-provided value | test.go:0:0:0:0 | test.go | | +| test.go:123:16:123:20 | param | test.go:122:11:122:32 | call to Param | test.go:123:16:123:20 | param | Cross-site scripting vulnerability due to $@. | test.go:122:11:122:32 | call to Param | user-provided value | test.go:0:0:0:0 | test.go | | +| test.go:129:20:129:32 | type conversion | test.go:128:11:128:32 | call to Param | test.go:129:20:129:32 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:128:11:128:32 | call to Param | user-provided value | test.go:0:0:0:0 | test.go | | +| test.go:135:29:135:41 | type conversion | test.go:134:11:134:32 | call to Param | test.go:135:29:135:41 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:134:11:134:32 | call to Param | user-provided value | test.go:0:0:0:0 | test.go | | +| test.go:148:31:148:36 | reader | test.go:146:11:146:32 | call to Param | test.go:148:31:148:36 | reader | Cross-site scripting vulnerability due to $@. | test.go:146:11:146:32 | call to Param | user-provided value | test.go:0:0:0:0 | test.go | | +| test.go:163:23:163:35 | type conversion | test.go:162:11:162:32 | call to Param | test.go:163:23:163:35 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:162:11:162:32 | call to Param | user-provided value | test.go:0:0:0:0 | test.go | | diff --git a/go/ql/test/library-tests/semmle/go/frameworks/Encoding/jsoniter.expected b/go/ql/test/library-tests/semmle/go/frameworks/Encoding/jsoniter.expected index af6b671225b..54d739e8a90 100644 --- a/go/ql/test/library-tests/semmle/go/frameworks/Encoding/jsoniter.expected +++ b/go/ql/test/library-tests/semmle/go/frameworks/Encoding/jsoniter.expected @@ -1,4 +1,4 @@ -| jsoniter.go:28:15:28:24 | selection of field | jsoniter.go:23:20:23:38 | call to getUntrustedBytes : slice type | jsoniter.go:28:15:28:24 | selection of field | This command depends on $@. | jsoniter.go:23:20:23:38 | call to getUntrustedBytes | a user-provided value | -| jsoniter.go:32:15:32:25 | selection of field | jsoniter.go:23:20:23:38 | call to getUntrustedBytes : slice type | jsoniter.go:32:15:32:25 | selection of field | This command depends on $@. | jsoniter.go:23:20:23:38 | call to getUntrustedBytes | a user-provided value | -| jsoniter.go:36:15:36:25 | selection of field | jsoniter.go:24:21:24:40 | call to getUntrustedString : string | jsoniter.go:36:15:36:25 | selection of field | This command depends on $@. | jsoniter.go:24:21:24:40 | call to getUntrustedString | a user-provided value | -| jsoniter.go:40:15:40:25 | selection of field | jsoniter.go:24:21:24:40 | call to getUntrustedString : string | jsoniter.go:40:15:40:25 | selection of field | This command depends on $@. | jsoniter.go:24:21:24:40 | call to getUntrustedString | a user-provided value | +| jsoniter.go:28:15:28:24 | selection of field | jsoniter.go:23:20:23:38 | call to getUntrustedBytes | jsoniter.go:28:15:28:24 | selection of field | This command depends on $@. | jsoniter.go:23:20:23:38 | call to getUntrustedBytes | a user-provided value | +| jsoniter.go:32:15:32:25 | selection of field | jsoniter.go:23:20:23:38 | call to getUntrustedBytes | jsoniter.go:32:15:32:25 | selection of field | This command depends on $@. | jsoniter.go:23:20:23:38 | call to getUntrustedBytes | a user-provided value | +| jsoniter.go:36:15:36:25 | selection of field | jsoniter.go:24:21:24:40 | call to getUntrustedString | jsoniter.go:36:15:36:25 | selection of field | This command depends on $@. | jsoniter.go:24:21:24:40 | call to getUntrustedString | a user-provided value | +| jsoniter.go:40:15:40:25 | selection of field | jsoniter.go:24:21:24:40 | call to getUntrustedString | jsoniter.go:40:15:40:25 | selection of field | This command depends on $@. | jsoniter.go:24:21:24:40 | call to getUntrustedString | a user-provided value | diff --git a/go/ql/test/library-tests/semmle/go/frameworks/Gorestful/gorestful.expected b/go/ql/test/library-tests/semmle/go/frameworks/Gorestful/gorestful.expected index 4c252dadb93..e60cc051e17 100644 --- a/go/ql/test/library-tests/semmle/go/frameworks/Gorestful/gorestful.expected +++ b/go/ql/test/library-tests/semmle/go/frameworks/Gorestful/gorestful.expected @@ -1,14 +1,14 @@ -| gorestful.go:15:15:15:47 | index expression | gorestful.go:15:15:15:44 | call to QueryParameters : slice type | gorestful.go:15:15:15:47 | index expression | This command depends on $@. | gorestful.go:15:15:15:44 | call to QueryParameters | a user-provided value | +| gorestful.go:15:15:15:47 | index expression | gorestful.go:15:15:15:44 | call to QueryParameters | gorestful.go:15:15:15:47 | index expression | This command depends on $@. | gorestful.go:15:15:15:44 | call to QueryParameters | a user-provided value | | gorestful.go:16:15:16:43 | call to QueryParameter | gorestful.go:16:15:16:43 | call to QueryParameter | gorestful.go:16:15:16:43 | call to QueryParameter | This command depends on $@. | gorestful.go:16:15:16:43 | call to QueryParameter | a user-provided value | -| gorestful.go:18:15:18:17 | val | gorestful.go:17:12:17:39 | call to BodyParameter : tuple type | gorestful.go:18:15:18:17 | val | This command depends on $@. | gorestful.go:17:12:17:39 | call to BodyParameter | a user-provided value | +| gorestful.go:18:15:18:17 | val | gorestful.go:17:12:17:39 | call to BodyParameter | gorestful.go:18:15:18:17 | val | This command depends on $@. | gorestful.go:17:12:17:39 | call to BodyParameter | a user-provided value | | gorestful.go:19:15:19:44 | call to HeaderParameter | gorestful.go:19:15:19:44 | call to HeaderParameter | gorestful.go:19:15:19:44 | call to HeaderParameter | This command depends on $@. | gorestful.go:19:15:19:44 | call to HeaderParameter | a user-provided value | | gorestful.go:20:15:20:42 | call to PathParameter | gorestful.go:20:15:20:42 | call to PathParameter | gorestful.go:20:15:20:42 | call to PathParameter | This command depends on $@. | gorestful.go:20:15:20:42 | call to PathParameter | a user-provided value | -| gorestful.go:21:15:21:45 | index expression | gorestful.go:21:15:21:38 | call to PathParameters : map type | gorestful.go:21:15:21:45 | index expression | This command depends on $@. | gorestful.go:21:15:21:38 | call to PathParameters | a user-provided value | -| gorestful.go:24:15:24:21 | selection of cmd | gorestful.go:23:21:23:24 | &... : pointer type | gorestful.go:24:15:24:21 | selection of cmd | This command depends on $@. | gorestful.go:23:21:23:24 | &... | a user-provided value | -| gorestful_v2.go:15:15:15:47 | index expression | gorestful_v2.go:15:15:15:44 | call to QueryParameters : slice type | gorestful_v2.go:15:15:15:47 | index expression | This command depends on $@. | gorestful_v2.go:15:15:15:44 | call to QueryParameters | a user-provided value | +| gorestful.go:21:15:21:45 | index expression | gorestful.go:21:15:21:38 | call to PathParameters | gorestful.go:21:15:21:45 | index expression | This command depends on $@. | gorestful.go:21:15:21:38 | call to PathParameters | a user-provided value | +| gorestful.go:24:15:24:21 | selection of cmd | gorestful.go:23:21:23:24 | &... | gorestful.go:24:15:24:21 | selection of cmd | This command depends on $@. | gorestful.go:23:21:23:24 | &... | a user-provided value | +| gorestful_v2.go:15:15:15:47 | index expression | gorestful_v2.go:15:15:15:44 | call to QueryParameters | gorestful_v2.go:15:15:15:47 | index expression | This command depends on $@. | gorestful_v2.go:15:15:15:44 | call to QueryParameters | a user-provided value | | gorestful_v2.go:16:15:16:43 | call to QueryParameter | gorestful_v2.go:16:15:16:43 | call to QueryParameter | gorestful_v2.go:16:15:16:43 | call to QueryParameter | This command depends on $@. | gorestful_v2.go:16:15:16:43 | call to QueryParameter | a user-provided value | -| gorestful_v2.go:18:15:18:17 | val | gorestful_v2.go:17:12:17:39 | call to BodyParameter : tuple type | gorestful_v2.go:18:15:18:17 | val | This command depends on $@. | gorestful_v2.go:17:12:17:39 | call to BodyParameter | a user-provided value | +| gorestful_v2.go:18:15:18:17 | val | gorestful_v2.go:17:12:17:39 | call to BodyParameter | gorestful_v2.go:18:15:18:17 | val | This command depends on $@. | gorestful_v2.go:17:12:17:39 | call to BodyParameter | a user-provided value | | gorestful_v2.go:19:15:19:44 | call to HeaderParameter | gorestful_v2.go:19:15:19:44 | call to HeaderParameter | gorestful_v2.go:19:15:19:44 | call to HeaderParameter | This command depends on $@. | gorestful_v2.go:19:15:19:44 | call to HeaderParameter | a user-provided value | | gorestful_v2.go:20:15:20:42 | call to PathParameter | gorestful_v2.go:20:15:20:42 | call to PathParameter | gorestful_v2.go:20:15:20:42 | call to PathParameter | This command depends on $@. | gorestful_v2.go:20:15:20:42 | call to PathParameter | a user-provided value | -| gorestful_v2.go:21:15:21:45 | index expression | gorestful_v2.go:21:15:21:38 | call to PathParameters : map type | gorestful_v2.go:21:15:21:45 | index expression | This command depends on $@. | gorestful_v2.go:21:15:21:38 | call to PathParameters | a user-provided value | -| gorestful_v2.go:24:15:24:21 | selection of cmd | gorestful_v2.go:23:21:23:24 | &... : pointer type | gorestful_v2.go:24:15:24:21 | selection of cmd | This command depends on $@. | gorestful_v2.go:23:21:23:24 | &... | a user-provided value | +| gorestful_v2.go:21:15:21:45 | index expression | gorestful_v2.go:21:15:21:38 | call to PathParameters | gorestful_v2.go:21:15:21:45 | index expression | This command depends on $@. | gorestful_v2.go:21:15:21:38 | call to PathParameters | a user-provided value | +| gorestful_v2.go:24:15:24:21 | selection of cmd | gorestful_v2.go:23:21:23:24 | &... | gorestful_v2.go:24:15:24:21 | selection of cmd | This command depends on $@. | gorestful_v2.go:23:21:23:24 | &... | a user-provided value | diff --git a/go/ql/test/library-tests/semmle/go/frameworks/Protobuf/TaintFlows.expected b/go/ql/test/library-tests/semmle/go/frameworks/Protobuf/TaintFlows.expected index b8d9451ba37..4c70d92720b 100644 --- a/go/ql/test/library-tests/semmle/go/frameworks/Protobuf/TaintFlows.expected +++ b/go/ql/test/library-tests/semmle/go/frameworks/Protobuf/TaintFlows.expected @@ -1,33 +1,33 @@ -| testDeprecatedApi.go:22:22:22:41 | call to getUntrustedString : string | testDeprecatedApi.go:26:12:26:21 | serialized | -| testDeprecatedApi.go:31:22:31:41 | call to getUntrustedString : string | testDeprecatedApi.go:37:12:37:21 | serialized | -| testDeprecatedApi.go:41:25:41:43 | call to getUntrustedBytes : slice type | testDeprecatedApi.go:45:13:45:29 | selection of Description | -| testDeprecatedApi.go:49:25:49:43 | call to getUntrustedBytes : slice type | testDeprecatedApi.go:53:13:53:34 | call to GetDescription | -| testDeprecatedApi.go:58:23:58:42 | call to getUntrustedString : string | testDeprecatedApi.go:65:12:65:21 | serialized | -| testDeprecatedApi.go:70:14:70:33 | call to getUntrustedString : string | testDeprecatedApi.go:77:12:77:21 | serialized | -| testDeprecatedApi.go:85:24:85:43 | call to getUntrustedString : string | testDeprecatedApi.go:89:12:89:21 | serialized | -| testDeprecatedApi.go:93:25:93:43 | call to getUntrustedBytes : slice type | testDeprecatedApi.go:97:13:97:31 | selection of Msg | -| testDeprecatedApi.go:104:22:104:41 | call to getUntrustedString : string | testDeprecatedApi.go:105:13:105:20 | selection of Id | -| testDeprecatedApi.go:112:22:112:41 | call to getUntrustedString : string | testDeprecatedApi.go:117:12:117:21 | serialized | -| testDeprecatedApi.go:133:29:133:48 | call to getUntrustedString : string | testDeprecatedApi.go:137:12:137:21 | serialized | -| testDeprecatedApi.go:143:20:143:39 | call to getUntrustedString : string | testDeprecatedApi.go:148:12:148:21 | serialized | -| testDeprecatedApi.go:152:25:152:43 | call to getUntrustedBytes : slice type | testDeprecatedApi.go:157:13:157:36 | index expression | -| testDeprecatedApi.go:161:25:161:43 | call to getUntrustedBytes : slice type | testDeprecatedApi.go:168:13:168:25 | index expression | -| testDeprecatedApi.go:176:24:176:43 | call to getUntrustedString : string | testDeprecatedApi.go:180:12:180:21 | serialized | -| testModernApi.go:11:22:11:41 | call to getUntrustedString : string | testModernApi.go:15:12:15:21 | serialized | -| testModernApi.go:20:22:20:41 | call to getUntrustedString : string | testModernApi.go:26:12:26:21 | serialized | -| testModernApi.go:30:25:30:43 | call to getUntrustedBytes : slice type | testModernApi.go:34:13:34:29 | selection of Description | -| testModernApi.go:38:25:38:43 | call to getUntrustedBytes : slice type | testModernApi.go:42:13:42:34 | call to GetDescription | -| testModernApi.go:47:23:47:42 | call to getUntrustedString : string | testModernApi.go:54:12:54:21 | serialized | -| testModernApi.go:59:22:59:41 | call to getUntrustedString : string | testModernApi.go:64:12:64:21 | serialized | -| testModernApi.go:71:22:71:41 | call to getUntrustedString : string | testModernApi.go:77:12:77:21 | serialized | -| testModernApi.go:98:14:98:33 | call to getUntrustedString : string | testModernApi.go:105:12:105:21 | serialized | -| testModernApi.go:113:24:113:43 | call to getUntrustedString : string | testModernApi.go:117:12:117:21 | serialized | -| testModernApi.go:121:25:121:43 | call to getUntrustedBytes : slice type | testModernApi.go:125:13:125:31 | selection of Msg | -| testModernApi.go:131:25:131:43 | call to getUntrustedBytes : slice type | testModernApi.go:135:13:135:29 | selection of Description | -| testModernApi.go:142:22:142:41 | call to getUntrustedString : string | testModernApi.go:143:13:143:20 | selection of Id | -| testModernApi.go:150:22:150:41 | call to getUntrustedString : string | testModernApi.go:155:12:155:21 | serialized | -| testModernApi.go:190:29:190:48 | call to getUntrustedString : string | testModernApi.go:194:12:194:21 | serialized | -| testModernApi.go:200:20:200:39 | call to getUntrustedString : string | testModernApi.go:205:12:205:21 | serialized | -| testModernApi.go:209:25:209:43 | call to getUntrustedBytes : slice type | testModernApi.go:214:13:214:36 | index expression | -| testModernApi.go:218:25:218:43 | call to getUntrustedBytes : slice type | testModernApi.go:225:13:225:25 | index expression | -| testModernApi.go:233:24:233:43 | call to getUntrustedString : string | testModernApi.go:237:12:237:21 | serialized | +| testDeprecatedApi.go:22:22:22:41 | call to getUntrustedString | testDeprecatedApi.go:26:12:26:21 | serialized | +| testDeprecatedApi.go:31:22:31:41 | call to getUntrustedString | testDeprecatedApi.go:37:12:37:21 | serialized | +| testDeprecatedApi.go:41:25:41:43 | call to getUntrustedBytes | testDeprecatedApi.go:45:13:45:29 | selection of Description | +| testDeprecatedApi.go:49:25:49:43 | call to getUntrustedBytes | testDeprecatedApi.go:53:13:53:34 | call to GetDescription | +| testDeprecatedApi.go:58:23:58:42 | call to getUntrustedString | testDeprecatedApi.go:65:12:65:21 | serialized | +| testDeprecatedApi.go:70:14:70:33 | call to getUntrustedString | testDeprecatedApi.go:77:12:77:21 | serialized | +| testDeprecatedApi.go:85:24:85:43 | call to getUntrustedString | testDeprecatedApi.go:89:12:89:21 | serialized | +| testDeprecatedApi.go:93:25:93:43 | call to getUntrustedBytes | testDeprecatedApi.go:97:13:97:31 | selection of Msg | +| testDeprecatedApi.go:104:22:104:41 | call to getUntrustedString | testDeprecatedApi.go:105:13:105:20 | selection of Id | +| testDeprecatedApi.go:112:22:112:41 | call to getUntrustedString | testDeprecatedApi.go:117:12:117:21 | serialized | +| testDeprecatedApi.go:133:29:133:48 | call to getUntrustedString | testDeprecatedApi.go:137:12:137:21 | serialized | +| testDeprecatedApi.go:143:20:143:39 | call to getUntrustedString | testDeprecatedApi.go:148:12:148:21 | serialized | +| testDeprecatedApi.go:152:25:152:43 | call to getUntrustedBytes | testDeprecatedApi.go:157:13:157:36 | index expression | +| testDeprecatedApi.go:161:25:161:43 | call to getUntrustedBytes | testDeprecatedApi.go:168:13:168:25 | index expression | +| testDeprecatedApi.go:176:24:176:43 | call to getUntrustedString | testDeprecatedApi.go:180:12:180:21 | serialized | +| testModernApi.go:11:22:11:41 | call to getUntrustedString | testModernApi.go:15:12:15:21 | serialized | +| testModernApi.go:20:22:20:41 | call to getUntrustedString | testModernApi.go:26:12:26:21 | serialized | +| testModernApi.go:30:25:30:43 | call to getUntrustedBytes | testModernApi.go:34:13:34:29 | selection of Description | +| testModernApi.go:38:25:38:43 | call to getUntrustedBytes | testModernApi.go:42:13:42:34 | call to GetDescription | +| testModernApi.go:47:23:47:42 | call to getUntrustedString | testModernApi.go:54:12:54:21 | serialized | +| testModernApi.go:59:22:59:41 | call to getUntrustedString | testModernApi.go:64:12:64:21 | serialized | +| testModernApi.go:71:22:71:41 | call to getUntrustedString | testModernApi.go:77:12:77:21 | serialized | +| testModernApi.go:98:14:98:33 | call to getUntrustedString | testModernApi.go:105:12:105:21 | serialized | +| testModernApi.go:113:24:113:43 | call to getUntrustedString | testModernApi.go:117:12:117:21 | serialized | +| testModernApi.go:121:25:121:43 | call to getUntrustedBytes | testModernApi.go:125:13:125:31 | selection of Msg | +| testModernApi.go:131:25:131:43 | call to getUntrustedBytes | testModernApi.go:135:13:135:29 | selection of Description | +| testModernApi.go:142:22:142:41 | call to getUntrustedString | testModernApi.go:143:13:143:20 | selection of Id | +| testModernApi.go:150:22:150:41 | call to getUntrustedString | testModernApi.go:155:12:155:21 | serialized | +| testModernApi.go:190:29:190:48 | call to getUntrustedString | testModernApi.go:194:12:194:21 | serialized | +| testModernApi.go:200:20:200:39 | call to getUntrustedString | testModernApi.go:205:12:205:21 | serialized | +| testModernApi.go:209:25:209:43 | call to getUntrustedBytes | testModernApi.go:214:13:214:36 | index expression | +| testModernApi.go:218:25:218:43 | call to getUntrustedBytes | testModernApi.go:225:13:225:25 | index expression | +| testModernApi.go:233:24:233:43 | call to getUntrustedString | testModernApi.go:237:12:237:21 | serialized | diff --git a/go/ql/test/library-tests/semmle/go/frameworks/Revel/OpenRedirect.expected b/go/ql/test/library-tests/semmle/go/frameworks/Revel/OpenRedirect.expected index f0411268af8..77436c0d149 100644 --- a/go/ql/test/library-tests/semmle/go/frameworks/Revel/OpenRedirect.expected +++ b/go/ql/test/library-tests/semmle/go/frameworks/Revel/OpenRedirect.expected @@ -1,8 +1,8 @@ edges -| EndToEnd.go:94:20:94:27 | selection of Params : pointer type | EndToEnd.go:94:20:94:49 | call to Get | +| EndToEnd.go:94:20:94:27 | selection of Params | EndToEnd.go:94:20:94:49 | call to Get | nodes -| EndToEnd.go:94:20:94:27 | selection of Params : pointer type | semmle.label | selection of Params : pointer type | +| EndToEnd.go:94:20:94:27 | selection of Params | semmle.label | selection of Params | | EndToEnd.go:94:20:94:49 | call to Get | semmle.label | call to Get | subpaths #select -| EndToEnd.go:94:20:94:49 | call to Get | EndToEnd.go:94:20:94:27 | selection of Params : pointer type | EndToEnd.go:94:20:94:49 | call to Get | Untrusted URL redirection depends on a $@. | EndToEnd.go:94:20:94:27 | selection of Params | user-provided value | +| EndToEnd.go:94:20:94:49 | call to Get | EndToEnd.go:94:20:94:27 | selection of Params | EndToEnd.go:94:20:94:49 | call to Get | Untrusted URL redirection depends on a $@. | EndToEnd.go:94:20:94:27 | selection of Params | user-provided value | diff --git a/go/ql/test/library-tests/semmle/go/frameworks/Revel/ReflectedXss.expected b/go/ql/test/library-tests/semmle/go/frameworks/Revel/ReflectedXss.expected index 8d8c3bc3360..7a11d9bd08e 100644 --- a/go/ql/test/library-tests/semmle/go/frameworks/Revel/ReflectedXss.expected +++ b/go/ql/test/library-tests/semmle/go/frameworks/Revel/ReflectedXss.expected @@ -1,24 +1,24 @@ edges -| EndToEnd.go:36:18:36:25 | selection of Params : pointer type | EndToEnd.go:37:24:37:26 | buf | -| EndToEnd.go:69:22:69:29 | selection of Params : pointer type | EndToEnd.go:69:22:69:51 | call to Get | -| Revel.go:70:22:70:29 | selection of Params : pointer type | Revel.go:70:22:70:35 | selection of Query | -| examples/booking/app/init.go:36:44:36:48 | selection of URL : pointer type | examples/booking/app/init.go:36:44:36:53 | selection of Path | -| examples/booking/app/init.go:40:49:40:53 | selection of URL : pointer type | examples/booking/app/init.go:40:49:40:58 | selection of Path | +| EndToEnd.go:36:18:36:25 | selection of Params | EndToEnd.go:37:24:37:26 | buf | +| EndToEnd.go:69:22:69:29 | selection of Params | EndToEnd.go:69:22:69:51 | call to Get | +| Revel.go:70:22:70:29 | selection of Params | Revel.go:70:22:70:35 | selection of Query | +| examples/booking/app/init.go:36:44:36:48 | selection of URL | examples/booking/app/init.go:36:44:36:53 | selection of Path | +| examples/booking/app/init.go:40:49:40:53 | selection of URL | examples/booking/app/init.go:40:49:40:58 | selection of Path | nodes -| EndToEnd.go:36:18:36:25 | selection of Params : pointer type | semmle.label | selection of Params : pointer type | +| EndToEnd.go:36:18:36:25 | selection of Params | semmle.label | selection of Params | | EndToEnd.go:37:24:37:26 | buf | semmle.label | buf | -| EndToEnd.go:69:22:69:29 | selection of Params : pointer type | semmle.label | selection of Params : pointer type | +| EndToEnd.go:69:22:69:29 | selection of Params | semmle.label | selection of Params | | EndToEnd.go:69:22:69:51 | call to Get | semmle.label | call to Get | -| Revel.go:70:22:70:29 | selection of Params : pointer type | semmle.label | selection of Params : pointer type | +| Revel.go:70:22:70:29 | selection of Params | semmle.label | selection of Params | | Revel.go:70:22:70:35 | selection of Query | semmle.label | selection of Query | -| examples/booking/app/init.go:36:44:36:48 | selection of URL : pointer type | semmle.label | selection of URL : pointer type | +| examples/booking/app/init.go:36:44:36:48 | selection of URL | semmle.label | selection of URL | | examples/booking/app/init.go:36:44:36:53 | selection of Path | semmle.label | selection of Path | -| examples/booking/app/init.go:40:49:40:53 | selection of URL : pointer type | semmle.label | selection of URL : pointer type | +| examples/booking/app/init.go:40:49:40:53 | selection of URL | semmle.label | selection of URL | | examples/booking/app/init.go:40:49:40:58 | selection of Path | semmle.label | selection of Path | subpaths #select -| EndToEnd.go:37:24:37:26 | buf | EndToEnd.go:36:18:36:25 | selection of Params : pointer type | EndToEnd.go:37:24:37:26 | buf | Cross-site scripting vulnerability due to $@. | EndToEnd.go:36:18:36:25 | selection of Params | user-provided value | EndToEnd.go:0:0:0:0 | EndToEnd.go | | -| EndToEnd.go:69:22:69:51 | call to Get | EndToEnd.go:69:22:69:29 | selection of Params : pointer type | EndToEnd.go:69:22:69:51 | call to Get | Cross-site scripting vulnerability due to $@. | EndToEnd.go:69:22:69:29 | selection of Params | user-provided value | EndToEnd.go:0:0:0:0 | EndToEnd.go | | -| Revel.go:70:22:70:35 | selection of Query | Revel.go:70:22:70:29 | selection of Params : pointer type | Revel.go:70:22:70:35 | selection of Query | Cross-site scripting vulnerability due to $@. The value is $@. | Revel.go:70:22:70:29 | selection of Params | user-provided value | views/myAppController/rawRead.html:1:1:2:9 | {{raw .Foo}}\n{{.Bar}}\n | instantiated as a raw template | -| examples/booking/app/init.go:36:44:36:53 | selection of Path | examples/booking/app/init.go:36:44:36:48 | selection of URL : pointer type | examples/booking/app/init.go:36:44:36:53 | selection of Path | Cross-site scripting vulnerability due to $@. | examples/booking/app/init.go:36:44:36:48 | selection of URL | user-provided value | examples/booking/app/init.go:0:0:0:0 | examples/booking/app/init.go | | -| examples/booking/app/init.go:40:49:40:58 | selection of Path | examples/booking/app/init.go:40:49:40:53 | selection of URL : pointer type | examples/booking/app/init.go:40:49:40:58 | selection of Path | Cross-site scripting vulnerability due to $@. | examples/booking/app/init.go:40:49:40:53 | selection of URL | user-provided value | examples/booking/app/init.go:0:0:0:0 | examples/booking/app/init.go | | +| EndToEnd.go:37:24:37:26 | buf | EndToEnd.go:36:18:36:25 | selection of Params | EndToEnd.go:37:24:37:26 | buf | Cross-site scripting vulnerability due to $@. | EndToEnd.go:36:18:36:25 | selection of Params | user-provided value | EndToEnd.go:0:0:0:0 | EndToEnd.go | | +| EndToEnd.go:69:22:69:51 | call to Get | EndToEnd.go:69:22:69:29 | selection of Params | EndToEnd.go:69:22:69:51 | call to Get | Cross-site scripting vulnerability due to $@. | EndToEnd.go:69:22:69:29 | selection of Params | user-provided value | EndToEnd.go:0:0:0:0 | EndToEnd.go | | +| Revel.go:70:22:70:35 | selection of Query | Revel.go:70:22:70:29 | selection of Params | Revel.go:70:22:70:35 | selection of Query | Cross-site scripting vulnerability due to $@. The value is $@. | Revel.go:70:22:70:29 | selection of Params | user-provided value | views/myAppController/rawRead.html:1:1:2:9 | {{raw .Foo}}\n{{.Bar}}\n | instantiated as a raw template | +| examples/booking/app/init.go:36:44:36:53 | selection of Path | examples/booking/app/init.go:36:44:36:48 | selection of URL | examples/booking/app/init.go:36:44:36:53 | selection of Path | Cross-site scripting vulnerability due to $@. | examples/booking/app/init.go:36:44:36:48 | selection of URL | user-provided value | examples/booking/app/init.go:0:0:0:0 | examples/booking/app/init.go | | +| examples/booking/app/init.go:40:49:40:58 | selection of Path | examples/booking/app/init.go:40:49:40:53 | selection of URL | examples/booking/app/init.go:40:49:40:58 | selection of Path | Cross-site scripting vulnerability due to $@. | examples/booking/app/init.go:40:49:40:53 | selection of URL | user-provided value | examples/booking/app/init.go:0:0:0:0 | examples/booking/app/init.go | | diff --git a/go/ql/test/library-tests/semmle/go/frameworks/Revel/TaintedPath.expected b/go/ql/test/library-tests/semmle/go/frameworks/Revel/TaintedPath.expected index 97e912afcc9..5cce1e37d95 100644 --- a/go/ql/test/library-tests/semmle/go/frameworks/Revel/TaintedPath.expected +++ b/go/ql/test/library-tests/semmle/go/frameworks/Revel/TaintedPath.expected @@ -1,12 +1,12 @@ edges -| EndToEnd.go:58:18:58:25 | selection of Params : pointer type | EndToEnd.go:58:18:58:47 | call to Get | -| EndToEnd.go:64:26:64:33 | selection of Params : pointer type | EndToEnd.go:64:26:64:55 | call to Get | +| EndToEnd.go:58:18:58:25 | selection of Params | EndToEnd.go:58:18:58:47 | call to Get | +| EndToEnd.go:64:26:64:33 | selection of Params | EndToEnd.go:64:26:64:55 | call to Get | nodes -| EndToEnd.go:58:18:58:25 | selection of Params : pointer type | semmle.label | selection of Params : pointer type | +| EndToEnd.go:58:18:58:25 | selection of Params | semmle.label | selection of Params | | EndToEnd.go:58:18:58:47 | call to Get | semmle.label | call to Get | -| EndToEnd.go:64:26:64:33 | selection of Params : pointer type | semmle.label | selection of Params : pointer type | +| EndToEnd.go:64:26:64:33 | selection of Params | semmle.label | selection of Params | | EndToEnd.go:64:26:64:55 | call to Get | semmle.label | call to Get | subpaths #select -| EndToEnd.go:58:18:58:47 | call to Get | EndToEnd.go:58:18:58:25 | selection of Params : pointer type | EndToEnd.go:58:18:58:47 | call to Get | This path depends on a $@. | EndToEnd.go:58:18:58:25 | selection of Params | user-provided value | -| EndToEnd.go:64:26:64:55 | call to Get | EndToEnd.go:64:26:64:33 | selection of Params : pointer type | EndToEnd.go:64:26:64:55 | call to Get | This path depends on a $@. | EndToEnd.go:64:26:64:33 | selection of Params | user-provided value | +| EndToEnd.go:58:18:58:47 | call to Get | EndToEnd.go:58:18:58:25 | selection of Params | EndToEnd.go:58:18:58:47 | call to Get | This path depends on a $@. | EndToEnd.go:58:18:58:25 | selection of Params | user-provided value | +| EndToEnd.go:64:26:64:55 | call to Get | EndToEnd.go:64:26:64:33 | selection of Params | EndToEnd.go:64:26:64:55 | call to Get | This path depends on a $@. | EndToEnd.go:64:26:64:33 | selection of Params | user-provided value | diff --git a/go/ql/test/library-tests/semmle/go/frameworks/Spew/TaintFlows.expected b/go/ql/test/library-tests/semmle/go/frameworks/Spew/TaintFlows.expected index f24231f8566..404524ec3d6 100644 --- a/go/ql/test/library-tests/semmle/go/frameworks/Spew/TaintFlows.expected +++ b/go/ql/test/library-tests/semmle/go/frameworks/Spew/TaintFlows.expected @@ -1,17 +1,17 @@ -| test.go:26:16:26:35 | call to getUntrustedString : string | test.go:33:14:33:23 | sUntrusted | -| test.go:26:16:26:35 | call to getUntrustedString : string | test.go:35:14:35:23 | sUntrusted | -| test.go:26:16:26:35 | call to getUntrustedString : string | test.go:41:18:41:27 | sUntrusted | -| test.go:26:16:26:35 | call to getUntrustedString : string | test.go:51:13:51:16 | str3 | -| test.go:28:16:28:35 | call to getUntrustedStruct : Person | test.go:30:12:30:21 | pUntrusted | -| test.go:28:16:28:35 | call to getUntrustedStruct : Person | test.go:31:13:31:22 | pUntrusted | -| test.go:28:16:28:35 | call to getUntrustedStruct : Person | test.go:32:15:32:24 | pUntrusted | -| test.go:28:16:28:35 | call to getUntrustedStruct : Person | test.go:34:17:34:26 | pUntrusted | -| test.go:28:16:28:35 | call to getUntrustedStruct : Person | test.go:36:17:36:26 | pUntrusted | -| test.go:28:16:28:35 | call to getUntrustedStruct : Person | test.go:38:16:38:25 | pUntrusted | -| test.go:28:16:28:35 | call to getUntrustedStruct : Person | test.go:39:17:39:26 | pUntrusted | -| test.go:28:16:28:35 | call to getUntrustedStruct : Person | test.go:40:19:40:28 | pUntrusted | -| test.go:28:16:28:35 | call to getUntrustedStruct : Person | test.go:42:21:42:30 | pUntrusted | -| test.go:28:16:28:35 | call to getUntrustedStruct : Person | test.go:45:13:45:16 | str1 | -| test.go:28:16:28:35 | call to getUntrustedStruct : Person | test.go:48:13:48:16 | str2 | -| test.go:28:16:28:35 | call to getUntrustedStruct : Person | test.go:54:13:54:16 | str4 | -| test.go:28:16:28:35 | call to getUntrustedStruct : Person | test.go:57:13:57:16 | str5 | +| test.go:26:16:26:35 | call to getUntrustedString | test.go:33:14:33:23 | sUntrusted | +| test.go:26:16:26:35 | call to getUntrustedString | test.go:35:14:35:23 | sUntrusted | +| test.go:26:16:26:35 | call to getUntrustedString | test.go:41:18:41:27 | sUntrusted | +| test.go:26:16:26:35 | call to getUntrustedString | test.go:51:13:51:16 | str3 | +| test.go:28:16:28:35 | call to getUntrustedStruct | test.go:30:12:30:21 | pUntrusted | +| test.go:28:16:28:35 | call to getUntrustedStruct | test.go:31:13:31:22 | pUntrusted | +| test.go:28:16:28:35 | call to getUntrustedStruct | test.go:32:15:32:24 | pUntrusted | +| test.go:28:16:28:35 | call to getUntrustedStruct | test.go:34:17:34:26 | pUntrusted | +| test.go:28:16:28:35 | call to getUntrustedStruct | test.go:36:17:36:26 | pUntrusted | +| test.go:28:16:28:35 | call to getUntrustedStruct | test.go:38:16:38:25 | pUntrusted | +| test.go:28:16:28:35 | call to getUntrustedStruct | test.go:39:17:39:26 | pUntrusted | +| test.go:28:16:28:35 | call to getUntrustedStruct | test.go:40:19:40:28 | pUntrusted | +| test.go:28:16:28:35 | call to getUntrustedStruct | test.go:42:21:42:30 | pUntrusted | +| test.go:28:16:28:35 | call to getUntrustedStruct | test.go:45:13:45:16 | str1 | +| test.go:28:16:28:35 | call to getUntrustedStruct | test.go:48:13:48:16 | str2 | +| test.go:28:16:28:35 | call to getUntrustedStruct | test.go:54:13:54:16 | str4 | +| test.go:28:16:28:35 | call to getUntrustedStruct | test.go:57:13:57:16 | str5 | diff --git a/go/ql/test/library-tests/semmle/go/frameworks/XNetHtml/ReflectedXss.expected b/go/ql/test/library-tests/semmle/go/frameworks/XNetHtml/ReflectedXss.expected index ca8c2655274..aa0daf2d591 100644 --- a/go/ql/test/library-tests/semmle/go/frameworks/XNetHtml/ReflectedXss.expected +++ b/go/ql/test/library-tests/semmle/go/frameworks/XNetHtml/ReflectedXss.expected @@ -1,28 +1,28 @@ edges -| test.go:10:2:10:42 | ... := ...[0] : pointer type | test.go:14:15:14:55 | type conversion | -| test.go:16:24:16:35 | selection of Body : ReadCloser | test.go:17:15:17:31 | type conversion | -| test.go:16:24:16:35 | selection of Body : ReadCloser | test.go:28:22:28:25 | node | -| test.go:19:36:19:47 | selection of Body : ReadCloser | test.go:20:15:20:32 | type conversion | -| test.go:22:33:22:44 | selection of Body : ReadCloser | test.go:23:15:23:35 | type conversion | -| test.go:25:45:25:56 | selection of Body : ReadCloser | test.go:26:15:26:36 | type conversion | -| test.go:30:33:30:44 | selection of Body : ReadCloser | test.go:31:15:31:34 | call to Buffered | -| test.go:30:33:30:44 | selection of Body : ReadCloser | test.go:32:15:32:29 | call to Raw | -| test.go:30:33:30:44 | selection of Body : ReadCloser | test.go:34:15:34:19 | value | -| test.go:30:33:30:44 | selection of Body : ReadCloser | test.go:35:15:35:30 | call to Text | -| test.go:30:33:30:44 | selection of Body : ReadCloser | test.go:36:15:36:44 | type conversion | +| test.go:10:2:10:42 | ... := ...[0] | test.go:14:15:14:55 | type conversion | +| test.go:16:24:16:35 | selection of Body | test.go:17:15:17:31 | type conversion | +| test.go:16:24:16:35 | selection of Body | test.go:28:22:28:25 | node | +| test.go:19:36:19:47 | selection of Body | test.go:20:15:20:32 | type conversion | +| test.go:22:33:22:44 | selection of Body | test.go:23:15:23:35 | type conversion | +| test.go:25:45:25:56 | selection of Body | test.go:26:15:26:36 | type conversion | +| test.go:30:33:30:44 | selection of Body | test.go:31:15:31:34 | call to Buffered | +| test.go:30:33:30:44 | selection of Body | test.go:32:15:32:29 | call to Raw | +| test.go:30:33:30:44 | selection of Body | test.go:34:15:34:19 | value | +| test.go:30:33:30:44 | selection of Body | test.go:35:15:35:30 | call to Text | +| test.go:30:33:30:44 | selection of Body | test.go:36:15:36:44 | type conversion | nodes -| test.go:10:2:10:42 | ... := ...[0] : pointer type | semmle.label | ... := ...[0] : pointer type | +| test.go:10:2:10:42 | ... := ...[0] | semmle.label | ... := ...[0] | | test.go:14:15:14:55 | type conversion | semmle.label | type conversion | -| test.go:16:24:16:35 | selection of Body : ReadCloser | semmle.label | selection of Body : ReadCloser | +| test.go:16:24:16:35 | selection of Body | semmle.label | selection of Body | | test.go:17:15:17:31 | type conversion | semmle.label | type conversion | -| test.go:19:36:19:47 | selection of Body : ReadCloser | semmle.label | selection of Body : ReadCloser | +| test.go:19:36:19:47 | selection of Body | semmle.label | selection of Body | | test.go:20:15:20:32 | type conversion | semmle.label | type conversion | -| test.go:22:33:22:44 | selection of Body : ReadCloser | semmle.label | selection of Body : ReadCloser | +| test.go:22:33:22:44 | selection of Body | semmle.label | selection of Body | | test.go:23:15:23:35 | type conversion | semmle.label | type conversion | -| test.go:25:45:25:56 | selection of Body : ReadCloser | semmle.label | selection of Body : ReadCloser | +| test.go:25:45:25:56 | selection of Body | semmle.label | selection of Body | | test.go:26:15:26:36 | type conversion | semmle.label | type conversion | | test.go:28:22:28:25 | node | semmle.label | node | -| test.go:30:33:30:44 | selection of Body : ReadCloser | semmle.label | selection of Body : ReadCloser | +| test.go:30:33:30:44 | selection of Body | semmle.label | selection of Body | | test.go:31:15:31:34 | call to Buffered | semmle.label | call to Buffered | | test.go:32:15:32:29 | call to Raw | semmle.label | call to Raw | | test.go:34:15:34:19 | value | semmle.label | value | @@ -30,14 +30,14 @@ nodes | test.go:36:15:36:44 | type conversion | semmle.label | type conversion | subpaths #select -| test.go:14:15:14:55 | type conversion | test.go:10:2:10:42 | ... := ...[0] : pointer type | test.go:14:15:14:55 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:10:2:10:42 | ... := ...[0] | user-provided value | test.go:0:0:0:0 | test.go | | -| test.go:17:15:17:31 | type conversion | test.go:16:24:16:35 | selection of Body : ReadCloser | test.go:17:15:17:31 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:16:24:16:35 | selection of Body | user-provided value | test.go:0:0:0:0 | test.go | | -| test.go:20:15:20:32 | type conversion | test.go:19:36:19:47 | selection of Body : ReadCloser | test.go:20:15:20:32 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:19:36:19:47 | selection of Body | user-provided value | test.go:0:0:0:0 | test.go | | -| test.go:23:15:23:35 | type conversion | test.go:22:33:22:44 | selection of Body : ReadCloser | test.go:23:15:23:35 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:22:33:22:44 | selection of Body | user-provided value | test.go:0:0:0:0 | test.go | | -| test.go:26:15:26:36 | type conversion | test.go:25:45:25:56 | selection of Body : ReadCloser | test.go:26:15:26:36 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:25:45:25:56 | selection of Body | user-provided value | test.go:0:0:0:0 | test.go | | -| test.go:28:22:28:25 | node | test.go:16:24:16:35 | selection of Body : ReadCloser | test.go:28:22:28:25 | node | Cross-site scripting vulnerability due to $@. | test.go:16:24:16:35 | selection of Body | user-provided value | test.go:0:0:0:0 | test.go | | -| test.go:31:15:31:34 | call to Buffered | test.go:30:33:30:44 | selection of Body : ReadCloser | test.go:31:15:31:34 | call to Buffered | Cross-site scripting vulnerability due to $@. | test.go:30:33:30:44 | selection of Body | user-provided value | test.go:0:0:0:0 | test.go | | -| test.go:32:15:32:29 | call to Raw | test.go:30:33:30:44 | selection of Body : ReadCloser | test.go:32:15:32:29 | call to Raw | Cross-site scripting vulnerability due to $@. | test.go:30:33:30:44 | selection of Body | user-provided value | test.go:0:0:0:0 | test.go | | -| test.go:34:15:34:19 | value | test.go:30:33:30:44 | selection of Body : ReadCloser | test.go:34:15:34:19 | value | Cross-site scripting vulnerability due to $@. | test.go:30:33:30:44 | selection of Body | user-provided value | test.go:0:0:0:0 | test.go | | -| test.go:35:15:35:30 | call to Text | test.go:30:33:30:44 | selection of Body : ReadCloser | test.go:35:15:35:30 | call to Text | Cross-site scripting vulnerability due to $@. | test.go:30:33:30:44 | selection of Body | user-provided value | test.go:0:0:0:0 | test.go | | -| test.go:36:15:36:44 | type conversion | test.go:30:33:30:44 | selection of Body : ReadCloser | test.go:36:15:36:44 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:30:33:30:44 | selection of Body | user-provided value | test.go:0:0:0:0 | test.go | | +| test.go:14:15:14:55 | type conversion | test.go:10:2:10:42 | ... := ...[0] | test.go:14:15:14:55 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:10:2:10:42 | ... := ...[0] | user-provided value | test.go:0:0:0:0 | test.go | | +| test.go:17:15:17:31 | type conversion | test.go:16:24:16:35 | selection of Body | test.go:17:15:17:31 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:16:24:16:35 | selection of Body | user-provided value | test.go:0:0:0:0 | test.go | | +| test.go:20:15:20:32 | type conversion | test.go:19:36:19:47 | selection of Body | test.go:20:15:20:32 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:19:36:19:47 | selection of Body | user-provided value | test.go:0:0:0:0 | test.go | | +| test.go:23:15:23:35 | type conversion | test.go:22:33:22:44 | selection of Body | test.go:23:15:23:35 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:22:33:22:44 | selection of Body | user-provided value | test.go:0:0:0:0 | test.go | | +| test.go:26:15:26:36 | type conversion | test.go:25:45:25:56 | selection of Body | test.go:26:15:26:36 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:25:45:25:56 | selection of Body | user-provided value | test.go:0:0:0:0 | test.go | | +| test.go:28:22:28:25 | node | test.go:16:24:16:35 | selection of Body | test.go:28:22:28:25 | node | Cross-site scripting vulnerability due to $@. | test.go:16:24:16:35 | selection of Body | user-provided value | test.go:0:0:0:0 | test.go | | +| test.go:31:15:31:34 | call to Buffered | test.go:30:33:30:44 | selection of Body | test.go:31:15:31:34 | call to Buffered | Cross-site scripting vulnerability due to $@. | test.go:30:33:30:44 | selection of Body | user-provided value | test.go:0:0:0:0 | test.go | | +| test.go:32:15:32:29 | call to Raw | test.go:30:33:30:44 | selection of Body | test.go:32:15:32:29 | call to Raw | Cross-site scripting vulnerability due to $@. | test.go:30:33:30:44 | selection of Body | user-provided value | test.go:0:0:0:0 | test.go | | +| test.go:34:15:34:19 | value | test.go:30:33:30:44 | selection of Body | test.go:34:15:34:19 | value | Cross-site scripting vulnerability due to $@. | test.go:30:33:30:44 | selection of Body | user-provided value | test.go:0:0:0:0 | test.go | | +| test.go:35:15:35:30 | call to Text | test.go:30:33:30:44 | selection of Body | test.go:35:15:35:30 | call to Text | Cross-site scripting vulnerability due to $@. | test.go:30:33:30:44 | selection of Body | user-provided value | test.go:0:0:0:0 | test.go | | +| test.go:36:15:36:44 | type conversion | test.go:30:33:30:44 | selection of Body | test.go:36:15:36:44 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:30:33:30:44 | selection of Body | user-provided value | test.go:0:0:0:0 | test.go | | diff --git a/go/ql/test/query-tests/Security/CWE-020/IncompleteHostnameRegexp/IncompleteHostnameRegexp.expected b/go/ql/test/query-tests/Security/CWE-020/IncompleteHostnameRegexp/IncompleteHostnameRegexp.expected index f73dd03f976..029366069d2 100644 --- a/go/ql/test/query-tests/Security/CWE-020/IncompleteHostnameRegexp/IncompleteHostnameRegexp.expected +++ b/go/ql/test/query-tests/Security/CWE-020/IncompleteHostnameRegexp/IncompleteHostnameRegexp.expected @@ -1,12 +1,12 @@ edges -| IncompleteHostnameRegexp.go:11:8:11:36 | "^((www\|beta).)?example.com/" : string | IncompleteHostnameRegexp.go:12:38:12:39 | re | +| IncompleteHostnameRegexp.go:11:8:11:36 | "^((www\|beta).)?example.com/" | IncompleteHostnameRegexp.go:12:38:12:39 | re | nodes -| IncompleteHostnameRegexp.go:11:8:11:36 | "^((www\|beta).)?example.com/" : string | semmle.label | "^((www\|beta).)?example.com/" : string | +| IncompleteHostnameRegexp.go:11:8:11:36 | "^((www\|beta).)?example.com/" | semmle.label | "^((www\|beta).)?example.com/" | | IncompleteHostnameRegexp.go:12:38:12:39 | re | semmle.label | re | | main.go:39:60:39:79 | "^test2.github.com$" | semmle.label | "^test2.github.com$" | | main.go:44:15:44:39 | `https://www.example.com` | semmle.label | `https://www.example.com` | subpaths #select -| IncompleteHostnameRegexp.go:11:8:11:36 | "^((www\|beta).)?example.com/" : string | IncompleteHostnameRegexp.go:11:8:11:36 | "^((www\|beta).)?example.com/" : string | IncompleteHostnameRegexp.go:12:38:12:39 | re | This regular expression has an unescaped dot before ')?example.com', so it might match more hosts than expected when $@. | IncompleteHostnameRegexp.go:12:38:12:39 | re | the regular expression is used | +| IncompleteHostnameRegexp.go:11:8:11:36 | "^((www\|beta).)?example.com/" | IncompleteHostnameRegexp.go:11:8:11:36 | "^((www\|beta).)?example.com/" | IncompleteHostnameRegexp.go:12:38:12:39 | re | This regular expression has an unescaped dot before ')?example.com', so it might match more hosts than expected when $@. | IncompleteHostnameRegexp.go:12:38:12:39 | re | the regular expression is used | | main.go:39:60:39:79 | "^test2.github.com$" | main.go:39:60:39:79 | "^test2.github.com$" | main.go:39:60:39:79 | "^test2.github.com$" | This regular expression has an unescaped dot before 'github.com', so it might match more hosts than expected when $@. | main.go:39:60:39:79 | "^test2.github.com$" | the regular expression is used | | main.go:44:15:44:39 | `https://www.example.com` | main.go:44:15:44:39 | `https://www.example.com` | main.go:44:15:44:39 | `https://www.example.com` | This regular expression has an unescaped dot before 'example.com', so it might match more hosts than expected when $@. | main.go:44:15:44:39 | `https://www.example.com` | the regular expression is used | diff --git a/go/ql/test/query-tests/Security/CWE-022/TaintedPath.expected b/go/ql/test/query-tests/Security/CWE-022/TaintedPath.expected index 568ba70ff81..3e26f767b5e 100644 --- a/go/ql/test/query-tests/Security/CWE-022/TaintedPath.expected +++ b/go/ql/test/query-tests/Security/CWE-022/TaintedPath.expected @@ -1,15 +1,15 @@ edges -| TaintedPath.go:13:18:13:22 | selection of URL : pointer type | TaintedPath.go:16:29:16:40 | tainted_path | -| TaintedPath.go:13:18:13:22 | selection of URL : pointer type | TaintedPath.go:20:28:20:69 | call to Join | -| tst.go:14:2:14:39 | ... := ...[1] : pointer type | tst.go:17:41:17:56 | selection of Filename | +| TaintedPath.go:13:18:13:22 | selection of URL | TaintedPath.go:16:29:16:40 | tainted_path | +| TaintedPath.go:13:18:13:22 | selection of URL | TaintedPath.go:20:28:20:69 | call to Join | +| tst.go:14:2:14:39 | ... := ...[1] | tst.go:17:41:17:56 | selection of Filename | nodes -| TaintedPath.go:13:18:13:22 | selection of URL : pointer type | semmle.label | selection of URL : pointer type | +| TaintedPath.go:13:18:13:22 | selection of URL | semmle.label | selection of URL | | TaintedPath.go:16:29:16:40 | tainted_path | semmle.label | tainted_path | | TaintedPath.go:20:28:20:69 | call to Join | semmle.label | call to Join | -| tst.go:14:2:14:39 | ... := ...[1] : pointer type | semmle.label | ... := ...[1] : pointer type | +| tst.go:14:2:14:39 | ... := ...[1] | semmle.label | ... := ...[1] | | tst.go:17:41:17:56 | selection of Filename | semmle.label | selection of Filename | subpaths #select -| TaintedPath.go:16:29:16:40 | tainted_path | TaintedPath.go:13:18:13:22 | selection of URL : pointer type | TaintedPath.go:16:29:16:40 | tainted_path | This path depends on a $@. | TaintedPath.go:13:18:13:22 | selection of URL | user-provided value | -| TaintedPath.go:20:28:20:69 | call to Join | TaintedPath.go:13:18:13:22 | selection of URL : pointer type | TaintedPath.go:20:28:20:69 | call to Join | This path depends on a $@. | TaintedPath.go:13:18:13:22 | selection of URL | user-provided value | -| tst.go:17:41:17:56 | selection of Filename | tst.go:14:2:14:39 | ... := ...[1] : pointer type | tst.go:17:41:17:56 | selection of Filename | This path depends on a $@. | tst.go:14:2:14:39 | ... := ...[1] | user-provided value | +| TaintedPath.go:16:29:16:40 | tainted_path | TaintedPath.go:13:18:13:22 | selection of URL | TaintedPath.go:16:29:16:40 | tainted_path | This path depends on a $@. | TaintedPath.go:13:18:13:22 | selection of URL | user-provided value | +| TaintedPath.go:20:28:20:69 | call to Join | TaintedPath.go:13:18:13:22 | selection of URL | TaintedPath.go:20:28:20:69 | call to Join | This path depends on a $@. | TaintedPath.go:13:18:13:22 | selection of URL | user-provided value | +| tst.go:17:41:17:56 | selection of Filename | tst.go:14:2:14:39 | ... := ...[1] | tst.go:17:41:17:56 | selection of Filename | This path depends on a $@. | tst.go:14:2:14:39 | ... := ...[1] | user-provided value | diff --git a/go/ql/test/query-tests/Security/CWE-022/UnsafeUnzipSymlink.expected b/go/ql/test/query-tests/Security/CWE-022/UnsafeUnzipSymlink.expected index f44b118d7d5..da8dc7ed50e 100644 --- a/go/ql/test/query-tests/Security/CWE-022/UnsafeUnzipSymlink.expected +++ b/go/ql/test/query-tests/Security/CWE-022/UnsafeUnzipSymlink.expected @@ -1,22 +1,22 @@ edges -| UnsafeUnzipSymlink.go:111:19:111:26 | definition of linkName : string | UnsafeUnzipSymlink.go:112:13:112:20 | linkName | -| UnsafeUnzipSymlink.go:111:29:111:36 | definition of fileName : string | UnsafeUnzipSymlink.go:112:23:112:30 | fileName | -| UnsafeUnzipSymlink.go:126:17:126:31 | selection of Linkname : string | UnsafeUnzipSymlink.go:111:19:111:26 | definition of linkName : string | -| UnsafeUnzipSymlink.go:126:34:126:44 | selection of Name : string | UnsafeUnzipSymlink.go:111:29:111:36 | definition of fileName : string | +| UnsafeUnzipSymlink.go:111:19:111:26 | definition of linkName | UnsafeUnzipSymlink.go:112:13:112:20 | linkName | +| UnsafeUnzipSymlink.go:111:29:111:36 | definition of fileName | UnsafeUnzipSymlink.go:112:23:112:30 | fileName | +| UnsafeUnzipSymlink.go:126:17:126:31 | selection of Linkname | UnsafeUnzipSymlink.go:111:19:111:26 | definition of linkName | +| UnsafeUnzipSymlink.go:126:34:126:44 | selection of Name | UnsafeUnzipSymlink.go:111:29:111:36 | definition of fileName | nodes | UnsafeUnzipSymlink.go:31:15:31:29 | selection of Linkname | semmle.label | selection of Linkname | | UnsafeUnzipSymlink.go:31:32:31:42 | selection of Name | semmle.label | selection of Name | | UnsafeUnzipSymlink.go:43:25:43:35 | selection of Name | semmle.label | selection of Name | -| UnsafeUnzipSymlink.go:111:19:111:26 | definition of linkName : string | semmle.label | definition of linkName : string | -| UnsafeUnzipSymlink.go:111:29:111:36 | definition of fileName : string | semmle.label | definition of fileName : string | +| UnsafeUnzipSymlink.go:111:19:111:26 | definition of linkName | semmle.label | definition of linkName | +| UnsafeUnzipSymlink.go:111:29:111:36 | definition of fileName | semmle.label | definition of fileName | | UnsafeUnzipSymlink.go:112:13:112:20 | linkName | semmle.label | linkName | | UnsafeUnzipSymlink.go:112:23:112:30 | fileName | semmle.label | fileName | -| UnsafeUnzipSymlink.go:126:17:126:31 | selection of Linkname : string | semmle.label | selection of Linkname : string | -| UnsafeUnzipSymlink.go:126:34:126:44 | selection of Name : string | semmle.label | selection of Name : string | +| UnsafeUnzipSymlink.go:126:17:126:31 | selection of Linkname | semmle.label | selection of Linkname | +| UnsafeUnzipSymlink.go:126:34:126:44 | selection of Name | semmle.label | selection of Name | subpaths #select | UnsafeUnzipSymlink.go:31:15:31:29 | selection of Linkname | UnsafeUnzipSymlink.go:31:15:31:29 | selection of Linkname | UnsafeUnzipSymlink.go:31:15:31:29 | selection of Linkname | Unresolved path from an archive header, which may point outside the archive root, is used in $@. | UnsafeUnzipSymlink.go:31:15:31:29 | selection of Linkname | symlink creation | | UnsafeUnzipSymlink.go:31:32:31:42 | selection of Name | UnsafeUnzipSymlink.go:31:32:31:42 | selection of Name | UnsafeUnzipSymlink.go:31:32:31:42 | selection of Name | Unresolved path from an archive header, which may point outside the archive root, is used in $@. | UnsafeUnzipSymlink.go:31:32:31:42 | selection of Name | symlink creation | | UnsafeUnzipSymlink.go:43:25:43:35 | selection of Name | UnsafeUnzipSymlink.go:43:25:43:35 | selection of Name | UnsafeUnzipSymlink.go:43:25:43:35 | selection of Name | Unresolved path from an archive header, which may point outside the archive root, is used in $@. | UnsafeUnzipSymlink.go:43:25:43:35 | selection of Name | symlink creation | -| UnsafeUnzipSymlink.go:126:17:126:31 | selection of Linkname | UnsafeUnzipSymlink.go:126:17:126:31 | selection of Linkname : string | UnsafeUnzipSymlink.go:112:13:112:20 | linkName | Unresolved path from an archive header, which may point outside the archive root, is used in $@. | UnsafeUnzipSymlink.go:112:13:112:20 | linkName | symlink creation | -| UnsafeUnzipSymlink.go:126:34:126:44 | selection of Name | UnsafeUnzipSymlink.go:126:34:126:44 | selection of Name : string | UnsafeUnzipSymlink.go:112:23:112:30 | fileName | Unresolved path from an archive header, which may point outside the archive root, is used in $@. | UnsafeUnzipSymlink.go:112:23:112:30 | fileName | symlink creation | +| UnsafeUnzipSymlink.go:126:17:126:31 | selection of Linkname | UnsafeUnzipSymlink.go:126:17:126:31 | selection of Linkname | UnsafeUnzipSymlink.go:112:13:112:20 | linkName | Unresolved path from an archive header, which may point outside the archive root, is used in $@. | UnsafeUnzipSymlink.go:112:13:112:20 | linkName | symlink creation | +| UnsafeUnzipSymlink.go:126:34:126:44 | selection of Name | UnsafeUnzipSymlink.go:126:34:126:44 | selection of Name | UnsafeUnzipSymlink.go:112:23:112:30 | fileName | Unresolved path from an archive header, which may point outside the archive root, is used in $@. | UnsafeUnzipSymlink.go:112:23:112:30 | fileName | symlink creation | diff --git a/go/ql/test/query-tests/Security/CWE-022/ZipSlip.expected b/go/ql/test/query-tests/Security/CWE-022/ZipSlip.expected index 2a58d80fe26..1506632f5c5 100644 --- a/go/ql/test/query-tests/Security/CWE-022/ZipSlip.expected +++ b/go/ql/test/query-tests/Security/CWE-022/ZipSlip.expected @@ -1,27 +1,27 @@ edges -| UnsafeUnzipSymlinkGood.go:52:24:52:32 | definition of candidate : string | UnsafeUnzipSymlinkGood.go:61:31:61:62 | call to Join | -| UnsafeUnzipSymlinkGood.go:72:3:72:25 | ... := ...[0] : pointer type | UnsafeUnzipSymlinkGood.go:76:24:76:38 | selection of Linkname : string | -| UnsafeUnzipSymlinkGood.go:72:3:72:25 | ... := ...[0] : pointer type | UnsafeUnzipSymlinkGood.go:76:70:76:80 | selection of Name : string | -| UnsafeUnzipSymlinkGood.go:76:24:76:38 | selection of Linkname : string | UnsafeUnzipSymlinkGood.go:52:24:52:32 | definition of candidate : string | -| UnsafeUnzipSymlinkGood.go:76:70:76:80 | selection of Name : string | UnsafeUnzipSymlinkGood.go:52:24:52:32 | definition of candidate : string | -| ZipSlip.go:11:2:15:2 | range statement[1] : pointer type | ZipSlip.go:14:20:14:20 | p | -| tarslip.go:15:2:15:30 | ... := ...[0] : pointer type | tarslip.go:16:14:16:34 | call to Dir | -| tst.go:23:2:43:2 | range statement[1] : pointer type | tst.go:29:20:29:23 | path | +| UnsafeUnzipSymlinkGood.go:52:24:52:32 | definition of candidate | UnsafeUnzipSymlinkGood.go:61:31:61:62 | call to Join | +| UnsafeUnzipSymlinkGood.go:72:3:72:25 | ... := ...[0] | UnsafeUnzipSymlinkGood.go:76:24:76:38 | selection of Linkname | +| UnsafeUnzipSymlinkGood.go:72:3:72:25 | ... := ...[0] | UnsafeUnzipSymlinkGood.go:76:70:76:80 | selection of Name | +| UnsafeUnzipSymlinkGood.go:76:24:76:38 | selection of Linkname | UnsafeUnzipSymlinkGood.go:52:24:52:32 | definition of candidate | +| UnsafeUnzipSymlinkGood.go:76:70:76:80 | selection of Name | UnsafeUnzipSymlinkGood.go:52:24:52:32 | definition of candidate | +| ZipSlip.go:11:2:15:2 | range statement[1] | ZipSlip.go:14:20:14:20 | p | +| tarslip.go:15:2:15:30 | ... := ...[0] | tarslip.go:16:14:16:34 | call to Dir | +| tst.go:23:2:43:2 | range statement[1] | tst.go:29:20:29:23 | path | nodes -| UnsafeUnzipSymlinkGood.go:52:24:52:32 | definition of candidate : string | semmle.label | definition of candidate : string | +| UnsafeUnzipSymlinkGood.go:52:24:52:32 | definition of candidate | semmle.label | definition of candidate | | UnsafeUnzipSymlinkGood.go:61:31:61:62 | call to Join | semmle.label | call to Join | -| UnsafeUnzipSymlinkGood.go:72:3:72:25 | ... := ...[0] : pointer type | semmle.label | ... := ...[0] : pointer type | -| UnsafeUnzipSymlinkGood.go:76:24:76:38 | selection of Linkname : string | semmle.label | selection of Linkname : string | -| UnsafeUnzipSymlinkGood.go:76:70:76:80 | selection of Name : string | semmle.label | selection of Name : string | -| ZipSlip.go:11:2:15:2 | range statement[1] : pointer type | semmle.label | range statement[1] : pointer type | +| UnsafeUnzipSymlinkGood.go:72:3:72:25 | ... := ...[0] | semmle.label | ... := ...[0] | +| UnsafeUnzipSymlinkGood.go:76:24:76:38 | selection of Linkname | semmle.label | selection of Linkname | +| UnsafeUnzipSymlinkGood.go:76:70:76:80 | selection of Name | semmle.label | selection of Name | +| ZipSlip.go:11:2:15:2 | range statement[1] | semmle.label | range statement[1] | | ZipSlip.go:14:20:14:20 | p | semmle.label | p | -| tarslip.go:15:2:15:30 | ... := ...[0] : pointer type | semmle.label | ... := ...[0] : pointer type | +| tarslip.go:15:2:15:30 | ... := ...[0] | semmle.label | ... := ...[0] | | tarslip.go:16:14:16:34 | call to Dir | semmle.label | call to Dir | -| tst.go:23:2:43:2 | range statement[1] : pointer type | semmle.label | range statement[1] : pointer type | +| tst.go:23:2:43:2 | range statement[1] | semmle.label | range statement[1] | | tst.go:29:20:29:23 | path | semmle.label | path | subpaths #select -| UnsafeUnzipSymlinkGood.go:72:3:72:25 | ... := ...[0] | UnsafeUnzipSymlinkGood.go:72:3:72:25 | ... := ...[0] : pointer type | UnsafeUnzipSymlinkGood.go:61:31:61:62 | call to Join | Unsanitized archive entry, which may contain '..', is used in a $@. | UnsafeUnzipSymlinkGood.go:61:31:61:62 | call to Join | file system operation | -| ZipSlip.go:11:2:15:2 | range statement[1] | ZipSlip.go:11:2:15:2 | range statement[1] : pointer type | ZipSlip.go:14:20:14:20 | p | Unsanitized archive entry, which may contain '..', is used in a $@. | ZipSlip.go:14:20:14:20 | p | file system operation | -| tarslip.go:15:2:15:30 | ... := ...[0] | tarslip.go:15:2:15:30 | ... := ...[0] : pointer type | tarslip.go:16:14:16:34 | call to Dir | Unsanitized archive entry, which may contain '..', is used in a $@. | tarslip.go:16:14:16:34 | call to Dir | file system operation | -| tst.go:23:2:43:2 | range statement[1] | tst.go:23:2:43:2 | range statement[1] : pointer type | tst.go:29:20:29:23 | path | Unsanitized archive entry, which may contain '..', is used in a $@. | tst.go:29:20:29:23 | path | file system operation | +| UnsafeUnzipSymlinkGood.go:72:3:72:25 | ... := ...[0] | UnsafeUnzipSymlinkGood.go:72:3:72:25 | ... := ...[0] | UnsafeUnzipSymlinkGood.go:61:31:61:62 | call to Join | Unsanitized archive entry, which may contain '..', is used in a $@. | UnsafeUnzipSymlinkGood.go:61:31:61:62 | call to Join | file system operation | +| ZipSlip.go:11:2:15:2 | range statement[1] | ZipSlip.go:11:2:15:2 | range statement[1] | ZipSlip.go:14:20:14:20 | p | Unsanitized archive entry, which may contain '..', is used in a $@. | ZipSlip.go:14:20:14:20 | p | file system operation | +| tarslip.go:15:2:15:30 | ... := ...[0] | tarslip.go:15:2:15:30 | ... := ...[0] | tarslip.go:16:14:16:34 | call to Dir | Unsanitized archive entry, which may contain '..', is used in a $@. | tarslip.go:16:14:16:34 | call to Dir | file system operation | +| tst.go:23:2:43:2 | range statement[1] | tst.go:23:2:43:2 | range statement[1] | tst.go:29:20:29:23 | path | Unsanitized archive entry, which may contain '..', is used in a $@. | tst.go:29:20:29:23 | path | file system operation | diff --git a/go/ql/test/query-tests/Security/CWE-078/CommandInjection.expected b/go/ql/test/query-tests/Security/CWE-078/CommandInjection.expected index 3c93a4657ca..b55f04d6eed 100644 --- a/go/ql/test/query-tests/Security/CWE-078/CommandInjection.expected +++ b/go/ql/test/query-tests/Security/CWE-078/CommandInjection.expected @@ -1,52 +1,52 @@ edges -| ArgumentInjection.go:9:10:9:16 | selection of URL : pointer type | ArgumentInjection.go:10:31:10:34 | path | -| CommandInjection.go:9:13:9:19 | selection of URL : pointer type | CommandInjection.go:10:22:10:28 | cmdName | -| GitSubcommands.go:10:13:10:19 | selection of URL : pointer type | GitSubcommands.go:12:31:12:37 | tainted | -| GitSubcommands.go:10:13:10:19 | selection of URL : pointer type | GitSubcommands.go:13:31:13:37 | tainted | -| GitSubcommands.go:10:13:10:19 | selection of URL : pointer type | GitSubcommands.go:14:30:14:36 | tainted | -| GitSubcommands.go:10:13:10:19 | selection of URL : pointer type | GitSubcommands.go:15:35:15:41 | tainted | -| GitSubcommands.go:10:13:10:19 | selection of URL : pointer type | GitSubcommands.go:16:36:16:42 | tainted | -| SanitizingDoubleDash.go:9:13:9:19 | selection of URL : pointer type | SanitizingDoubleDash.go:14:23:14:33 | slice expression | -| SanitizingDoubleDash.go:9:13:9:19 | selection of URL : pointer type | SanitizingDoubleDash.go:40:23:40:30 | arrayLit | -| SanitizingDoubleDash.go:9:13:9:19 | selection of URL : pointer type | SanitizingDoubleDash.go:54:23:54:30 | arrayLit | -| SanitizingDoubleDash.go:9:13:9:19 | selection of URL : pointer type | SanitizingDoubleDash.go:70:23:70:30 | arrayLit | -| SanitizingDoubleDash.go:9:13:9:19 | selection of URL : pointer type | SanitizingDoubleDash.go:80:23:80:29 | tainted | -| SanitizingDoubleDash.go:92:13:92:19 | selection of URL : pointer type | SanitizingDoubleDash.go:96:24:96:34 | slice expression | -| SanitizingDoubleDash.go:92:13:92:19 | selection of URL : pointer type | SanitizingDoubleDash.go:101:24:101:34 | slice expression | -| SanitizingDoubleDash.go:92:13:92:19 | selection of URL : pointer type | SanitizingDoubleDash.go:105:30:105:36 | tainted : string | -| SanitizingDoubleDash.go:92:13:92:19 | selection of URL : pointer type | SanitizingDoubleDash.go:106:24:106:31 | arrayLit | -| SanitizingDoubleDash.go:92:13:92:19 | selection of URL : pointer type | SanitizingDoubleDash.go:112:24:112:31 | arrayLit | -| SanitizingDoubleDash.go:92:13:92:19 | selection of URL : pointer type | SanitizingDoubleDash.go:118:24:118:31 | arrayLit | -| SanitizingDoubleDash.go:92:13:92:19 | selection of URL : pointer type | SanitizingDoubleDash.go:124:24:124:31 | arrayLit | -| SanitizingDoubleDash.go:92:13:92:19 | selection of URL : pointer type | SanitizingDoubleDash.go:130:24:130:31 | arrayLit | -| SanitizingDoubleDash.go:92:13:92:19 | selection of URL : pointer type | SanitizingDoubleDash.go:137:24:137:31 | arrayLit | -| SanitizingDoubleDash.go:92:13:92:19 | selection of URL : pointer type | SanitizingDoubleDash.go:144:24:144:31 | arrayLit | -| SanitizingDoubleDash.go:92:13:92:19 | selection of URL : pointer type | SanitizingDoubleDash.go:148:30:148:36 | tainted | -| SanitizingDoubleDash.go:92:13:92:19 | selection of URL : pointer type | SanitizingDoubleDash.go:152:24:152:30 | tainted | -| SanitizingDoubleDash.go:105:15:105:37 | slice literal [array] : string | SanitizingDoubleDash.go:106:24:106:31 | arrayLit | -| SanitizingDoubleDash.go:105:30:105:36 | tainted : string | SanitizingDoubleDash.go:105:15:105:37 | slice literal [array] : string | +| ArgumentInjection.go:9:10:9:16 | selection of URL | ArgumentInjection.go:10:31:10:34 | path | +| CommandInjection.go:9:13:9:19 | selection of URL | CommandInjection.go:10:22:10:28 | cmdName | +| GitSubcommands.go:10:13:10:19 | selection of URL | GitSubcommands.go:12:31:12:37 | tainted | +| GitSubcommands.go:10:13:10:19 | selection of URL | GitSubcommands.go:13:31:13:37 | tainted | +| GitSubcommands.go:10:13:10:19 | selection of URL | GitSubcommands.go:14:30:14:36 | tainted | +| GitSubcommands.go:10:13:10:19 | selection of URL | GitSubcommands.go:15:35:15:41 | tainted | +| GitSubcommands.go:10:13:10:19 | selection of URL | GitSubcommands.go:16:36:16:42 | tainted | +| SanitizingDoubleDash.go:9:13:9:19 | selection of URL | SanitizingDoubleDash.go:14:23:14:33 | slice expression | +| SanitizingDoubleDash.go:9:13:9:19 | selection of URL | SanitizingDoubleDash.go:40:23:40:30 | arrayLit | +| SanitizingDoubleDash.go:9:13:9:19 | selection of URL | SanitizingDoubleDash.go:54:23:54:30 | arrayLit | +| SanitizingDoubleDash.go:9:13:9:19 | selection of URL | SanitizingDoubleDash.go:70:23:70:30 | arrayLit | +| SanitizingDoubleDash.go:9:13:9:19 | selection of URL | SanitizingDoubleDash.go:80:23:80:29 | tainted | +| SanitizingDoubleDash.go:92:13:92:19 | selection of URL | SanitizingDoubleDash.go:96:24:96:34 | slice expression | +| SanitizingDoubleDash.go:92:13:92:19 | selection of URL | SanitizingDoubleDash.go:101:24:101:34 | slice expression | +| SanitizingDoubleDash.go:92:13:92:19 | selection of URL | SanitizingDoubleDash.go:105:30:105:36 | tainted | +| SanitizingDoubleDash.go:92:13:92:19 | selection of URL | SanitizingDoubleDash.go:106:24:106:31 | arrayLit | +| SanitizingDoubleDash.go:92:13:92:19 | selection of URL | SanitizingDoubleDash.go:112:24:112:31 | arrayLit | +| SanitizingDoubleDash.go:92:13:92:19 | selection of URL | SanitizingDoubleDash.go:118:24:118:31 | arrayLit | +| SanitizingDoubleDash.go:92:13:92:19 | selection of URL | SanitizingDoubleDash.go:124:24:124:31 | arrayLit | +| SanitizingDoubleDash.go:92:13:92:19 | selection of URL | SanitizingDoubleDash.go:130:24:130:31 | arrayLit | +| SanitizingDoubleDash.go:92:13:92:19 | selection of URL | SanitizingDoubleDash.go:137:24:137:31 | arrayLit | +| SanitizingDoubleDash.go:92:13:92:19 | selection of URL | SanitizingDoubleDash.go:144:24:144:31 | arrayLit | +| SanitizingDoubleDash.go:92:13:92:19 | selection of URL | SanitizingDoubleDash.go:148:30:148:36 | tainted | +| SanitizingDoubleDash.go:92:13:92:19 | selection of URL | SanitizingDoubleDash.go:152:24:152:30 | tainted | +| SanitizingDoubleDash.go:105:15:105:37 | slice literal [array] | SanitizingDoubleDash.go:106:24:106:31 | arrayLit | +| SanitizingDoubleDash.go:105:30:105:36 | tainted | SanitizingDoubleDash.go:105:15:105:37 | slice literal [array] | nodes -| ArgumentInjection.go:9:10:9:16 | selection of URL : pointer type | semmle.label | selection of URL : pointer type | +| ArgumentInjection.go:9:10:9:16 | selection of URL | semmle.label | selection of URL | | ArgumentInjection.go:10:31:10:34 | path | semmle.label | path | -| CommandInjection.go:9:13:9:19 | selection of URL : pointer type | semmle.label | selection of URL : pointer type | +| CommandInjection.go:9:13:9:19 | selection of URL | semmle.label | selection of URL | | CommandInjection.go:10:22:10:28 | cmdName | semmle.label | cmdName | -| GitSubcommands.go:10:13:10:19 | selection of URL : pointer type | semmle.label | selection of URL : pointer type | +| GitSubcommands.go:10:13:10:19 | selection of URL | semmle.label | selection of URL | | GitSubcommands.go:12:31:12:37 | tainted | semmle.label | tainted | | GitSubcommands.go:13:31:13:37 | tainted | semmle.label | tainted | | GitSubcommands.go:14:30:14:36 | tainted | semmle.label | tainted | | GitSubcommands.go:15:35:15:41 | tainted | semmle.label | tainted | | GitSubcommands.go:16:36:16:42 | tainted | semmle.label | tainted | -| SanitizingDoubleDash.go:9:13:9:19 | selection of URL : pointer type | semmle.label | selection of URL : pointer type | +| SanitizingDoubleDash.go:9:13:9:19 | selection of URL | semmle.label | selection of URL | | SanitizingDoubleDash.go:14:23:14:33 | slice expression | semmle.label | slice expression | | SanitizingDoubleDash.go:40:23:40:30 | arrayLit | semmle.label | arrayLit | | SanitizingDoubleDash.go:54:23:54:30 | arrayLit | semmle.label | arrayLit | | SanitizingDoubleDash.go:70:23:70:30 | arrayLit | semmle.label | arrayLit | | SanitizingDoubleDash.go:80:23:80:29 | tainted | semmle.label | tainted | -| SanitizingDoubleDash.go:92:13:92:19 | selection of URL : pointer type | semmle.label | selection of URL : pointer type | +| SanitizingDoubleDash.go:92:13:92:19 | selection of URL | semmle.label | selection of URL | | SanitizingDoubleDash.go:96:24:96:34 | slice expression | semmle.label | slice expression | | SanitizingDoubleDash.go:101:24:101:34 | slice expression | semmle.label | slice expression | -| SanitizingDoubleDash.go:105:15:105:37 | slice literal [array] : string | semmle.label | slice literal [array] : string | -| SanitizingDoubleDash.go:105:30:105:36 | tainted : string | semmle.label | tainted : string | +| SanitizingDoubleDash.go:105:15:105:37 | slice literal [array] | semmle.label | slice literal [array] | +| SanitizingDoubleDash.go:105:30:105:36 | tainted | semmle.label | tainted | | SanitizingDoubleDash.go:106:24:106:31 | arrayLit | semmle.label | arrayLit | | SanitizingDoubleDash.go:112:24:112:31 | arrayLit | semmle.label | arrayLit | | SanitizingDoubleDash.go:118:24:118:31 | arrayLit | semmle.label | arrayLit | @@ -58,26 +58,26 @@ nodes | SanitizingDoubleDash.go:152:24:152:30 | tainted | semmle.label | tainted | subpaths #select -| ArgumentInjection.go:10:31:10:34 | path | ArgumentInjection.go:9:10:9:16 | selection of URL : pointer type | ArgumentInjection.go:10:31:10:34 | path | This command depends on a $@. | ArgumentInjection.go:9:10:9:16 | selection of URL | user-provided value | -| CommandInjection.go:10:22:10:28 | cmdName | CommandInjection.go:9:13:9:19 | selection of URL : pointer type | CommandInjection.go:10:22:10:28 | cmdName | This command depends on a $@. | CommandInjection.go:9:13:9:19 | selection of URL | user-provided value | -| GitSubcommands.go:12:31:12:37 | tainted | GitSubcommands.go:10:13:10:19 | selection of URL : pointer type | GitSubcommands.go:12:31:12:37 | tainted | This command depends on a $@. | GitSubcommands.go:10:13:10:19 | selection of URL | user-provided value | -| GitSubcommands.go:13:31:13:37 | tainted | GitSubcommands.go:10:13:10:19 | selection of URL : pointer type | GitSubcommands.go:13:31:13:37 | tainted | This command depends on a $@. | GitSubcommands.go:10:13:10:19 | selection of URL | user-provided value | -| GitSubcommands.go:14:30:14:36 | tainted | GitSubcommands.go:10:13:10:19 | selection of URL : pointer type | GitSubcommands.go:14:30:14:36 | tainted | This command depends on a $@. | GitSubcommands.go:10:13:10:19 | selection of URL | user-provided value | -| GitSubcommands.go:15:35:15:41 | tainted | GitSubcommands.go:10:13:10:19 | selection of URL : pointer type | GitSubcommands.go:15:35:15:41 | tainted | This command depends on a $@. | GitSubcommands.go:10:13:10:19 | selection of URL | user-provided value | -| GitSubcommands.go:16:36:16:42 | tainted | GitSubcommands.go:10:13:10:19 | selection of URL : pointer type | GitSubcommands.go:16:36:16:42 | tainted | This command depends on a $@. | GitSubcommands.go:10:13:10:19 | selection of URL | user-provided value | -| SanitizingDoubleDash.go:14:23:14:33 | slice expression | SanitizingDoubleDash.go:9:13:9:19 | selection of URL : pointer type | SanitizingDoubleDash.go:14:23:14:33 | slice expression | This command depends on a $@. | SanitizingDoubleDash.go:9:13:9:19 | selection of URL | user-provided value | -| SanitizingDoubleDash.go:40:23:40:30 | arrayLit | SanitizingDoubleDash.go:9:13:9:19 | selection of URL : pointer type | SanitizingDoubleDash.go:40:23:40:30 | arrayLit | This command depends on a $@. | SanitizingDoubleDash.go:9:13:9:19 | selection of URL | user-provided value | -| SanitizingDoubleDash.go:54:23:54:30 | arrayLit | SanitizingDoubleDash.go:9:13:9:19 | selection of URL : pointer type | SanitizingDoubleDash.go:54:23:54:30 | arrayLit | This command depends on a $@. | SanitizingDoubleDash.go:9:13:9:19 | selection of URL | user-provided value | -| SanitizingDoubleDash.go:70:23:70:30 | arrayLit | SanitizingDoubleDash.go:9:13:9:19 | selection of URL : pointer type | SanitizingDoubleDash.go:70:23:70:30 | arrayLit | This command depends on a $@. | SanitizingDoubleDash.go:9:13:9:19 | selection of URL | user-provided value | -| SanitizingDoubleDash.go:80:23:80:29 | tainted | SanitizingDoubleDash.go:9:13:9:19 | selection of URL : pointer type | SanitizingDoubleDash.go:80:23:80:29 | tainted | This command depends on a $@. | SanitizingDoubleDash.go:9:13:9:19 | selection of URL | user-provided value | -| SanitizingDoubleDash.go:96:24:96:34 | slice expression | SanitizingDoubleDash.go:92:13:92:19 | selection of URL : pointer type | SanitizingDoubleDash.go:96:24:96:34 | slice expression | This command depends on a $@. | SanitizingDoubleDash.go:92:13:92:19 | selection of URL | user-provided value | -| SanitizingDoubleDash.go:101:24:101:34 | slice expression | SanitizingDoubleDash.go:92:13:92:19 | selection of URL : pointer type | SanitizingDoubleDash.go:101:24:101:34 | slice expression | This command depends on a $@. | SanitizingDoubleDash.go:92:13:92:19 | selection of URL | user-provided value | -| SanitizingDoubleDash.go:106:24:106:31 | arrayLit | SanitizingDoubleDash.go:92:13:92:19 | selection of URL : pointer type | SanitizingDoubleDash.go:106:24:106:31 | arrayLit | This command depends on a $@. | SanitizingDoubleDash.go:92:13:92:19 | selection of URL | user-provided value | -| SanitizingDoubleDash.go:112:24:112:31 | arrayLit | SanitizingDoubleDash.go:92:13:92:19 | selection of URL : pointer type | SanitizingDoubleDash.go:112:24:112:31 | arrayLit | This command depends on a $@. | SanitizingDoubleDash.go:92:13:92:19 | selection of URL | user-provided value | -| SanitizingDoubleDash.go:118:24:118:31 | arrayLit | SanitizingDoubleDash.go:92:13:92:19 | selection of URL : pointer type | SanitizingDoubleDash.go:118:24:118:31 | arrayLit | This command depends on a $@. | SanitizingDoubleDash.go:92:13:92:19 | selection of URL | user-provided value | -| SanitizingDoubleDash.go:124:24:124:31 | arrayLit | SanitizingDoubleDash.go:92:13:92:19 | selection of URL : pointer type | SanitizingDoubleDash.go:124:24:124:31 | arrayLit | This command depends on a $@. | SanitizingDoubleDash.go:92:13:92:19 | selection of URL | user-provided value | -| SanitizingDoubleDash.go:130:24:130:31 | arrayLit | SanitizingDoubleDash.go:92:13:92:19 | selection of URL : pointer type | SanitizingDoubleDash.go:130:24:130:31 | arrayLit | This command depends on a $@. | SanitizingDoubleDash.go:92:13:92:19 | selection of URL | user-provided value | -| SanitizingDoubleDash.go:137:24:137:31 | arrayLit | SanitizingDoubleDash.go:92:13:92:19 | selection of URL : pointer type | SanitizingDoubleDash.go:137:24:137:31 | arrayLit | This command depends on a $@. | SanitizingDoubleDash.go:92:13:92:19 | selection of URL | user-provided value | -| SanitizingDoubleDash.go:144:24:144:31 | arrayLit | SanitizingDoubleDash.go:92:13:92:19 | selection of URL : pointer type | SanitizingDoubleDash.go:144:24:144:31 | arrayLit | This command depends on a $@. | SanitizingDoubleDash.go:92:13:92:19 | selection of URL | user-provided value | -| SanitizingDoubleDash.go:148:30:148:36 | tainted | SanitizingDoubleDash.go:92:13:92:19 | selection of URL : pointer type | SanitizingDoubleDash.go:148:30:148:36 | tainted | This command depends on a $@. | SanitizingDoubleDash.go:92:13:92:19 | selection of URL | user-provided value | -| SanitizingDoubleDash.go:152:24:152:30 | tainted | SanitizingDoubleDash.go:92:13:92:19 | selection of URL : pointer type | SanitizingDoubleDash.go:152:24:152:30 | tainted | This command depends on a $@. | SanitizingDoubleDash.go:92:13:92:19 | selection of URL | user-provided value | +| ArgumentInjection.go:10:31:10:34 | path | ArgumentInjection.go:9:10:9:16 | selection of URL | ArgumentInjection.go:10:31:10:34 | path | This command depends on a $@. | ArgumentInjection.go:9:10:9:16 | selection of URL | user-provided value | +| CommandInjection.go:10:22:10:28 | cmdName | CommandInjection.go:9:13:9:19 | selection of URL | CommandInjection.go:10:22:10:28 | cmdName | This command depends on a $@. | CommandInjection.go:9:13:9:19 | selection of URL | user-provided value | +| GitSubcommands.go:12:31:12:37 | tainted | GitSubcommands.go:10:13:10:19 | selection of URL | GitSubcommands.go:12:31:12:37 | tainted | This command depends on a $@. | GitSubcommands.go:10:13:10:19 | selection of URL | user-provided value | +| GitSubcommands.go:13:31:13:37 | tainted | GitSubcommands.go:10:13:10:19 | selection of URL | GitSubcommands.go:13:31:13:37 | tainted | This command depends on a $@. | GitSubcommands.go:10:13:10:19 | selection of URL | user-provided value | +| GitSubcommands.go:14:30:14:36 | tainted | GitSubcommands.go:10:13:10:19 | selection of URL | GitSubcommands.go:14:30:14:36 | tainted | This command depends on a $@. | GitSubcommands.go:10:13:10:19 | selection of URL | user-provided value | +| GitSubcommands.go:15:35:15:41 | tainted | GitSubcommands.go:10:13:10:19 | selection of URL | GitSubcommands.go:15:35:15:41 | tainted | This command depends on a $@. | GitSubcommands.go:10:13:10:19 | selection of URL | user-provided value | +| GitSubcommands.go:16:36:16:42 | tainted | GitSubcommands.go:10:13:10:19 | selection of URL | GitSubcommands.go:16:36:16:42 | tainted | This command depends on a $@. | GitSubcommands.go:10:13:10:19 | selection of URL | user-provided value | +| SanitizingDoubleDash.go:14:23:14:33 | slice expression | SanitizingDoubleDash.go:9:13:9:19 | selection of URL | SanitizingDoubleDash.go:14:23:14:33 | slice expression | This command depends on a $@. | SanitizingDoubleDash.go:9:13:9:19 | selection of URL | user-provided value | +| SanitizingDoubleDash.go:40:23:40:30 | arrayLit | SanitizingDoubleDash.go:9:13:9:19 | selection of URL | SanitizingDoubleDash.go:40:23:40:30 | arrayLit | This command depends on a $@. | SanitizingDoubleDash.go:9:13:9:19 | selection of URL | user-provided value | +| SanitizingDoubleDash.go:54:23:54:30 | arrayLit | SanitizingDoubleDash.go:9:13:9:19 | selection of URL | SanitizingDoubleDash.go:54:23:54:30 | arrayLit | This command depends on a $@. | SanitizingDoubleDash.go:9:13:9:19 | selection of URL | user-provided value | +| SanitizingDoubleDash.go:70:23:70:30 | arrayLit | SanitizingDoubleDash.go:9:13:9:19 | selection of URL | SanitizingDoubleDash.go:70:23:70:30 | arrayLit | This command depends on a $@. | SanitizingDoubleDash.go:9:13:9:19 | selection of URL | user-provided value | +| SanitizingDoubleDash.go:80:23:80:29 | tainted | SanitizingDoubleDash.go:9:13:9:19 | selection of URL | SanitizingDoubleDash.go:80:23:80:29 | tainted | This command depends on a $@. | SanitizingDoubleDash.go:9:13:9:19 | selection of URL | user-provided value | +| SanitizingDoubleDash.go:96:24:96:34 | slice expression | SanitizingDoubleDash.go:92:13:92:19 | selection of URL | SanitizingDoubleDash.go:96:24:96:34 | slice expression | This command depends on a $@. | SanitizingDoubleDash.go:92:13:92:19 | selection of URL | user-provided value | +| SanitizingDoubleDash.go:101:24:101:34 | slice expression | SanitizingDoubleDash.go:92:13:92:19 | selection of URL | SanitizingDoubleDash.go:101:24:101:34 | slice expression | This command depends on a $@. | SanitizingDoubleDash.go:92:13:92:19 | selection of URL | user-provided value | +| SanitizingDoubleDash.go:106:24:106:31 | arrayLit | SanitizingDoubleDash.go:92:13:92:19 | selection of URL | SanitizingDoubleDash.go:106:24:106:31 | arrayLit | This command depends on a $@. | SanitizingDoubleDash.go:92:13:92:19 | selection of URL | user-provided value | +| SanitizingDoubleDash.go:112:24:112:31 | arrayLit | SanitizingDoubleDash.go:92:13:92:19 | selection of URL | SanitizingDoubleDash.go:112:24:112:31 | arrayLit | This command depends on a $@. | SanitizingDoubleDash.go:92:13:92:19 | selection of URL | user-provided value | +| SanitizingDoubleDash.go:118:24:118:31 | arrayLit | SanitizingDoubleDash.go:92:13:92:19 | selection of URL | SanitizingDoubleDash.go:118:24:118:31 | arrayLit | This command depends on a $@. | SanitizingDoubleDash.go:92:13:92:19 | selection of URL | user-provided value | +| SanitizingDoubleDash.go:124:24:124:31 | arrayLit | SanitizingDoubleDash.go:92:13:92:19 | selection of URL | SanitizingDoubleDash.go:124:24:124:31 | arrayLit | This command depends on a $@. | SanitizingDoubleDash.go:92:13:92:19 | selection of URL | user-provided value | +| SanitizingDoubleDash.go:130:24:130:31 | arrayLit | SanitizingDoubleDash.go:92:13:92:19 | selection of URL | SanitizingDoubleDash.go:130:24:130:31 | arrayLit | This command depends on a $@. | SanitizingDoubleDash.go:92:13:92:19 | selection of URL | user-provided value | +| SanitizingDoubleDash.go:137:24:137:31 | arrayLit | SanitizingDoubleDash.go:92:13:92:19 | selection of URL | SanitizingDoubleDash.go:137:24:137:31 | arrayLit | This command depends on a $@. | SanitizingDoubleDash.go:92:13:92:19 | selection of URL | user-provided value | +| SanitizingDoubleDash.go:144:24:144:31 | arrayLit | SanitizingDoubleDash.go:92:13:92:19 | selection of URL | SanitizingDoubleDash.go:144:24:144:31 | arrayLit | This command depends on a $@. | SanitizingDoubleDash.go:92:13:92:19 | selection of URL | user-provided value | +| SanitizingDoubleDash.go:148:30:148:36 | tainted | SanitizingDoubleDash.go:92:13:92:19 | selection of URL | SanitizingDoubleDash.go:148:30:148:36 | tainted | This command depends on a $@. | SanitizingDoubleDash.go:92:13:92:19 | selection of URL | user-provided value | +| SanitizingDoubleDash.go:152:24:152:30 | tainted | SanitizingDoubleDash.go:92:13:92:19 | selection of URL | SanitizingDoubleDash.go:152:24:152:30 | tainted | This command depends on a $@. | SanitizingDoubleDash.go:92:13:92:19 | selection of URL | user-provided value | diff --git a/go/ql/test/query-tests/Security/CWE-078/StoredCommand.expected b/go/ql/test/query-tests/Security/CWE-078/StoredCommand.expected index a01ffb68838..ea667480966 100644 --- a/go/ql/test/query-tests/Security/CWE-078/StoredCommand.expected +++ b/go/ql/test/query-tests/Security/CWE-078/StoredCommand.expected @@ -1,8 +1,8 @@ edges -| StoredCommand.go:11:2:11:27 | ... := ...[0] : pointer type | StoredCommand.go:14:22:14:28 | cmdName | +| StoredCommand.go:11:2:11:27 | ... := ...[0] | StoredCommand.go:14:22:14:28 | cmdName | nodes -| StoredCommand.go:11:2:11:27 | ... := ...[0] : pointer type | semmle.label | ... := ...[0] : pointer type | +| StoredCommand.go:11:2:11:27 | ... := ...[0] | semmle.label | ... := ...[0] | | StoredCommand.go:14:22:14:28 | cmdName | semmle.label | cmdName | subpaths #select -| StoredCommand.go:14:22:14:28 | cmdName | StoredCommand.go:11:2:11:27 | ... := ...[0] : pointer type | StoredCommand.go:14:22:14:28 | cmdName | This command depends on a $@. | StoredCommand.go:11:2:11:27 | ... := ...[0] | stored value | +| StoredCommand.go:14:22:14:28 | cmdName | StoredCommand.go:11:2:11:27 | ... := ...[0] | StoredCommand.go:14:22:14:28 | cmdName | This command depends on a $@. | StoredCommand.go:11:2:11:27 | ... := ...[0] | stored value | diff --git a/go/ql/test/query-tests/Security/CWE-079/ReflectedXss.expected b/go/ql/test/query-tests/Security/CWE-079/ReflectedXss.expected index a5a5028447a..428f3e9edd3 100644 --- a/go/ql/test/query-tests/Security/CWE-079/ReflectedXss.expected +++ b/go/ql/test/query-tests/Security/CWE-079/ReflectedXss.expected @@ -1,87 +1,87 @@ edges -| ReflectedXss.go:11:15:11:20 | selection of Form : Values | ReflectedXss.go:14:44:14:51 | username | -| contenttype.go:11:11:11:16 | selection of Form : Values | contenttype.go:17:11:17:22 | type conversion | -| contenttype.go:49:11:49:16 | selection of Form : Values | contenttype.go:53:34:53:37 | data | -| contenttype.go:63:10:63:28 | call to FormValue : string | contenttype.go:64:52:64:55 | data | -| contenttype.go:73:10:73:28 | call to FormValue : string | contenttype.go:79:11:79:14 | data | -| contenttype.go:88:10:88:28 | call to FormValue : string | contenttype.go:91:4:91:7 | data | -| contenttype.go:113:10:113:28 | call to FormValue : string | contenttype.go:114:50:114:53 | data | -| reflectedxsstest.go:27:2:27:38 | ... := ...[0] : pointer type | reflectedxsstest.go:28:10:28:57 | type conversion | -| reflectedxsstest.go:31:2:31:44 | ... := ...[0] : File | reflectedxsstest.go:33:10:33:57 | type conversion | -| reflectedxsstest.go:31:2:31:44 | ... := ...[1] : pointer type | reflectedxsstest.go:34:10:34:62 | type conversion | -| reflectedxsstest.go:38:2:38:35 | ... := ...[0] : pointer type | reflectedxsstest.go:44:10:44:55 | type conversion | -| reflectedxsstest.go:38:2:38:35 | ... := ...[0] : pointer type | reflectedxsstest.go:45:10:45:18 | byteSlice | -| reflectedxsstest.go:51:14:51:18 | selection of URL : pointer type | reflectedxsstest.go:54:11:54:21 | type conversion | -| tst.go:14:15:14:20 | selection of Form : Values | tst.go:18:12:18:39 | type conversion | -| tst.go:48:14:48:19 | selection of Form : Values | tst.go:53:12:53:26 | type conversion | -| websocketXss.go:30:7:30:10 | definition of xnet : slice type | websocketXss.go:32:24:32:27 | xnet | -| websocketXss.go:34:3:34:7 | definition of xnet2 : slice type | websocketXss.go:36:24:36:28 | xnet2 | -| websocketXss.go:40:3:40:40 | ... := ...[1] : slice type | websocketXss.go:41:24:41:29 | nhooyr | -| websocketXss.go:46:7:46:16 | definition of gorillaMsg : slice type | websocketXss.go:48:24:48:33 | gorillaMsg | -| websocketXss.go:50:3:50:10 | definition of gorilla2 : slice type | websocketXss.go:52:24:52:31 | gorilla2 | -| websocketXss.go:54:3:54:38 | ... := ...[1] : slice type | websocketXss.go:55:24:55:31 | gorilla3 | +| ReflectedXss.go:11:15:11:20 | selection of Form | ReflectedXss.go:14:44:14:51 | username | +| contenttype.go:11:11:11:16 | selection of Form | contenttype.go:17:11:17:22 | type conversion | +| contenttype.go:49:11:49:16 | selection of Form | contenttype.go:53:34:53:37 | data | +| contenttype.go:63:10:63:28 | call to FormValue | contenttype.go:64:52:64:55 | data | +| contenttype.go:73:10:73:28 | call to FormValue | contenttype.go:79:11:79:14 | data | +| contenttype.go:88:10:88:28 | call to FormValue | contenttype.go:91:4:91:7 | data | +| contenttype.go:113:10:113:28 | call to FormValue | contenttype.go:114:50:114:53 | data | +| reflectedxsstest.go:27:2:27:38 | ... := ...[0] | reflectedxsstest.go:28:10:28:57 | type conversion | +| reflectedxsstest.go:31:2:31:44 | ... := ...[0] | reflectedxsstest.go:33:10:33:57 | type conversion | +| reflectedxsstest.go:31:2:31:44 | ... := ...[1] | reflectedxsstest.go:34:10:34:62 | type conversion | +| reflectedxsstest.go:38:2:38:35 | ... := ...[0] | reflectedxsstest.go:44:10:44:55 | type conversion | +| reflectedxsstest.go:38:2:38:35 | ... := ...[0] | reflectedxsstest.go:45:10:45:18 | byteSlice | +| reflectedxsstest.go:51:14:51:18 | selection of URL | reflectedxsstest.go:54:11:54:21 | type conversion | +| tst.go:14:15:14:20 | selection of Form | tst.go:18:12:18:39 | type conversion | +| tst.go:48:14:48:19 | selection of Form | tst.go:53:12:53:26 | type conversion | +| websocketXss.go:30:7:30:10 | definition of xnet | websocketXss.go:32:24:32:27 | xnet | +| websocketXss.go:34:3:34:7 | definition of xnet2 | websocketXss.go:36:24:36:28 | xnet2 | +| websocketXss.go:40:3:40:40 | ... := ...[1] | websocketXss.go:41:24:41:29 | nhooyr | +| websocketXss.go:46:7:46:16 | definition of gorillaMsg | websocketXss.go:48:24:48:33 | gorillaMsg | +| websocketXss.go:50:3:50:10 | definition of gorilla2 | websocketXss.go:52:24:52:31 | gorilla2 | +| websocketXss.go:54:3:54:38 | ... := ...[1] | websocketXss.go:55:24:55:31 | gorilla3 | nodes -| ReflectedXss.go:11:15:11:20 | selection of Form : Values | semmle.label | selection of Form : Values | +| ReflectedXss.go:11:15:11:20 | selection of Form | semmle.label | selection of Form | | ReflectedXss.go:14:44:14:51 | username | semmle.label | username | -| contenttype.go:11:11:11:16 | selection of Form : Values | semmle.label | selection of Form : Values | +| contenttype.go:11:11:11:16 | selection of Form | semmle.label | selection of Form | | contenttype.go:17:11:17:22 | type conversion | semmle.label | type conversion | -| contenttype.go:49:11:49:16 | selection of Form : Values | semmle.label | selection of Form : Values | +| contenttype.go:49:11:49:16 | selection of Form | semmle.label | selection of Form | | contenttype.go:53:34:53:37 | data | semmle.label | data | -| contenttype.go:63:10:63:28 | call to FormValue : string | semmle.label | call to FormValue : string | +| contenttype.go:63:10:63:28 | call to FormValue | semmle.label | call to FormValue | | contenttype.go:64:52:64:55 | data | semmle.label | data | -| contenttype.go:73:10:73:28 | call to FormValue : string | semmle.label | call to FormValue : string | +| contenttype.go:73:10:73:28 | call to FormValue | semmle.label | call to FormValue | | contenttype.go:79:11:79:14 | data | semmle.label | data | -| contenttype.go:88:10:88:28 | call to FormValue : string | semmle.label | call to FormValue : string | +| contenttype.go:88:10:88:28 | call to FormValue | semmle.label | call to FormValue | | contenttype.go:91:4:91:7 | data | semmle.label | data | -| contenttype.go:113:10:113:28 | call to FormValue : string | semmle.label | call to FormValue : string | +| contenttype.go:113:10:113:28 | call to FormValue | semmle.label | call to FormValue | | contenttype.go:114:50:114:53 | data | semmle.label | data | -| reflectedxsstest.go:27:2:27:38 | ... := ...[0] : pointer type | semmle.label | ... := ...[0] : pointer type | +| reflectedxsstest.go:27:2:27:38 | ... := ...[0] | semmle.label | ... := ...[0] | | reflectedxsstest.go:28:10:28:57 | type conversion | semmle.label | type conversion | -| reflectedxsstest.go:31:2:31:44 | ... := ...[0] : File | semmle.label | ... := ...[0] : File | -| reflectedxsstest.go:31:2:31:44 | ... := ...[1] : pointer type | semmle.label | ... := ...[1] : pointer type | +| reflectedxsstest.go:31:2:31:44 | ... := ...[0] | semmle.label | ... := ...[0] | +| reflectedxsstest.go:31:2:31:44 | ... := ...[1] | semmle.label | ... := ...[1] | | reflectedxsstest.go:33:10:33:57 | type conversion | semmle.label | type conversion | | reflectedxsstest.go:34:10:34:62 | type conversion | semmle.label | type conversion | -| reflectedxsstest.go:38:2:38:35 | ... := ...[0] : pointer type | semmle.label | ... := ...[0] : pointer type | +| reflectedxsstest.go:38:2:38:35 | ... := ...[0] | semmle.label | ... := ...[0] | | reflectedxsstest.go:44:10:44:55 | type conversion | semmle.label | type conversion | | reflectedxsstest.go:45:10:45:18 | byteSlice | semmle.label | byteSlice | -| reflectedxsstest.go:51:14:51:18 | selection of URL : pointer type | semmle.label | selection of URL : pointer type | +| reflectedxsstest.go:51:14:51:18 | selection of URL | semmle.label | selection of URL | | reflectedxsstest.go:54:11:54:21 | type conversion | semmle.label | type conversion | -| tst.go:14:15:14:20 | selection of Form : Values | semmle.label | selection of Form : Values | +| tst.go:14:15:14:20 | selection of Form | semmle.label | selection of Form | | tst.go:18:12:18:39 | type conversion | semmle.label | type conversion | -| tst.go:48:14:48:19 | selection of Form : Values | semmle.label | selection of Form : Values | +| tst.go:48:14:48:19 | selection of Form | semmle.label | selection of Form | | tst.go:53:12:53:26 | type conversion | semmle.label | type conversion | -| websocketXss.go:30:7:30:10 | definition of xnet : slice type | semmle.label | definition of xnet : slice type | +| websocketXss.go:30:7:30:10 | definition of xnet | semmle.label | definition of xnet | | websocketXss.go:32:24:32:27 | xnet | semmle.label | xnet | -| websocketXss.go:34:3:34:7 | definition of xnet2 : slice type | semmle.label | definition of xnet2 : slice type | +| websocketXss.go:34:3:34:7 | definition of xnet2 | semmle.label | definition of xnet2 | | websocketXss.go:36:24:36:28 | xnet2 | semmle.label | xnet2 | -| websocketXss.go:40:3:40:40 | ... := ...[1] : slice type | semmle.label | ... := ...[1] : slice type | +| websocketXss.go:40:3:40:40 | ... := ...[1] | semmle.label | ... := ...[1] | | websocketXss.go:41:24:41:29 | nhooyr | semmle.label | nhooyr | -| websocketXss.go:46:7:46:16 | definition of gorillaMsg : slice type | semmle.label | definition of gorillaMsg : slice type | +| websocketXss.go:46:7:46:16 | definition of gorillaMsg | semmle.label | definition of gorillaMsg | | websocketXss.go:48:24:48:33 | gorillaMsg | semmle.label | gorillaMsg | -| websocketXss.go:50:3:50:10 | definition of gorilla2 : slice type | semmle.label | definition of gorilla2 : slice type | +| websocketXss.go:50:3:50:10 | definition of gorilla2 | semmle.label | definition of gorilla2 | | websocketXss.go:52:24:52:31 | gorilla2 | semmle.label | gorilla2 | -| websocketXss.go:54:3:54:38 | ... := ...[1] : slice type | semmle.label | ... := ...[1] : slice type | +| websocketXss.go:54:3:54:38 | ... := ...[1] | semmle.label | ... := ...[1] | | websocketXss.go:55:24:55:31 | gorilla3 | semmle.label | gorilla3 | subpaths #select -| ReflectedXss.go:14:44:14:51 | username | ReflectedXss.go:11:15:11:20 | selection of Form : Values | ReflectedXss.go:14:44:14:51 | username | Cross-site scripting vulnerability due to $@. | ReflectedXss.go:11:15:11:20 | selection of Form | user-provided value | ReflectedXss.go:0:0:0:0 | ReflectedXss.go | | -| contenttype.go:17:11:17:22 | type conversion | contenttype.go:11:11:11:16 | selection of Form : Values | contenttype.go:17:11:17:22 | type conversion | Cross-site scripting vulnerability due to $@. | contenttype.go:11:11:11:16 | selection of Form | user-provided value | contenttype.go:0:0:0:0 | contenttype.go | | -| contenttype.go:53:34:53:37 | data | contenttype.go:49:11:49:16 | selection of Form : Values | contenttype.go:53:34:53:37 | data | Cross-site scripting vulnerability due to $@. | contenttype.go:49:11:49:16 | selection of Form | user-provided value | contenttype.go:0:0:0:0 | contenttype.go | | -| contenttype.go:64:52:64:55 | data | contenttype.go:63:10:63:28 | call to FormValue : string | contenttype.go:64:52:64:55 | data | Cross-site scripting vulnerability due to $@. | contenttype.go:63:10:63:28 | call to FormValue | user-provided value | contenttype.go:0:0:0:0 | contenttype.go | | -| contenttype.go:79:11:79:14 | data | contenttype.go:73:10:73:28 | call to FormValue : string | contenttype.go:79:11:79:14 | data | Cross-site scripting vulnerability due to $@. | contenttype.go:73:10:73:28 | call to FormValue | user-provided value | contenttype.go:0:0:0:0 | contenttype.go | | -| contenttype.go:91:4:91:7 | data | contenttype.go:88:10:88:28 | call to FormValue : string | contenttype.go:91:4:91:7 | data | Cross-site scripting vulnerability due to $@. | contenttype.go:88:10:88:28 | call to FormValue | user-provided value | contenttype.go:0:0:0:0 | contenttype.go | | -| contenttype.go:114:50:114:53 | data | contenttype.go:113:10:113:28 | call to FormValue : string | contenttype.go:114:50:114:53 | data | Cross-site scripting vulnerability due to $@. | contenttype.go:113:10:113:28 | call to FormValue | user-provided value | contenttype.go:0:0:0:0 | contenttype.go | | -| reflectedxsstest.go:28:10:28:57 | type conversion | reflectedxsstest.go:27:2:27:38 | ... := ...[0] : pointer type | reflectedxsstest.go:28:10:28:57 | type conversion | Cross-site scripting vulnerability due to $@. | reflectedxsstest.go:27:2:27:38 | ... := ...[0] | user-provided value | reflectedxsstest.go:0:0:0:0 | reflectedxsstest.go | | -| reflectedxsstest.go:33:10:33:57 | type conversion | reflectedxsstest.go:31:2:31:44 | ... := ...[0] : File | reflectedxsstest.go:33:10:33:57 | type conversion | Cross-site scripting vulnerability due to $@. | reflectedxsstest.go:31:2:31:44 | ... := ...[0] | user-provided value | reflectedxsstest.go:0:0:0:0 | reflectedxsstest.go | | -| reflectedxsstest.go:34:10:34:62 | type conversion | reflectedxsstest.go:31:2:31:44 | ... := ...[1] : pointer type | reflectedxsstest.go:34:10:34:62 | type conversion | Cross-site scripting vulnerability due to $@. | reflectedxsstest.go:31:2:31:44 | ... := ...[1] | user-provided value | reflectedxsstest.go:0:0:0:0 | reflectedxsstest.go | | -| reflectedxsstest.go:44:10:44:55 | type conversion | reflectedxsstest.go:38:2:38:35 | ... := ...[0] : pointer type | reflectedxsstest.go:44:10:44:55 | type conversion | Cross-site scripting vulnerability due to $@. | reflectedxsstest.go:38:2:38:35 | ... := ...[0] | user-provided value | reflectedxsstest.go:0:0:0:0 | reflectedxsstest.go | | -| reflectedxsstest.go:45:10:45:18 | byteSlice | reflectedxsstest.go:38:2:38:35 | ... := ...[0] : pointer type | reflectedxsstest.go:45:10:45:18 | byteSlice | Cross-site scripting vulnerability due to $@. | reflectedxsstest.go:38:2:38:35 | ... := ...[0] | user-provided value | reflectedxsstest.go:0:0:0:0 | reflectedxsstest.go | | -| reflectedxsstest.go:54:11:54:21 | type conversion | reflectedxsstest.go:51:14:51:18 | selection of URL : pointer type | reflectedxsstest.go:54:11:54:21 | type conversion | Cross-site scripting vulnerability due to $@. | reflectedxsstest.go:51:14:51:18 | selection of URL | user-provided value | reflectedxsstest.go:0:0:0:0 | reflectedxsstest.go | | -| tst.go:18:12:18:39 | type conversion | tst.go:14:15:14:20 | selection of Form : Values | tst.go:18:12:18:39 | type conversion | Cross-site scripting vulnerability due to $@. | tst.go:14:15:14:20 | selection of Form | user-provided value | tst.go:0:0:0:0 | tst.go | | -| tst.go:53:12:53:26 | type conversion | tst.go:48:14:48:19 | selection of Form : Values | tst.go:53:12:53:26 | type conversion | Cross-site scripting vulnerability due to $@. | tst.go:48:14:48:19 | selection of Form | user-provided value | tst.go:0:0:0:0 | tst.go | | -| websocketXss.go:32:24:32:27 | xnet | websocketXss.go:30:7:30:10 | definition of xnet : slice type | websocketXss.go:32:24:32:27 | xnet | Cross-site scripting vulnerability due to $@. | websocketXss.go:30:7:30:10 | definition of xnet | user-provided value | websocketXss.go:0:0:0:0 | websocketXss.go | | -| websocketXss.go:36:24:36:28 | xnet2 | websocketXss.go:34:3:34:7 | definition of xnet2 : slice type | websocketXss.go:36:24:36:28 | xnet2 | Cross-site scripting vulnerability due to $@. | websocketXss.go:34:3:34:7 | definition of xnet2 | user-provided value | websocketXss.go:0:0:0:0 | websocketXss.go | | -| websocketXss.go:41:24:41:29 | nhooyr | websocketXss.go:40:3:40:40 | ... := ...[1] : slice type | websocketXss.go:41:24:41:29 | nhooyr | Cross-site scripting vulnerability due to $@. | websocketXss.go:40:3:40:40 | ... := ...[1] | user-provided value | websocketXss.go:0:0:0:0 | websocketXss.go | | -| websocketXss.go:48:24:48:33 | gorillaMsg | websocketXss.go:46:7:46:16 | definition of gorillaMsg : slice type | websocketXss.go:48:24:48:33 | gorillaMsg | Cross-site scripting vulnerability due to $@. | websocketXss.go:46:7:46:16 | definition of gorillaMsg | user-provided value | websocketXss.go:0:0:0:0 | websocketXss.go | | -| websocketXss.go:52:24:52:31 | gorilla2 | websocketXss.go:50:3:50:10 | definition of gorilla2 : slice type | websocketXss.go:52:24:52:31 | gorilla2 | Cross-site scripting vulnerability due to $@. | websocketXss.go:50:3:50:10 | definition of gorilla2 | user-provided value | websocketXss.go:0:0:0:0 | websocketXss.go | | -| websocketXss.go:55:24:55:31 | gorilla3 | websocketXss.go:54:3:54:38 | ... := ...[1] : slice type | websocketXss.go:55:24:55:31 | gorilla3 | Cross-site scripting vulnerability due to $@. | websocketXss.go:54:3:54:38 | ... := ...[1] | user-provided value | websocketXss.go:0:0:0:0 | websocketXss.go | | +| ReflectedXss.go:14:44:14:51 | username | ReflectedXss.go:11:15:11:20 | selection of Form | ReflectedXss.go:14:44:14:51 | username | Cross-site scripting vulnerability due to $@. | ReflectedXss.go:11:15:11:20 | selection of Form | user-provided value | ReflectedXss.go:0:0:0:0 | ReflectedXss.go | | +| contenttype.go:17:11:17:22 | type conversion | contenttype.go:11:11:11:16 | selection of Form | contenttype.go:17:11:17:22 | type conversion | Cross-site scripting vulnerability due to $@. | contenttype.go:11:11:11:16 | selection of Form | user-provided value | contenttype.go:0:0:0:0 | contenttype.go | | +| contenttype.go:53:34:53:37 | data | contenttype.go:49:11:49:16 | selection of Form | contenttype.go:53:34:53:37 | data | Cross-site scripting vulnerability due to $@. | contenttype.go:49:11:49:16 | selection of Form | user-provided value | contenttype.go:0:0:0:0 | contenttype.go | | +| contenttype.go:64:52:64:55 | data | contenttype.go:63:10:63:28 | call to FormValue | contenttype.go:64:52:64:55 | data | Cross-site scripting vulnerability due to $@. | contenttype.go:63:10:63:28 | call to FormValue | user-provided value | contenttype.go:0:0:0:0 | contenttype.go | | +| contenttype.go:79:11:79:14 | data | contenttype.go:73:10:73:28 | call to FormValue | contenttype.go:79:11:79:14 | data | Cross-site scripting vulnerability due to $@. | contenttype.go:73:10:73:28 | call to FormValue | user-provided value | contenttype.go:0:0:0:0 | contenttype.go | | +| contenttype.go:91:4:91:7 | data | contenttype.go:88:10:88:28 | call to FormValue | contenttype.go:91:4:91:7 | data | Cross-site scripting vulnerability due to $@. | contenttype.go:88:10:88:28 | call to FormValue | user-provided value | contenttype.go:0:0:0:0 | contenttype.go | | +| contenttype.go:114:50:114:53 | data | contenttype.go:113:10:113:28 | call to FormValue | contenttype.go:114:50:114:53 | data | Cross-site scripting vulnerability due to $@. | contenttype.go:113:10:113:28 | call to FormValue | user-provided value | contenttype.go:0:0:0:0 | contenttype.go | | +| reflectedxsstest.go:28:10:28:57 | type conversion | reflectedxsstest.go:27:2:27:38 | ... := ...[0] | reflectedxsstest.go:28:10:28:57 | type conversion | Cross-site scripting vulnerability due to $@. | reflectedxsstest.go:27:2:27:38 | ... := ...[0] | user-provided value | reflectedxsstest.go:0:0:0:0 | reflectedxsstest.go | | +| reflectedxsstest.go:33:10:33:57 | type conversion | reflectedxsstest.go:31:2:31:44 | ... := ...[0] | reflectedxsstest.go:33:10:33:57 | type conversion | Cross-site scripting vulnerability due to $@. | reflectedxsstest.go:31:2:31:44 | ... := ...[0] | user-provided value | reflectedxsstest.go:0:0:0:0 | reflectedxsstest.go | | +| reflectedxsstest.go:34:10:34:62 | type conversion | reflectedxsstest.go:31:2:31:44 | ... := ...[1] | reflectedxsstest.go:34:10:34:62 | type conversion | Cross-site scripting vulnerability due to $@. | reflectedxsstest.go:31:2:31:44 | ... := ...[1] | user-provided value | reflectedxsstest.go:0:0:0:0 | reflectedxsstest.go | | +| reflectedxsstest.go:44:10:44:55 | type conversion | reflectedxsstest.go:38:2:38:35 | ... := ...[0] | reflectedxsstest.go:44:10:44:55 | type conversion | Cross-site scripting vulnerability due to $@. | reflectedxsstest.go:38:2:38:35 | ... := ...[0] | user-provided value | reflectedxsstest.go:0:0:0:0 | reflectedxsstest.go | | +| reflectedxsstest.go:45:10:45:18 | byteSlice | reflectedxsstest.go:38:2:38:35 | ... := ...[0] | reflectedxsstest.go:45:10:45:18 | byteSlice | Cross-site scripting vulnerability due to $@. | reflectedxsstest.go:38:2:38:35 | ... := ...[0] | user-provided value | reflectedxsstest.go:0:0:0:0 | reflectedxsstest.go | | +| reflectedxsstest.go:54:11:54:21 | type conversion | reflectedxsstest.go:51:14:51:18 | selection of URL | reflectedxsstest.go:54:11:54:21 | type conversion | Cross-site scripting vulnerability due to $@. | reflectedxsstest.go:51:14:51:18 | selection of URL | user-provided value | reflectedxsstest.go:0:0:0:0 | reflectedxsstest.go | | +| tst.go:18:12:18:39 | type conversion | tst.go:14:15:14:20 | selection of Form | tst.go:18:12:18:39 | type conversion | Cross-site scripting vulnerability due to $@. | tst.go:14:15:14:20 | selection of Form | user-provided value | tst.go:0:0:0:0 | tst.go | | +| tst.go:53:12:53:26 | type conversion | tst.go:48:14:48:19 | selection of Form | tst.go:53:12:53:26 | type conversion | Cross-site scripting vulnerability due to $@. | tst.go:48:14:48:19 | selection of Form | user-provided value | tst.go:0:0:0:0 | tst.go | | +| websocketXss.go:32:24:32:27 | xnet | websocketXss.go:30:7:30:10 | definition of xnet | websocketXss.go:32:24:32:27 | xnet | Cross-site scripting vulnerability due to $@. | websocketXss.go:30:7:30:10 | definition of xnet | user-provided value | websocketXss.go:0:0:0:0 | websocketXss.go | | +| websocketXss.go:36:24:36:28 | xnet2 | websocketXss.go:34:3:34:7 | definition of xnet2 | websocketXss.go:36:24:36:28 | xnet2 | Cross-site scripting vulnerability due to $@. | websocketXss.go:34:3:34:7 | definition of xnet2 | user-provided value | websocketXss.go:0:0:0:0 | websocketXss.go | | +| websocketXss.go:41:24:41:29 | nhooyr | websocketXss.go:40:3:40:40 | ... := ...[1] | websocketXss.go:41:24:41:29 | nhooyr | Cross-site scripting vulnerability due to $@. | websocketXss.go:40:3:40:40 | ... := ...[1] | user-provided value | websocketXss.go:0:0:0:0 | websocketXss.go | | +| websocketXss.go:48:24:48:33 | gorillaMsg | websocketXss.go:46:7:46:16 | definition of gorillaMsg | websocketXss.go:48:24:48:33 | gorillaMsg | Cross-site scripting vulnerability due to $@. | websocketXss.go:46:7:46:16 | definition of gorillaMsg | user-provided value | websocketXss.go:0:0:0:0 | websocketXss.go | | +| websocketXss.go:52:24:52:31 | gorilla2 | websocketXss.go:50:3:50:10 | definition of gorilla2 | websocketXss.go:52:24:52:31 | gorilla2 | Cross-site scripting vulnerability due to $@. | websocketXss.go:50:3:50:10 | definition of gorilla2 | user-provided value | websocketXss.go:0:0:0:0 | websocketXss.go | | +| websocketXss.go:55:24:55:31 | gorilla3 | websocketXss.go:54:3:54:38 | ... := ...[1] | websocketXss.go:55:24:55:31 | gorilla3 | Cross-site scripting vulnerability due to $@. | websocketXss.go:54:3:54:38 | ... := ...[1] | user-provided value | websocketXss.go:0:0:0:0 | websocketXss.go | | diff --git a/go/ql/test/query-tests/Security/CWE-079/StoredXss.expected b/go/ql/test/query-tests/Security/CWE-079/StoredXss.expected index b93e7c74201..1e513a5d4a9 100644 --- a/go/ql/test/query-tests/Security/CWE-079/StoredXss.expected +++ b/go/ql/test/query-tests/Security/CWE-079/StoredXss.expected @@ -1,16 +1,16 @@ edges -| StoredXss.go:13:21:13:31 | call to Name : string | StoredXss.go:13:21:13:36 | ...+... | -| stored.go:18:3:18:28 | ... := ...[0] : pointer type | stored.go:30:22:30:25 | name | -| stored.go:59:30:59:33 | definition of path : string | stored.go:61:22:61:25 | path | +| StoredXss.go:13:21:13:31 | call to Name | StoredXss.go:13:21:13:36 | ...+... | +| stored.go:18:3:18:28 | ... := ...[0] | stored.go:30:22:30:25 | name | +| stored.go:59:30:59:33 | definition of path | stored.go:61:22:61:25 | path | nodes -| StoredXss.go:13:21:13:31 | call to Name : string | semmle.label | call to Name : string | +| StoredXss.go:13:21:13:31 | call to Name | semmle.label | call to Name | | StoredXss.go:13:21:13:36 | ...+... | semmle.label | ...+... | -| stored.go:18:3:18:28 | ... := ...[0] : pointer type | semmle.label | ... := ...[0] : pointer type | +| stored.go:18:3:18:28 | ... := ...[0] | semmle.label | ... := ...[0] | | stored.go:30:22:30:25 | name | semmle.label | name | -| stored.go:59:30:59:33 | definition of path : string | semmle.label | definition of path : string | +| stored.go:59:30:59:33 | definition of path | semmle.label | definition of path | | stored.go:61:22:61:25 | path | semmle.label | path | subpaths #select -| StoredXss.go:13:21:13:36 | ...+... | StoredXss.go:13:21:13:31 | call to Name : string | StoredXss.go:13:21:13:36 | ...+... | Stored cross-site scripting vulnerability due to $@. | StoredXss.go:13:21:13:31 | call to Name | stored value | -| stored.go:30:22:30:25 | name | stored.go:18:3:18:28 | ... := ...[0] : pointer type | stored.go:30:22:30:25 | name | Stored cross-site scripting vulnerability due to $@. | stored.go:18:3:18:28 | ... := ...[0] | stored value | -| stored.go:61:22:61:25 | path | stored.go:59:30:59:33 | definition of path : string | stored.go:61:22:61:25 | path | Stored cross-site scripting vulnerability due to $@. | stored.go:59:30:59:33 | definition of path | stored value | +| StoredXss.go:13:21:13:36 | ...+... | StoredXss.go:13:21:13:31 | call to Name | StoredXss.go:13:21:13:36 | ...+... | Stored cross-site scripting vulnerability due to $@. | StoredXss.go:13:21:13:31 | call to Name | stored value | +| stored.go:30:22:30:25 | name | stored.go:18:3:18:28 | ... := ...[0] | stored.go:30:22:30:25 | name | Stored cross-site scripting vulnerability due to $@. | stored.go:18:3:18:28 | ... := ...[0] | stored value | +| stored.go:61:22:61:25 | path | stored.go:59:30:59:33 | definition of path | stored.go:61:22:61:25 | path | Stored cross-site scripting vulnerability due to $@. | stored.go:59:30:59:33 | definition of path | stored value | diff --git a/go/ql/test/query-tests/Security/CWE-089/SqlInjection.expected b/go/ql/test/query-tests/Security/CWE-089/SqlInjection.expected index 521824433a2..7f9f8a8f19f 100644 --- a/go/ql/test/query-tests/Security/CWE-089/SqlInjection.expected +++ b/go/ql/test/query-tests/Security/CWE-089/SqlInjection.expected @@ -1,112 +1,112 @@ edges -| SqlInjection.go:11:3:11:9 | selection of URL : pointer type | SqlInjection.go:12:11:12:11 | q | -| issue48.go:17:25:17:32 | selection of Body : ReadCloser | issue48.go:22:11:22:12 | q3 | -| issue48.go:27:26:27:33 | selection of Body : ReadCloser | issue48.go:32:11:32:12 | q4 | -| issue48.go:37:17:37:50 | type conversion : string | issue48.go:41:11:41:12 | q5 | -| issue48.go:37:24:37:30 | selection of URL : pointer type | issue48.go:37:17:37:50 | type conversion : string | -| main.go:10:11:10:16 | selection of Form : Values | main.go:10:11:10:28 | index expression | -| main.go:14:63:14:67 | selection of URL : pointer type | main.go:14:11:14:84 | call to Sprintf | -| main.go:15:63:15:70 | selection of Header : Header | main.go:15:11:15:85 | call to Sprintf | -| main.go:27:17:30:2 | &... [pointer, Category] : slice type | main.go:33:3:33:13 | RequestData [pointer, Category] : slice type | -| main.go:27:18:30:2 | struct literal [Category] : slice type | main.go:27:17:30:2 | &... [pointer, Category] : slice type | -| main.go:29:13:29:19 | selection of URL : pointer type | main.go:29:13:29:39 | index expression : slice type | -| main.go:29:13:29:39 | index expression : slice type | main.go:27:18:30:2 | struct literal [Category] : slice type | -| main.go:33:3:33:13 | RequestData [pointer, Category] : slice type | main.go:33:3:33:13 | implicit dereference [Category] : slice type | -| main.go:33:3:33:13 | implicit dereference [Category] : slice type | main.go:33:3:33:22 | selection of Category : slice type | -| main.go:33:3:33:22 | selection of Category : slice type | main.go:34:11:34:11 | q | -| main.go:38:2:38:12 | definition of RequestData [pointer, Category] : slice type | main.go:39:2:39:12 | RequestData [pointer, Category] : slice type | -| main.go:38:2:38:12 | definition of RequestData [pointer, Category] : slice type | main.go:42:3:42:13 | RequestData [pointer, Category] : slice type | -| main.go:39:2:39:12 | RequestData [pointer, Category] : slice type | main.go:39:2:39:12 | implicit dereference [Category] : slice type | -| main.go:39:2:39:12 | implicit dereference [Category] : slice type | main.go:38:2:38:12 | definition of RequestData [pointer, Category] : slice type | -| main.go:39:25:39:31 | selection of URL : pointer type | main.go:39:25:39:51 | index expression : slice type | -| main.go:39:25:39:51 | index expression : slice type | main.go:39:2:39:12 | implicit dereference [Category] : slice type | -| main.go:42:3:42:13 | RequestData [pointer, Category] : slice type | main.go:42:3:42:13 | implicit dereference [Category] : slice type | -| main.go:42:3:42:13 | implicit dereference [Category] : slice type | main.go:42:3:42:22 | selection of Category : slice type | -| main.go:42:3:42:22 | selection of Category : slice type | main.go:43:11:43:11 | q | -| main.go:47:2:47:12 | definition of RequestData [pointer, Category] : slice type | main.go:48:4:48:14 | RequestData [pointer, Category] : slice type | -| main.go:47:2:47:12 | definition of RequestData [pointer, Category] : slice type | main.go:51:3:51:13 | RequestData [pointer, Category] : slice type | -| main.go:48:3:48:14 | star expression [Category] : slice type | main.go:47:2:47:12 | definition of RequestData [pointer, Category] : slice type | -| main.go:48:4:48:14 | RequestData [pointer, Category] : slice type | main.go:48:3:48:14 | star expression [Category] : slice type | -| main.go:48:28:48:34 | selection of URL : pointer type | main.go:48:28:48:54 | index expression : slice type | -| main.go:48:28:48:54 | index expression : slice type | main.go:48:3:48:14 | star expression [Category] : slice type | -| main.go:51:3:51:13 | RequestData [pointer, Category] : slice type | main.go:51:3:51:13 | implicit dereference [Category] : slice type | -| main.go:51:3:51:13 | implicit dereference [Category] : slice type | main.go:51:3:51:22 | selection of Category : slice type | -| main.go:51:3:51:22 | selection of Category : slice type | main.go:52:11:52:11 | q | -| main.go:56:2:56:12 | definition of RequestData [pointer, Category] : slice type | main.go:57:4:57:14 | RequestData [pointer, Category] : slice type | -| main.go:56:2:56:12 | definition of RequestData [pointer, Category] : slice type | main.go:60:5:60:15 | RequestData [pointer, Category] : slice type | -| main.go:57:3:57:14 | star expression [Category] : slice type | main.go:56:2:56:12 | definition of RequestData [pointer, Category] : slice type | -| main.go:57:4:57:14 | RequestData [pointer, Category] : slice type | main.go:57:3:57:14 | star expression [Category] : slice type | -| main.go:57:28:57:34 | selection of URL : pointer type | main.go:57:28:57:54 | index expression : slice type | -| main.go:57:28:57:54 | index expression : slice type | main.go:57:3:57:14 | star expression [Category] : slice type | -| main.go:60:3:60:25 | selection of Category : slice type | main.go:61:11:61:11 | q | -| main.go:60:4:60:15 | star expression [Category] : slice type | main.go:60:3:60:25 | selection of Category : slice type | -| main.go:60:5:60:15 | RequestData [pointer, Category] : slice type | main.go:60:4:60:15 | star expression [Category] : slice type | -| mongoDB.go:40:20:40:30 | call to Referer : string | mongoDB.go:57:22:57:29 | pipeline | -| mongoDB.go:40:20:40:30 | call to Referer : string | mongoDB.go:61:27:61:32 | filter | -| mongoDB.go:40:20:40:30 | call to Referer : string | mongoDB.go:63:23:63:28 | filter | -| mongoDB.go:40:20:40:30 | call to Referer : string | mongoDB.go:64:22:64:27 | filter | -| mongoDB.go:40:20:40:30 | call to Referer : string | mongoDB.go:66:32:66:37 | filter | -| mongoDB.go:40:20:40:30 | call to Referer : string | mongoDB.go:69:17:69:22 | filter | -| mongoDB.go:40:20:40:30 | call to Referer : string | mongoDB.go:70:20:70:25 | filter | -| mongoDB.go:40:20:40:30 | call to Referer : string | mongoDB.go:71:29:71:34 | filter | -| mongoDB.go:40:20:40:30 | call to Referer : string | mongoDB.go:72:30:72:35 | filter | -| mongoDB.go:40:20:40:30 | call to Referer : string | mongoDB.go:73:29:73:34 | filter | -| mongoDB.go:40:20:40:30 | call to Referer : string | mongoDB.go:78:23:78:28 | filter | -| mongoDB.go:40:20:40:30 | call to Referer : string | mongoDB.go:79:23:79:28 | filter | -| mongoDB.go:40:20:40:30 | call to Referer : string | mongoDB.go:80:22:80:27 | filter | -| mongoDB.go:40:20:40:30 | call to Referer : string | mongoDB.go:81:18:81:25 | pipeline | +| SqlInjection.go:11:3:11:9 | selection of URL | SqlInjection.go:12:11:12:11 | q | +| issue48.go:17:25:17:32 | selection of Body | issue48.go:22:11:22:12 | q3 | +| issue48.go:27:26:27:33 | selection of Body | issue48.go:32:11:32:12 | q4 | +| issue48.go:37:17:37:50 | type conversion | issue48.go:41:11:41:12 | q5 | +| issue48.go:37:24:37:30 | selection of URL | issue48.go:37:17:37:50 | type conversion | +| main.go:10:11:10:16 | selection of Form | main.go:10:11:10:28 | index expression | +| main.go:14:63:14:67 | selection of URL | main.go:14:11:14:84 | call to Sprintf | +| main.go:15:63:15:70 | selection of Header | main.go:15:11:15:85 | call to Sprintf | +| main.go:27:17:30:2 | &... [pointer, Category] | main.go:33:3:33:13 | RequestData [pointer, Category] | +| main.go:27:18:30:2 | struct literal [Category] | main.go:27:17:30:2 | &... [pointer, Category] | +| main.go:29:13:29:19 | selection of URL | main.go:29:13:29:39 | index expression | +| main.go:29:13:29:39 | index expression | main.go:27:18:30:2 | struct literal [Category] | +| main.go:33:3:33:13 | RequestData [pointer, Category] | main.go:33:3:33:13 | implicit dereference [Category] | +| main.go:33:3:33:13 | implicit dereference [Category] | main.go:33:3:33:22 | selection of Category | +| main.go:33:3:33:22 | selection of Category | main.go:34:11:34:11 | q | +| main.go:38:2:38:12 | definition of RequestData [pointer, Category] | main.go:39:2:39:12 | RequestData [pointer, Category] | +| main.go:38:2:38:12 | definition of RequestData [pointer, Category] | main.go:42:3:42:13 | RequestData [pointer, Category] | +| main.go:39:2:39:12 | RequestData [pointer, Category] | main.go:39:2:39:12 | implicit dereference [Category] | +| main.go:39:2:39:12 | implicit dereference [Category] | main.go:38:2:38:12 | definition of RequestData [pointer, Category] | +| main.go:39:25:39:31 | selection of URL | main.go:39:25:39:51 | index expression | +| main.go:39:25:39:51 | index expression | main.go:39:2:39:12 | implicit dereference [Category] | +| main.go:42:3:42:13 | RequestData [pointer, Category] | main.go:42:3:42:13 | implicit dereference [Category] | +| main.go:42:3:42:13 | implicit dereference [Category] | main.go:42:3:42:22 | selection of Category | +| main.go:42:3:42:22 | selection of Category | main.go:43:11:43:11 | q | +| main.go:47:2:47:12 | definition of RequestData [pointer, Category] | main.go:48:4:48:14 | RequestData [pointer, Category] | +| main.go:47:2:47:12 | definition of RequestData [pointer, Category] | main.go:51:3:51:13 | RequestData [pointer, Category] | +| main.go:48:3:48:14 | star expression [Category] | main.go:47:2:47:12 | definition of RequestData [pointer, Category] | +| main.go:48:4:48:14 | RequestData [pointer, Category] | main.go:48:3:48:14 | star expression [Category] | +| main.go:48:28:48:34 | selection of URL | main.go:48:28:48:54 | index expression | +| main.go:48:28:48:54 | index expression | main.go:48:3:48:14 | star expression [Category] | +| main.go:51:3:51:13 | RequestData [pointer, Category] | main.go:51:3:51:13 | implicit dereference [Category] | +| main.go:51:3:51:13 | implicit dereference [Category] | main.go:51:3:51:22 | selection of Category | +| main.go:51:3:51:22 | selection of Category | main.go:52:11:52:11 | q | +| main.go:56:2:56:12 | definition of RequestData [pointer, Category] | main.go:57:4:57:14 | RequestData [pointer, Category] | +| main.go:56:2:56:12 | definition of RequestData [pointer, Category] | main.go:60:5:60:15 | RequestData [pointer, Category] | +| main.go:57:3:57:14 | star expression [Category] | main.go:56:2:56:12 | definition of RequestData [pointer, Category] | +| main.go:57:4:57:14 | RequestData [pointer, Category] | main.go:57:3:57:14 | star expression [Category] | +| main.go:57:28:57:34 | selection of URL | main.go:57:28:57:54 | index expression | +| main.go:57:28:57:54 | index expression | main.go:57:3:57:14 | star expression [Category] | +| main.go:60:3:60:25 | selection of Category | main.go:61:11:61:11 | q | +| main.go:60:4:60:15 | star expression [Category] | main.go:60:3:60:25 | selection of Category | +| main.go:60:5:60:15 | RequestData [pointer, Category] | main.go:60:4:60:15 | star expression [Category] | +| mongoDB.go:40:20:40:30 | call to Referer | mongoDB.go:57:22:57:29 | pipeline | +| mongoDB.go:40:20:40:30 | call to Referer | mongoDB.go:61:27:61:32 | filter | +| mongoDB.go:40:20:40:30 | call to Referer | mongoDB.go:63:23:63:28 | filter | +| mongoDB.go:40:20:40:30 | call to Referer | mongoDB.go:64:22:64:27 | filter | +| mongoDB.go:40:20:40:30 | call to Referer | mongoDB.go:66:32:66:37 | filter | +| mongoDB.go:40:20:40:30 | call to Referer | mongoDB.go:69:17:69:22 | filter | +| mongoDB.go:40:20:40:30 | call to Referer | mongoDB.go:70:20:70:25 | filter | +| mongoDB.go:40:20:40:30 | call to Referer | mongoDB.go:71:29:71:34 | filter | +| mongoDB.go:40:20:40:30 | call to Referer | mongoDB.go:72:30:72:35 | filter | +| mongoDB.go:40:20:40:30 | call to Referer | mongoDB.go:73:29:73:34 | filter | +| mongoDB.go:40:20:40:30 | call to Referer | mongoDB.go:78:23:78:28 | filter | +| mongoDB.go:40:20:40:30 | call to Referer | mongoDB.go:79:23:79:28 | filter | +| mongoDB.go:40:20:40:30 | call to Referer | mongoDB.go:80:22:80:27 | filter | +| mongoDB.go:40:20:40:30 | call to Referer | mongoDB.go:81:18:81:25 | pipeline | nodes -| SqlInjection.go:11:3:11:9 | selection of URL : pointer type | semmle.label | selection of URL : pointer type | +| SqlInjection.go:11:3:11:9 | selection of URL | semmle.label | selection of URL | | SqlInjection.go:12:11:12:11 | q | semmle.label | q | -| issue48.go:17:25:17:32 | selection of Body : ReadCloser | semmle.label | selection of Body : ReadCloser | +| issue48.go:17:25:17:32 | selection of Body | semmle.label | selection of Body | | issue48.go:22:11:22:12 | q3 | semmle.label | q3 | -| issue48.go:27:26:27:33 | selection of Body : ReadCloser | semmle.label | selection of Body : ReadCloser | +| issue48.go:27:26:27:33 | selection of Body | semmle.label | selection of Body | | issue48.go:32:11:32:12 | q4 | semmle.label | q4 | -| issue48.go:37:17:37:50 | type conversion : string | semmle.label | type conversion : string | -| issue48.go:37:24:37:30 | selection of URL : pointer type | semmle.label | selection of URL : pointer type | +| issue48.go:37:17:37:50 | type conversion | semmle.label | type conversion | +| issue48.go:37:24:37:30 | selection of URL | semmle.label | selection of URL | | issue48.go:41:11:41:12 | q5 | semmle.label | q5 | -| main.go:10:11:10:16 | selection of Form : Values | semmle.label | selection of Form : Values | +| main.go:10:11:10:16 | selection of Form | semmle.label | selection of Form | | main.go:10:11:10:28 | index expression | semmle.label | index expression | | main.go:14:11:14:84 | call to Sprintf | semmle.label | call to Sprintf | -| main.go:14:63:14:67 | selection of URL : pointer type | semmle.label | selection of URL : pointer type | +| main.go:14:63:14:67 | selection of URL | semmle.label | selection of URL | | main.go:15:11:15:85 | call to Sprintf | semmle.label | call to Sprintf | -| main.go:15:63:15:70 | selection of Header : Header | semmle.label | selection of Header : Header | -| main.go:27:17:30:2 | &... [pointer, Category] : slice type | semmle.label | &... [pointer, Category] : slice type | -| main.go:27:18:30:2 | struct literal [Category] : slice type | semmle.label | struct literal [Category] : slice type | -| main.go:29:13:29:19 | selection of URL : pointer type | semmle.label | selection of URL : pointer type | -| main.go:29:13:29:39 | index expression : slice type | semmle.label | index expression : slice type | -| main.go:33:3:33:13 | RequestData [pointer, Category] : slice type | semmle.label | RequestData [pointer, Category] : slice type | -| main.go:33:3:33:13 | implicit dereference [Category] : slice type | semmle.label | implicit dereference [Category] : slice type | -| main.go:33:3:33:22 | selection of Category : slice type | semmle.label | selection of Category : slice type | +| main.go:15:63:15:70 | selection of Header | semmle.label | selection of Header | +| main.go:27:17:30:2 | &... [pointer, Category] | semmle.label | &... [pointer, Category] | +| main.go:27:18:30:2 | struct literal [Category] | semmle.label | struct literal [Category] | +| main.go:29:13:29:19 | selection of URL | semmle.label | selection of URL | +| main.go:29:13:29:39 | index expression | semmle.label | index expression | +| main.go:33:3:33:13 | RequestData [pointer, Category] | semmle.label | RequestData [pointer, Category] | +| main.go:33:3:33:13 | implicit dereference [Category] | semmle.label | implicit dereference [Category] | +| main.go:33:3:33:22 | selection of Category | semmle.label | selection of Category | | main.go:34:11:34:11 | q | semmle.label | q | -| main.go:38:2:38:12 | definition of RequestData [pointer, Category] : slice type | semmle.label | definition of RequestData [pointer, Category] : slice type | -| main.go:39:2:39:12 | RequestData [pointer, Category] : slice type | semmle.label | RequestData [pointer, Category] : slice type | -| main.go:39:2:39:12 | implicit dereference [Category] : slice type | semmle.label | implicit dereference [Category] : slice type | -| main.go:39:25:39:31 | selection of URL : pointer type | semmle.label | selection of URL : pointer type | -| main.go:39:25:39:51 | index expression : slice type | semmle.label | index expression : slice type | -| main.go:42:3:42:13 | RequestData [pointer, Category] : slice type | semmle.label | RequestData [pointer, Category] : slice type | -| main.go:42:3:42:13 | implicit dereference [Category] : slice type | semmle.label | implicit dereference [Category] : slice type | -| main.go:42:3:42:22 | selection of Category : slice type | semmle.label | selection of Category : slice type | +| main.go:38:2:38:12 | definition of RequestData [pointer, Category] | semmle.label | definition of RequestData [pointer, Category] | +| main.go:39:2:39:12 | RequestData [pointer, Category] | semmle.label | RequestData [pointer, Category] | +| main.go:39:2:39:12 | implicit dereference [Category] | semmle.label | implicit dereference [Category] | +| main.go:39:25:39:31 | selection of URL | semmle.label | selection of URL | +| main.go:39:25:39:51 | index expression | semmle.label | index expression | +| main.go:42:3:42:13 | RequestData [pointer, Category] | semmle.label | RequestData [pointer, Category] | +| main.go:42:3:42:13 | implicit dereference [Category] | semmle.label | implicit dereference [Category] | +| main.go:42:3:42:22 | selection of Category | semmle.label | selection of Category | | main.go:43:11:43:11 | q | semmle.label | q | -| main.go:47:2:47:12 | definition of RequestData [pointer, Category] : slice type | semmle.label | definition of RequestData [pointer, Category] : slice type | -| main.go:48:3:48:14 | star expression [Category] : slice type | semmle.label | star expression [Category] : slice type | -| main.go:48:4:48:14 | RequestData [pointer, Category] : slice type | semmle.label | RequestData [pointer, Category] : slice type | -| main.go:48:28:48:34 | selection of URL : pointer type | semmle.label | selection of URL : pointer type | -| main.go:48:28:48:54 | index expression : slice type | semmle.label | index expression : slice type | -| main.go:51:3:51:13 | RequestData [pointer, Category] : slice type | semmle.label | RequestData [pointer, Category] : slice type | -| main.go:51:3:51:13 | implicit dereference [Category] : slice type | semmle.label | implicit dereference [Category] : slice type | -| main.go:51:3:51:22 | selection of Category : slice type | semmle.label | selection of Category : slice type | +| main.go:47:2:47:12 | definition of RequestData [pointer, Category] | semmle.label | definition of RequestData [pointer, Category] | +| main.go:48:3:48:14 | star expression [Category] | semmle.label | star expression [Category] | +| main.go:48:4:48:14 | RequestData [pointer, Category] | semmle.label | RequestData [pointer, Category] | +| main.go:48:28:48:34 | selection of URL | semmle.label | selection of URL | +| main.go:48:28:48:54 | index expression | semmle.label | index expression | +| main.go:51:3:51:13 | RequestData [pointer, Category] | semmle.label | RequestData [pointer, Category] | +| main.go:51:3:51:13 | implicit dereference [Category] | semmle.label | implicit dereference [Category] | +| main.go:51:3:51:22 | selection of Category | semmle.label | selection of Category | | main.go:52:11:52:11 | q | semmle.label | q | -| main.go:56:2:56:12 | definition of RequestData [pointer, Category] : slice type | semmle.label | definition of RequestData [pointer, Category] : slice type | -| main.go:57:3:57:14 | star expression [Category] : slice type | semmle.label | star expression [Category] : slice type | -| main.go:57:4:57:14 | RequestData [pointer, Category] : slice type | semmle.label | RequestData [pointer, Category] : slice type | -| main.go:57:28:57:34 | selection of URL : pointer type | semmle.label | selection of URL : pointer type | -| main.go:57:28:57:54 | index expression : slice type | semmle.label | index expression : slice type | -| main.go:60:3:60:25 | selection of Category : slice type | semmle.label | selection of Category : slice type | -| main.go:60:4:60:15 | star expression [Category] : slice type | semmle.label | star expression [Category] : slice type | -| main.go:60:5:60:15 | RequestData [pointer, Category] : slice type | semmle.label | RequestData [pointer, Category] : slice type | +| main.go:56:2:56:12 | definition of RequestData [pointer, Category] | semmle.label | definition of RequestData [pointer, Category] | +| main.go:57:3:57:14 | star expression [Category] | semmle.label | star expression [Category] | +| main.go:57:4:57:14 | RequestData [pointer, Category] | semmle.label | RequestData [pointer, Category] | +| main.go:57:28:57:34 | selection of URL | semmle.label | selection of URL | +| main.go:57:28:57:54 | index expression | semmle.label | index expression | +| main.go:60:3:60:25 | selection of Category | semmle.label | selection of Category | +| main.go:60:4:60:15 | star expression [Category] | semmle.label | star expression [Category] | +| main.go:60:5:60:15 | RequestData [pointer, Category] | semmle.label | RequestData [pointer, Category] | | main.go:61:11:61:11 | q | semmle.label | q | -| mongoDB.go:40:20:40:30 | call to Referer : string | semmle.label | call to Referer : string | +| mongoDB.go:40:20:40:30 | call to Referer | semmle.label | call to Referer | | mongoDB.go:57:22:57:29 | pipeline | semmle.label | pipeline | | mongoDB.go:61:27:61:32 | filter | semmle.label | filter | | mongoDB.go:63:23:63:28 | filter | semmle.label | filter | @@ -123,28 +123,28 @@ nodes | mongoDB.go:81:18:81:25 | pipeline | semmle.label | pipeline | subpaths #select -| SqlInjection.go:12:11:12:11 | q | SqlInjection.go:11:3:11:9 | selection of URL : pointer type | SqlInjection.go:12:11:12:11 | q | This query depends on a $@. | SqlInjection.go:11:3:11:9 | selection of URL | user-provided value | -| issue48.go:22:11:22:12 | q3 | issue48.go:17:25:17:32 | selection of Body : ReadCloser | issue48.go:22:11:22:12 | q3 | This query depends on a $@. | issue48.go:17:25:17:32 | selection of Body | user-provided value | -| issue48.go:32:11:32:12 | q4 | issue48.go:27:26:27:33 | selection of Body : ReadCloser | issue48.go:32:11:32:12 | q4 | This query depends on a $@. | issue48.go:27:26:27:33 | selection of Body | user-provided value | -| issue48.go:41:11:41:12 | q5 | issue48.go:37:24:37:30 | selection of URL : pointer type | issue48.go:41:11:41:12 | q5 | This query depends on a $@. | issue48.go:37:24:37:30 | selection of URL | user-provided value | -| main.go:10:11:10:28 | index expression | main.go:10:11:10:16 | selection of Form : Values | main.go:10:11:10:28 | index expression | This query depends on a $@. | main.go:10:11:10:16 | selection of Form | user-provided value | -| main.go:14:11:14:84 | call to Sprintf | main.go:14:63:14:67 | selection of URL : pointer type | main.go:14:11:14:84 | call to Sprintf | This query depends on a $@. | main.go:14:63:14:67 | selection of URL | user-provided value | -| main.go:15:11:15:85 | call to Sprintf | main.go:15:63:15:70 | selection of Header : Header | main.go:15:11:15:85 | call to Sprintf | This query depends on a $@. | main.go:15:63:15:70 | selection of Header | user-provided value | -| main.go:34:11:34:11 | q | main.go:29:13:29:19 | selection of URL : pointer type | main.go:34:11:34:11 | q | This query depends on a $@. | main.go:29:13:29:19 | selection of URL | user-provided value | -| main.go:43:11:43:11 | q | main.go:39:25:39:31 | selection of URL : pointer type | main.go:43:11:43:11 | q | This query depends on a $@. | main.go:39:25:39:31 | selection of URL | user-provided value | -| main.go:52:11:52:11 | q | main.go:48:28:48:34 | selection of URL : pointer type | main.go:52:11:52:11 | q | This query depends on a $@. | main.go:48:28:48:34 | selection of URL | user-provided value | -| main.go:61:11:61:11 | q | main.go:57:28:57:34 | selection of URL : pointer type | main.go:61:11:61:11 | q | This query depends on a $@. | main.go:57:28:57:34 | selection of URL | user-provided value | -| mongoDB.go:57:22:57:29 | pipeline | mongoDB.go:40:20:40:30 | call to Referer : string | mongoDB.go:57:22:57:29 | pipeline | This query depends on a $@. | mongoDB.go:40:20:40:30 | call to Referer | user-provided value | -| mongoDB.go:61:27:61:32 | filter | mongoDB.go:40:20:40:30 | call to Referer : string | mongoDB.go:61:27:61:32 | filter | This query depends on a $@. | mongoDB.go:40:20:40:30 | call to Referer | user-provided value | -| mongoDB.go:63:23:63:28 | filter | mongoDB.go:40:20:40:30 | call to Referer : string | mongoDB.go:63:23:63:28 | filter | This query depends on a $@. | mongoDB.go:40:20:40:30 | call to Referer | user-provided value | -| mongoDB.go:64:22:64:27 | filter | mongoDB.go:40:20:40:30 | call to Referer : string | mongoDB.go:64:22:64:27 | filter | This query depends on a $@. | mongoDB.go:40:20:40:30 | call to Referer | user-provided value | -| mongoDB.go:66:32:66:37 | filter | mongoDB.go:40:20:40:30 | call to Referer : string | mongoDB.go:66:32:66:37 | filter | This query depends on a $@. | mongoDB.go:40:20:40:30 | call to Referer | user-provided value | -| mongoDB.go:69:17:69:22 | filter | mongoDB.go:40:20:40:30 | call to Referer : string | mongoDB.go:69:17:69:22 | filter | This query depends on a $@. | mongoDB.go:40:20:40:30 | call to Referer | user-provided value | -| mongoDB.go:70:20:70:25 | filter | mongoDB.go:40:20:40:30 | call to Referer : string | mongoDB.go:70:20:70:25 | filter | This query depends on a $@. | mongoDB.go:40:20:40:30 | call to Referer | user-provided value | -| mongoDB.go:71:29:71:34 | filter | mongoDB.go:40:20:40:30 | call to Referer : string | mongoDB.go:71:29:71:34 | filter | This query depends on a $@. | mongoDB.go:40:20:40:30 | call to Referer | user-provided value | -| mongoDB.go:72:30:72:35 | filter | mongoDB.go:40:20:40:30 | call to Referer : string | mongoDB.go:72:30:72:35 | filter | This query depends on a $@. | mongoDB.go:40:20:40:30 | call to Referer | user-provided value | -| mongoDB.go:73:29:73:34 | filter | mongoDB.go:40:20:40:30 | call to Referer : string | mongoDB.go:73:29:73:34 | filter | This query depends on a $@. | mongoDB.go:40:20:40:30 | call to Referer | user-provided value | -| mongoDB.go:78:23:78:28 | filter | mongoDB.go:40:20:40:30 | call to Referer : string | mongoDB.go:78:23:78:28 | filter | This query depends on a $@. | mongoDB.go:40:20:40:30 | call to Referer | user-provided value | -| mongoDB.go:79:23:79:28 | filter | mongoDB.go:40:20:40:30 | call to Referer : string | mongoDB.go:79:23:79:28 | filter | This query depends on a $@. | mongoDB.go:40:20:40:30 | call to Referer | user-provided value | -| mongoDB.go:80:22:80:27 | filter | mongoDB.go:40:20:40:30 | call to Referer : string | mongoDB.go:80:22:80:27 | filter | This query depends on a $@. | mongoDB.go:40:20:40:30 | call to Referer | user-provided value | -| mongoDB.go:81:18:81:25 | pipeline | mongoDB.go:40:20:40:30 | call to Referer : string | mongoDB.go:81:18:81:25 | pipeline | This query depends on a $@. | mongoDB.go:40:20:40:30 | call to Referer | user-provided value | +| SqlInjection.go:12:11:12:11 | q | SqlInjection.go:11:3:11:9 | selection of URL | SqlInjection.go:12:11:12:11 | q | This query depends on a $@. | SqlInjection.go:11:3:11:9 | selection of URL | user-provided value | +| issue48.go:22:11:22:12 | q3 | issue48.go:17:25:17:32 | selection of Body | issue48.go:22:11:22:12 | q3 | This query depends on a $@. | issue48.go:17:25:17:32 | selection of Body | user-provided value | +| issue48.go:32:11:32:12 | q4 | issue48.go:27:26:27:33 | selection of Body | issue48.go:32:11:32:12 | q4 | This query depends on a $@. | issue48.go:27:26:27:33 | selection of Body | user-provided value | +| issue48.go:41:11:41:12 | q5 | issue48.go:37:24:37:30 | selection of URL | issue48.go:41:11:41:12 | q5 | This query depends on a $@. | issue48.go:37:24:37:30 | selection of URL | user-provided value | +| main.go:10:11:10:28 | index expression | main.go:10:11:10:16 | selection of Form | main.go:10:11:10:28 | index expression | This query depends on a $@. | main.go:10:11:10:16 | selection of Form | user-provided value | +| main.go:14:11:14:84 | call to Sprintf | main.go:14:63:14:67 | selection of URL | main.go:14:11:14:84 | call to Sprintf | This query depends on a $@. | main.go:14:63:14:67 | selection of URL | user-provided value | +| main.go:15:11:15:85 | call to Sprintf | main.go:15:63:15:70 | selection of Header | main.go:15:11:15:85 | call to Sprintf | This query depends on a $@. | main.go:15:63:15:70 | selection of Header | user-provided value | +| main.go:34:11:34:11 | q | main.go:29:13:29:19 | selection of URL | main.go:34:11:34:11 | q | This query depends on a $@. | main.go:29:13:29:19 | selection of URL | user-provided value | +| main.go:43:11:43:11 | q | main.go:39:25:39:31 | selection of URL | main.go:43:11:43:11 | q | This query depends on a $@. | main.go:39:25:39:31 | selection of URL | user-provided value | +| main.go:52:11:52:11 | q | main.go:48:28:48:34 | selection of URL | main.go:52:11:52:11 | q | This query depends on a $@. | main.go:48:28:48:34 | selection of URL | user-provided value | +| main.go:61:11:61:11 | q | main.go:57:28:57:34 | selection of URL | main.go:61:11:61:11 | q | This query depends on a $@. | main.go:57:28:57:34 | selection of URL | user-provided value | +| mongoDB.go:57:22:57:29 | pipeline | mongoDB.go:40:20:40:30 | call to Referer | mongoDB.go:57:22:57:29 | pipeline | This query depends on a $@. | mongoDB.go:40:20:40:30 | call to Referer | user-provided value | +| mongoDB.go:61:27:61:32 | filter | mongoDB.go:40:20:40:30 | call to Referer | mongoDB.go:61:27:61:32 | filter | This query depends on a $@. | mongoDB.go:40:20:40:30 | call to Referer | user-provided value | +| mongoDB.go:63:23:63:28 | filter | mongoDB.go:40:20:40:30 | call to Referer | mongoDB.go:63:23:63:28 | filter | This query depends on a $@. | mongoDB.go:40:20:40:30 | call to Referer | user-provided value | +| mongoDB.go:64:22:64:27 | filter | mongoDB.go:40:20:40:30 | call to Referer | mongoDB.go:64:22:64:27 | filter | This query depends on a $@. | mongoDB.go:40:20:40:30 | call to Referer | user-provided value | +| mongoDB.go:66:32:66:37 | filter | mongoDB.go:40:20:40:30 | call to Referer | mongoDB.go:66:32:66:37 | filter | This query depends on a $@. | mongoDB.go:40:20:40:30 | call to Referer | user-provided value | +| mongoDB.go:69:17:69:22 | filter | mongoDB.go:40:20:40:30 | call to Referer | mongoDB.go:69:17:69:22 | filter | This query depends on a $@. | mongoDB.go:40:20:40:30 | call to Referer | user-provided value | +| mongoDB.go:70:20:70:25 | filter | mongoDB.go:40:20:40:30 | call to Referer | mongoDB.go:70:20:70:25 | filter | This query depends on a $@. | mongoDB.go:40:20:40:30 | call to Referer | user-provided value | +| mongoDB.go:71:29:71:34 | filter | mongoDB.go:40:20:40:30 | call to Referer | mongoDB.go:71:29:71:34 | filter | This query depends on a $@. | mongoDB.go:40:20:40:30 | call to Referer | user-provided value | +| mongoDB.go:72:30:72:35 | filter | mongoDB.go:40:20:40:30 | call to Referer | mongoDB.go:72:30:72:35 | filter | This query depends on a $@. | mongoDB.go:40:20:40:30 | call to Referer | user-provided value | +| mongoDB.go:73:29:73:34 | filter | mongoDB.go:40:20:40:30 | call to Referer | mongoDB.go:73:29:73:34 | filter | This query depends on a $@. | mongoDB.go:40:20:40:30 | call to Referer | user-provided value | +| mongoDB.go:78:23:78:28 | filter | mongoDB.go:40:20:40:30 | call to Referer | mongoDB.go:78:23:78:28 | filter | This query depends on a $@. | mongoDB.go:40:20:40:30 | call to Referer | user-provided value | +| mongoDB.go:79:23:79:28 | filter | mongoDB.go:40:20:40:30 | call to Referer | mongoDB.go:79:23:79:28 | filter | This query depends on a $@. | mongoDB.go:40:20:40:30 | call to Referer | user-provided value | +| mongoDB.go:80:22:80:27 | filter | mongoDB.go:40:20:40:30 | call to Referer | mongoDB.go:80:22:80:27 | filter | This query depends on a $@. | mongoDB.go:40:20:40:30 | call to Referer | user-provided value | +| mongoDB.go:81:18:81:25 | pipeline | mongoDB.go:40:20:40:30 | call to Referer | mongoDB.go:81:18:81:25 | pipeline | This query depends on a $@. | mongoDB.go:40:20:40:30 | call to Referer | user-provided value | diff --git a/go/ql/test/query-tests/Security/CWE-089/StringBreak.expected b/go/ql/test/query-tests/Security/CWE-089/StringBreak.expected index cf3f362ead9..52c76ed52ce 100644 --- a/go/ql/test/query-tests/Security/CWE-089/StringBreak.expected +++ b/go/ql/test/query-tests/Security/CWE-089/StringBreak.expected @@ -1,20 +1,20 @@ edges -| StringBreak.go:10:2:10:40 | ... := ...[0] : slice type | StringBreak.go:14:47:14:57 | versionJSON | -| StringBreakMismatched.go:12:2:12:40 | ... := ...[0] : slice type | StringBreakMismatched.go:13:29:13:47 | type conversion : slice type | -| StringBreakMismatched.go:13:29:13:47 | type conversion : slice type | StringBreakMismatched.go:17:26:17:32 | escaped | -| StringBreakMismatched.go:24:2:24:40 | ... := ...[0] : slice type | StringBreakMismatched.go:25:29:25:47 | type conversion : slice type | -| StringBreakMismatched.go:25:29:25:47 | type conversion : slice type | StringBreakMismatched.go:29:27:29:33 | escaped | +| StringBreak.go:10:2:10:40 | ... := ...[0] | StringBreak.go:14:47:14:57 | versionJSON | +| StringBreakMismatched.go:12:2:12:40 | ... := ...[0] | StringBreakMismatched.go:13:29:13:47 | type conversion | +| StringBreakMismatched.go:13:29:13:47 | type conversion | StringBreakMismatched.go:17:26:17:32 | escaped | +| StringBreakMismatched.go:24:2:24:40 | ... := ...[0] | StringBreakMismatched.go:25:29:25:47 | type conversion | +| StringBreakMismatched.go:25:29:25:47 | type conversion | StringBreakMismatched.go:29:27:29:33 | escaped | nodes -| StringBreak.go:10:2:10:40 | ... := ...[0] : slice type | semmle.label | ... := ...[0] : slice type | +| StringBreak.go:10:2:10:40 | ... := ...[0] | semmle.label | ... := ...[0] | | StringBreak.go:14:47:14:57 | versionJSON | semmle.label | versionJSON | -| StringBreakMismatched.go:12:2:12:40 | ... := ...[0] : slice type | semmle.label | ... := ...[0] : slice type | -| StringBreakMismatched.go:13:29:13:47 | type conversion : slice type | semmle.label | type conversion : slice type | +| StringBreakMismatched.go:12:2:12:40 | ... := ...[0] | semmle.label | ... := ...[0] | +| StringBreakMismatched.go:13:29:13:47 | type conversion | semmle.label | type conversion | | StringBreakMismatched.go:17:26:17:32 | escaped | semmle.label | escaped | -| StringBreakMismatched.go:24:2:24:40 | ... := ...[0] : slice type | semmle.label | ... := ...[0] : slice type | -| StringBreakMismatched.go:25:29:25:47 | type conversion : slice type | semmle.label | type conversion : slice type | +| StringBreakMismatched.go:24:2:24:40 | ... := ...[0] | semmle.label | ... := ...[0] | +| StringBreakMismatched.go:25:29:25:47 | type conversion | semmle.label | type conversion | | StringBreakMismatched.go:29:27:29:33 | escaped | semmle.label | escaped | subpaths #select -| StringBreak.go:14:47:14:57 | versionJSON | StringBreak.go:10:2:10:40 | ... := ...[0] : slice type | StringBreak.go:14:47:14:57 | versionJSON | If this $@ contains a single quote, it could break out of the enclosing quotes. | StringBreak.go:10:2:10:40 | ... := ...[0] | JSON value | -| StringBreakMismatched.go:17:26:17:32 | escaped | StringBreakMismatched.go:12:2:12:40 | ... := ...[0] : slice type | StringBreakMismatched.go:17:26:17:32 | escaped | If this $@ contains a single quote, it could break out of the enclosing quotes. | StringBreakMismatched.go:12:2:12:40 | ... := ...[0] | JSON value | -| StringBreakMismatched.go:29:27:29:33 | escaped | StringBreakMismatched.go:24:2:24:40 | ... := ...[0] : slice type | StringBreakMismatched.go:29:27:29:33 | escaped | If this $@ contains a double quote, it could break out of the enclosing quotes. | StringBreakMismatched.go:24:2:24:40 | ... := ...[0] | JSON value | +| StringBreak.go:14:47:14:57 | versionJSON | StringBreak.go:10:2:10:40 | ... := ...[0] | StringBreak.go:14:47:14:57 | versionJSON | If this $@ contains a single quote, it could break out of the enclosing quotes. | StringBreak.go:10:2:10:40 | ... := ...[0] | JSON value | +| StringBreakMismatched.go:17:26:17:32 | escaped | StringBreakMismatched.go:12:2:12:40 | ... := ...[0] | StringBreakMismatched.go:17:26:17:32 | escaped | If this $@ contains a single quote, it could break out of the enclosing quotes. | StringBreakMismatched.go:12:2:12:40 | ... := ...[0] | JSON value | +| StringBreakMismatched.go:29:27:29:33 | escaped | StringBreakMismatched.go:24:2:24:40 | ... := ...[0] | StringBreakMismatched.go:29:27:29:33 | escaped | If this $@ contains a double quote, it could break out of the enclosing quotes. | StringBreakMismatched.go:24:2:24:40 | ... := ...[0] | JSON value | diff --git a/go/ql/test/query-tests/Security/CWE-190/AllocationSizeOverflow.expected b/go/ql/test/query-tests/Security/CWE-190/AllocationSizeOverflow.expected index 474cc5aa42c..4dd0a7d7cf4 100644 --- a/go/ql/test/query-tests/Security/CWE-190/AllocationSizeOverflow.expected +++ b/go/ql/test/query-tests/Security/CWE-190/AllocationSizeOverflow.expected @@ -1,42 +1,42 @@ edges -| AllocationSizeOverflow.go:6:2:6:33 | ... := ...[0] : slice type | AllocationSizeOverflow.go:10:10:10:22 | call to len | -| tst2.go:9:2:9:37 | ... := ...[0] : slice type | tst2.go:10:22:10:30 | call to len | -| tst2.go:14:2:14:29 | ... := ...[0] : slice type | tst2.go:15:22:15:30 | call to len | -| tst3.go:6:2:6:31 | ... := ...[0] : slice type | tst3.go:7:22:7:34 | call to len | -| tst3.go:6:2:6:31 | ... := ...[0] : slice type | tst3.go:24:16:24:28 | call to len | -| tst3.go:6:2:6:31 | ... := ...[0] : slice type | tst3.go:32:16:32:28 | call to len | -| tst.go:14:2:14:30 | ... = ...[0] : slice type | tst.go:15:22:15:34 | call to len | -| tst.go:20:2:20:31 | ... = ...[0] : slice type | tst.go:21:22:21:34 | call to len | -| tst.go:26:2:26:31 | ... = ...[0] : slice type | tst.go:27:26:27:38 | call to len | -| tst.go:34:2:34:30 | ... = ...[0] : slice type | tst.go:35:22:35:34 | call to len | +| AllocationSizeOverflow.go:6:2:6:33 | ... := ...[0] | AllocationSizeOverflow.go:10:10:10:22 | call to len | +| tst2.go:9:2:9:37 | ... := ...[0] | tst2.go:10:22:10:30 | call to len | +| tst2.go:14:2:14:29 | ... := ...[0] | tst2.go:15:22:15:30 | call to len | +| tst3.go:6:2:6:31 | ... := ...[0] | tst3.go:7:22:7:34 | call to len | +| tst3.go:6:2:6:31 | ... := ...[0] | tst3.go:24:16:24:28 | call to len | +| tst3.go:6:2:6:31 | ... := ...[0] | tst3.go:32:16:32:28 | call to len | +| tst.go:14:2:14:30 | ... = ...[0] | tst.go:15:22:15:34 | call to len | +| tst.go:20:2:20:31 | ... = ...[0] | tst.go:21:22:21:34 | call to len | +| tst.go:26:2:26:31 | ... = ...[0] | tst.go:27:26:27:38 | call to len | +| tst.go:34:2:34:30 | ... = ...[0] | tst.go:35:22:35:34 | call to len | nodes -| AllocationSizeOverflow.go:6:2:6:33 | ... := ...[0] : slice type | semmle.label | ... := ...[0] : slice type | +| AllocationSizeOverflow.go:6:2:6:33 | ... := ...[0] | semmle.label | ... := ...[0] | | AllocationSizeOverflow.go:10:10:10:22 | call to len | semmle.label | call to len | -| tst2.go:9:2:9:37 | ... := ...[0] : slice type | semmle.label | ... := ...[0] : slice type | +| tst2.go:9:2:9:37 | ... := ...[0] | semmle.label | ... := ...[0] | | tst2.go:10:22:10:30 | call to len | semmle.label | call to len | -| tst2.go:14:2:14:29 | ... := ...[0] : slice type | semmle.label | ... := ...[0] : slice type | +| tst2.go:14:2:14:29 | ... := ...[0] | semmle.label | ... := ...[0] | | tst2.go:15:22:15:30 | call to len | semmle.label | call to len | -| tst3.go:6:2:6:31 | ... := ...[0] : slice type | semmle.label | ... := ...[0] : slice type | +| tst3.go:6:2:6:31 | ... := ...[0] | semmle.label | ... := ...[0] | | tst3.go:7:22:7:34 | call to len | semmle.label | call to len | | tst3.go:24:16:24:28 | call to len | semmle.label | call to len | | tst3.go:32:16:32:28 | call to len | semmle.label | call to len | -| tst.go:14:2:14:30 | ... = ...[0] : slice type | semmle.label | ... = ...[0] : slice type | +| tst.go:14:2:14:30 | ... = ...[0] | semmle.label | ... = ...[0] | | tst.go:15:22:15:34 | call to len | semmle.label | call to len | -| tst.go:20:2:20:31 | ... = ...[0] : slice type | semmle.label | ... = ...[0] : slice type | +| tst.go:20:2:20:31 | ... = ...[0] | semmle.label | ... = ...[0] | | tst.go:21:22:21:34 | call to len | semmle.label | call to len | -| tst.go:26:2:26:31 | ... = ...[0] : slice type | semmle.label | ... = ...[0] : slice type | +| tst.go:26:2:26:31 | ... = ...[0] | semmle.label | ... = ...[0] | | tst.go:27:26:27:38 | call to len | semmle.label | call to len | -| tst.go:34:2:34:30 | ... = ...[0] : slice type | semmle.label | ... = ...[0] : slice type | +| tst.go:34:2:34:30 | ... = ...[0] | semmle.label | ... = ...[0] | | tst.go:35:22:35:34 | call to len | semmle.label | call to len | subpaths #select -| AllocationSizeOverflow.go:10:10:10:22 | call to len | AllocationSizeOverflow.go:6:2:6:33 | ... := ...[0] : slice type | AllocationSizeOverflow.go:10:10:10:22 | call to len | This operation, which is used in an $@, involves a $@ and might overflow. | AllocationSizeOverflow.go:11:25:11:28 | size | allocation | AllocationSizeOverflow.go:6:2:6:33 | ... := ...[0] : slice type | potentially large value | -| tst2.go:10:22:10:30 | call to len | tst2.go:9:2:9:37 | ... := ...[0] : slice type | tst2.go:10:22:10:30 | call to len | This operation, which is used in an $@, involves a $@ and might overflow. | tst2.go:10:22:10:32 | ...+... | allocation | tst2.go:9:2:9:37 | ... := ...[0] : slice type | potentially large value | -| tst2.go:15:22:15:30 | call to len | tst2.go:14:2:14:29 | ... := ...[0] : slice type | tst2.go:15:22:15:30 | call to len | This operation, which is used in an $@, involves a $@ and might overflow. | tst2.go:15:22:15:32 | ...+... | allocation | tst2.go:14:2:14:29 | ... := ...[0] : slice type | potentially large value | -| tst3.go:7:22:7:34 | call to len | tst3.go:6:2:6:31 | ... := ...[0] : slice type | tst3.go:7:22:7:34 | call to len | This operation, which is used in an $@, involves a $@ and might overflow. | tst3.go:7:22:7:36 | ...+... | allocation | tst3.go:6:2:6:31 | ... := ...[0] : slice type | potentially large value | -| tst3.go:24:16:24:28 | call to len | tst3.go:6:2:6:31 | ... := ...[0] : slice type | tst3.go:24:16:24:28 | call to len | This operation, which is used in an $@, involves a $@ and might overflow. | tst3.go:27:24:27:32 | newlength | allocation | tst3.go:6:2:6:31 | ... := ...[0] : slice type | potentially large value | -| tst3.go:32:16:32:28 | call to len | tst3.go:6:2:6:31 | ... := ...[0] : slice type | tst3.go:32:16:32:28 | call to len | This operation, which is used in an $@, involves a $@ and might overflow. | tst3.go:36:23:36:31 | newlength | allocation | tst3.go:6:2:6:31 | ... := ...[0] : slice type | potentially large value | -| tst.go:15:22:15:34 | call to len | tst.go:14:2:14:30 | ... = ...[0] : slice type | tst.go:15:22:15:34 | call to len | This operation, which is used in an $@, involves a $@ and might overflow. | tst.go:15:22:15:36 | ...+... | allocation | tst.go:14:2:14:30 | ... = ...[0] : slice type | potentially large value | -| tst.go:21:22:21:34 | call to len | tst.go:20:2:20:31 | ... = ...[0] : slice type | tst.go:21:22:21:34 | call to len | This operation, which is used in an $@, involves a $@ and might overflow. | tst.go:21:22:21:36 | ...+... | allocation | tst.go:20:2:20:31 | ... = ...[0] : slice type | potentially large value | -| tst.go:27:26:27:38 | call to len | tst.go:26:2:26:31 | ... = ...[0] : slice type | tst.go:27:26:27:38 | call to len | This operation, which is used in an $@, involves a $@ and might overflow. | tst.go:27:26:27:40 | ...+... | allocation | tst.go:26:2:26:31 | ... = ...[0] : slice type | potentially large value | -| tst.go:35:22:35:34 | call to len | tst.go:34:2:34:30 | ... = ...[0] : slice type | tst.go:35:22:35:34 | call to len | This operation, which is used in an $@, involves a $@ and might overflow. | tst.go:35:22:35:36 | ...+... | allocation | tst.go:34:2:34:30 | ... = ...[0] : slice type | potentially large value | +| AllocationSizeOverflow.go:10:10:10:22 | call to len | AllocationSizeOverflow.go:6:2:6:33 | ... := ...[0] | AllocationSizeOverflow.go:10:10:10:22 | call to len | This operation, which is used in an $@, involves a $@ and might overflow. | AllocationSizeOverflow.go:11:25:11:28 | size | allocation | AllocationSizeOverflow.go:6:2:6:33 | ... := ...[0] | potentially large value | +| tst2.go:10:22:10:30 | call to len | tst2.go:9:2:9:37 | ... := ...[0] | tst2.go:10:22:10:30 | call to len | This operation, which is used in an $@, involves a $@ and might overflow. | tst2.go:10:22:10:32 | ...+... | allocation | tst2.go:9:2:9:37 | ... := ...[0] | potentially large value | +| tst2.go:15:22:15:30 | call to len | tst2.go:14:2:14:29 | ... := ...[0] | tst2.go:15:22:15:30 | call to len | This operation, which is used in an $@, involves a $@ and might overflow. | tst2.go:15:22:15:32 | ...+... | allocation | tst2.go:14:2:14:29 | ... := ...[0] | potentially large value | +| tst3.go:7:22:7:34 | call to len | tst3.go:6:2:6:31 | ... := ...[0] | tst3.go:7:22:7:34 | call to len | This operation, which is used in an $@, involves a $@ and might overflow. | tst3.go:7:22:7:36 | ...+... | allocation | tst3.go:6:2:6:31 | ... := ...[0] | potentially large value | +| tst3.go:24:16:24:28 | call to len | tst3.go:6:2:6:31 | ... := ...[0] | tst3.go:24:16:24:28 | call to len | This operation, which is used in an $@, involves a $@ and might overflow. | tst3.go:27:24:27:32 | newlength | allocation | tst3.go:6:2:6:31 | ... := ...[0] | potentially large value | +| tst3.go:32:16:32:28 | call to len | tst3.go:6:2:6:31 | ... := ...[0] | tst3.go:32:16:32:28 | call to len | This operation, which is used in an $@, involves a $@ and might overflow. | tst3.go:36:23:36:31 | newlength | allocation | tst3.go:6:2:6:31 | ... := ...[0] | potentially large value | +| tst.go:15:22:15:34 | call to len | tst.go:14:2:14:30 | ... = ...[0] | tst.go:15:22:15:34 | call to len | This operation, which is used in an $@, involves a $@ and might overflow. | tst.go:15:22:15:36 | ...+... | allocation | tst.go:14:2:14:30 | ... = ...[0] | potentially large value | +| tst.go:21:22:21:34 | call to len | tst.go:20:2:20:31 | ... = ...[0] | tst.go:21:22:21:34 | call to len | This operation, which is used in an $@, involves a $@ and might overflow. | tst.go:21:22:21:36 | ...+... | allocation | tst.go:20:2:20:31 | ... = ...[0] | potentially large value | +| tst.go:27:26:27:38 | call to len | tst.go:26:2:26:31 | ... = ...[0] | tst.go:27:26:27:38 | call to len | This operation, which is used in an $@, involves a $@ and might overflow. | tst.go:27:26:27:40 | ...+... | allocation | tst.go:26:2:26:31 | ... = ...[0] | potentially large value | +| tst.go:35:22:35:34 | call to len | tst.go:34:2:34:30 | ... = ...[0] | tst.go:35:22:35:34 | call to len | This operation, which is used in an $@, involves a $@ and might overflow. | tst.go:35:22:35:36 | ...+... | allocation | tst.go:34:2:34:30 | ... = ...[0] | potentially large value | diff --git a/go/ql/test/query-tests/Security/CWE-209/StackTraceExposure.expected b/go/ql/test/query-tests/Security/CWE-209/StackTraceExposure.expected index ff8c7a9f72f..99042f7a497 100644 --- a/go/ql/test/query-tests/Security/CWE-209/StackTraceExposure.expected +++ b/go/ql/test/query-tests/Security/CWE-209/StackTraceExposure.expected @@ -1,8 +1,8 @@ edges -| test.go:14:2:14:4 | definition of buf : slice type | test.go:17:10:17:12 | buf | +| test.go:14:2:14:4 | definition of buf | test.go:17:10:17:12 | buf | nodes -| test.go:14:2:14:4 | definition of buf : slice type | semmle.label | definition of buf : slice type | +| test.go:14:2:14:4 | definition of buf | semmle.label | definition of buf | | test.go:17:10:17:12 | buf | semmle.label | buf | subpaths #select -| test.go:17:10:17:12 | buf | test.go:14:2:14:4 | definition of buf : slice type | test.go:17:10:17:12 | buf | HTTP response depends on $@ and may be exposed to an external user. | test.go:14:2:14:4 | definition of buf | stack trace information | +| test.go:17:10:17:12 | buf | test.go:14:2:14:4 | definition of buf | test.go:17:10:17:12 | buf | HTTP response depends on $@ and may be exposed to an external user. | test.go:14:2:14:4 | definition of buf | stack trace information | diff --git a/go/ql/test/query-tests/Security/CWE-312/CleartextLogging.expected b/go/ql/test/query-tests/Security/CWE-312/CleartextLogging.expected index 698779c4ad0..5daa517378e 100644 --- a/go/ql/test/query-tests/Security/CWE-312/CleartextLogging.expected +++ b/go/ql/test/query-tests/Security/CWE-312/CleartextLogging.expected @@ -1,135 +1,135 @@ edges -| klog.go:20:30:20:37 | selection of Header : Header | klog.go:22:15:22:20 | header | -| klog.go:28:13:28:20 | selection of Header : Header | klog.go:28:13:28:41 | call to Get | -| main.go:21:19:21:26 | password : string | main.go:22:29:22:34 | fields | -| overrides.go:9:9:9:16 | password : string | overrides.go:13:14:13:23 | call to String | -| passwords.go:8:12:8:12 | definition of x : string | passwords.go:9:14:9:14 | x | -| passwords.go:30:8:30:15 | password : string | passwords.go:8:12:8:12 | definition of x : string | -| passwords.go:34:28:34:35 | password : string | passwords.go:34:14:34:35 | ...+... | -| passwords.go:37:13:37:13 | x : string | passwords.go:39:14:39:17 | obj1 | -| passwords.go:42:6:42:13 | password : string | passwords.go:44:14:44:17 | obj2 | -| passwords.go:48:11:48:18 | password : string | passwords.go:47:14:47:17 | obj3 | -| passwords.go:86:16:86:36 | call to make : map type | passwords.go:88:14:88:26 | utilityObject | -| passwords.go:90:12:90:19 | password : string | passwords.go:91:23:91:28 | secret | -| passwords.go:101:33:101:40 | password : string | passwords.go:101:15:101:40 | ...+... | -| passwords.go:107:34:107:41 | password : string | passwords.go:107:16:107:41 | ...+... | -| passwords.go:112:33:112:40 | password : string | passwords.go:112:15:112:40 | ...+... | -| passwords.go:116:28:116:36 | password1 : stringable | passwords.go:116:14:116:45 | ...+... | -| passwords.go:118:12:123:2 | struct literal [x] : string | passwords.go:126:14:126:19 | config [x] : string | -| passwords.go:118:12:123:2 | struct literal [y] : string | passwords.go:127:14:127:19 | config [y] : string | -| passwords.go:119:13:119:13 | x : string | passwords.go:125:14:125:19 | config | -| passwords.go:121:13:121:20 | password : string | passwords.go:118:12:123:2 | struct literal [x] : string | -| passwords.go:121:13:121:20 | password : string | passwords.go:125:14:125:19 | config | -| passwords.go:122:13:122:25 | call to getPassword : string | passwords.go:118:12:123:2 | struct literal [y] : string | -| passwords.go:122:13:122:25 | call to getPassword : string | passwords.go:125:14:125:19 | config | -| passwords.go:126:14:126:19 | config [x] : string | passwords.go:126:14:126:21 | selection of x | -| passwords.go:127:14:127:19 | config [y] : string | passwords.go:127:14:127:21 | selection of y | -| protobuf.go:11:2:11:6 | definition of query [pointer, Description] : string | protobuf.go:12:2:12:6 | query [pointer, Description] : string | -| protobuf.go:11:2:11:6 | definition of query [pointer, Description] : string | protobuf.go:14:14:14:18 | query [pointer, Description] : string | -| protobuf.go:12:2:12:6 | implicit dereference [Description] : string | protobuf.go:11:2:11:6 | definition of query [pointer, Description] : string | -| protobuf.go:12:2:12:6 | query [pointer, Description] : string | protobuf.go:12:2:12:6 | implicit dereference [Description] : string | -| protobuf.go:12:22:12:29 | password : string | protobuf.go:12:2:12:6 | implicit dereference [Description] : string | -| protobuf.go:14:14:14:18 | query [pointer, Description] : string | protobuf.go:14:14:14:35 | call to GetDescription | -| protobuf.go:14:14:14:18 | query [pointer, Description] : string | protos/query/query.pb.go:117:7:117:7 | definition of x [pointer, Description] : string | -| protos/query/query.pb.go:117:7:117:7 | definition of x [pointer, Description] : string | protos/query/query.pb.go:119:10:119:10 | x [pointer, Description] : string | -| protos/query/query.pb.go:119:10:119:10 | implicit dereference [Description] : string | protos/query/query.pb.go:119:10:119:22 | selection of Description : string | -| protos/query/query.pb.go:119:10:119:10 | x [pointer, Description] : string | protos/query/query.pb.go:119:10:119:10 | implicit dereference [Description] : string | -| util.go:16:9:16:18 | selection of password : string | passwords.go:28:14:28:28 | call to getPassword | +| klog.go:20:30:20:37 | selection of Header | klog.go:22:15:22:20 | header | +| klog.go:28:13:28:20 | selection of Header | klog.go:28:13:28:41 | call to Get | +| main.go:21:19:21:26 | password | main.go:22:29:22:34 | fields | +| overrides.go:9:9:9:16 | password | overrides.go:13:14:13:23 | call to String | +| passwords.go:8:12:8:12 | definition of x | passwords.go:9:14:9:14 | x | +| passwords.go:30:8:30:15 | password | passwords.go:8:12:8:12 | definition of x | +| passwords.go:34:28:34:35 | password | passwords.go:34:14:34:35 | ...+... | +| passwords.go:37:13:37:13 | x | passwords.go:39:14:39:17 | obj1 | +| passwords.go:42:6:42:13 | password | passwords.go:44:14:44:17 | obj2 | +| passwords.go:48:11:48:18 | password | passwords.go:47:14:47:17 | obj3 | +| passwords.go:86:16:86:36 | call to make | passwords.go:88:14:88:26 | utilityObject | +| passwords.go:90:12:90:19 | password | passwords.go:91:23:91:28 | secret | +| passwords.go:101:33:101:40 | password | passwords.go:101:15:101:40 | ...+... | +| passwords.go:107:34:107:41 | password | passwords.go:107:16:107:41 | ...+... | +| passwords.go:112:33:112:40 | password | passwords.go:112:15:112:40 | ...+... | +| passwords.go:116:28:116:36 | password1 | passwords.go:116:14:116:45 | ...+... | +| passwords.go:118:12:123:2 | struct literal [x] | passwords.go:126:14:126:19 | config [x] | +| passwords.go:118:12:123:2 | struct literal [y] | passwords.go:127:14:127:19 | config [y] | +| passwords.go:119:13:119:13 | x | passwords.go:125:14:125:19 | config | +| passwords.go:121:13:121:20 | password | passwords.go:118:12:123:2 | struct literal [x] | +| passwords.go:121:13:121:20 | password | passwords.go:125:14:125:19 | config | +| passwords.go:122:13:122:25 | call to getPassword | passwords.go:118:12:123:2 | struct literal [y] | +| passwords.go:122:13:122:25 | call to getPassword | passwords.go:125:14:125:19 | config | +| passwords.go:126:14:126:19 | config [x] | passwords.go:126:14:126:21 | selection of x | +| passwords.go:127:14:127:19 | config [y] | passwords.go:127:14:127:21 | selection of y | +| protobuf.go:11:2:11:6 | definition of query [pointer, Description] | protobuf.go:12:2:12:6 | query [pointer, Description] | +| protobuf.go:11:2:11:6 | definition of query [pointer, Description] | protobuf.go:14:14:14:18 | query [pointer, Description] | +| protobuf.go:12:2:12:6 | implicit dereference [Description] | protobuf.go:11:2:11:6 | definition of query [pointer, Description] | +| protobuf.go:12:2:12:6 | query [pointer, Description] | protobuf.go:12:2:12:6 | implicit dereference [Description] | +| protobuf.go:12:22:12:29 | password | protobuf.go:12:2:12:6 | implicit dereference [Description] | +| protobuf.go:14:14:14:18 | query [pointer, Description] | protobuf.go:14:14:14:35 | call to GetDescription | +| protobuf.go:14:14:14:18 | query [pointer, Description] | protos/query/query.pb.go:117:7:117:7 | definition of x [pointer, Description] | +| protos/query/query.pb.go:117:7:117:7 | definition of x [pointer, Description] | protos/query/query.pb.go:119:10:119:10 | x [pointer, Description] | +| protos/query/query.pb.go:119:10:119:10 | implicit dereference [Description] | protos/query/query.pb.go:119:10:119:22 | selection of Description | +| protos/query/query.pb.go:119:10:119:10 | x [pointer, Description] | protos/query/query.pb.go:119:10:119:10 | implicit dereference [Description] | +| util.go:16:9:16:18 | selection of password | passwords.go:28:14:28:28 | call to getPassword | nodes -| klog.go:20:30:20:37 | selection of Header : Header | semmle.label | selection of Header : Header | +| klog.go:20:30:20:37 | selection of Header | semmle.label | selection of Header | | klog.go:22:15:22:20 | header | semmle.label | header | -| klog.go:28:13:28:20 | selection of Header : Header | semmle.label | selection of Header : Header | +| klog.go:28:13:28:20 | selection of Header | semmle.label | selection of Header | | klog.go:28:13:28:41 | call to Get | semmle.label | call to Get | | main.go:15:14:15:21 | password | semmle.label | password | | main.go:17:12:17:19 | password | semmle.label | password | | main.go:18:17:18:24 | password | semmle.label | password | -| main.go:21:19:21:26 | password : string | semmle.label | password : string | +| main.go:21:19:21:26 | password | semmle.label | password | | main.go:22:29:22:34 | fields | semmle.label | fields | | main.go:25:35:25:42 | password | semmle.label | password | -| overrides.go:9:9:9:16 | password : string | semmle.label | password : string | +| overrides.go:9:9:9:16 | password | semmle.label | password | | overrides.go:13:14:13:23 | call to String | semmle.label | call to String | -| passwords.go:8:12:8:12 | definition of x : string | semmle.label | definition of x : string | +| passwords.go:8:12:8:12 | definition of x | semmle.label | definition of x | | passwords.go:9:14:9:14 | x | semmle.label | x | | passwords.go:25:14:25:21 | password | semmle.label | password | | passwords.go:26:14:26:23 | selection of password | semmle.label | selection of password | | passwords.go:27:14:27:26 | call to getPassword | semmle.label | call to getPassword | | passwords.go:28:14:28:28 | call to getPassword | semmle.label | call to getPassword | -| passwords.go:30:8:30:15 | password : string | semmle.label | password : string | +| passwords.go:30:8:30:15 | password | semmle.label | password | | passwords.go:32:12:32:19 | password | semmle.label | password | | passwords.go:34:14:34:35 | ...+... | semmle.label | ...+... | -| passwords.go:34:28:34:35 | password : string | semmle.label | password : string | -| passwords.go:37:13:37:13 | x : string | semmle.label | x : string | +| passwords.go:34:28:34:35 | password | semmle.label | password | +| passwords.go:37:13:37:13 | x | semmle.label | x | | passwords.go:39:14:39:17 | obj1 | semmle.label | obj1 | -| passwords.go:42:6:42:13 | password : string | semmle.label | password : string | +| passwords.go:42:6:42:13 | password | semmle.label | password | | passwords.go:44:14:44:17 | obj2 | semmle.label | obj2 | | passwords.go:47:14:47:17 | obj3 | semmle.label | obj3 | -| passwords.go:48:11:48:18 | password : string | semmle.label | password : string | +| passwords.go:48:11:48:18 | password | semmle.label | password | | passwords.go:51:14:51:27 | fixed_password | semmle.label | fixed_password | -| passwords.go:86:16:86:36 | call to make : map type | semmle.label | call to make : map type | +| passwords.go:86:16:86:36 | call to make | semmle.label | call to make | | passwords.go:88:14:88:26 | utilityObject | semmle.label | utilityObject | -| passwords.go:90:12:90:19 | password : string | semmle.label | password : string | +| passwords.go:90:12:90:19 | password | semmle.label | password | | passwords.go:91:23:91:28 | secret | semmle.label | secret | | passwords.go:101:15:101:40 | ...+... | semmle.label | ...+... | -| passwords.go:101:33:101:40 | password : string | semmle.label | password : string | +| passwords.go:101:33:101:40 | password | semmle.label | password | | passwords.go:107:16:107:41 | ...+... | semmle.label | ...+... | -| passwords.go:107:34:107:41 | password : string | semmle.label | password : string | +| passwords.go:107:34:107:41 | password | semmle.label | password | | passwords.go:112:15:112:40 | ...+... | semmle.label | ...+... | -| passwords.go:112:33:112:40 | password : string | semmle.label | password : string | +| passwords.go:112:33:112:40 | password | semmle.label | password | | passwords.go:116:14:116:45 | ...+... | semmle.label | ...+... | -| passwords.go:116:28:116:36 | password1 : stringable | semmle.label | password1 : stringable | -| passwords.go:118:12:123:2 | struct literal [x] : string | semmle.label | struct literal [x] : string | -| passwords.go:118:12:123:2 | struct literal [y] : string | semmle.label | struct literal [y] : string | -| passwords.go:119:13:119:13 | x : string | semmle.label | x : string | -| passwords.go:121:13:121:20 | password : string | semmle.label | password : string | -| passwords.go:122:13:122:25 | call to getPassword : string | semmle.label | call to getPassword : string | +| passwords.go:116:28:116:36 | password1 | semmle.label | password1 | +| passwords.go:118:12:123:2 | struct literal [x] | semmle.label | struct literal [x] | +| passwords.go:118:12:123:2 | struct literal [y] | semmle.label | struct literal [y] | +| passwords.go:119:13:119:13 | x | semmle.label | x | +| passwords.go:121:13:121:20 | password | semmle.label | password | +| passwords.go:122:13:122:25 | call to getPassword | semmle.label | call to getPassword | | passwords.go:125:14:125:19 | config | semmle.label | config | -| passwords.go:126:14:126:19 | config [x] : string | semmle.label | config [x] : string | +| passwords.go:126:14:126:19 | config [x] | semmle.label | config [x] | | passwords.go:126:14:126:21 | selection of x | semmle.label | selection of x | -| passwords.go:127:14:127:19 | config [y] : string | semmle.label | config [y] : string | +| passwords.go:127:14:127:19 | config [y] | semmle.label | config [y] | | passwords.go:127:14:127:21 | selection of y | semmle.label | selection of y | -| protobuf.go:11:2:11:6 | definition of query [pointer, Description] : string | semmle.label | definition of query [pointer, Description] : string | -| protobuf.go:12:2:12:6 | implicit dereference [Description] : string | semmle.label | implicit dereference [Description] : string | -| protobuf.go:12:2:12:6 | query [pointer, Description] : string | semmle.label | query [pointer, Description] : string | -| protobuf.go:12:22:12:29 | password : string | semmle.label | password : string | -| protobuf.go:14:14:14:18 | query [pointer, Description] : string | semmle.label | query [pointer, Description] : string | +| protobuf.go:11:2:11:6 | definition of query [pointer, Description] | semmle.label | definition of query [pointer, Description] | +| protobuf.go:12:2:12:6 | implicit dereference [Description] | semmle.label | implicit dereference [Description] | +| protobuf.go:12:2:12:6 | query [pointer, Description] | semmle.label | query [pointer, Description] | +| protobuf.go:12:22:12:29 | password | semmle.label | password | +| protobuf.go:14:14:14:18 | query [pointer, Description] | semmle.label | query [pointer, Description] | | protobuf.go:14:14:14:35 | call to GetDescription | semmle.label | call to GetDescription | -| protos/query/query.pb.go:117:7:117:7 | definition of x [pointer, Description] : string | semmle.label | definition of x [pointer, Description] : string | -| protos/query/query.pb.go:119:10:119:10 | implicit dereference [Description] : string | semmle.label | implicit dereference [Description] : string | -| protos/query/query.pb.go:119:10:119:10 | x [pointer, Description] : string | semmle.label | x [pointer, Description] : string | -| protos/query/query.pb.go:119:10:119:22 | selection of Description : string | semmle.label | selection of Description : string | -| util.go:16:9:16:18 | selection of password : string | semmle.label | selection of password : string | +| protos/query/query.pb.go:117:7:117:7 | definition of x [pointer, Description] | semmle.label | definition of x [pointer, Description] | +| protos/query/query.pb.go:119:10:119:10 | implicit dereference [Description] | semmle.label | implicit dereference [Description] | +| protos/query/query.pb.go:119:10:119:10 | x [pointer, Description] | semmle.label | x [pointer, Description] | +| protos/query/query.pb.go:119:10:119:22 | selection of Description | semmle.label | selection of Description | +| util.go:16:9:16:18 | selection of password | semmle.label | selection of password | subpaths -| protobuf.go:14:14:14:18 | query [pointer, Description] : string | protos/query/query.pb.go:117:7:117:7 | definition of x [pointer, Description] : string | protos/query/query.pb.go:119:10:119:22 | selection of Description : string | protobuf.go:14:14:14:35 | call to GetDescription | +| protobuf.go:14:14:14:18 | query [pointer, Description] | protos/query/query.pb.go:117:7:117:7 | definition of x [pointer, Description] | protos/query/query.pb.go:119:10:119:22 | selection of Description | protobuf.go:14:14:14:35 | call to GetDescription | #select -| klog.go:22:15:22:20 | header | klog.go:20:30:20:37 | selection of Header : Header | klog.go:22:15:22:20 | header | $@ flows to a logging call. | klog.go:20:30:20:37 | selection of Header | Sensitive data returned by HTTP request headers | -| klog.go:28:13:28:41 | call to Get | klog.go:28:13:28:20 | selection of Header : Header | klog.go:28:13:28:41 | call to Get | $@ flows to a logging call. | klog.go:28:13:28:20 | selection of Header | Sensitive data returned by HTTP request headers | +| klog.go:22:15:22:20 | header | klog.go:20:30:20:37 | selection of Header | klog.go:22:15:22:20 | header | $@ flows to a logging call. | klog.go:20:30:20:37 | selection of Header | Sensitive data returned by HTTP request headers | +| klog.go:28:13:28:41 | call to Get | klog.go:28:13:28:20 | selection of Header | klog.go:28:13:28:41 | call to Get | $@ flows to a logging call. | klog.go:28:13:28:20 | selection of Header | Sensitive data returned by HTTP request headers | | main.go:15:14:15:21 | password | main.go:15:14:15:21 | password | main.go:15:14:15:21 | password | $@ flows to a logging call. | main.go:15:14:15:21 | password | Sensitive data returned by an access to password | | main.go:17:12:17:19 | password | main.go:17:12:17:19 | password | main.go:17:12:17:19 | password | $@ flows to a logging call. | main.go:17:12:17:19 | password | Sensitive data returned by an access to password | | main.go:18:17:18:24 | password | main.go:18:17:18:24 | password | main.go:18:17:18:24 | password | $@ flows to a logging call. | main.go:18:17:18:24 | password | Sensitive data returned by an access to password | -| main.go:22:29:22:34 | fields | main.go:21:19:21:26 | password : string | main.go:22:29:22:34 | fields | $@ flows to a logging call. | main.go:21:19:21:26 | password | Sensitive data returned by an access to password | +| main.go:22:29:22:34 | fields | main.go:21:19:21:26 | password | main.go:22:29:22:34 | fields | $@ flows to a logging call. | main.go:21:19:21:26 | password | Sensitive data returned by an access to password | | main.go:25:35:25:42 | password | main.go:25:35:25:42 | password | main.go:25:35:25:42 | password | $@ flows to a logging call. | main.go:25:35:25:42 | password | Sensitive data returned by an access to password | -| overrides.go:13:14:13:23 | call to String | overrides.go:9:9:9:16 | password : string | overrides.go:13:14:13:23 | call to String | $@ flows to a logging call. | overrides.go:9:9:9:16 | password | Sensitive data returned by an access to password | -| passwords.go:9:14:9:14 | x | passwords.go:30:8:30:15 | password : string | passwords.go:9:14:9:14 | x | $@ flows to a logging call. | passwords.go:30:8:30:15 | password | Sensitive data returned by an access to password | +| overrides.go:13:14:13:23 | call to String | overrides.go:9:9:9:16 | password | overrides.go:13:14:13:23 | call to String | $@ flows to a logging call. | overrides.go:9:9:9:16 | password | Sensitive data returned by an access to password | +| passwords.go:9:14:9:14 | x | passwords.go:30:8:30:15 | password | passwords.go:9:14:9:14 | x | $@ flows to a logging call. | passwords.go:30:8:30:15 | password | Sensitive data returned by an access to password | | passwords.go:25:14:25:21 | password | passwords.go:25:14:25:21 | password | passwords.go:25:14:25:21 | password | $@ flows to a logging call. | passwords.go:25:14:25:21 | password | Sensitive data returned by an access to password | | passwords.go:26:14:26:23 | selection of password | passwords.go:26:14:26:23 | selection of password | passwords.go:26:14:26:23 | selection of password | $@ flows to a logging call. | passwords.go:26:14:26:23 | selection of password | Sensitive data returned by an access to password | | passwords.go:27:14:27:26 | call to getPassword | passwords.go:27:14:27:26 | call to getPassword | passwords.go:27:14:27:26 | call to getPassword | $@ flows to a logging call. | passwords.go:27:14:27:26 | call to getPassword | Sensitive data returned by a call to getPassword | | passwords.go:28:14:28:28 | call to getPassword | passwords.go:28:14:28:28 | call to getPassword | passwords.go:28:14:28:28 | call to getPassword | $@ flows to a logging call. | passwords.go:28:14:28:28 | call to getPassword | Sensitive data returned by a call to getPassword | -| passwords.go:28:14:28:28 | call to getPassword | util.go:16:9:16:18 | selection of password : string | passwords.go:28:14:28:28 | call to getPassword | $@ flows to a logging call. | util.go:16:9:16:18 | selection of password | Sensitive data returned by an access to password | +| passwords.go:28:14:28:28 | call to getPassword | util.go:16:9:16:18 | selection of password | passwords.go:28:14:28:28 | call to getPassword | $@ flows to a logging call. | util.go:16:9:16:18 | selection of password | Sensitive data returned by an access to password | | passwords.go:32:12:32:19 | password | passwords.go:32:12:32:19 | password | passwords.go:32:12:32:19 | password | $@ flows to a logging call. | passwords.go:32:12:32:19 | password | Sensitive data returned by an access to password | -| passwords.go:34:14:34:35 | ...+... | passwords.go:34:28:34:35 | password : string | passwords.go:34:14:34:35 | ...+... | $@ flows to a logging call. | passwords.go:34:28:34:35 | password | Sensitive data returned by an access to password | -| passwords.go:39:14:39:17 | obj1 | passwords.go:37:13:37:13 | x : string | passwords.go:39:14:39:17 | obj1 | $@ flows to a logging call. | passwords.go:37:13:37:13 | x | Sensitive data returned by an access to password | -| passwords.go:44:14:44:17 | obj2 | passwords.go:42:6:42:13 | password : string | passwords.go:44:14:44:17 | obj2 | $@ flows to a logging call. | passwords.go:42:6:42:13 | password | Sensitive data returned by an access to password | -| passwords.go:47:14:47:17 | obj3 | passwords.go:48:11:48:18 | password : string | passwords.go:47:14:47:17 | obj3 | $@ flows to a logging call. | passwords.go:48:11:48:18 | password | Sensitive data returned by an access to password | +| passwords.go:34:14:34:35 | ...+... | passwords.go:34:28:34:35 | password | passwords.go:34:14:34:35 | ...+... | $@ flows to a logging call. | passwords.go:34:28:34:35 | password | Sensitive data returned by an access to password | +| passwords.go:39:14:39:17 | obj1 | passwords.go:37:13:37:13 | x | passwords.go:39:14:39:17 | obj1 | $@ flows to a logging call. | passwords.go:37:13:37:13 | x | Sensitive data returned by an access to password | +| passwords.go:44:14:44:17 | obj2 | passwords.go:42:6:42:13 | password | passwords.go:44:14:44:17 | obj2 | $@ flows to a logging call. | passwords.go:42:6:42:13 | password | Sensitive data returned by an access to password | +| passwords.go:47:14:47:17 | obj3 | passwords.go:48:11:48:18 | password | passwords.go:47:14:47:17 | obj3 | $@ flows to a logging call. | passwords.go:48:11:48:18 | password | Sensitive data returned by an access to password | | passwords.go:51:14:51:27 | fixed_password | passwords.go:51:14:51:27 | fixed_password | passwords.go:51:14:51:27 | fixed_password | $@ flows to a logging call. | passwords.go:51:14:51:27 | fixed_password | Sensitive data returned by an access to fixed_password | -| passwords.go:88:14:88:26 | utilityObject | passwords.go:86:16:86:36 | call to make : map type | passwords.go:88:14:88:26 | utilityObject | $@ flows to a logging call. | passwords.go:86:16:86:36 | call to make | Sensitive data returned by an access to passwordSet | -| passwords.go:91:23:91:28 | secret | passwords.go:90:12:90:19 | password : string | passwords.go:91:23:91:28 | secret | $@ flows to a logging call. | passwords.go:90:12:90:19 | password | Sensitive data returned by an access to password | -| passwords.go:101:15:101:40 | ...+... | passwords.go:101:33:101:40 | password : string | passwords.go:101:15:101:40 | ...+... | $@ flows to a logging call. | passwords.go:101:33:101:40 | password | Sensitive data returned by an access to password | -| passwords.go:107:16:107:41 | ...+... | passwords.go:107:34:107:41 | password : string | passwords.go:107:16:107:41 | ...+... | $@ flows to a logging call. | passwords.go:107:34:107:41 | password | Sensitive data returned by an access to password | -| passwords.go:112:15:112:40 | ...+... | passwords.go:112:33:112:40 | password : string | passwords.go:112:15:112:40 | ...+... | $@ flows to a logging call. | passwords.go:112:33:112:40 | password | Sensitive data returned by an access to password | -| passwords.go:116:14:116:45 | ...+... | passwords.go:116:28:116:36 | password1 : stringable | passwords.go:116:14:116:45 | ...+... | $@ flows to a logging call. | passwords.go:116:28:116:36 | password1 | Sensitive data returned by an access to password1 | -| passwords.go:125:14:125:19 | config | passwords.go:119:13:119:13 | x : string | passwords.go:125:14:125:19 | config | $@ flows to a logging call. | passwords.go:119:13:119:13 | x | Sensitive data returned by an access to password | -| passwords.go:125:14:125:19 | config | passwords.go:121:13:121:20 | password : string | passwords.go:125:14:125:19 | config | $@ flows to a logging call. | passwords.go:121:13:121:20 | password | Sensitive data returned by an access to password | -| passwords.go:125:14:125:19 | config | passwords.go:122:13:122:25 | call to getPassword : string | passwords.go:125:14:125:19 | config | $@ flows to a logging call. | passwords.go:122:13:122:25 | call to getPassword | Sensitive data returned by a call to getPassword | -| passwords.go:126:14:126:21 | selection of x | passwords.go:121:13:121:20 | password : string | passwords.go:126:14:126:21 | selection of x | $@ flows to a logging call. | passwords.go:121:13:121:20 | password | Sensitive data returned by an access to password | -| passwords.go:127:14:127:21 | selection of y | passwords.go:122:13:122:25 | call to getPassword : string | passwords.go:127:14:127:21 | selection of y | $@ flows to a logging call. | passwords.go:122:13:122:25 | call to getPassword | Sensitive data returned by a call to getPassword | -| protobuf.go:14:14:14:35 | call to GetDescription | protobuf.go:12:22:12:29 | password : string | protobuf.go:14:14:14:35 | call to GetDescription | $@ flows to a logging call. | protobuf.go:12:22:12:29 | password | Sensitive data returned by an access to password | +| passwords.go:88:14:88:26 | utilityObject | passwords.go:86:16:86:36 | call to make | passwords.go:88:14:88:26 | utilityObject | $@ flows to a logging call. | passwords.go:86:16:86:36 | call to make | Sensitive data returned by an access to passwordSet | +| passwords.go:91:23:91:28 | secret | passwords.go:90:12:90:19 | password | passwords.go:91:23:91:28 | secret | $@ flows to a logging call. | passwords.go:90:12:90:19 | password | Sensitive data returned by an access to password | +| passwords.go:101:15:101:40 | ...+... | passwords.go:101:33:101:40 | password | passwords.go:101:15:101:40 | ...+... | $@ flows to a logging call. | passwords.go:101:33:101:40 | password | Sensitive data returned by an access to password | +| passwords.go:107:16:107:41 | ...+... | passwords.go:107:34:107:41 | password | passwords.go:107:16:107:41 | ...+... | $@ flows to a logging call. | passwords.go:107:34:107:41 | password | Sensitive data returned by an access to password | +| passwords.go:112:15:112:40 | ...+... | passwords.go:112:33:112:40 | password | passwords.go:112:15:112:40 | ...+... | $@ flows to a logging call. | passwords.go:112:33:112:40 | password | Sensitive data returned by an access to password | +| passwords.go:116:14:116:45 | ...+... | passwords.go:116:28:116:36 | password1 | passwords.go:116:14:116:45 | ...+... | $@ flows to a logging call. | passwords.go:116:28:116:36 | password1 | Sensitive data returned by an access to password1 | +| passwords.go:125:14:125:19 | config | passwords.go:119:13:119:13 | x | passwords.go:125:14:125:19 | config | $@ flows to a logging call. | passwords.go:119:13:119:13 | x | Sensitive data returned by an access to password | +| passwords.go:125:14:125:19 | config | passwords.go:121:13:121:20 | password | passwords.go:125:14:125:19 | config | $@ flows to a logging call. | passwords.go:121:13:121:20 | password | Sensitive data returned by an access to password | +| passwords.go:125:14:125:19 | config | passwords.go:122:13:122:25 | call to getPassword | passwords.go:125:14:125:19 | config | $@ flows to a logging call. | passwords.go:122:13:122:25 | call to getPassword | Sensitive data returned by a call to getPassword | +| passwords.go:126:14:126:21 | selection of x | passwords.go:121:13:121:20 | password | passwords.go:126:14:126:21 | selection of x | $@ flows to a logging call. | passwords.go:121:13:121:20 | password | Sensitive data returned by an access to password | +| passwords.go:127:14:127:21 | selection of y | passwords.go:122:13:122:25 | call to getPassword | passwords.go:127:14:127:21 | selection of y | $@ flows to a logging call. | passwords.go:122:13:122:25 | call to getPassword | Sensitive data returned by a call to getPassword | +| protobuf.go:14:14:14:35 | call to GetDescription | protobuf.go:12:22:12:29 | password | protobuf.go:14:14:14:35 | call to GetDescription | $@ flows to a logging call. | protobuf.go:12:22:12:29 | password | Sensitive data returned by an access to password | diff --git a/go/ql/test/query-tests/Security/CWE-322/InsecureHostKeyCallback.expected b/go/ql/test/query-tests/Security/CWE-322/InsecureHostKeyCallback.expected index e7fbbc39fb2..2376ab7a7cf 100644 --- a/go/ql/test/query-tests/Security/CWE-322/InsecureHostKeyCallback.expected +++ b/go/ql/test/query-tests/Security/CWE-322/InsecureHostKeyCallback.expected @@ -1,50 +1,48 @@ edges -| InsecureHostKeyCallbackExample.go:16:4:18:4 | function literal : signature type | InsecureHostKeyCallbackExample.go:15:20:18:5 | type conversion | -| InsecureHostKeyCallbackExample.go:31:14:34:4 | type conversion : signature type | InsecureHostKeyCallbackExample.go:39:20:39:27 | callback | -| InsecureHostKeyCallbackExample.go:32:3:34:3 | function literal : signature type | InsecureHostKeyCallbackExample.go:31:14:34:4 | type conversion : signature type | -| InsecureHostKeyCallbackExample.go:45:3:47:3 | function literal : signature type | InsecureHostKeyCallbackExample.go:52:20:52:48 | type conversion | -| InsecureHostKeyCallbackExample.go:58:39:58:46 | definition of callback : HostKeyCallback | InsecureHostKeyCallbackExample.go:62:20:62:27 | callback | -| InsecureHostKeyCallbackExample.go:58:39:58:46 | definition of callback : signature type | InsecureHostKeyCallbackExample.go:62:20:62:27 | callback | -| InsecureHostKeyCallbackExample.go:68:48:68:55 | definition of callback : signature type | InsecureHostKeyCallbackExample.go:78:28:78:35 | callback | -| InsecureHostKeyCallbackExample.go:94:3:94:43 | ... := ...[0] : HostKeyCallback | InsecureHostKeyCallbackExample.go:95:28:95:35 | callback | -| InsecureHostKeyCallbackExample.go:102:22:105:4 | type conversion : signature type | InsecureHostKeyCallbackExample.go:107:35:107:50 | insecureCallback : signature type | -| InsecureHostKeyCallbackExample.go:103:3:105:3 | function literal : signature type | InsecureHostKeyCallbackExample.go:102:22:105:4 | type conversion : signature type | -| InsecureHostKeyCallbackExample.go:107:35:107:50 | insecureCallback : signature type | InsecureHostKeyCallbackExample.go:58:39:58:46 | definition of callback : signature type | -| InsecureHostKeyCallbackExample.go:109:31:115:4 | type conversion : signature type | InsecureHostKeyCallbackExample.go:117:35:117:59 | potentiallySecureCallback : signature type | -| InsecureHostKeyCallbackExample.go:109:31:115:4 | type conversion : signature type | InsecureHostKeyCallbackExample.go:120:44:120:68 | potentiallySecureCallback : signature type | -| InsecureHostKeyCallbackExample.go:110:3:115:3 | function literal : signature type | InsecureHostKeyCallbackExample.go:109:31:115:4 | type conversion : signature type | -| InsecureHostKeyCallbackExample.go:117:35:117:59 | potentiallySecureCallback : signature type | InsecureHostKeyCallbackExample.go:58:39:58:46 | definition of callback : signature type | -| InsecureHostKeyCallbackExample.go:118:35:118:61 | call to InsecureIgnoreHostKey : HostKeyCallback | InsecureHostKeyCallbackExample.go:58:39:58:46 | definition of callback : HostKeyCallback | -| InsecureHostKeyCallbackExample.go:120:44:120:68 | potentiallySecureCallback : signature type | InsecureHostKeyCallbackExample.go:68:48:68:55 | definition of callback : signature type | +| InsecureHostKeyCallbackExample.go:16:4:18:4 | function literal | InsecureHostKeyCallbackExample.go:15:20:18:5 | type conversion | +| InsecureHostKeyCallbackExample.go:31:14:34:4 | type conversion | InsecureHostKeyCallbackExample.go:39:20:39:27 | callback | +| InsecureHostKeyCallbackExample.go:32:3:34:3 | function literal | InsecureHostKeyCallbackExample.go:31:14:34:4 | type conversion | +| InsecureHostKeyCallbackExample.go:45:3:47:3 | function literal | InsecureHostKeyCallbackExample.go:52:20:52:48 | type conversion | +| InsecureHostKeyCallbackExample.go:58:39:58:46 | definition of callback | InsecureHostKeyCallbackExample.go:62:20:62:27 | callback | +| InsecureHostKeyCallbackExample.go:68:48:68:55 | definition of callback | InsecureHostKeyCallbackExample.go:78:28:78:35 | callback | +| InsecureHostKeyCallbackExample.go:94:3:94:43 | ... := ...[0] | InsecureHostKeyCallbackExample.go:95:28:95:35 | callback | +| InsecureHostKeyCallbackExample.go:102:22:105:4 | type conversion | InsecureHostKeyCallbackExample.go:107:35:107:50 | insecureCallback | +| InsecureHostKeyCallbackExample.go:103:3:105:3 | function literal | InsecureHostKeyCallbackExample.go:102:22:105:4 | type conversion | +| InsecureHostKeyCallbackExample.go:107:35:107:50 | insecureCallback | InsecureHostKeyCallbackExample.go:58:39:58:46 | definition of callback | +| InsecureHostKeyCallbackExample.go:109:31:115:4 | type conversion | InsecureHostKeyCallbackExample.go:117:35:117:59 | potentiallySecureCallback | +| InsecureHostKeyCallbackExample.go:109:31:115:4 | type conversion | InsecureHostKeyCallbackExample.go:120:44:120:68 | potentiallySecureCallback | +| InsecureHostKeyCallbackExample.go:110:3:115:3 | function literal | InsecureHostKeyCallbackExample.go:109:31:115:4 | type conversion | +| InsecureHostKeyCallbackExample.go:117:35:117:59 | potentiallySecureCallback | InsecureHostKeyCallbackExample.go:58:39:58:46 | definition of callback | +| InsecureHostKeyCallbackExample.go:118:35:118:61 | call to InsecureIgnoreHostKey | InsecureHostKeyCallbackExample.go:58:39:58:46 | definition of callback | +| InsecureHostKeyCallbackExample.go:120:44:120:68 | potentiallySecureCallback | InsecureHostKeyCallbackExample.go:68:48:68:55 | definition of callback | nodes | InsecureHostKeyCallbackExample.go:15:20:18:5 | type conversion | semmle.label | type conversion | -| InsecureHostKeyCallbackExample.go:16:4:18:4 | function literal : signature type | semmle.label | function literal : signature type | +| InsecureHostKeyCallbackExample.go:16:4:18:4 | function literal | semmle.label | function literal | | InsecureHostKeyCallbackExample.go:26:20:26:46 | call to InsecureIgnoreHostKey | semmle.label | call to InsecureIgnoreHostKey | -| InsecureHostKeyCallbackExample.go:31:14:34:4 | type conversion : signature type | semmle.label | type conversion : signature type | -| InsecureHostKeyCallbackExample.go:32:3:34:3 | function literal : signature type | semmle.label | function literal : signature type | +| InsecureHostKeyCallbackExample.go:31:14:34:4 | type conversion | semmle.label | type conversion | +| InsecureHostKeyCallbackExample.go:32:3:34:3 | function literal | semmle.label | function literal | | InsecureHostKeyCallbackExample.go:39:20:39:27 | callback | semmle.label | callback | -| InsecureHostKeyCallbackExample.go:45:3:47:3 | function literal : signature type | semmle.label | function literal : signature type | +| InsecureHostKeyCallbackExample.go:45:3:47:3 | function literal | semmle.label | function literal | | InsecureHostKeyCallbackExample.go:52:20:52:48 | type conversion | semmle.label | type conversion | -| InsecureHostKeyCallbackExample.go:58:39:58:46 | definition of callback : HostKeyCallback | semmle.label | definition of callback : HostKeyCallback | -| InsecureHostKeyCallbackExample.go:58:39:58:46 | definition of callback : signature type | semmle.label | definition of callback : signature type | +| InsecureHostKeyCallbackExample.go:58:39:58:46 | definition of callback | semmle.label | definition of callback | | InsecureHostKeyCallbackExample.go:62:20:62:27 | callback | semmle.label | callback | -| InsecureHostKeyCallbackExample.go:68:48:68:55 | definition of callback : signature type | semmle.label | definition of callback : signature type | +| InsecureHostKeyCallbackExample.go:68:48:68:55 | definition of callback | semmle.label | definition of callback | | InsecureHostKeyCallbackExample.go:76:28:76:54 | call to InsecureIgnoreHostKey | semmle.label | call to InsecureIgnoreHostKey | | InsecureHostKeyCallbackExample.go:78:28:78:35 | callback | semmle.label | callback | | InsecureHostKeyCallbackExample.go:92:28:92:54 | call to InsecureIgnoreHostKey | semmle.label | call to InsecureIgnoreHostKey | -| InsecureHostKeyCallbackExample.go:94:3:94:43 | ... := ...[0] : HostKeyCallback | semmle.label | ... := ...[0] : HostKeyCallback | +| InsecureHostKeyCallbackExample.go:94:3:94:43 | ... := ...[0] | semmle.label | ... := ...[0] | | InsecureHostKeyCallbackExample.go:95:28:95:35 | callback | semmle.label | callback | -| InsecureHostKeyCallbackExample.go:102:22:105:4 | type conversion : signature type | semmle.label | type conversion : signature type | -| InsecureHostKeyCallbackExample.go:103:3:105:3 | function literal : signature type | semmle.label | function literal : signature type | -| InsecureHostKeyCallbackExample.go:107:35:107:50 | insecureCallback : signature type | semmle.label | insecureCallback : signature type | -| InsecureHostKeyCallbackExample.go:109:31:115:4 | type conversion : signature type | semmle.label | type conversion : signature type | -| InsecureHostKeyCallbackExample.go:110:3:115:3 | function literal : signature type | semmle.label | function literal : signature type | -| InsecureHostKeyCallbackExample.go:117:35:117:59 | potentiallySecureCallback : signature type | semmle.label | potentiallySecureCallback : signature type | -| InsecureHostKeyCallbackExample.go:118:35:118:61 | call to InsecureIgnoreHostKey : HostKeyCallback | semmle.label | call to InsecureIgnoreHostKey : HostKeyCallback | -| InsecureHostKeyCallbackExample.go:120:44:120:68 | potentiallySecureCallback : signature type | semmle.label | potentiallySecureCallback : signature type | +| InsecureHostKeyCallbackExample.go:102:22:105:4 | type conversion | semmle.label | type conversion | +| InsecureHostKeyCallbackExample.go:103:3:105:3 | function literal | semmle.label | function literal | +| InsecureHostKeyCallbackExample.go:107:35:107:50 | insecureCallback | semmle.label | insecureCallback | +| InsecureHostKeyCallbackExample.go:109:31:115:4 | type conversion | semmle.label | type conversion | +| InsecureHostKeyCallbackExample.go:110:3:115:3 | function literal | semmle.label | function literal | +| InsecureHostKeyCallbackExample.go:117:35:117:59 | potentiallySecureCallback | semmle.label | potentiallySecureCallback | +| InsecureHostKeyCallbackExample.go:118:35:118:61 | call to InsecureIgnoreHostKey | semmle.label | call to InsecureIgnoreHostKey | +| InsecureHostKeyCallbackExample.go:120:44:120:68 | potentiallySecureCallback | semmle.label | potentiallySecureCallback | subpaths #select -| InsecureHostKeyCallbackExample.go:15:20:18:5 | type conversion | InsecureHostKeyCallbackExample.go:16:4:18:4 | function literal : signature type | InsecureHostKeyCallbackExample.go:15:20:18:5 | type conversion | Configuring SSH ClientConfig with insecure HostKeyCallback implementation from $@. | InsecureHostKeyCallbackExample.go:16:4:18:4 | function literal | this source | +| InsecureHostKeyCallbackExample.go:15:20:18:5 | type conversion | InsecureHostKeyCallbackExample.go:16:4:18:4 | function literal | InsecureHostKeyCallbackExample.go:15:20:18:5 | type conversion | Configuring SSH ClientConfig with insecure HostKeyCallback implementation from $@. | InsecureHostKeyCallbackExample.go:16:4:18:4 | function literal | this source | | InsecureHostKeyCallbackExample.go:26:20:26:46 | call to InsecureIgnoreHostKey | InsecureHostKeyCallbackExample.go:26:20:26:46 | call to InsecureIgnoreHostKey | InsecureHostKeyCallbackExample.go:26:20:26:46 | call to InsecureIgnoreHostKey | Configuring SSH ClientConfig with insecure HostKeyCallback implementation from $@. | InsecureHostKeyCallbackExample.go:26:20:26:46 | call to InsecureIgnoreHostKey | this source | -| InsecureHostKeyCallbackExample.go:39:20:39:27 | callback | InsecureHostKeyCallbackExample.go:32:3:34:3 | function literal : signature type | InsecureHostKeyCallbackExample.go:39:20:39:27 | callback | Configuring SSH ClientConfig with insecure HostKeyCallback implementation from $@. | InsecureHostKeyCallbackExample.go:32:3:34:3 | function literal | this source | -| InsecureHostKeyCallbackExample.go:52:20:52:48 | type conversion | InsecureHostKeyCallbackExample.go:45:3:47:3 | function literal : signature type | InsecureHostKeyCallbackExample.go:52:20:52:48 | type conversion | Configuring SSH ClientConfig with insecure HostKeyCallback implementation from $@. | InsecureHostKeyCallbackExample.go:45:3:47:3 | function literal | this source | +| InsecureHostKeyCallbackExample.go:39:20:39:27 | callback | InsecureHostKeyCallbackExample.go:32:3:34:3 | function literal | InsecureHostKeyCallbackExample.go:39:20:39:27 | callback | Configuring SSH ClientConfig with insecure HostKeyCallback implementation from $@. | InsecureHostKeyCallbackExample.go:32:3:34:3 | function literal | this source | +| InsecureHostKeyCallbackExample.go:52:20:52:48 | type conversion | InsecureHostKeyCallbackExample.go:45:3:47:3 | function literal | InsecureHostKeyCallbackExample.go:52:20:52:48 | type conversion | Configuring SSH ClientConfig with insecure HostKeyCallback implementation from $@. | InsecureHostKeyCallbackExample.go:45:3:47:3 | function literal | this source | diff --git a/go/ql/test/query-tests/Security/CWE-326/InsufficientKeySize.expected b/go/ql/test/query-tests/Security/CWE-326/InsufficientKeySize.expected index fb9488b7165..fb1058af01c 100644 --- a/go/ql/test/query-tests/Security/CWE-326/InsufficientKeySize.expected +++ b/go/ql/test/query-tests/Security/CWE-326/InsufficientKeySize.expected @@ -1,28 +1,28 @@ edges -| InsufficientKeySize.go:13:10:13:13 | 1024 : int | InsufficientKeySize.go:14:31:14:34 | size | -| InsufficientKeySize.go:18:7:18:10 | 1024 : int | InsufficientKeySize.go:25:11:25:14 | definition of size : int | -| InsufficientKeySize.go:25:11:25:14 | definition of size : int | InsufficientKeySize.go:26:31:26:34 | size | -| InsufficientKeySize.go:30:13:30:16 | 1024 : int | InsufficientKeySize.go:32:32:32:38 | keyBits | -| InsufficientKeySize.go:44:13:44:16 | 1024 : int | InsufficientKeySize.go:47:32:47:38 | keyBits | -| InsufficientKeySize.go:61:21:61:24 | 1024 : int | InsufficientKeySize.go:67:31:67:37 | keyBits | +| InsufficientKeySize.go:13:10:13:13 | 1024 | InsufficientKeySize.go:14:31:14:34 | size | +| InsufficientKeySize.go:18:7:18:10 | 1024 | InsufficientKeySize.go:25:11:25:14 | definition of size | +| InsufficientKeySize.go:25:11:25:14 | definition of size | InsufficientKeySize.go:26:31:26:34 | size | +| InsufficientKeySize.go:30:13:30:16 | 1024 | InsufficientKeySize.go:32:32:32:38 | keyBits | +| InsufficientKeySize.go:44:13:44:16 | 1024 | InsufficientKeySize.go:47:32:47:38 | keyBits | +| InsufficientKeySize.go:61:21:61:24 | 1024 | InsufficientKeySize.go:67:31:67:37 | keyBits | nodes | InsufficientKeySize.go:9:31:9:34 | 1024 | semmle.label | 1024 | -| InsufficientKeySize.go:13:10:13:13 | 1024 : int | semmle.label | 1024 : int | +| InsufficientKeySize.go:13:10:13:13 | 1024 | semmle.label | 1024 | | InsufficientKeySize.go:14:31:14:34 | size | semmle.label | size | -| InsufficientKeySize.go:18:7:18:10 | 1024 : int | semmle.label | 1024 : int | -| InsufficientKeySize.go:25:11:25:14 | definition of size : int | semmle.label | definition of size : int | +| InsufficientKeySize.go:18:7:18:10 | 1024 | semmle.label | 1024 | +| InsufficientKeySize.go:25:11:25:14 | definition of size | semmle.label | definition of size | | InsufficientKeySize.go:26:31:26:34 | size | semmle.label | size | -| InsufficientKeySize.go:30:13:30:16 | 1024 : int | semmle.label | 1024 : int | +| InsufficientKeySize.go:30:13:30:16 | 1024 | semmle.label | 1024 | | InsufficientKeySize.go:32:32:32:38 | keyBits | semmle.label | keyBits | -| InsufficientKeySize.go:44:13:44:16 | 1024 : int | semmle.label | 1024 : int | +| InsufficientKeySize.go:44:13:44:16 | 1024 | semmle.label | 1024 | | InsufficientKeySize.go:47:32:47:38 | keyBits | semmle.label | keyBits | -| InsufficientKeySize.go:61:21:61:24 | 1024 : int | semmle.label | 1024 : int | +| InsufficientKeySize.go:61:21:61:24 | 1024 | semmle.label | 1024 | | InsufficientKeySize.go:67:31:67:37 | keyBits | semmle.label | keyBits | subpaths #select | InsufficientKeySize.go:9:31:9:34 | 1024 | InsufficientKeySize.go:9:31:9:34 | 1024 | InsufficientKeySize.go:9:31:9:34 | 1024 | The size of this RSA key should be at least 2048 bits. | -| InsufficientKeySize.go:14:31:14:34 | size | InsufficientKeySize.go:13:10:13:13 | 1024 : int | InsufficientKeySize.go:14:31:14:34 | size | The size of this RSA key should be at least 2048 bits. | -| InsufficientKeySize.go:26:31:26:34 | size | InsufficientKeySize.go:18:7:18:10 | 1024 : int | InsufficientKeySize.go:26:31:26:34 | size | The size of this RSA key should be at least 2048 bits. | -| InsufficientKeySize.go:32:32:32:38 | keyBits | InsufficientKeySize.go:30:13:30:16 | 1024 : int | InsufficientKeySize.go:32:32:32:38 | keyBits | The size of this RSA key should be at least 2048 bits. | -| InsufficientKeySize.go:47:32:47:38 | keyBits | InsufficientKeySize.go:44:13:44:16 | 1024 : int | InsufficientKeySize.go:47:32:47:38 | keyBits | The size of this RSA key should be at least 2048 bits. | -| InsufficientKeySize.go:67:31:67:37 | keyBits | InsufficientKeySize.go:61:21:61:24 | 1024 : int | InsufficientKeySize.go:67:31:67:37 | keyBits | The size of this RSA key should be at least 2048 bits. | +| InsufficientKeySize.go:14:31:14:34 | size | InsufficientKeySize.go:13:10:13:13 | 1024 | InsufficientKeySize.go:14:31:14:34 | size | The size of this RSA key should be at least 2048 bits. | +| InsufficientKeySize.go:26:31:26:34 | size | InsufficientKeySize.go:18:7:18:10 | 1024 | InsufficientKeySize.go:26:31:26:34 | size | The size of this RSA key should be at least 2048 bits. | +| InsufficientKeySize.go:32:32:32:38 | keyBits | InsufficientKeySize.go:30:13:30:16 | 1024 | InsufficientKeySize.go:32:32:32:38 | keyBits | The size of this RSA key should be at least 2048 bits. | +| InsufficientKeySize.go:47:32:47:38 | keyBits | InsufficientKeySize.go:44:13:44:16 | 1024 | InsufficientKeySize.go:47:32:47:38 | keyBits | The size of this RSA key should be at least 2048 bits. | +| InsufficientKeySize.go:67:31:67:37 | keyBits | InsufficientKeySize.go:61:21:61:24 | 1024 | InsufficientKeySize.go:67:31:67:37 | keyBits | The size of this RSA key should be at least 2048 bits. | diff --git a/go/ql/test/query-tests/Security/CWE-327/UnsafeTLS.expected b/go/ql/test/query-tests/Security/CWE-327/UnsafeTLS.expected index 78bb9148a09..ba37534511a 100644 --- a/go/ql/test/query-tests/Security/CWE-327/UnsafeTLS.expected +++ b/go/ql/test/query-tests/Security/CWE-327/UnsafeTLS.expected @@ -1,35 +1,35 @@ edges -| UnsafeTLS.go:131:14:131:29 | selection of VersionTLS13 : uint16 | UnsafeTLS.go:136:16:136:22 | version | -| UnsafeTLS.go:133:14:133:29 | selection of VersionSSL30 : uint16 | UnsafeTLS.go:136:16:136:22 | version | -| UnsafeTLS.go:260:5:260:32 | selection of TLS_RSA_WITH_RC4_128_SHA : uint16 | UnsafeTLS.go:259:18:266:4 | slice literal | -| UnsafeTLS.go:261:5:261:39 | selection of TLS_RSA_WITH_AES_128_CBC_SHA256 : uint16 | UnsafeTLS.go:259:18:266:4 | slice literal | -| UnsafeTLS.go:262:5:262:40 | selection of TLS_ECDHE_ECDSA_WITH_RC4_128_SHA : uint16 | UnsafeTLS.go:259:18:266:4 | slice literal | -| UnsafeTLS.go:263:5:263:38 | selection of TLS_ECDHE_RSA_WITH_RC4_128_SHA : uint16 | UnsafeTLS.go:259:18:266:4 | slice literal | -| UnsafeTLS.go:264:5:264:47 | selection of TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 : uint16 | UnsafeTLS.go:259:18:266:4 | slice literal | -| UnsafeTLS.go:265:5:265:45 | selection of TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 : uint16 | UnsafeTLS.go:259:18:266:4 | slice literal | -| UnsafeTLS.go:273:5:273:32 | selection of TLS_RSA_WITH_RC4_128_SHA : uint16 | UnsafeTLS.go:272:18:274:4 | slice literal | -| UnsafeTLS.go:281:5:281:39 | selection of TLS_RSA_WITH_AES_128_CBC_SHA256 : uint16 | UnsafeTLS.go:280:18:282:4 | slice literal | -| UnsafeTLS.go:289:5:289:40 | selection of TLS_ECDHE_ECDSA_WITH_RC4_128_SHA : uint16 | UnsafeTLS.go:288:18:290:4 | slice literal | -| UnsafeTLS.go:297:5:297:38 | selection of TLS_ECDHE_RSA_WITH_RC4_128_SHA : uint16 | UnsafeTLS.go:296:18:298:4 | slice literal | -| UnsafeTLS.go:305:5:305:47 | selection of TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 : uint16 | UnsafeTLS.go:304:18:306:4 | slice literal | -| UnsafeTLS.go:313:5:313:45 | selection of TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 : uint16 | UnsafeTLS.go:312:18:314:4 | slice literal | -| UnsafeTLS.go:329:53:329:93 | selection of TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 : uint16 | UnsafeTLS.go:329:25:329:94 | call to append | -| UnsafeTLS.go:334:13:334:38 | call to InsecureCipherSuites : slice type | UnsafeTLS.go:336:26:336:58 | call to append | -| UnsafeTLS.go:342:13:342:38 | call to InsecureCipherSuites : slice type | UnsafeTLS.go:346:25:346:36 | cipherSuites | -| UnsafeTLS.go:351:13:351:38 | call to InsecureCipherSuites : slice type | UnsafeTLS.go:355:25:355:36 | cipherSuites | -| UnsafeTLS.go:363:5:363:47 | selection of TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 : uint16 | UnsafeTLS.go:362:18:364:4 | slice literal | -| UnsafeTLS.go:371:5:371:47 | selection of TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 : uint16 | UnsafeTLS.go:370:18:372:4 | slice literal | -| UnsafeTLS.go:379:5:379:47 | selection of TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 : uint16 | UnsafeTLS.go:378:18:380:4 | slice literal | -| UnsafeTLS.go:387:5:387:47 | selection of TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 : uint16 | UnsafeTLS.go:386:18:388:4 | slice literal | -| UnsafeTLS.go:395:5:395:47 | selection of TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 : uint16 | UnsafeTLS.go:394:18:396:4 | slice literal | -| UnsafeTLS.go:403:4:403:46 | selection of TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 : uint16 | UnsafeTLS.go:402:33:404:3 | slice literal | -| UnsafeTLS.go:410:4:410:46 | selection of TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 : uint16 | UnsafeTLS.go:409:31:411:3 | slice literal | -| UnsafeTLS.go:419:6:419:48 | selection of TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 : uint16 | UnsafeTLS.go:418:19:420:5 | slice literal | -| UnsafeTLS.go:426:6:426:48 | selection of TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 : uint16 | UnsafeTLS.go:425:19:427:5 | slice literal | -| UnsafeTLS.go:433:6:433:48 | selection of TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 : uint16 | UnsafeTLS.go:432:19:434:5 | slice literal | -| UnsafeTLS.go:443:6:443:48 | selection of TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 : uint16 | UnsafeTLS.go:442:19:444:5 | slice literal | -| UnsafeTLS.go:450:6:450:48 | selection of TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 : uint16 | UnsafeTLS.go:449:19:451:5 | slice literal | -| UnsafeTLS.go:457:6:457:48 | selection of TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 : uint16 | UnsafeTLS.go:456:19:458:5 | slice literal | +| UnsafeTLS.go:131:14:131:29 | selection of VersionTLS13 | UnsafeTLS.go:136:16:136:22 | version | +| UnsafeTLS.go:133:14:133:29 | selection of VersionSSL30 | UnsafeTLS.go:136:16:136:22 | version | +| UnsafeTLS.go:260:5:260:32 | selection of TLS_RSA_WITH_RC4_128_SHA | UnsafeTLS.go:259:18:266:4 | slice literal | +| UnsafeTLS.go:261:5:261:39 | selection of TLS_RSA_WITH_AES_128_CBC_SHA256 | UnsafeTLS.go:259:18:266:4 | slice literal | +| UnsafeTLS.go:262:5:262:40 | selection of TLS_ECDHE_ECDSA_WITH_RC4_128_SHA | UnsafeTLS.go:259:18:266:4 | slice literal | +| UnsafeTLS.go:263:5:263:38 | selection of TLS_ECDHE_RSA_WITH_RC4_128_SHA | UnsafeTLS.go:259:18:266:4 | slice literal | +| UnsafeTLS.go:264:5:264:47 | selection of TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 | UnsafeTLS.go:259:18:266:4 | slice literal | +| UnsafeTLS.go:265:5:265:45 | selection of TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 | UnsafeTLS.go:259:18:266:4 | slice literal | +| UnsafeTLS.go:273:5:273:32 | selection of TLS_RSA_WITH_RC4_128_SHA | UnsafeTLS.go:272:18:274:4 | slice literal | +| UnsafeTLS.go:281:5:281:39 | selection of TLS_RSA_WITH_AES_128_CBC_SHA256 | UnsafeTLS.go:280:18:282:4 | slice literal | +| UnsafeTLS.go:289:5:289:40 | selection of TLS_ECDHE_ECDSA_WITH_RC4_128_SHA | UnsafeTLS.go:288:18:290:4 | slice literal | +| UnsafeTLS.go:297:5:297:38 | selection of TLS_ECDHE_RSA_WITH_RC4_128_SHA | UnsafeTLS.go:296:18:298:4 | slice literal | +| UnsafeTLS.go:305:5:305:47 | selection of TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 | UnsafeTLS.go:304:18:306:4 | slice literal | +| UnsafeTLS.go:313:5:313:45 | selection of TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 | UnsafeTLS.go:312:18:314:4 | slice literal | +| UnsafeTLS.go:329:53:329:93 | selection of TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 | UnsafeTLS.go:329:25:329:94 | call to append | +| UnsafeTLS.go:334:13:334:38 | call to InsecureCipherSuites | UnsafeTLS.go:336:26:336:58 | call to append | +| UnsafeTLS.go:342:13:342:38 | call to InsecureCipherSuites | UnsafeTLS.go:346:25:346:36 | cipherSuites | +| UnsafeTLS.go:351:13:351:38 | call to InsecureCipherSuites | UnsafeTLS.go:355:25:355:36 | cipherSuites | +| UnsafeTLS.go:363:5:363:47 | selection of TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 | UnsafeTLS.go:362:18:364:4 | slice literal | +| UnsafeTLS.go:371:5:371:47 | selection of TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 | UnsafeTLS.go:370:18:372:4 | slice literal | +| UnsafeTLS.go:379:5:379:47 | selection of TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 | UnsafeTLS.go:378:18:380:4 | slice literal | +| UnsafeTLS.go:387:5:387:47 | selection of TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 | UnsafeTLS.go:386:18:388:4 | slice literal | +| UnsafeTLS.go:395:5:395:47 | selection of TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 | UnsafeTLS.go:394:18:396:4 | slice literal | +| UnsafeTLS.go:403:4:403:46 | selection of TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 | UnsafeTLS.go:402:33:404:3 | slice literal | +| UnsafeTLS.go:410:4:410:46 | selection of TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 | UnsafeTLS.go:409:31:411:3 | slice literal | +| UnsafeTLS.go:419:6:419:48 | selection of TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 | UnsafeTLS.go:418:19:420:5 | slice literal | +| UnsafeTLS.go:426:6:426:48 | selection of TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 | UnsafeTLS.go:425:19:427:5 | slice literal | +| UnsafeTLS.go:433:6:433:48 | selection of TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 | UnsafeTLS.go:432:19:434:5 | slice literal | +| UnsafeTLS.go:443:6:443:48 | selection of TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 | UnsafeTLS.go:442:19:444:5 | slice literal | +| UnsafeTLS.go:450:6:450:48 | selection of TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 | UnsafeTLS.go:449:19:451:5 | slice literal | +| UnsafeTLS.go:457:6:457:48 | selection of TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 | UnsafeTLS.go:456:19:458:5 | slice literal | nodes | UnsafeTLS.go:21:23:21:23 | 0 | semmle.label | 0 | | UnsafeTLS.go:25:23:25:23 | 0 | semmle.label | 0 | @@ -50,8 +50,8 @@ nodes | UnsafeTLS.go:111:16:111:16 | 0 | semmle.label | 0 | | UnsafeTLS.go:117:16:117:16 | 0 | semmle.label | 0 | | UnsafeTLS.go:123:16:123:16 | 0 | semmle.label | 0 | -| UnsafeTLS.go:131:14:131:29 | selection of VersionTLS13 : uint16 | semmle.label | selection of VersionTLS13 : uint16 | -| UnsafeTLS.go:133:14:133:29 | selection of VersionSSL30 : uint16 | semmle.label | selection of VersionSSL30 : uint16 | +| UnsafeTLS.go:131:14:131:29 | selection of VersionTLS13 | semmle.label | selection of VersionTLS13 | +| UnsafeTLS.go:133:14:133:29 | selection of VersionSSL30 | semmle.label | selection of VersionSSL30 | | UnsafeTLS.go:136:16:136:22 | version | semmle.label | version | | UnsafeTLS.go:144:24:144:39 | selection of VersionTLS13 | semmle.label | selection of VersionTLS13 | | UnsafeTLS.go:146:24:146:39 | selection of VersionSSL30 | semmle.label | selection of VersionSSL30 | @@ -72,58 +72,58 @@ nodes | UnsafeTLS.go:243:16:243:16 | 0 | semmle.label | 0 | | UnsafeTLS.go:250:16:250:16 | 0 | semmle.label | 0 | | UnsafeTLS.go:259:18:266:4 | slice literal | semmle.label | slice literal | -| UnsafeTLS.go:260:5:260:32 | selection of TLS_RSA_WITH_RC4_128_SHA : uint16 | semmle.label | selection of TLS_RSA_WITH_RC4_128_SHA : uint16 | -| UnsafeTLS.go:261:5:261:39 | selection of TLS_RSA_WITH_AES_128_CBC_SHA256 : uint16 | semmle.label | selection of TLS_RSA_WITH_AES_128_CBC_SHA256 : uint16 | -| UnsafeTLS.go:262:5:262:40 | selection of TLS_ECDHE_ECDSA_WITH_RC4_128_SHA : uint16 | semmle.label | selection of TLS_ECDHE_ECDSA_WITH_RC4_128_SHA : uint16 | -| UnsafeTLS.go:263:5:263:38 | selection of TLS_ECDHE_RSA_WITH_RC4_128_SHA : uint16 | semmle.label | selection of TLS_ECDHE_RSA_WITH_RC4_128_SHA : uint16 | -| UnsafeTLS.go:264:5:264:47 | selection of TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 : uint16 | semmle.label | selection of TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 : uint16 | -| UnsafeTLS.go:265:5:265:45 | selection of TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 : uint16 | semmle.label | selection of TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 : uint16 | +| UnsafeTLS.go:260:5:260:32 | selection of TLS_RSA_WITH_RC4_128_SHA | semmle.label | selection of TLS_RSA_WITH_RC4_128_SHA | +| UnsafeTLS.go:261:5:261:39 | selection of TLS_RSA_WITH_AES_128_CBC_SHA256 | semmle.label | selection of TLS_RSA_WITH_AES_128_CBC_SHA256 | +| UnsafeTLS.go:262:5:262:40 | selection of TLS_ECDHE_ECDSA_WITH_RC4_128_SHA | semmle.label | selection of TLS_ECDHE_ECDSA_WITH_RC4_128_SHA | +| UnsafeTLS.go:263:5:263:38 | selection of TLS_ECDHE_RSA_WITH_RC4_128_SHA | semmle.label | selection of TLS_ECDHE_RSA_WITH_RC4_128_SHA | +| UnsafeTLS.go:264:5:264:47 | selection of TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 | semmle.label | selection of TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 | +| UnsafeTLS.go:265:5:265:45 | selection of TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 | semmle.label | selection of TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 | | UnsafeTLS.go:272:18:274:4 | slice literal | semmle.label | slice literal | -| UnsafeTLS.go:273:5:273:32 | selection of TLS_RSA_WITH_RC4_128_SHA : uint16 | semmle.label | selection of TLS_RSA_WITH_RC4_128_SHA : uint16 | +| UnsafeTLS.go:273:5:273:32 | selection of TLS_RSA_WITH_RC4_128_SHA | semmle.label | selection of TLS_RSA_WITH_RC4_128_SHA | | UnsafeTLS.go:280:18:282:4 | slice literal | semmle.label | slice literal | -| UnsafeTLS.go:281:5:281:39 | selection of TLS_RSA_WITH_AES_128_CBC_SHA256 : uint16 | semmle.label | selection of TLS_RSA_WITH_AES_128_CBC_SHA256 : uint16 | +| UnsafeTLS.go:281:5:281:39 | selection of TLS_RSA_WITH_AES_128_CBC_SHA256 | semmle.label | selection of TLS_RSA_WITH_AES_128_CBC_SHA256 | | UnsafeTLS.go:288:18:290:4 | slice literal | semmle.label | slice literal | -| UnsafeTLS.go:289:5:289:40 | selection of TLS_ECDHE_ECDSA_WITH_RC4_128_SHA : uint16 | semmle.label | selection of TLS_ECDHE_ECDSA_WITH_RC4_128_SHA : uint16 | +| UnsafeTLS.go:289:5:289:40 | selection of TLS_ECDHE_ECDSA_WITH_RC4_128_SHA | semmle.label | selection of TLS_ECDHE_ECDSA_WITH_RC4_128_SHA | | UnsafeTLS.go:296:18:298:4 | slice literal | semmle.label | slice literal | -| UnsafeTLS.go:297:5:297:38 | selection of TLS_ECDHE_RSA_WITH_RC4_128_SHA : uint16 | semmle.label | selection of TLS_ECDHE_RSA_WITH_RC4_128_SHA : uint16 | +| UnsafeTLS.go:297:5:297:38 | selection of TLS_ECDHE_RSA_WITH_RC4_128_SHA | semmle.label | selection of TLS_ECDHE_RSA_WITH_RC4_128_SHA | | UnsafeTLS.go:304:18:306:4 | slice literal | semmle.label | slice literal | -| UnsafeTLS.go:305:5:305:47 | selection of TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 : uint16 | semmle.label | selection of TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 : uint16 | +| UnsafeTLS.go:305:5:305:47 | selection of TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 | semmle.label | selection of TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 | | UnsafeTLS.go:312:18:314:4 | slice literal | semmle.label | slice literal | -| UnsafeTLS.go:313:5:313:45 | selection of TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 : uint16 | semmle.label | selection of TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 : uint16 | +| UnsafeTLS.go:313:5:313:45 | selection of TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 | semmle.label | selection of TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 | | UnsafeTLS.go:329:25:329:94 | call to append | semmle.label | call to append | -| UnsafeTLS.go:329:53:329:93 | selection of TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 : uint16 | semmle.label | selection of TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 : uint16 | -| UnsafeTLS.go:334:13:334:38 | call to InsecureCipherSuites : slice type | semmle.label | call to InsecureCipherSuites : slice type | +| UnsafeTLS.go:329:53:329:93 | selection of TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 | semmle.label | selection of TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 | +| UnsafeTLS.go:334:13:334:38 | call to InsecureCipherSuites | semmle.label | call to InsecureCipherSuites | | UnsafeTLS.go:336:26:336:58 | call to append | semmle.label | call to append | -| UnsafeTLS.go:342:13:342:38 | call to InsecureCipherSuites : slice type | semmle.label | call to InsecureCipherSuites : slice type | +| UnsafeTLS.go:342:13:342:38 | call to InsecureCipherSuites | semmle.label | call to InsecureCipherSuites | | UnsafeTLS.go:346:25:346:36 | cipherSuites | semmle.label | cipherSuites | -| UnsafeTLS.go:351:13:351:38 | call to InsecureCipherSuites : slice type | semmle.label | call to InsecureCipherSuites : slice type | +| UnsafeTLS.go:351:13:351:38 | call to InsecureCipherSuites | semmle.label | call to InsecureCipherSuites | | UnsafeTLS.go:355:25:355:36 | cipherSuites | semmle.label | cipherSuites | | UnsafeTLS.go:362:18:364:4 | slice literal | semmle.label | slice literal | -| UnsafeTLS.go:363:5:363:47 | selection of TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 : uint16 | semmle.label | selection of TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 : uint16 | +| UnsafeTLS.go:363:5:363:47 | selection of TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 | semmle.label | selection of TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 | | UnsafeTLS.go:370:18:372:4 | slice literal | semmle.label | slice literal | -| UnsafeTLS.go:371:5:371:47 | selection of TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 : uint16 | semmle.label | selection of TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 : uint16 | +| UnsafeTLS.go:371:5:371:47 | selection of TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 | semmle.label | selection of TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 | | UnsafeTLS.go:378:18:380:4 | slice literal | semmle.label | slice literal | -| UnsafeTLS.go:379:5:379:47 | selection of TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 : uint16 | semmle.label | selection of TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 : uint16 | +| UnsafeTLS.go:379:5:379:47 | selection of TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 | semmle.label | selection of TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 | | UnsafeTLS.go:386:18:388:4 | slice literal | semmle.label | slice literal | -| UnsafeTLS.go:387:5:387:47 | selection of TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 : uint16 | semmle.label | selection of TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 : uint16 | +| UnsafeTLS.go:387:5:387:47 | selection of TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 | semmle.label | selection of TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 | | UnsafeTLS.go:394:18:396:4 | slice literal | semmle.label | slice literal | -| UnsafeTLS.go:395:5:395:47 | selection of TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 : uint16 | semmle.label | selection of TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 : uint16 | +| UnsafeTLS.go:395:5:395:47 | selection of TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 | semmle.label | selection of TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 | | UnsafeTLS.go:402:33:404:3 | slice literal | semmle.label | slice literal | -| UnsafeTLS.go:403:4:403:46 | selection of TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 : uint16 | semmle.label | selection of TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 : uint16 | +| UnsafeTLS.go:403:4:403:46 | selection of TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 | semmle.label | selection of TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 | | UnsafeTLS.go:409:31:411:3 | slice literal | semmle.label | slice literal | -| UnsafeTLS.go:410:4:410:46 | selection of TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 : uint16 | semmle.label | selection of TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 : uint16 | +| UnsafeTLS.go:410:4:410:46 | selection of TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 | semmle.label | selection of TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 | | UnsafeTLS.go:418:19:420:5 | slice literal | semmle.label | slice literal | -| UnsafeTLS.go:419:6:419:48 | selection of TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 : uint16 | semmle.label | selection of TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 : uint16 | +| UnsafeTLS.go:419:6:419:48 | selection of TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 | semmle.label | selection of TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 | | UnsafeTLS.go:425:19:427:5 | slice literal | semmle.label | slice literal | -| UnsafeTLS.go:426:6:426:48 | selection of TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 : uint16 | semmle.label | selection of TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 : uint16 | +| UnsafeTLS.go:426:6:426:48 | selection of TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 | semmle.label | selection of TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 | | UnsafeTLS.go:432:19:434:5 | slice literal | semmle.label | slice literal | -| UnsafeTLS.go:433:6:433:48 | selection of TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 : uint16 | semmle.label | selection of TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 : uint16 | +| UnsafeTLS.go:433:6:433:48 | selection of TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 | semmle.label | selection of TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 | | UnsafeTLS.go:442:19:444:5 | slice literal | semmle.label | slice literal | -| UnsafeTLS.go:443:6:443:48 | selection of TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 : uint16 | semmle.label | selection of TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 : uint16 | +| UnsafeTLS.go:443:6:443:48 | selection of TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 | semmle.label | selection of TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 | | UnsafeTLS.go:449:19:451:5 | slice literal | semmle.label | slice literal | -| UnsafeTLS.go:450:6:450:48 | selection of TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 : uint16 | semmle.label | selection of TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 : uint16 | +| UnsafeTLS.go:450:6:450:48 | selection of TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 | semmle.label | selection of TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 | | UnsafeTLS.go:456:19:458:5 | slice literal | semmle.label | slice literal | -| UnsafeTLS.go:457:6:457:48 | selection of TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 : uint16 | semmle.label | selection of TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 : uint16 | +| UnsafeTLS.go:457:6:457:48 | selection of TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 | semmle.label | selection of TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 | subpaths #select | UnsafeTLS.go:21:23:21:23 | 0 | UnsafeTLS.go:21:23:21:23 | 0 | UnsafeTLS.go:21:23:21:23 | 0 | Using lowest TLS version for MinVersion. | @@ -141,22 +141,22 @@ subpaths | UnsafeTLS.go:111:16:111:16 | 0 | UnsafeTLS.go:111:16:111:16 | 0 | UnsafeTLS.go:111:16:111:16 | 0 | Using lowest TLS version for MinVersion. | | UnsafeTLS.go:201:17:201:17 | 0 | UnsafeTLS.go:201:17:201:17 | 0 | UnsafeTLS.go:201:17:201:17 | 0 | Using lowest TLS version for MinVersion. | | UnsafeTLS.go:219:17:219:17 | 0 | UnsafeTLS.go:219:17:219:17 | 0 | UnsafeTLS.go:219:17:219:17 | 0 | Using lowest TLS version for MinVersion. | -| UnsafeTLS.go:259:18:266:4 | slice literal | UnsafeTLS.go:260:5:260:32 | selection of TLS_RSA_WITH_RC4_128_SHA : uint16 | UnsafeTLS.go:259:18:266:4 | slice literal | Use of an insecure cipher suite: TLS_RSA_WITH_RC4_128_SHA. | -| UnsafeTLS.go:259:18:266:4 | slice literal | UnsafeTLS.go:261:5:261:39 | selection of TLS_RSA_WITH_AES_128_CBC_SHA256 : uint16 | UnsafeTLS.go:259:18:266:4 | slice literal | Use of an insecure cipher suite: TLS_RSA_WITH_AES_128_CBC_SHA256. | -| UnsafeTLS.go:259:18:266:4 | slice literal | UnsafeTLS.go:262:5:262:40 | selection of TLS_ECDHE_ECDSA_WITH_RC4_128_SHA : uint16 | UnsafeTLS.go:259:18:266:4 | slice literal | Use of an insecure cipher suite: TLS_ECDHE_ECDSA_WITH_RC4_128_SHA. | -| UnsafeTLS.go:259:18:266:4 | slice literal | UnsafeTLS.go:263:5:263:38 | selection of TLS_ECDHE_RSA_WITH_RC4_128_SHA : uint16 | UnsafeTLS.go:259:18:266:4 | slice literal | Use of an insecure cipher suite: TLS_ECDHE_RSA_WITH_RC4_128_SHA. | -| UnsafeTLS.go:259:18:266:4 | slice literal | UnsafeTLS.go:264:5:264:47 | selection of TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 : uint16 | UnsafeTLS.go:259:18:266:4 | slice literal | Use of an insecure cipher suite: TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256. | -| UnsafeTLS.go:259:18:266:4 | slice literal | UnsafeTLS.go:265:5:265:45 | selection of TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 : uint16 | UnsafeTLS.go:259:18:266:4 | slice literal | Use of an insecure cipher suite: TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256. | -| UnsafeTLS.go:272:18:274:4 | slice literal | UnsafeTLS.go:273:5:273:32 | selection of TLS_RSA_WITH_RC4_128_SHA : uint16 | UnsafeTLS.go:272:18:274:4 | slice literal | Use of an insecure cipher suite: TLS_RSA_WITH_RC4_128_SHA. | -| UnsafeTLS.go:280:18:282:4 | slice literal | UnsafeTLS.go:281:5:281:39 | selection of TLS_RSA_WITH_AES_128_CBC_SHA256 : uint16 | UnsafeTLS.go:280:18:282:4 | slice literal | Use of an insecure cipher suite: TLS_RSA_WITH_AES_128_CBC_SHA256. | -| UnsafeTLS.go:288:18:290:4 | slice literal | UnsafeTLS.go:289:5:289:40 | selection of TLS_ECDHE_ECDSA_WITH_RC4_128_SHA : uint16 | UnsafeTLS.go:288:18:290:4 | slice literal | Use of an insecure cipher suite: TLS_ECDHE_ECDSA_WITH_RC4_128_SHA. | -| UnsafeTLS.go:296:18:298:4 | slice literal | UnsafeTLS.go:297:5:297:38 | selection of TLS_ECDHE_RSA_WITH_RC4_128_SHA : uint16 | UnsafeTLS.go:296:18:298:4 | slice literal | Use of an insecure cipher suite: TLS_ECDHE_RSA_WITH_RC4_128_SHA. | -| UnsafeTLS.go:304:18:306:4 | slice literal | UnsafeTLS.go:305:5:305:47 | selection of TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 : uint16 | UnsafeTLS.go:304:18:306:4 | slice literal | Use of an insecure cipher suite: TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256. | -| UnsafeTLS.go:312:18:314:4 | slice literal | UnsafeTLS.go:313:5:313:45 | selection of TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 : uint16 | UnsafeTLS.go:312:18:314:4 | slice literal | Use of an insecure cipher suite: TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256. | -| UnsafeTLS.go:329:25:329:94 | call to append | UnsafeTLS.go:329:53:329:93 | selection of TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 : uint16 | UnsafeTLS.go:329:25:329:94 | call to append | Use of an insecure cipher suite: TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256. | -| UnsafeTLS.go:336:26:336:58 | call to append | UnsafeTLS.go:334:13:334:38 | call to InsecureCipherSuites : slice type | UnsafeTLS.go:336:26:336:58 | call to append | Use of an insecure cipher suite. | -| UnsafeTLS.go:346:25:346:36 | cipherSuites | UnsafeTLS.go:342:13:342:38 | call to InsecureCipherSuites : slice type | UnsafeTLS.go:346:25:346:36 | cipherSuites | Use of an insecure cipher suite. | -| UnsafeTLS.go:355:25:355:36 | cipherSuites | UnsafeTLS.go:351:13:351:38 | call to InsecureCipherSuites : slice type | UnsafeTLS.go:355:25:355:36 | cipherSuites | Use of an insecure cipher suite. | -| UnsafeTLS.go:362:18:364:4 | slice literal | UnsafeTLS.go:363:5:363:47 | selection of TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 : uint16 | UnsafeTLS.go:362:18:364:4 | slice literal | Use of an insecure cipher suite: TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256. | -| UnsafeTLS.go:432:19:434:5 | slice literal | UnsafeTLS.go:433:6:433:48 | selection of TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 : uint16 | UnsafeTLS.go:432:19:434:5 | slice literal | Use of an insecure cipher suite: TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256. | -| UnsafeTLS.go:456:19:458:5 | slice literal | UnsafeTLS.go:457:6:457:48 | selection of TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 : uint16 | UnsafeTLS.go:456:19:458:5 | slice literal | Use of an insecure cipher suite: TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256. | +| UnsafeTLS.go:259:18:266:4 | slice literal | UnsafeTLS.go:260:5:260:32 | selection of TLS_RSA_WITH_RC4_128_SHA | UnsafeTLS.go:259:18:266:4 | slice literal | Use of an insecure cipher suite: TLS_RSA_WITH_RC4_128_SHA. | +| UnsafeTLS.go:259:18:266:4 | slice literal | UnsafeTLS.go:261:5:261:39 | selection of TLS_RSA_WITH_AES_128_CBC_SHA256 | UnsafeTLS.go:259:18:266:4 | slice literal | Use of an insecure cipher suite: TLS_RSA_WITH_AES_128_CBC_SHA256. | +| UnsafeTLS.go:259:18:266:4 | slice literal | UnsafeTLS.go:262:5:262:40 | selection of TLS_ECDHE_ECDSA_WITH_RC4_128_SHA | UnsafeTLS.go:259:18:266:4 | slice literal | Use of an insecure cipher suite: TLS_ECDHE_ECDSA_WITH_RC4_128_SHA. | +| UnsafeTLS.go:259:18:266:4 | slice literal | UnsafeTLS.go:263:5:263:38 | selection of TLS_ECDHE_RSA_WITH_RC4_128_SHA | UnsafeTLS.go:259:18:266:4 | slice literal | Use of an insecure cipher suite: TLS_ECDHE_RSA_WITH_RC4_128_SHA. | +| UnsafeTLS.go:259:18:266:4 | slice literal | UnsafeTLS.go:264:5:264:47 | selection of TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 | UnsafeTLS.go:259:18:266:4 | slice literal | Use of an insecure cipher suite: TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256. | +| UnsafeTLS.go:259:18:266:4 | slice literal | UnsafeTLS.go:265:5:265:45 | selection of TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 | UnsafeTLS.go:259:18:266:4 | slice literal | Use of an insecure cipher suite: TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256. | +| UnsafeTLS.go:272:18:274:4 | slice literal | UnsafeTLS.go:273:5:273:32 | selection of TLS_RSA_WITH_RC4_128_SHA | UnsafeTLS.go:272:18:274:4 | slice literal | Use of an insecure cipher suite: TLS_RSA_WITH_RC4_128_SHA. | +| UnsafeTLS.go:280:18:282:4 | slice literal | UnsafeTLS.go:281:5:281:39 | selection of TLS_RSA_WITH_AES_128_CBC_SHA256 | UnsafeTLS.go:280:18:282:4 | slice literal | Use of an insecure cipher suite: TLS_RSA_WITH_AES_128_CBC_SHA256. | +| UnsafeTLS.go:288:18:290:4 | slice literal | UnsafeTLS.go:289:5:289:40 | selection of TLS_ECDHE_ECDSA_WITH_RC4_128_SHA | UnsafeTLS.go:288:18:290:4 | slice literal | Use of an insecure cipher suite: TLS_ECDHE_ECDSA_WITH_RC4_128_SHA. | +| UnsafeTLS.go:296:18:298:4 | slice literal | UnsafeTLS.go:297:5:297:38 | selection of TLS_ECDHE_RSA_WITH_RC4_128_SHA | UnsafeTLS.go:296:18:298:4 | slice literal | Use of an insecure cipher suite: TLS_ECDHE_RSA_WITH_RC4_128_SHA. | +| UnsafeTLS.go:304:18:306:4 | slice literal | UnsafeTLS.go:305:5:305:47 | selection of TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 | UnsafeTLS.go:304:18:306:4 | slice literal | Use of an insecure cipher suite: TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256. | +| UnsafeTLS.go:312:18:314:4 | slice literal | UnsafeTLS.go:313:5:313:45 | selection of TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 | UnsafeTLS.go:312:18:314:4 | slice literal | Use of an insecure cipher suite: TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256. | +| UnsafeTLS.go:329:25:329:94 | call to append | UnsafeTLS.go:329:53:329:93 | selection of TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 | UnsafeTLS.go:329:25:329:94 | call to append | Use of an insecure cipher suite: TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256. | +| UnsafeTLS.go:336:26:336:58 | call to append | UnsafeTLS.go:334:13:334:38 | call to InsecureCipherSuites | UnsafeTLS.go:336:26:336:58 | call to append | Use of an insecure cipher suite. | +| UnsafeTLS.go:346:25:346:36 | cipherSuites | UnsafeTLS.go:342:13:342:38 | call to InsecureCipherSuites | UnsafeTLS.go:346:25:346:36 | cipherSuites | Use of an insecure cipher suite. | +| UnsafeTLS.go:355:25:355:36 | cipherSuites | UnsafeTLS.go:351:13:351:38 | call to InsecureCipherSuites | UnsafeTLS.go:355:25:355:36 | cipherSuites | Use of an insecure cipher suite. | +| UnsafeTLS.go:362:18:364:4 | slice literal | UnsafeTLS.go:363:5:363:47 | selection of TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 | UnsafeTLS.go:362:18:364:4 | slice literal | Use of an insecure cipher suite: TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256. | +| UnsafeTLS.go:432:19:434:5 | slice literal | UnsafeTLS.go:433:6:433:48 | selection of TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 | UnsafeTLS.go:432:19:434:5 | slice literal | Use of an insecure cipher suite: TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256. | +| UnsafeTLS.go:456:19:458:5 | slice literal | UnsafeTLS.go:457:6:457:48 | selection of TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 | UnsafeTLS.go:456:19:458:5 | slice literal | Use of an insecure cipher suite: TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256. | diff --git a/go/ql/test/query-tests/Security/CWE-327/WeakCryptoAlgorithm.expected b/go/ql/test/query-tests/Security/CWE-327/WeakCryptoAlgorithm.expected index 50d09ac532d..a107cd75df0 100644 --- a/go/ql/test/query-tests/Security/CWE-327/WeakCryptoAlgorithm.expected +++ b/go/ql/test/query-tests/Security/CWE-327/WeakCryptoAlgorithm.expected @@ -1,17 +1,17 @@ edges -| Crypto.go:16:9:16:16 | password : slice type | Crypto.go:19:25:19:27 | buf | -| Crypto.go:16:9:16:16 | password : slice type | Crypto.go:22:10:22:12 | buf | -| Crypto.go:16:9:16:16 | password : slice type | Crypto.go:25:16:25:18 | buf | -| Crypto.go:16:9:16:16 | password : slice type | Crypto.go:28:11:28:13 | buf | +| Crypto.go:16:9:16:16 | password | Crypto.go:19:25:19:27 | buf | +| Crypto.go:16:9:16:16 | password | Crypto.go:22:10:22:12 | buf | +| Crypto.go:16:9:16:16 | password | Crypto.go:25:16:25:18 | buf | +| Crypto.go:16:9:16:16 | password | Crypto.go:28:11:28:13 | buf | nodes -| Crypto.go:16:9:16:16 | password : slice type | semmle.label | password : slice type | +| Crypto.go:16:9:16:16 | password | semmle.label | password | | Crypto.go:19:25:19:27 | buf | semmle.label | buf | | Crypto.go:22:10:22:12 | buf | semmle.label | buf | | Crypto.go:25:16:25:18 | buf | semmle.label | buf | | Crypto.go:28:11:28:13 | buf | semmle.label | buf | subpaths #select -| Crypto.go:19:25:19:27 | buf | Crypto.go:16:9:16:16 | password : slice type | Crypto.go:19:25:19:27 | buf | $@ is used in a weak cryptographic algorithm. | Crypto.go:16:9:16:16 | password | Sensitive data | -| Crypto.go:22:10:22:12 | buf | Crypto.go:16:9:16:16 | password : slice type | Crypto.go:22:10:22:12 | buf | $@ is used in a weak cryptographic algorithm. | Crypto.go:16:9:16:16 | password | Sensitive data | -| Crypto.go:25:16:25:18 | buf | Crypto.go:16:9:16:16 | password : slice type | Crypto.go:25:16:25:18 | buf | $@ is used in a weak cryptographic algorithm. | Crypto.go:16:9:16:16 | password | Sensitive data | -| Crypto.go:28:11:28:13 | buf | Crypto.go:16:9:16:16 | password : slice type | Crypto.go:28:11:28:13 | buf | $@ is used in a weak cryptographic algorithm. | Crypto.go:16:9:16:16 | password | Sensitive data | +| Crypto.go:19:25:19:27 | buf | Crypto.go:16:9:16:16 | password | Crypto.go:19:25:19:27 | buf | $@ is used in a weak cryptographic algorithm. | Crypto.go:16:9:16:16 | password | Sensitive data | +| Crypto.go:22:10:22:12 | buf | Crypto.go:16:9:16:16 | password | Crypto.go:22:10:22:12 | buf | $@ is used in a weak cryptographic algorithm. | Crypto.go:16:9:16:16 | password | Sensitive data | +| Crypto.go:25:16:25:18 | buf | Crypto.go:16:9:16:16 | password | Crypto.go:25:16:25:18 | buf | $@ is used in a weak cryptographic algorithm. | Crypto.go:16:9:16:16 | password | Sensitive data | +| Crypto.go:28:11:28:13 | buf | Crypto.go:16:9:16:16 | password | Crypto.go:28:11:28:13 | buf | $@ is used in a weak cryptographic algorithm. | Crypto.go:16:9:16:16 | password | Sensitive data | diff --git a/go/ql/test/query-tests/Security/CWE-338/InsecureRandomness/InsecureRandomness.expected b/go/ql/test/query-tests/Security/CWE-338/InsecureRandomness/InsecureRandomness.expected index 2ba310c6ee1..9e767daf186 100644 --- a/go/ql/test/query-tests/Security/CWE-338/InsecureRandomness/InsecureRandomness.expected +++ b/go/ql/test/query-tests/Security/CWE-338/InsecureRandomness/InsecureRandomness.expected @@ -1,16 +1,16 @@ edges -| sample.go:15:24:15:63 | type conversion : string | sample.go:16:9:16:15 | slice expression : slice type | -| sample.go:15:49:15:61 | call to Uint32 : uint32 | sample.go:15:24:15:63 | type conversion : string | -| sample.go:16:9:16:15 | slice expression : slice type | sample.go:26:25:26:30 | call to Guid | -| sample.go:34:12:34:40 | call to New : pointer type | sample.go:37:25:37:29 | nonce | -| sample.go:34:12:34:40 | call to New : pointer type | sample.go:37:32:37:36 | nonce | +| sample.go:15:24:15:63 | type conversion | sample.go:16:9:16:15 | slice expression | +| sample.go:15:49:15:61 | call to Uint32 | sample.go:15:24:15:63 | type conversion | +| sample.go:16:9:16:15 | slice expression | sample.go:26:25:26:30 | call to Guid | +| sample.go:34:12:34:40 | call to New | sample.go:37:25:37:29 | nonce | +| sample.go:34:12:34:40 | call to New | sample.go:37:32:37:36 | nonce | nodes | InsecureRandomness.go:12:18:12:40 | call to Intn | semmle.label | call to Intn | -| sample.go:15:24:15:63 | type conversion : string | semmle.label | type conversion : string | -| sample.go:15:49:15:61 | call to Uint32 : uint32 | semmle.label | call to Uint32 : uint32 | -| sample.go:16:9:16:15 | slice expression : slice type | semmle.label | slice expression : slice type | +| sample.go:15:24:15:63 | type conversion | semmle.label | type conversion | +| sample.go:15:49:15:61 | call to Uint32 | semmle.label | call to Uint32 | +| sample.go:16:9:16:15 | slice expression | semmle.label | slice expression | | sample.go:26:25:26:30 | call to Guid | semmle.label | call to Guid | -| sample.go:34:12:34:40 | call to New : pointer type | semmle.label | call to New : pointer type | +| sample.go:34:12:34:40 | call to New | semmle.label | call to New | | sample.go:37:25:37:29 | nonce | semmle.label | nonce | | sample.go:37:32:37:36 | nonce | semmle.label | nonce | | sample.go:43:17:43:39 | call to Intn | semmle.label | call to Intn | @@ -21,7 +21,7 @@ nodes subpaths #select | InsecureRandomness.go:12:18:12:40 | call to Intn | InsecureRandomness.go:12:18:12:40 | call to Intn | InsecureRandomness.go:12:18:12:40 | call to Intn | A password-related function depends on a $@ generated with a cryptographically weak RNG. | InsecureRandomness.go:12:18:12:40 | call to Intn | random number | -| sample.go:26:25:26:30 | call to Guid | sample.go:15:49:15:61 | call to Uint32 : uint32 | sample.go:26:25:26:30 | call to Guid | This cryptographic algorithm depends on a $@ generated with a cryptographically weak RNG. | sample.go:15:49:15:61 | call to Uint32 | random number | -| sample.go:37:25:37:29 | nonce | sample.go:34:12:34:40 | call to New : pointer type | sample.go:37:25:37:29 | nonce | This cryptographic algorithm depends on a $@ generated with a cryptographically weak RNG. | sample.go:34:12:34:40 | call to New | random number | -| sample.go:37:32:37:36 | nonce | sample.go:34:12:34:40 | call to New : pointer type | sample.go:37:32:37:36 | nonce | This cryptographic algorithm depends on a $@ generated with a cryptographically weak RNG. | sample.go:34:12:34:40 | call to New | random number | +| sample.go:26:25:26:30 | call to Guid | sample.go:15:49:15:61 | call to Uint32 | sample.go:26:25:26:30 | call to Guid | This cryptographic algorithm depends on a $@ generated with a cryptographically weak RNG. | sample.go:15:49:15:61 | call to Uint32 | random number | +| sample.go:37:25:37:29 | nonce | sample.go:34:12:34:40 | call to New | sample.go:37:25:37:29 | nonce | This cryptographic algorithm depends on a $@ generated with a cryptographically weak RNG. | sample.go:34:12:34:40 | call to New | random number | +| sample.go:37:32:37:36 | nonce | sample.go:34:12:34:40 | call to New | sample.go:37:32:37:36 | nonce | This cryptographic algorithm depends on a $@ generated with a cryptographically weak RNG. | sample.go:34:12:34:40 | call to New | random number | | sample.go:43:17:43:39 | call to Intn | sample.go:43:17:43:39 | call to Intn | sample.go:43:17:43:39 | call to Intn | A password-related function depends on a $@ generated with a cryptographically weak RNG. | sample.go:43:17:43:39 | call to Intn | random number | diff --git a/go/ql/test/query-tests/Security/CWE-352/ConstantOauth2State.expected b/go/ql/test/query-tests/Security/CWE-352/ConstantOauth2State.expected index 06cc9c6618e..c21e28717c7 100644 --- a/go/ql/test/query-tests/Security/CWE-352/ConstantOauth2State.expected +++ b/go/ql/test/query-tests/Security/CWE-352/ConstantOauth2State.expected @@ -1,61 +1,61 @@ edges -| ConstantOauth2State.go:20:26:20:32 | "state" : string literal | ConstantOauth2State.go:50:26:50:41 | stateStringConst | -| ConstantOauth2State.go:20:26:20:32 | "state" : string literal | ConstantOauth2State.go:147:26:147:41 | stateStringConst | -| ConstantOauth2State.go:20:26:20:32 | "state" : string literal | ConstantOauth2State.go:169:26:169:41 | stateStringConst | -| ConstantOauth2State.go:20:26:20:32 | "state" : string literal | ConstantOauth2State.go:191:26:191:41 | stateStringConst | -| ConstantOauth2State.go:20:26:20:32 | "state" : string literal | ConstantOauth2State.go:210:26:210:41 | stateStringConst | -| ConstantOauth2State.go:20:26:20:32 | "state" : string literal | ConstantOauth2State.go:232:26:232:41 | stateStringConst | -| ConstantOauth2State.go:20:26:20:32 | "state" : string literal | ConstantOauth2State.go:249:26:249:41 | stateStringConst | -| ConstantOauth2State.go:20:26:20:32 | "state" : string literal | ConstantOauth2State.go:266:26:266:41 | stateStringConst | -| ConstantOauth2State.go:20:26:20:32 | "state" : string literal | ConstantOauth2State.go:282:26:282:41 | stateStringConst | -| ConstantOauth2State.go:22:22:22:28 | "state" : string | ConstantOauth2State.go:65:26:65:39 | stateStringVar | -| ConstantOauth2State.go:80:11:80:25 | call to newFixedState : string | ConstantOauth2State.go:81:26:81:30 | state | -| ConstantOauth2State.go:86:9:86:15 | "state" : string | ConstantOauth2State.go:80:11:80:25 | call to newFixedState : string | -| ConstantOauth2State.go:147:9:147:42 | call to AuthCodeURL : string | ConstantOauth2State.go:148:54:148:56 | url | -| ConstantOauth2State.go:169:9:169:42 | call to AuthCodeURL : string | ConstantOauth2State.go:170:54:170:56 | url | -| ConstantOauth2State.go:191:9:191:42 | call to AuthCodeURL : string | ConstantOauth2State.go:192:54:192:56 | url | -| ConstantOauth2State.go:210:9:210:42 | call to AuthCodeURL : string | ConstantOauth2State.go:211:54:211:56 | url | -| ConstantOauth2State.go:232:9:232:42 | call to AuthCodeURL : string | ConstantOauth2State.go:233:28:233:30 | url | -| ConstantOauth2State.go:239:17:239:39 | "http://localhost:8080" : string | ConstantOauth2State.go:249:9:249:12 | conf | -| ConstantOauth2State.go:256:38:256:60 | "http://localhost:8080" : string | ConstantOauth2State.go:266:9:266:12 | conf | -| ConstantOauth2State.go:272:17:272:21 | "oob" : string | ConstantOauth2State.go:282:9:282:12 | conf | +| ConstantOauth2State.go:20:26:20:32 | "state" | ConstantOauth2State.go:50:26:50:41 | stateStringConst | +| ConstantOauth2State.go:20:26:20:32 | "state" | ConstantOauth2State.go:147:26:147:41 | stateStringConst | +| ConstantOauth2State.go:20:26:20:32 | "state" | ConstantOauth2State.go:169:26:169:41 | stateStringConst | +| ConstantOauth2State.go:20:26:20:32 | "state" | ConstantOauth2State.go:191:26:191:41 | stateStringConst | +| ConstantOauth2State.go:20:26:20:32 | "state" | ConstantOauth2State.go:210:26:210:41 | stateStringConst | +| ConstantOauth2State.go:20:26:20:32 | "state" | ConstantOauth2State.go:232:26:232:41 | stateStringConst | +| ConstantOauth2State.go:20:26:20:32 | "state" | ConstantOauth2State.go:249:26:249:41 | stateStringConst | +| ConstantOauth2State.go:20:26:20:32 | "state" | ConstantOauth2State.go:266:26:266:41 | stateStringConst | +| ConstantOauth2State.go:20:26:20:32 | "state" | ConstantOauth2State.go:282:26:282:41 | stateStringConst | +| ConstantOauth2State.go:22:22:22:28 | "state" | ConstantOauth2State.go:65:26:65:39 | stateStringVar | +| ConstantOauth2State.go:80:11:80:25 | call to newFixedState | ConstantOauth2State.go:81:26:81:30 | state | +| ConstantOauth2State.go:86:9:86:15 | "state" | ConstantOauth2State.go:80:11:80:25 | call to newFixedState | +| ConstantOauth2State.go:147:9:147:42 | call to AuthCodeURL | ConstantOauth2State.go:148:54:148:56 | url | +| ConstantOauth2State.go:169:9:169:42 | call to AuthCodeURL | ConstantOauth2State.go:170:54:170:56 | url | +| ConstantOauth2State.go:191:9:191:42 | call to AuthCodeURL | ConstantOauth2State.go:192:54:192:56 | url | +| ConstantOauth2State.go:210:9:210:42 | call to AuthCodeURL | ConstantOauth2State.go:211:54:211:56 | url | +| ConstantOauth2State.go:232:9:232:42 | call to AuthCodeURL | ConstantOauth2State.go:233:28:233:30 | url | +| ConstantOauth2State.go:239:17:239:39 | "http://localhost:8080" | ConstantOauth2State.go:249:9:249:12 | conf | +| ConstantOauth2State.go:256:38:256:60 | "http://localhost:8080" | ConstantOauth2State.go:266:9:266:12 | conf | +| ConstantOauth2State.go:272:17:272:21 | "oob" | ConstantOauth2State.go:282:9:282:12 | conf | nodes -| ConstantOauth2State.go:20:26:20:32 | "state" : string literal | semmle.label | "state" : string literal | -| ConstantOauth2State.go:22:22:22:28 | "state" : string | semmle.label | "state" : string | +| ConstantOauth2State.go:20:26:20:32 | "state" | semmle.label | "state" | +| ConstantOauth2State.go:22:22:22:28 | "state" | semmle.label | "state" | | ConstantOauth2State.go:35:26:35:32 | "state" | semmle.label | "state" | | ConstantOauth2State.go:50:26:50:41 | stateStringConst | semmle.label | stateStringConst | | ConstantOauth2State.go:65:26:65:39 | stateStringVar | semmle.label | stateStringVar | -| ConstantOauth2State.go:80:11:80:25 | call to newFixedState : string | semmle.label | call to newFixedState : string | +| ConstantOauth2State.go:80:11:80:25 | call to newFixedState | semmle.label | call to newFixedState | | ConstantOauth2State.go:81:26:81:30 | state | semmle.label | state | -| ConstantOauth2State.go:86:9:86:15 | "state" : string | semmle.label | "state" : string | -| ConstantOauth2State.go:147:9:147:42 | call to AuthCodeURL : string | semmle.label | call to AuthCodeURL : string | +| ConstantOauth2State.go:86:9:86:15 | "state" | semmle.label | "state" | +| ConstantOauth2State.go:147:9:147:42 | call to AuthCodeURL | semmle.label | call to AuthCodeURL | | ConstantOauth2State.go:147:26:147:41 | stateStringConst | semmle.label | stateStringConst | | ConstantOauth2State.go:148:54:148:56 | url | semmle.label | url | -| ConstantOauth2State.go:169:9:169:42 | call to AuthCodeURL : string | semmle.label | call to AuthCodeURL : string | +| ConstantOauth2State.go:169:9:169:42 | call to AuthCodeURL | semmle.label | call to AuthCodeURL | | ConstantOauth2State.go:169:26:169:41 | stateStringConst | semmle.label | stateStringConst | | ConstantOauth2State.go:170:54:170:56 | url | semmle.label | url | -| ConstantOauth2State.go:191:9:191:42 | call to AuthCodeURL : string | semmle.label | call to AuthCodeURL : string | +| ConstantOauth2State.go:191:9:191:42 | call to AuthCodeURL | semmle.label | call to AuthCodeURL | | ConstantOauth2State.go:191:26:191:41 | stateStringConst | semmle.label | stateStringConst | | ConstantOauth2State.go:192:54:192:56 | url | semmle.label | url | -| ConstantOauth2State.go:210:9:210:42 | call to AuthCodeURL : string | semmle.label | call to AuthCodeURL : string | +| ConstantOauth2State.go:210:9:210:42 | call to AuthCodeURL | semmle.label | call to AuthCodeURL | | ConstantOauth2State.go:210:26:210:41 | stateStringConst | semmle.label | stateStringConst | | ConstantOauth2State.go:211:54:211:56 | url | semmle.label | url | -| ConstantOauth2State.go:232:9:232:42 | call to AuthCodeURL : string | semmle.label | call to AuthCodeURL : string | +| ConstantOauth2State.go:232:9:232:42 | call to AuthCodeURL | semmle.label | call to AuthCodeURL | | ConstantOauth2State.go:232:26:232:41 | stateStringConst | semmle.label | stateStringConst | | ConstantOauth2State.go:233:28:233:30 | url | semmle.label | url | -| ConstantOauth2State.go:239:17:239:39 | "http://localhost:8080" : string | semmle.label | "http://localhost:8080" : string | +| ConstantOauth2State.go:239:17:239:39 | "http://localhost:8080" | semmle.label | "http://localhost:8080" | | ConstantOauth2State.go:249:9:249:12 | conf | semmle.label | conf | | ConstantOauth2State.go:249:26:249:41 | stateStringConst | semmle.label | stateStringConst | -| ConstantOauth2State.go:256:38:256:60 | "http://localhost:8080" : string | semmle.label | "http://localhost:8080" : string | +| ConstantOauth2State.go:256:38:256:60 | "http://localhost:8080" | semmle.label | "http://localhost:8080" | | ConstantOauth2State.go:266:9:266:12 | conf | semmle.label | conf | | ConstantOauth2State.go:266:26:266:41 | stateStringConst | semmle.label | stateStringConst | -| ConstantOauth2State.go:272:17:272:21 | "oob" : string | semmle.label | "oob" : string | +| ConstantOauth2State.go:272:17:272:21 | "oob" | semmle.label | "oob" | | ConstantOauth2State.go:282:9:282:12 | conf | semmle.label | conf | | ConstantOauth2State.go:282:26:282:41 | stateStringConst | semmle.label | stateStringConst | subpaths #select | ConstantOauth2State.go:35:26:35:32 | "state" | ConstantOauth2State.go:35:26:35:32 | "state" | ConstantOauth2State.go:35:26:35:32 | "state" | Using a constant $@ to create oauth2 URLs. | ConstantOauth2State.go:35:26:35:32 | "state" | state string | -| ConstantOauth2State.go:50:26:50:41 | stateStringConst | ConstantOauth2State.go:20:26:20:32 | "state" : string literal | ConstantOauth2State.go:50:26:50:41 | stateStringConst | Using a constant $@ to create oauth2 URLs. | ConstantOauth2State.go:20:26:20:32 | "state" | state string | -| ConstantOauth2State.go:65:26:65:39 | stateStringVar | ConstantOauth2State.go:22:22:22:28 | "state" : string | ConstantOauth2State.go:65:26:65:39 | stateStringVar | Using a constant $@ to create oauth2 URLs. | ConstantOauth2State.go:22:22:22:28 | "state" | state string | -| ConstantOauth2State.go:81:26:81:30 | state | ConstantOauth2State.go:86:9:86:15 | "state" : string | ConstantOauth2State.go:81:26:81:30 | state | Using a constant $@ to create oauth2 URLs. | ConstantOauth2State.go:86:9:86:15 | "state" | state string | -| ConstantOauth2State.go:232:26:232:41 | stateStringConst | ConstantOauth2State.go:20:26:20:32 | "state" : string literal | ConstantOauth2State.go:232:26:232:41 | stateStringConst | Using a constant $@ to create oauth2 URLs. | ConstantOauth2State.go:20:26:20:32 | "state" | state string | +| ConstantOauth2State.go:50:26:50:41 | stateStringConst | ConstantOauth2State.go:20:26:20:32 | "state" | ConstantOauth2State.go:50:26:50:41 | stateStringConst | Using a constant $@ to create oauth2 URLs. | ConstantOauth2State.go:20:26:20:32 | "state" | state string | +| ConstantOauth2State.go:65:26:65:39 | stateStringVar | ConstantOauth2State.go:22:22:22:28 | "state" | ConstantOauth2State.go:65:26:65:39 | stateStringVar | Using a constant $@ to create oauth2 URLs. | ConstantOauth2State.go:22:22:22:28 | "state" | state string | +| ConstantOauth2State.go:81:26:81:30 | state | ConstantOauth2State.go:86:9:86:15 | "state" | ConstantOauth2State.go:81:26:81:30 | state | Using a constant $@ to create oauth2 URLs. | ConstantOauth2State.go:86:9:86:15 | "state" | state string | +| ConstantOauth2State.go:232:26:232:41 | stateStringConst | ConstantOauth2State.go:20:26:20:32 | "state" | ConstantOauth2State.go:232:26:232:41 | stateStringConst | Using a constant $@ to create oauth2 URLs. | ConstantOauth2State.go:20:26:20:32 | "state" | state string | diff --git a/go/ql/test/query-tests/Security/CWE-601/BadRedirectCheck/BadRedirectCheck.expected b/go/ql/test/query-tests/Security/CWE-601/BadRedirectCheck/BadRedirectCheck.expected index 240c71fb6c1..df3c6383bc4 100644 --- a/go/ql/test/query-tests/Security/CWE-601/BadRedirectCheck/BadRedirectCheck.expected +++ b/go/ql/test/query-tests/Security/CWE-601/BadRedirectCheck/BadRedirectCheck.expected @@ -1,56 +1,56 @@ edges -| BadRedirectCheck.go:3:18:3:22 | argument corresponding to redir : string | BadRedirectCheck.go:5:10:5:14 | redir : string | -| BadRedirectCheck.go:3:18:3:22 | definition of redir : string | BadRedirectCheck.go:5:10:5:14 | redir : string | -| BadRedirectCheck.go:5:10:5:14 | redir : string | main.go:11:25:11:45 | call to sanitizeUrl | -| cves.go:14:23:14:25 | argument corresponding to url : string | cves.go:16:26:16:28 | url | -| cves.go:33:14:33:34 | call to Get : string | cves.go:37:25:37:32 | redirect | -| cves.go:41:14:41:34 | call to Get : string | cves.go:45:25:45:32 | redirect | -| main.go:10:18:10:25 | argument corresponding to redirect : string | main.go:11:37:11:44 | redirect : string | -| main.go:11:37:11:44 | redirect : string | BadRedirectCheck.go:3:18:3:22 | definition of redir : string | -| main.go:11:37:11:44 | redirect : string | main.go:11:25:11:45 | call to sanitizeUrl | -| main.go:32:24:32:26 | argument corresponding to url : string | main.go:34:26:34:28 | url | -| main.go:68:17:68:24 | argument corresponding to redirect : string | main.go:73:9:73:28 | call to Clean : string | -| main.go:68:17:68:24 | definition of redirect : string | main.go:73:9:73:28 | call to Clean : string | -| main.go:73:9:73:28 | call to Clean : string | main.go:77:25:77:39 | call to getTarget1 | -| main.go:76:19:76:21 | argument corresponding to url : string | main.go:77:36:77:38 | url : string | -| main.go:77:36:77:38 | url : string | main.go:68:17:68:24 | definition of redirect : string | -| main.go:77:36:77:38 | url : string | main.go:77:25:77:39 | call to getTarget1 | -| main.go:87:9:87:14 | selection of Path : string | main.go:91:25:91:39 | call to getTarget2 | +| BadRedirectCheck.go:3:18:3:22 | argument corresponding to redir | BadRedirectCheck.go:5:10:5:14 | redir | +| BadRedirectCheck.go:3:18:3:22 | definition of redir | BadRedirectCheck.go:5:10:5:14 | redir | +| BadRedirectCheck.go:5:10:5:14 | redir | main.go:11:25:11:45 | call to sanitizeUrl | +| cves.go:14:23:14:25 | argument corresponding to url | cves.go:16:26:16:28 | url | +| cves.go:33:14:33:34 | call to Get | cves.go:37:25:37:32 | redirect | +| cves.go:41:14:41:34 | call to Get | cves.go:45:25:45:32 | redirect | +| main.go:10:18:10:25 | argument corresponding to redirect | main.go:11:37:11:44 | redirect | +| main.go:11:37:11:44 | redirect | BadRedirectCheck.go:3:18:3:22 | definition of redir | +| main.go:11:37:11:44 | redirect | main.go:11:25:11:45 | call to sanitizeUrl | +| main.go:32:24:32:26 | argument corresponding to url | main.go:34:26:34:28 | url | +| main.go:68:17:68:24 | argument corresponding to redirect | main.go:73:9:73:28 | call to Clean | +| main.go:68:17:68:24 | definition of redirect | main.go:73:9:73:28 | call to Clean | +| main.go:73:9:73:28 | call to Clean | main.go:77:25:77:39 | call to getTarget1 | +| main.go:76:19:76:21 | argument corresponding to url | main.go:77:36:77:38 | url | +| main.go:77:36:77:38 | url | main.go:68:17:68:24 | definition of redirect | +| main.go:77:36:77:38 | url | main.go:77:25:77:39 | call to getTarget1 | +| main.go:87:9:87:14 | selection of Path | main.go:91:25:91:39 | call to getTarget2 | nodes -| BadRedirectCheck.go:3:18:3:22 | argument corresponding to redir : string | semmle.label | argument corresponding to redir : string | -| BadRedirectCheck.go:3:18:3:22 | definition of redir : string | semmle.label | definition of redir : string | -| BadRedirectCheck.go:5:10:5:14 | redir : string | semmle.label | redir : string | -| BadRedirectCheck.go:5:10:5:14 | redir : string | semmle.label | redir : string | -| cves.go:14:23:14:25 | argument corresponding to url : string | semmle.label | argument corresponding to url : string | +| BadRedirectCheck.go:3:18:3:22 | argument corresponding to redir | semmle.label | argument corresponding to redir | +| BadRedirectCheck.go:3:18:3:22 | definition of redir | semmle.label | definition of redir | +| BadRedirectCheck.go:5:10:5:14 | redir | semmle.label | redir | +| BadRedirectCheck.go:5:10:5:14 | redir | semmle.label | redir | +| cves.go:14:23:14:25 | argument corresponding to url | semmle.label | argument corresponding to url | | cves.go:16:26:16:28 | url | semmle.label | url | -| cves.go:33:14:33:34 | call to Get : string | semmle.label | call to Get : string | +| cves.go:33:14:33:34 | call to Get | semmle.label | call to Get | | cves.go:37:25:37:32 | redirect | semmle.label | redirect | -| cves.go:41:14:41:34 | call to Get : string | semmle.label | call to Get : string | +| cves.go:41:14:41:34 | call to Get | semmle.label | call to Get | | cves.go:45:25:45:32 | redirect | semmle.label | redirect | -| main.go:10:18:10:25 | argument corresponding to redirect : string | semmle.label | argument corresponding to redirect : string | +| main.go:10:18:10:25 | argument corresponding to redirect | semmle.label | argument corresponding to redirect | | main.go:11:25:11:45 | call to sanitizeUrl | semmle.label | call to sanitizeUrl | -| main.go:11:37:11:44 | redirect : string | semmle.label | redirect : string | -| main.go:32:24:32:26 | argument corresponding to url : string | semmle.label | argument corresponding to url : string | +| main.go:11:37:11:44 | redirect | semmle.label | redirect | +| main.go:32:24:32:26 | argument corresponding to url | semmle.label | argument corresponding to url | | main.go:34:26:34:28 | url | semmle.label | url | -| main.go:68:17:68:24 | argument corresponding to redirect : string | semmle.label | argument corresponding to redirect : string | -| main.go:68:17:68:24 | definition of redirect : string | semmle.label | definition of redirect : string | -| main.go:73:9:73:28 | call to Clean : string | semmle.label | call to Clean : string | -| main.go:73:9:73:28 | call to Clean : string | semmle.label | call to Clean : string | -| main.go:76:19:76:21 | argument corresponding to url : string | semmle.label | argument corresponding to url : string | +| main.go:68:17:68:24 | argument corresponding to redirect | semmle.label | argument corresponding to redirect | +| main.go:68:17:68:24 | definition of redirect | semmle.label | definition of redirect | +| main.go:73:9:73:28 | call to Clean | semmle.label | call to Clean | +| main.go:73:9:73:28 | call to Clean | semmle.label | call to Clean | +| main.go:76:19:76:21 | argument corresponding to url | semmle.label | argument corresponding to url | | main.go:77:25:77:39 | call to getTarget1 | semmle.label | call to getTarget1 | -| main.go:77:36:77:38 | url : string | semmle.label | url : string | -| main.go:87:9:87:14 | selection of Path : string | semmle.label | selection of Path : string | +| main.go:77:36:77:38 | url | semmle.label | url | +| main.go:87:9:87:14 | selection of Path | semmle.label | selection of Path | | main.go:91:25:91:39 | call to getTarget2 | semmle.label | call to getTarget2 | subpaths -| main.go:11:37:11:44 | redirect : string | BadRedirectCheck.go:3:18:3:22 | definition of redir : string | BadRedirectCheck.go:5:10:5:14 | redir : string | main.go:11:25:11:45 | call to sanitizeUrl | -| main.go:77:36:77:38 | url : string | main.go:68:17:68:24 | definition of redirect : string | main.go:73:9:73:28 | call to Clean : string | main.go:77:25:77:39 | call to getTarget1 | +| main.go:11:37:11:44 | redirect | BadRedirectCheck.go:3:18:3:22 | definition of redir | BadRedirectCheck.go:5:10:5:14 | redir | main.go:11:25:11:45 | call to sanitizeUrl | +| main.go:77:36:77:38 | url | main.go:68:17:68:24 | definition of redirect | main.go:73:9:73:28 | call to Clean | main.go:77:25:77:39 | call to getTarget1 | #select -| BadRedirectCheck.go:4:23:4:37 | ...==... | BadRedirectCheck.go:3:18:3:22 | argument corresponding to redir : string | main.go:11:25:11:45 | call to sanitizeUrl | This is a check that $@, which flows into a $@, has a leading slash, but not that it does not have '/' or '\\' in its second position. | BadRedirectCheck.go:3:18:3:22 | argument corresponding to redir | this value | main.go:11:25:11:45 | call to sanitizeUrl | redirect | -| BadRedirectCheck.go:4:23:4:37 | ...==... | main.go:10:18:10:25 | argument corresponding to redirect : string | main.go:11:25:11:45 | call to sanitizeUrl | This is a check that $@, which flows into a $@, has a leading slash, but not that it does not have '/' or '\\' in its second position. | main.go:10:18:10:25 | argument corresponding to redirect | this value | main.go:11:25:11:45 | call to sanitizeUrl | redirect | -| cves.go:11:26:11:38 | ...==... | cves.go:14:23:14:25 | argument corresponding to url : string | cves.go:16:26:16:28 | url | This is a check that $@, which flows into a $@, has a leading slash, but not that it does not have '/' or '\\' in its second position. | cves.go:14:23:14:25 | argument corresponding to url | this value | cves.go:16:26:16:28 | url | redirect | -| cves.go:34:6:34:37 | call to HasPrefix | cves.go:33:14:33:34 | call to Get : string | cves.go:37:25:37:32 | redirect | This is a check that $@, which flows into a $@, has a leading slash, but not that it does not have '/' or '\\' in its second position. | cves.go:33:14:33:34 | call to Get | this value | cves.go:37:25:37:32 | redirect | redirect | -| cves.go:42:6:42:37 | call to HasPrefix | cves.go:41:14:41:34 | call to Get : string | cves.go:45:25:45:32 | redirect | This is a check that $@, which flows into a $@, has a leading slash, but not that it does not have '/' or '\\' in its second position. | cves.go:41:14:41:34 | call to Get | this value | cves.go:45:25:45:32 | redirect | redirect | -| main.go:25:7:25:38 | call to HasPrefix | main.go:32:24:32:26 | argument corresponding to url : string | main.go:34:26:34:28 | url | This is a check that $@, which flows into a $@, has a leading slash, but not that it does not have '/' or '\\' in its second position. | main.go:32:24:32:26 | argument corresponding to url | this value | main.go:34:26:34:28 | url | redirect | -| main.go:69:5:69:22 | ...!=... | main.go:68:17:68:24 | argument corresponding to redirect : string | main.go:77:25:77:39 | call to getTarget1 | This is a check that $@, which flows into a $@, has a leading slash, but not that it does not have '/' or '\\' in its second position. | main.go:68:17:68:24 | argument corresponding to redirect | this value | main.go:77:25:77:39 | call to getTarget1 | redirect | -| main.go:69:5:69:22 | ...!=... | main.go:76:19:76:21 | argument corresponding to url : string | main.go:77:25:77:39 | call to getTarget1 | This is a check that $@, which flows into a $@, has a leading slash, but not that it does not have '/' or '\\' in its second position. | main.go:76:19:76:21 | argument corresponding to url | this value | main.go:77:25:77:39 | call to getTarget1 | redirect | -| main.go:83:5:83:20 | ...!=... | main.go:87:9:87:14 | selection of Path : string | main.go:91:25:91:39 | call to getTarget2 | This is a check that $@, which flows into a $@, has a leading slash, but not that it does not have '/' or '\\' in its second position. | main.go:87:9:87:14 | selection of Path | this value | main.go:91:25:91:39 | call to getTarget2 | redirect | +| BadRedirectCheck.go:4:23:4:37 | ...==... | BadRedirectCheck.go:3:18:3:22 | argument corresponding to redir | main.go:11:25:11:45 | call to sanitizeUrl | This is a check that $@, which flows into a $@, has a leading slash, but not that it does not have '/' or '\\' in its second position. | BadRedirectCheck.go:3:18:3:22 | argument corresponding to redir | this value | main.go:11:25:11:45 | call to sanitizeUrl | redirect | +| BadRedirectCheck.go:4:23:4:37 | ...==... | main.go:10:18:10:25 | argument corresponding to redirect | main.go:11:25:11:45 | call to sanitizeUrl | This is a check that $@, which flows into a $@, has a leading slash, but not that it does not have '/' or '\\' in its second position. | main.go:10:18:10:25 | argument corresponding to redirect | this value | main.go:11:25:11:45 | call to sanitizeUrl | redirect | +| cves.go:11:26:11:38 | ...==... | cves.go:14:23:14:25 | argument corresponding to url | cves.go:16:26:16:28 | url | This is a check that $@, which flows into a $@, has a leading slash, but not that it does not have '/' or '\\' in its second position. | cves.go:14:23:14:25 | argument corresponding to url | this value | cves.go:16:26:16:28 | url | redirect | +| cves.go:34:6:34:37 | call to HasPrefix | cves.go:33:14:33:34 | call to Get | cves.go:37:25:37:32 | redirect | This is a check that $@, which flows into a $@, has a leading slash, but not that it does not have '/' or '\\' in its second position. | cves.go:33:14:33:34 | call to Get | this value | cves.go:37:25:37:32 | redirect | redirect | +| cves.go:42:6:42:37 | call to HasPrefix | cves.go:41:14:41:34 | call to Get | cves.go:45:25:45:32 | redirect | This is a check that $@, which flows into a $@, has a leading slash, but not that it does not have '/' or '\\' in its second position. | cves.go:41:14:41:34 | call to Get | this value | cves.go:45:25:45:32 | redirect | redirect | +| main.go:25:7:25:38 | call to HasPrefix | main.go:32:24:32:26 | argument corresponding to url | main.go:34:26:34:28 | url | This is a check that $@, which flows into a $@, has a leading slash, but not that it does not have '/' or '\\' in its second position. | main.go:32:24:32:26 | argument corresponding to url | this value | main.go:34:26:34:28 | url | redirect | +| main.go:69:5:69:22 | ...!=... | main.go:68:17:68:24 | argument corresponding to redirect | main.go:77:25:77:39 | call to getTarget1 | This is a check that $@, which flows into a $@, has a leading slash, but not that it does not have '/' or '\\' in its second position. | main.go:68:17:68:24 | argument corresponding to redirect | this value | main.go:77:25:77:39 | call to getTarget1 | redirect | +| main.go:69:5:69:22 | ...!=... | main.go:76:19:76:21 | argument corresponding to url | main.go:77:25:77:39 | call to getTarget1 | This is a check that $@, which flows into a $@, has a leading slash, but not that it does not have '/' or '\\' in its second position. | main.go:76:19:76:21 | argument corresponding to url | this value | main.go:77:25:77:39 | call to getTarget1 | redirect | +| main.go:83:5:83:20 | ...!=... | main.go:87:9:87:14 | selection of Path | main.go:91:25:91:39 | call to getTarget2 | This is a check that $@, which flows into a $@, has a leading slash, but not that it does not have '/' or '\\' in its second position. | main.go:87:9:87:14 | selection of Path | this value | main.go:91:25:91:39 | call to getTarget2 | redirect | diff --git a/go/ql/test/query-tests/Security/CWE-601/OpenUrlRedirect/OpenUrlRedirect.expected b/go/ql/test/query-tests/Security/CWE-601/OpenUrlRedirect/OpenUrlRedirect.expected index 7cf22603fb1..f7e2677efef 100644 --- a/go/ql/test/query-tests/Security/CWE-601/OpenUrlRedirect/OpenUrlRedirect.expected +++ b/go/ql/test/query-tests/Security/CWE-601/OpenUrlRedirect/OpenUrlRedirect.expected @@ -1,125 +1,125 @@ edges -| OpenUrlRedirect.go:10:23:10:28 | selection of Form : Values | OpenUrlRedirect.go:10:23:10:42 | call to Get | -| stdlib.go:13:13:13:18 | selection of Form : Values | stdlib.go:15:30:15:35 | target | -| stdlib.go:22:13:22:18 | selection of Form : Values | stdlib.go:24:30:24:35 | target | -| stdlib.go:31:13:31:18 | selection of Form : Values | stdlib.go:35:30:35:39 | ...+... | -| stdlib.go:44:13:44:18 | selection of Form : Values | stdlib.go:46:23:46:28 | target | -| stdlib.go:64:13:64:18 | selection of Form : Values | stdlib.go:67:23:67:40 | ...+... | -| stdlib.go:89:13:89:18 | selection of Form : Values | stdlib.go:92:23:92:28 | target | -| stdlib.go:107:54:107:54 | definition of r [pointer, URL, pointer] : URL | stdlib.go:112:4:112:4 | r [pointer, URL, pointer] : URL | -| stdlib.go:107:54:107:54 | definition of r [pointer, URL, pointer] : URL | stdlib.go:112:4:112:4 | r [pointer, URL, pointer] : URL | -| stdlib.go:107:54:107:54 | definition of r [pointer, URL] : pointer type | stdlib.go:112:4:112:4 | r [pointer, URL] : pointer type | -| stdlib.go:107:54:107:54 | definition of r [pointer, URL] : pointer type | stdlib.go:112:4:112:4 | r [pointer, URL] : pointer type | -| stdlib.go:107:54:107:54 | definition of r [pointer, URL] : pointer type | stdlib.go:113:24:113:24 | r [pointer, URL] : pointer type | -| stdlib.go:107:54:107:54 | definition of r [pointer, URL] : pointer type | stdlib.go:113:24:113:24 | r [pointer, URL] : pointer type | -| stdlib.go:112:4:112:4 | implicit dereference [URL, pointer] : URL | stdlib.go:107:54:107:54 | definition of r [pointer, URL, pointer] : URL | -| stdlib.go:112:4:112:4 | implicit dereference [URL, pointer] : URL | stdlib.go:107:54:107:54 | definition of r [pointer, URL, pointer] : URL | -| stdlib.go:112:4:112:4 | implicit dereference [URL, pointer] : URL | stdlib.go:112:4:112:8 | selection of URL [pointer] : URL | -| stdlib.go:112:4:112:4 | implicit dereference [URL, pointer] : URL | stdlib.go:112:4:112:8 | selection of URL [pointer] : URL | -| stdlib.go:112:4:112:4 | implicit dereference [URL] : pointer type | stdlib.go:107:54:107:54 | definition of r [pointer, URL] : pointer type | -| stdlib.go:112:4:112:4 | implicit dereference [URL] : pointer type | stdlib.go:107:54:107:54 | definition of r [pointer, URL] : pointer type | -| stdlib.go:112:4:112:4 | implicit dereference [URL] : pointer type | stdlib.go:112:4:112:8 | selection of URL : pointer type | -| stdlib.go:112:4:112:4 | implicit dereference [URL] : pointer type | stdlib.go:112:4:112:8 | selection of URL : pointer type | -| stdlib.go:112:4:112:4 | r [pointer, URL, pointer] : URL | stdlib.go:112:4:112:4 | implicit dereference [URL, pointer] : URL | -| stdlib.go:112:4:112:4 | r [pointer, URL, pointer] : URL | stdlib.go:112:4:112:4 | implicit dereference [URL, pointer] : URL | -| stdlib.go:112:4:112:4 | r [pointer, URL] : pointer type | stdlib.go:112:4:112:4 | implicit dereference [URL] : pointer type | -| stdlib.go:112:4:112:4 | r [pointer, URL] : pointer type | stdlib.go:112:4:112:4 | implicit dereference [URL] : pointer type | -| stdlib.go:112:4:112:8 | implicit dereference : URL | stdlib.go:112:4:112:8 | implicit dereference : URL | -| stdlib.go:112:4:112:8 | implicit dereference : URL | stdlib.go:112:4:112:8 | implicit dereference : URL | -| stdlib.go:112:4:112:8 | implicit dereference : URL | stdlib.go:112:4:112:8 | selection of URL : pointer type | -| stdlib.go:112:4:112:8 | implicit dereference : URL | stdlib.go:112:4:112:8 | selection of URL : pointer type | -| stdlib.go:112:4:112:8 | implicit dereference : URL | stdlib.go:112:4:112:8 | selection of URL [pointer] : URL | -| stdlib.go:112:4:112:8 | implicit dereference : URL | stdlib.go:112:4:112:8 | selection of URL [pointer] : URL | -| stdlib.go:112:4:112:8 | selection of URL : pointer type | stdlib.go:112:4:112:4 | implicit dereference [URL] : pointer type | -| stdlib.go:112:4:112:8 | selection of URL : pointer type | stdlib.go:112:4:112:4 | implicit dereference [URL] : pointer type | -| stdlib.go:112:4:112:8 | selection of URL : pointer type | stdlib.go:112:4:112:8 | implicit dereference : URL | -| stdlib.go:112:4:112:8 | selection of URL : pointer type | stdlib.go:112:4:112:8 | implicit dereference : URL | -| stdlib.go:112:4:112:8 | selection of URL : pointer type | stdlib.go:112:4:112:8 | selection of URL : pointer type | -| stdlib.go:112:4:112:8 | selection of URL : pointer type | stdlib.go:112:4:112:8 | selection of URL : pointer type | -| stdlib.go:112:4:112:8 | selection of URL [pointer] : URL | stdlib.go:112:4:112:4 | implicit dereference [URL, pointer] : URL | -| stdlib.go:112:4:112:8 | selection of URL [pointer] : URL | stdlib.go:112:4:112:4 | implicit dereference [URL, pointer] : URL | -| stdlib.go:112:4:112:8 | selection of URL [pointer] : URL | stdlib.go:112:4:112:8 | implicit dereference : URL | -| stdlib.go:112:4:112:8 | selection of URL [pointer] : URL | stdlib.go:112:4:112:8 | implicit dereference : URL | -| stdlib.go:113:24:113:24 | implicit dereference [URL] : pointer type | stdlib.go:113:24:113:28 | selection of URL : pointer type | -| stdlib.go:113:24:113:24 | implicit dereference [URL] : pointer type | stdlib.go:113:24:113:28 | selection of URL : pointer type | -| stdlib.go:113:24:113:24 | r [pointer, URL] : pointer type | stdlib.go:113:24:113:24 | implicit dereference [URL] : pointer type | -| stdlib.go:113:24:113:24 | r [pointer, URL] : pointer type | stdlib.go:113:24:113:24 | implicit dereference [URL] : pointer type | -| stdlib.go:113:24:113:28 | selection of URL : pointer type | stdlib.go:113:24:113:37 | call to String | -| stdlib.go:113:24:113:28 | selection of URL : pointer type | stdlib.go:113:24:113:37 | call to String | -| stdlib.go:146:13:146:18 | selection of Form : Values | stdlib.go:152:23:152:28 | target | -| stdlib.go:159:11:159:15 | selection of URL : pointer type | stdlib.go:162:24:162:35 | call to String | -| stdlib.go:159:11:159:15 | selection of URL : pointer type | stdlib.go:162:24:162:35 | call to String | -| stdlib.go:173:35:173:39 | selection of URL : pointer type | stdlib.go:173:24:173:52 | ...+... | -| stdlib.go:173:35:173:39 | selection of URL : pointer type | stdlib.go:173:24:173:52 | ...+... | -| stdlib.go:182:13:182:33 | call to FormValue : string | stdlib.go:184:23:184:28 | target | -| stdlib.go:190:36:190:56 | call to FormValue : string | stdlib.go:192:23:192:33 | selection of Path | -| stdlib.go:190:36:190:56 | call to FormValue : string | stdlib.go:194:23:194:42 | call to EscapedPath | +| OpenUrlRedirect.go:10:23:10:28 | selection of Form | OpenUrlRedirect.go:10:23:10:42 | call to Get | +| stdlib.go:13:13:13:18 | selection of Form | stdlib.go:15:30:15:35 | target | +| stdlib.go:22:13:22:18 | selection of Form | stdlib.go:24:30:24:35 | target | +| stdlib.go:31:13:31:18 | selection of Form | stdlib.go:35:30:35:39 | ...+... | +| stdlib.go:44:13:44:18 | selection of Form | stdlib.go:46:23:46:28 | target | +| stdlib.go:64:13:64:18 | selection of Form | stdlib.go:67:23:67:40 | ...+... | +| stdlib.go:89:13:89:18 | selection of Form | stdlib.go:92:23:92:28 | target | +| stdlib.go:107:54:107:54 | definition of r [pointer, URL, pointer] | stdlib.go:112:4:112:4 | r [pointer, URL, pointer] | +| stdlib.go:107:54:107:54 | definition of r [pointer, URL, pointer] | stdlib.go:112:4:112:4 | r [pointer, URL, pointer] | +| stdlib.go:107:54:107:54 | definition of r [pointer, URL] | stdlib.go:112:4:112:4 | r [pointer, URL] | +| stdlib.go:107:54:107:54 | definition of r [pointer, URL] | stdlib.go:112:4:112:4 | r [pointer, URL] | +| stdlib.go:107:54:107:54 | definition of r [pointer, URL] | stdlib.go:113:24:113:24 | r [pointer, URL] | +| stdlib.go:107:54:107:54 | definition of r [pointer, URL] | stdlib.go:113:24:113:24 | r [pointer, URL] | +| stdlib.go:112:4:112:4 | implicit dereference [URL, pointer] | stdlib.go:107:54:107:54 | definition of r [pointer, URL, pointer] | +| stdlib.go:112:4:112:4 | implicit dereference [URL, pointer] | stdlib.go:107:54:107:54 | definition of r [pointer, URL, pointer] | +| stdlib.go:112:4:112:4 | implicit dereference [URL, pointer] | stdlib.go:112:4:112:8 | selection of URL [pointer] | +| stdlib.go:112:4:112:4 | implicit dereference [URL, pointer] | stdlib.go:112:4:112:8 | selection of URL [pointer] | +| stdlib.go:112:4:112:4 | implicit dereference [URL] | stdlib.go:107:54:107:54 | definition of r [pointer, URL] | +| stdlib.go:112:4:112:4 | implicit dereference [URL] | stdlib.go:107:54:107:54 | definition of r [pointer, URL] | +| stdlib.go:112:4:112:4 | implicit dereference [URL] | stdlib.go:112:4:112:8 | selection of URL | +| stdlib.go:112:4:112:4 | implicit dereference [URL] | stdlib.go:112:4:112:8 | selection of URL | +| stdlib.go:112:4:112:4 | r [pointer, URL, pointer] | stdlib.go:112:4:112:4 | implicit dereference [URL, pointer] | +| stdlib.go:112:4:112:4 | r [pointer, URL, pointer] | stdlib.go:112:4:112:4 | implicit dereference [URL, pointer] | +| stdlib.go:112:4:112:4 | r [pointer, URL] | stdlib.go:112:4:112:4 | implicit dereference [URL] | +| stdlib.go:112:4:112:4 | r [pointer, URL] | stdlib.go:112:4:112:4 | implicit dereference [URL] | +| stdlib.go:112:4:112:8 | implicit dereference | stdlib.go:112:4:112:8 | implicit dereference | +| stdlib.go:112:4:112:8 | implicit dereference | stdlib.go:112:4:112:8 | implicit dereference | +| stdlib.go:112:4:112:8 | implicit dereference | stdlib.go:112:4:112:8 | selection of URL | +| stdlib.go:112:4:112:8 | implicit dereference | stdlib.go:112:4:112:8 | selection of URL | +| stdlib.go:112:4:112:8 | implicit dereference | stdlib.go:112:4:112:8 | selection of URL [pointer] | +| stdlib.go:112:4:112:8 | implicit dereference | stdlib.go:112:4:112:8 | selection of URL [pointer] | +| stdlib.go:112:4:112:8 | selection of URL | stdlib.go:112:4:112:4 | implicit dereference [URL] | +| stdlib.go:112:4:112:8 | selection of URL | stdlib.go:112:4:112:4 | implicit dereference [URL] | +| stdlib.go:112:4:112:8 | selection of URL | stdlib.go:112:4:112:8 | implicit dereference | +| stdlib.go:112:4:112:8 | selection of URL | stdlib.go:112:4:112:8 | implicit dereference | +| stdlib.go:112:4:112:8 | selection of URL | stdlib.go:112:4:112:8 | selection of URL | +| stdlib.go:112:4:112:8 | selection of URL | stdlib.go:112:4:112:8 | selection of URL | +| stdlib.go:112:4:112:8 | selection of URL [pointer] | stdlib.go:112:4:112:4 | implicit dereference [URL, pointer] | +| stdlib.go:112:4:112:8 | selection of URL [pointer] | stdlib.go:112:4:112:4 | implicit dereference [URL, pointer] | +| stdlib.go:112:4:112:8 | selection of URL [pointer] | stdlib.go:112:4:112:8 | implicit dereference | +| stdlib.go:112:4:112:8 | selection of URL [pointer] | stdlib.go:112:4:112:8 | implicit dereference | +| stdlib.go:113:24:113:24 | implicit dereference [URL] | stdlib.go:113:24:113:28 | selection of URL | +| stdlib.go:113:24:113:24 | implicit dereference [URL] | stdlib.go:113:24:113:28 | selection of URL | +| stdlib.go:113:24:113:24 | r [pointer, URL] | stdlib.go:113:24:113:24 | implicit dereference [URL] | +| stdlib.go:113:24:113:24 | r [pointer, URL] | stdlib.go:113:24:113:24 | implicit dereference [URL] | +| stdlib.go:113:24:113:28 | selection of URL | stdlib.go:113:24:113:37 | call to String | +| stdlib.go:113:24:113:28 | selection of URL | stdlib.go:113:24:113:37 | call to String | +| stdlib.go:146:13:146:18 | selection of Form | stdlib.go:152:23:152:28 | target | +| stdlib.go:159:11:159:15 | selection of URL | stdlib.go:162:24:162:35 | call to String | +| stdlib.go:159:11:159:15 | selection of URL | stdlib.go:162:24:162:35 | call to String | +| stdlib.go:173:35:173:39 | selection of URL | stdlib.go:173:24:173:52 | ...+... | +| stdlib.go:173:35:173:39 | selection of URL | stdlib.go:173:24:173:52 | ...+... | +| stdlib.go:182:13:182:33 | call to FormValue | stdlib.go:184:23:184:28 | target | +| stdlib.go:190:36:190:56 | call to FormValue | stdlib.go:192:23:192:33 | selection of Path | +| stdlib.go:190:36:190:56 | call to FormValue | stdlib.go:194:23:194:42 | call to EscapedPath | nodes -| OpenUrlRedirect.go:10:23:10:28 | selection of Form : Values | semmle.label | selection of Form : Values | +| OpenUrlRedirect.go:10:23:10:28 | selection of Form | semmle.label | selection of Form | | OpenUrlRedirect.go:10:23:10:42 | call to Get | semmle.label | call to Get | -| stdlib.go:13:13:13:18 | selection of Form : Values | semmle.label | selection of Form : Values | +| stdlib.go:13:13:13:18 | selection of Form | semmle.label | selection of Form | | stdlib.go:15:30:15:35 | target | semmle.label | target | -| stdlib.go:22:13:22:18 | selection of Form : Values | semmle.label | selection of Form : Values | +| stdlib.go:22:13:22:18 | selection of Form | semmle.label | selection of Form | | stdlib.go:24:30:24:35 | target | semmle.label | target | -| stdlib.go:31:13:31:18 | selection of Form : Values | semmle.label | selection of Form : Values | +| stdlib.go:31:13:31:18 | selection of Form | semmle.label | selection of Form | | stdlib.go:35:30:35:39 | ...+... | semmle.label | ...+... | -| stdlib.go:44:13:44:18 | selection of Form : Values | semmle.label | selection of Form : Values | +| stdlib.go:44:13:44:18 | selection of Form | semmle.label | selection of Form | | stdlib.go:46:23:46:28 | target | semmle.label | target | -| stdlib.go:64:13:64:18 | selection of Form : Values | semmle.label | selection of Form : Values | +| stdlib.go:64:13:64:18 | selection of Form | semmle.label | selection of Form | | stdlib.go:67:23:67:40 | ...+... | semmle.label | ...+... | -| stdlib.go:89:13:89:18 | selection of Form : Values | semmle.label | selection of Form : Values | +| stdlib.go:89:13:89:18 | selection of Form | semmle.label | selection of Form | | stdlib.go:92:23:92:28 | target | semmle.label | target | -| stdlib.go:107:54:107:54 | definition of r [pointer, URL, pointer] : URL | semmle.label | definition of r [pointer, URL, pointer] : URL | -| stdlib.go:107:54:107:54 | definition of r [pointer, URL, pointer] : URL | semmle.label | definition of r [pointer, URL, pointer] : URL | -| stdlib.go:107:54:107:54 | definition of r [pointer, URL] : pointer type | semmle.label | definition of r [pointer, URL] : pointer type | -| stdlib.go:107:54:107:54 | definition of r [pointer, URL] : pointer type | semmle.label | definition of r [pointer, URL] : pointer type | -| stdlib.go:112:4:112:4 | implicit dereference [URL, pointer] : URL | semmle.label | implicit dereference [URL, pointer] : URL | -| stdlib.go:112:4:112:4 | implicit dereference [URL, pointer] : URL | semmle.label | implicit dereference [URL, pointer] : URL | -| stdlib.go:112:4:112:4 | implicit dereference [URL] : pointer type | semmle.label | implicit dereference [URL] : pointer type | -| stdlib.go:112:4:112:4 | implicit dereference [URL] : pointer type | semmle.label | implicit dereference [URL] : pointer type | -| stdlib.go:112:4:112:4 | r [pointer, URL, pointer] : URL | semmle.label | r [pointer, URL, pointer] : URL | -| stdlib.go:112:4:112:4 | r [pointer, URL, pointer] : URL | semmle.label | r [pointer, URL, pointer] : URL | -| stdlib.go:112:4:112:4 | r [pointer, URL] : pointer type | semmle.label | r [pointer, URL] : pointer type | -| stdlib.go:112:4:112:4 | r [pointer, URL] : pointer type | semmle.label | r [pointer, URL] : pointer type | -| stdlib.go:112:4:112:8 | implicit dereference : URL | semmle.label | implicit dereference : URL | -| stdlib.go:112:4:112:8 | implicit dereference : URL | semmle.label | implicit dereference : URL | -| stdlib.go:112:4:112:8 | selection of URL : pointer type | semmle.label | selection of URL : pointer type | -| stdlib.go:112:4:112:8 | selection of URL : pointer type | semmle.label | selection of URL : pointer type | -| stdlib.go:112:4:112:8 | selection of URL [pointer] : URL | semmle.label | selection of URL [pointer] : URL | -| stdlib.go:112:4:112:8 | selection of URL [pointer] : URL | semmle.label | selection of URL [pointer] : URL | -| stdlib.go:113:24:113:24 | implicit dereference [URL] : pointer type | semmle.label | implicit dereference [URL] : pointer type | -| stdlib.go:113:24:113:24 | implicit dereference [URL] : pointer type | semmle.label | implicit dereference [URL] : pointer type | -| stdlib.go:113:24:113:24 | r [pointer, URL] : pointer type | semmle.label | r [pointer, URL] : pointer type | -| stdlib.go:113:24:113:24 | r [pointer, URL] : pointer type | semmle.label | r [pointer, URL] : pointer type | -| stdlib.go:113:24:113:28 | selection of URL : pointer type | semmle.label | selection of URL : pointer type | -| stdlib.go:113:24:113:28 | selection of URL : pointer type | semmle.label | selection of URL : pointer type | +| stdlib.go:107:54:107:54 | definition of r [pointer, URL, pointer] | semmle.label | definition of r [pointer, URL, pointer] | +| stdlib.go:107:54:107:54 | definition of r [pointer, URL, pointer] | semmle.label | definition of r [pointer, URL, pointer] | +| stdlib.go:107:54:107:54 | definition of r [pointer, URL] | semmle.label | definition of r [pointer, URL] | +| stdlib.go:107:54:107:54 | definition of r [pointer, URL] | semmle.label | definition of r [pointer, URL] | +| stdlib.go:112:4:112:4 | implicit dereference [URL, pointer] | semmle.label | implicit dereference [URL, pointer] | +| stdlib.go:112:4:112:4 | implicit dereference [URL, pointer] | semmle.label | implicit dereference [URL, pointer] | +| stdlib.go:112:4:112:4 | implicit dereference [URL] | semmle.label | implicit dereference [URL] | +| stdlib.go:112:4:112:4 | implicit dereference [URL] | semmle.label | implicit dereference [URL] | +| stdlib.go:112:4:112:4 | r [pointer, URL, pointer] | semmle.label | r [pointer, URL, pointer] | +| stdlib.go:112:4:112:4 | r [pointer, URL, pointer] | semmle.label | r [pointer, URL, pointer] | +| stdlib.go:112:4:112:4 | r [pointer, URL] | semmle.label | r [pointer, URL] | +| stdlib.go:112:4:112:4 | r [pointer, URL] | semmle.label | r [pointer, URL] | +| stdlib.go:112:4:112:8 | implicit dereference | semmle.label | implicit dereference | +| stdlib.go:112:4:112:8 | implicit dereference | semmle.label | implicit dereference | +| stdlib.go:112:4:112:8 | selection of URL | semmle.label | selection of URL | +| stdlib.go:112:4:112:8 | selection of URL | semmle.label | selection of URL | +| stdlib.go:112:4:112:8 | selection of URL [pointer] | semmle.label | selection of URL [pointer] | +| stdlib.go:112:4:112:8 | selection of URL [pointer] | semmle.label | selection of URL [pointer] | +| stdlib.go:113:24:113:24 | implicit dereference [URL] | semmle.label | implicit dereference [URL] | +| stdlib.go:113:24:113:24 | implicit dereference [URL] | semmle.label | implicit dereference [URL] | +| stdlib.go:113:24:113:24 | r [pointer, URL] | semmle.label | r [pointer, URL] | +| stdlib.go:113:24:113:24 | r [pointer, URL] | semmle.label | r [pointer, URL] | +| stdlib.go:113:24:113:28 | selection of URL | semmle.label | selection of URL | +| stdlib.go:113:24:113:28 | selection of URL | semmle.label | selection of URL | | stdlib.go:113:24:113:37 | call to String | semmle.label | call to String | | stdlib.go:113:24:113:37 | call to String | semmle.label | call to String | -| stdlib.go:146:13:146:18 | selection of Form : Values | semmle.label | selection of Form : Values | +| stdlib.go:146:13:146:18 | selection of Form | semmle.label | selection of Form | | stdlib.go:152:23:152:28 | target | semmle.label | target | -| stdlib.go:159:11:159:15 | selection of URL : pointer type | semmle.label | selection of URL : pointer type | -| stdlib.go:159:11:159:15 | selection of URL : pointer type | semmle.label | selection of URL : pointer type | +| stdlib.go:159:11:159:15 | selection of URL | semmle.label | selection of URL | +| stdlib.go:159:11:159:15 | selection of URL | semmle.label | selection of URL | | stdlib.go:162:24:162:35 | call to String | semmle.label | call to String | | stdlib.go:162:24:162:35 | call to String | semmle.label | call to String | | stdlib.go:173:24:173:52 | ...+... | semmle.label | ...+... | | stdlib.go:173:24:173:52 | ...+... | semmle.label | ...+... | -| stdlib.go:173:35:173:39 | selection of URL : pointer type | semmle.label | selection of URL : pointer type | -| stdlib.go:173:35:173:39 | selection of URL : pointer type | semmle.label | selection of URL : pointer type | -| stdlib.go:182:13:182:33 | call to FormValue : string | semmle.label | call to FormValue : string | +| stdlib.go:173:35:173:39 | selection of URL | semmle.label | selection of URL | +| stdlib.go:173:35:173:39 | selection of URL | semmle.label | selection of URL | +| stdlib.go:182:13:182:33 | call to FormValue | semmle.label | call to FormValue | | stdlib.go:184:23:184:28 | target | semmle.label | target | -| stdlib.go:190:36:190:56 | call to FormValue : string | semmle.label | call to FormValue : string | +| stdlib.go:190:36:190:56 | call to FormValue | semmle.label | call to FormValue | | stdlib.go:192:23:192:33 | selection of Path | semmle.label | selection of Path | | stdlib.go:194:23:194:42 | call to EscapedPath | semmle.label | call to EscapedPath | subpaths #select -| OpenUrlRedirect.go:10:23:10:42 | call to Get | OpenUrlRedirect.go:10:23:10:28 | selection of Form : Values | OpenUrlRedirect.go:10:23:10:42 | call to Get | Untrusted URL redirection depends on a $@. | OpenUrlRedirect.go:10:23:10:28 | selection of Form | user-provided value | -| stdlib.go:15:30:15:35 | target | stdlib.go:13:13:13:18 | selection of Form : Values | stdlib.go:15:30:15:35 | target | Untrusted URL redirection depends on a $@. | stdlib.go:13:13:13:18 | selection of Form | user-provided value | -| stdlib.go:24:30:24:35 | target | stdlib.go:22:13:22:18 | selection of Form : Values | stdlib.go:24:30:24:35 | target | Untrusted URL redirection depends on a $@. | stdlib.go:22:13:22:18 | selection of Form | user-provided value | -| stdlib.go:35:30:35:39 | ...+... | stdlib.go:31:13:31:18 | selection of Form : Values | stdlib.go:35:30:35:39 | ...+... | Untrusted URL redirection depends on a $@. | stdlib.go:31:13:31:18 | selection of Form | user-provided value | -| stdlib.go:46:23:46:28 | target | stdlib.go:44:13:44:18 | selection of Form : Values | stdlib.go:46:23:46:28 | target | Untrusted URL redirection depends on a $@. | stdlib.go:44:13:44:18 | selection of Form | user-provided value | -| stdlib.go:67:23:67:40 | ...+... | stdlib.go:64:13:64:18 | selection of Form : Values | stdlib.go:67:23:67:40 | ...+... | Untrusted URL redirection depends on a $@. | stdlib.go:64:13:64:18 | selection of Form | user-provided value | -| stdlib.go:92:23:92:28 | target | stdlib.go:89:13:89:18 | selection of Form : Values | stdlib.go:92:23:92:28 | target | Untrusted URL redirection depends on a $@. | stdlib.go:89:13:89:18 | selection of Form | user-provided value | -| stdlib.go:152:23:152:28 | target | stdlib.go:146:13:146:18 | selection of Form : Values | stdlib.go:152:23:152:28 | target | Untrusted URL redirection depends on a $@. | stdlib.go:146:13:146:18 | selection of Form | user-provided value | -| stdlib.go:184:23:184:28 | target | stdlib.go:182:13:182:33 | call to FormValue : string | stdlib.go:184:23:184:28 | target | Untrusted URL redirection depends on a $@. | stdlib.go:182:13:182:33 | call to FormValue | user-provided value | -| stdlib.go:192:23:192:33 | selection of Path | stdlib.go:190:36:190:56 | call to FormValue : string | stdlib.go:192:23:192:33 | selection of Path | Untrusted URL redirection depends on a $@. | stdlib.go:190:36:190:56 | call to FormValue | user-provided value | -| stdlib.go:194:23:194:42 | call to EscapedPath | stdlib.go:190:36:190:56 | call to FormValue : string | stdlib.go:194:23:194:42 | call to EscapedPath | Untrusted URL redirection depends on a $@. | stdlib.go:190:36:190:56 | call to FormValue | user-provided value | +| OpenUrlRedirect.go:10:23:10:42 | call to Get | OpenUrlRedirect.go:10:23:10:28 | selection of Form | OpenUrlRedirect.go:10:23:10:42 | call to Get | Untrusted URL redirection depends on a $@. | OpenUrlRedirect.go:10:23:10:28 | selection of Form | user-provided value | +| stdlib.go:15:30:15:35 | target | stdlib.go:13:13:13:18 | selection of Form | stdlib.go:15:30:15:35 | target | Untrusted URL redirection depends on a $@. | stdlib.go:13:13:13:18 | selection of Form | user-provided value | +| stdlib.go:24:30:24:35 | target | stdlib.go:22:13:22:18 | selection of Form | stdlib.go:24:30:24:35 | target | Untrusted URL redirection depends on a $@. | stdlib.go:22:13:22:18 | selection of Form | user-provided value | +| stdlib.go:35:30:35:39 | ...+... | stdlib.go:31:13:31:18 | selection of Form | stdlib.go:35:30:35:39 | ...+... | Untrusted URL redirection depends on a $@. | stdlib.go:31:13:31:18 | selection of Form | user-provided value | +| stdlib.go:46:23:46:28 | target | stdlib.go:44:13:44:18 | selection of Form | stdlib.go:46:23:46:28 | target | Untrusted URL redirection depends on a $@. | stdlib.go:44:13:44:18 | selection of Form | user-provided value | +| stdlib.go:67:23:67:40 | ...+... | stdlib.go:64:13:64:18 | selection of Form | stdlib.go:67:23:67:40 | ...+... | Untrusted URL redirection depends on a $@. | stdlib.go:64:13:64:18 | selection of Form | user-provided value | +| stdlib.go:92:23:92:28 | target | stdlib.go:89:13:89:18 | selection of Form | stdlib.go:92:23:92:28 | target | Untrusted URL redirection depends on a $@. | stdlib.go:89:13:89:18 | selection of Form | user-provided value | +| stdlib.go:152:23:152:28 | target | stdlib.go:146:13:146:18 | selection of Form | stdlib.go:152:23:152:28 | target | Untrusted URL redirection depends on a $@. | stdlib.go:146:13:146:18 | selection of Form | user-provided value | +| stdlib.go:184:23:184:28 | target | stdlib.go:182:13:182:33 | call to FormValue | stdlib.go:184:23:184:28 | target | Untrusted URL redirection depends on a $@. | stdlib.go:182:13:182:33 | call to FormValue | user-provided value | +| stdlib.go:192:23:192:33 | selection of Path | stdlib.go:190:36:190:56 | call to FormValue | stdlib.go:192:23:192:33 | selection of Path | Untrusted URL redirection depends on a $@. | stdlib.go:190:36:190:56 | call to FormValue | user-provided value | +| stdlib.go:194:23:194:42 | call to EscapedPath | stdlib.go:190:36:190:56 | call to FormValue | stdlib.go:194:23:194:42 | call to EscapedPath | Untrusted URL redirection depends on a $@. | stdlib.go:190:36:190:56 | call to FormValue | user-provided value | diff --git a/go/ql/test/query-tests/Security/CWE-640/EmailInjection.expected b/go/ql/test/query-tests/Security/CWE-640/EmailInjection.expected index 2061b253cdc..797d06f208e 100644 --- a/go/ql/test/query-tests/Security/CWE-640/EmailInjection.expected +++ b/go/ql/test/query-tests/Security/CWE-640/EmailInjection.expected @@ -1,44 +1,44 @@ edges -| EmailBad.go:9:10:9:17 | selection of Header : Header | EmailBad.go:12:56:12:67 | type conversion | -| main.go:29:21:29:31 | call to Referer : string | main.go:31:57:31:78 | type conversion | -| main.go:37:21:37:31 | call to Referer : string | main.go:40:3:40:7 | definition of write | -| main.go:46:21:46:31 | call to Referer : string | main.go:52:46:52:59 | untrustedInput | -| main.go:46:21:46:31 | call to Referer : string | main.go:53:52:53:65 | untrustedInput | -| main.go:58:21:58:31 | call to Referer : string | main.go:63:16:63:22 | content | -| main.go:68:21:68:31 | call to Referer : string | main.go:76:50:76:56 | content | -| main.go:68:21:68:31 | call to Referer : string | main.go:76:59:76:65 | content | -| main.go:68:21:68:31 | call to Referer : string | main.go:77:16:77:22 | content | -| main.go:82:21:82:31 | call to Referer : string | main.go:89:37:89:50 | untrustedInput | -| main.go:82:21:82:31 | call to Referer : string | main.go:93:16:93:23 | content2 | +| EmailBad.go:9:10:9:17 | selection of Header | EmailBad.go:12:56:12:67 | type conversion | +| main.go:29:21:29:31 | call to Referer | main.go:31:57:31:78 | type conversion | +| main.go:37:21:37:31 | call to Referer | main.go:40:3:40:7 | definition of write | +| main.go:46:21:46:31 | call to Referer | main.go:52:46:52:59 | untrustedInput | +| main.go:46:21:46:31 | call to Referer | main.go:53:52:53:65 | untrustedInput | +| main.go:58:21:58:31 | call to Referer | main.go:63:16:63:22 | content | +| main.go:68:21:68:31 | call to Referer | main.go:76:50:76:56 | content | +| main.go:68:21:68:31 | call to Referer | main.go:76:59:76:65 | content | +| main.go:68:21:68:31 | call to Referer | main.go:77:16:77:22 | content | +| main.go:82:21:82:31 | call to Referer | main.go:89:37:89:50 | untrustedInput | +| main.go:82:21:82:31 | call to Referer | main.go:93:16:93:23 | content2 | nodes -| EmailBad.go:9:10:9:17 | selection of Header : Header | semmle.label | selection of Header : Header | +| EmailBad.go:9:10:9:17 | selection of Header | semmle.label | selection of Header | | EmailBad.go:12:56:12:67 | type conversion | semmle.label | type conversion | -| main.go:29:21:29:31 | call to Referer : string | semmle.label | call to Referer : string | +| main.go:29:21:29:31 | call to Referer | semmle.label | call to Referer | | main.go:31:57:31:78 | type conversion | semmle.label | type conversion | -| main.go:37:21:37:31 | call to Referer : string | semmle.label | call to Referer : string | +| main.go:37:21:37:31 | call to Referer | semmle.label | call to Referer | | main.go:40:3:40:7 | definition of write | semmle.label | definition of write | -| main.go:46:21:46:31 | call to Referer : string | semmle.label | call to Referer : string | +| main.go:46:21:46:31 | call to Referer | semmle.label | call to Referer | | main.go:52:46:52:59 | untrustedInput | semmle.label | untrustedInput | | main.go:53:52:53:65 | untrustedInput | semmle.label | untrustedInput | -| main.go:58:21:58:31 | call to Referer : string | semmle.label | call to Referer : string | +| main.go:58:21:58:31 | call to Referer | semmle.label | call to Referer | | main.go:63:16:63:22 | content | semmle.label | content | -| main.go:68:21:68:31 | call to Referer : string | semmle.label | call to Referer : string | +| main.go:68:21:68:31 | call to Referer | semmle.label | call to Referer | | main.go:76:50:76:56 | content | semmle.label | content | | main.go:76:59:76:65 | content | semmle.label | content | | main.go:77:16:77:22 | content | semmle.label | content | -| main.go:82:21:82:31 | call to Referer : string | semmle.label | call to Referer : string | +| main.go:82:21:82:31 | call to Referer | semmle.label | call to Referer | | main.go:89:37:89:50 | untrustedInput | semmle.label | untrustedInput | | main.go:93:16:93:23 | content2 | semmle.label | content2 | subpaths #select -| EmailBad.go:12:56:12:67 | type conversion | EmailBad.go:9:10:9:17 | selection of Header : Header | EmailBad.go:12:56:12:67 | type conversion | Email content may contain $@. | EmailBad.go:9:10:9:17 | selection of Header | untrusted input | -| main.go:31:57:31:78 | type conversion | main.go:29:21:29:31 | call to Referer : string | main.go:31:57:31:78 | type conversion | Email content may contain $@. | main.go:29:21:29:31 | call to Referer | untrusted input | -| main.go:40:3:40:7 | definition of write | main.go:37:21:37:31 | call to Referer : string | main.go:40:3:40:7 | definition of write | Email content may contain $@. | main.go:37:21:37:31 | call to Referer | untrusted input | -| main.go:52:46:52:59 | untrustedInput | main.go:46:21:46:31 | call to Referer : string | main.go:52:46:52:59 | untrustedInput | Email content may contain $@. | main.go:46:21:46:31 | call to Referer | untrusted input | -| main.go:53:52:53:65 | untrustedInput | main.go:46:21:46:31 | call to Referer : string | main.go:53:52:53:65 | untrustedInput | Email content may contain $@. | main.go:46:21:46:31 | call to Referer | untrusted input | -| main.go:63:16:63:22 | content | main.go:58:21:58:31 | call to Referer : string | main.go:63:16:63:22 | content | Email content may contain $@. | main.go:58:21:58:31 | call to Referer | untrusted input | -| main.go:76:50:76:56 | content | main.go:68:21:68:31 | call to Referer : string | main.go:76:50:76:56 | content | Email content may contain $@. | main.go:68:21:68:31 | call to Referer | untrusted input | -| main.go:76:59:76:65 | content | main.go:68:21:68:31 | call to Referer : string | main.go:76:59:76:65 | content | Email content may contain $@. | main.go:68:21:68:31 | call to Referer | untrusted input | -| main.go:77:16:77:22 | content | main.go:68:21:68:31 | call to Referer : string | main.go:77:16:77:22 | content | Email content may contain $@. | main.go:68:21:68:31 | call to Referer | untrusted input | -| main.go:89:37:89:50 | untrustedInput | main.go:82:21:82:31 | call to Referer : string | main.go:89:37:89:50 | untrustedInput | Email content may contain $@. | main.go:82:21:82:31 | call to Referer | untrusted input | -| main.go:93:16:93:23 | content2 | main.go:82:21:82:31 | call to Referer : string | main.go:93:16:93:23 | content2 | Email content may contain $@. | main.go:82:21:82:31 | call to Referer | untrusted input | +| EmailBad.go:12:56:12:67 | type conversion | EmailBad.go:9:10:9:17 | selection of Header | EmailBad.go:12:56:12:67 | type conversion | Email content may contain $@. | EmailBad.go:9:10:9:17 | selection of Header | untrusted input | +| main.go:31:57:31:78 | type conversion | main.go:29:21:29:31 | call to Referer | main.go:31:57:31:78 | type conversion | Email content may contain $@. | main.go:29:21:29:31 | call to Referer | untrusted input | +| main.go:40:3:40:7 | definition of write | main.go:37:21:37:31 | call to Referer | main.go:40:3:40:7 | definition of write | Email content may contain $@. | main.go:37:21:37:31 | call to Referer | untrusted input | +| main.go:52:46:52:59 | untrustedInput | main.go:46:21:46:31 | call to Referer | main.go:52:46:52:59 | untrustedInput | Email content may contain $@. | main.go:46:21:46:31 | call to Referer | untrusted input | +| main.go:53:52:53:65 | untrustedInput | main.go:46:21:46:31 | call to Referer | main.go:53:52:53:65 | untrustedInput | Email content may contain $@. | main.go:46:21:46:31 | call to Referer | untrusted input | +| main.go:63:16:63:22 | content | main.go:58:21:58:31 | call to Referer | main.go:63:16:63:22 | content | Email content may contain $@. | main.go:58:21:58:31 | call to Referer | untrusted input | +| main.go:76:50:76:56 | content | main.go:68:21:68:31 | call to Referer | main.go:76:50:76:56 | content | Email content may contain $@. | main.go:68:21:68:31 | call to Referer | untrusted input | +| main.go:76:59:76:65 | content | main.go:68:21:68:31 | call to Referer | main.go:76:59:76:65 | content | Email content may contain $@. | main.go:68:21:68:31 | call to Referer | untrusted input | +| main.go:77:16:77:22 | content | main.go:68:21:68:31 | call to Referer | main.go:77:16:77:22 | content | Email content may contain $@. | main.go:68:21:68:31 | call to Referer | untrusted input | +| main.go:89:37:89:50 | untrustedInput | main.go:82:21:82:31 | call to Referer | main.go:89:37:89:50 | untrustedInput | Email content may contain $@. | main.go:82:21:82:31 | call to Referer | untrusted input | +| main.go:93:16:93:23 | content2 | main.go:82:21:82:31 | call to Referer | main.go:93:16:93:23 | content2 | Email content may contain $@. | main.go:82:21:82:31 | call to Referer | untrusted input | diff --git a/go/ql/test/query-tests/Security/CWE-643/XPathInjection.expected b/go/ql/test/query-tests/Security/CWE-643/XPathInjection.expected index 081b1a2cdba..a391fe96b64 100644 --- a/go/ql/test/query-tests/Security/CWE-643/XPathInjection.expected +++ b/go/ql/test/query-tests/Security/CWE-643/XPathInjection.expected @@ -1,57 +1,57 @@ edges -| XPathInjection.go:13:14:13:19 | selection of Form : Values | XPathInjection.go:16:29:16:91 | ...+... | -| tst.go:32:14:32:19 | selection of Form : Values | tst.go:35:23:35:85 | ...+... | -| tst.go:32:14:32:19 | selection of Form : Values | tst.go:38:24:38:86 | ...+... | -| tst.go:32:14:32:19 | selection of Form : Values | tst.go:41:24:41:82 | ...+... | -| tst.go:46:14:46:19 | selection of Form : Values | tst.go:49:26:49:84 | ...+... | -| tst.go:46:14:46:19 | selection of Form : Values | tst.go:52:29:52:87 | ...+... | -| tst.go:46:14:46:19 | selection of Form : Values | tst.go:55:33:55:91 | ...+... | -| tst.go:46:14:46:19 | selection of Form : Values | tst.go:58:30:58:88 | ...+... | -| tst.go:63:14:63:19 | selection of Form : Values | tst.go:66:25:66:83 | ...+... | -| tst.go:63:14:63:19 | selection of Form : Values | tst.go:69:28:69:86 | ...+... | -| tst.go:63:14:63:19 | selection of Form : Values | tst.go:72:25:72:83 | ...+... | -| tst.go:63:14:63:19 | selection of Form : Values | tst.go:75:34:75:92 | ...+... | -| tst.go:63:14:63:19 | selection of Form : Values | tst.go:78:32:78:90 | ...+... | -| tst.go:63:14:63:19 | selection of Form : Values | tst.go:81:29:81:87 | ...+... | -| tst.go:63:14:63:19 | selection of Form : Values | tst.go:84:23:84:85 | ...+... | -| tst.go:63:14:63:19 | selection of Form : Values | tst.go:87:22:87:84 | ...+... | -| tst.go:92:14:92:19 | selection of Form : Values | tst.go:95:26:95:84 | ...+... | -| tst.go:92:14:92:19 | selection of Form : Values | tst.go:98:29:98:87 | ...+... | -| tst.go:92:14:92:19 | selection of Form : Values | tst.go:101:33:101:91 | ...+... | -| tst.go:92:14:92:19 | selection of Form : Values | tst.go:104:30:104:88 | ...+... | -| tst.go:109:14:109:19 | selection of Form : Values | tst.go:112:25:112:87 | ...+... | -| tst.go:109:14:109:19 | selection of Form : Values | tst.go:115:26:115:88 | ...+... | -| tst.go:120:14:120:19 | selection of Form : Values | tst.go:124:23:124:126 | ...+... | -| tst.go:120:14:120:19 | selection of Form : Values | tst.go:127:24:127:127 | ...+... | -| tst.go:120:14:120:19 | selection of Form : Values | tst.go:130:27:130:122 | ...+... | -| tst.go:121:14:121:19 | selection of Form : Values | tst.go:124:23:124:126 | ...+... | -| tst.go:121:14:121:19 | selection of Form : Values | tst.go:127:24:127:127 | ...+... | -| tst.go:121:14:121:19 | selection of Form : Values | tst.go:130:27:130:122 | ...+... | -| tst.go:138:14:138:19 | selection of Form : Values | tst.go:141:27:141:89 | ...+... | -| tst.go:138:14:138:19 | selection of Form : Values | tst.go:144:28:144:90 | ...+... | -| tst.go:149:14:149:19 | selection of Form : Values | tst.go:153:33:153:136 | ...+... | -| tst.go:149:14:149:19 | selection of Form : Values | tst.go:156:18:156:121 | ...+... | -| tst.go:149:14:149:19 | selection of Form : Values | tst.go:162:31:162:126 | ...+... | -| tst.go:149:14:149:19 | selection of Form : Values | tst.go:171:21:171:116 | ...+... | -| tst.go:149:14:149:19 | selection of Form : Values | tst.go:180:27:180:122 | ...+... | -| tst.go:150:14:150:19 | selection of Form : Values | tst.go:153:33:153:136 | ...+... | -| tst.go:150:14:150:19 | selection of Form : Values | tst.go:156:18:156:121 | ...+... | -| tst.go:150:14:150:19 | selection of Form : Values | tst.go:162:31:162:126 | ...+... | -| tst.go:150:14:150:19 | selection of Form : Values | tst.go:171:21:171:116 | ...+... | -| tst.go:150:14:150:19 | selection of Form : Values | tst.go:180:27:180:122 | ...+... | +| XPathInjection.go:13:14:13:19 | selection of Form | XPathInjection.go:16:29:16:91 | ...+... | +| tst.go:32:14:32:19 | selection of Form | tst.go:35:23:35:85 | ...+... | +| tst.go:32:14:32:19 | selection of Form | tst.go:38:24:38:86 | ...+... | +| tst.go:32:14:32:19 | selection of Form | tst.go:41:24:41:82 | ...+... | +| tst.go:46:14:46:19 | selection of Form | tst.go:49:26:49:84 | ...+... | +| tst.go:46:14:46:19 | selection of Form | tst.go:52:29:52:87 | ...+... | +| tst.go:46:14:46:19 | selection of Form | tst.go:55:33:55:91 | ...+... | +| tst.go:46:14:46:19 | selection of Form | tst.go:58:30:58:88 | ...+... | +| tst.go:63:14:63:19 | selection of Form | tst.go:66:25:66:83 | ...+... | +| tst.go:63:14:63:19 | selection of Form | tst.go:69:28:69:86 | ...+... | +| tst.go:63:14:63:19 | selection of Form | tst.go:72:25:72:83 | ...+... | +| tst.go:63:14:63:19 | selection of Form | tst.go:75:34:75:92 | ...+... | +| tst.go:63:14:63:19 | selection of Form | tst.go:78:32:78:90 | ...+... | +| tst.go:63:14:63:19 | selection of Form | tst.go:81:29:81:87 | ...+... | +| tst.go:63:14:63:19 | selection of Form | tst.go:84:23:84:85 | ...+... | +| tst.go:63:14:63:19 | selection of Form | tst.go:87:22:87:84 | ...+... | +| tst.go:92:14:92:19 | selection of Form | tst.go:95:26:95:84 | ...+... | +| tst.go:92:14:92:19 | selection of Form | tst.go:98:29:98:87 | ...+... | +| tst.go:92:14:92:19 | selection of Form | tst.go:101:33:101:91 | ...+... | +| tst.go:92:14:92:19 | selection of Form | tst.go:104:30:104:88 | ...+... | +| tst.go:109:14:109:19 | selection of Form | tst.go:112:25:112:87 | ...+... | +| tst.go:109:14:109:19 | selection of Form | tst.go:115:26:115:88 | ...+... | +| tst.go:120:14:120:19 | selection of Form | tst.go:124:23:124:126 | ...+... | +| tst.go:120:14:120:19 | selection of Form | tst.go:127:24:127:127 | ...+... | +| tst.go:120:14:120:19 | selection of Form | tst.go:130:27:130:122 | ...+... | +| tst.go:121:14:121:19 | selection of Form | tst.go:124:23:124:126 | ...+... | +| tst.go:121:14:121:19 | selection of Form | tst.go:127:24:127:127 | ...+... | +| tst.go:121:14:121:19 | selection of Form | tst.go:130:27:130:122 | ...+... | +| tst.go:138:14:138:19 | selection of Form | tst.go:141:27:141:89 | ...+... | +| tst.go:138:14:138:19 | selection of Form | tst.go:144:28:144:90 | ...+... | +| tst.go:149:14:149:19 | selection of Form | tst.go:153:33:153:136 | ...+... | +| tst.go:149:14:149:19 | selection of Form | tst.go:156:18:156:121 | ...+... | +| tst.go:149:14:149:19 | selection of Form | tst.go:162:31:162:126 | ...+... | +| tst.go:149:14:149:19 | selection of Form | tst.go:171:21:171:116 | ...+... | +| tst.go:149:14:149:19 | selection of Form | tst.go:180:27:180:122 | ...+... | +| tst.go:150:14:150:19 | selection of Form | tst.go:153:33:153:136 | ...+... | +| tst.go:150:14:150:19 | selection of Form | tst.go:156:18:156:121 | ...+... | +| tst.go:150:14:150:19 | selection of Form | tst.go:162:31:162:126 | ...+... | +| tst.go:150:14:150:19 | selection of Form | tst.go:171:21:171:116 | ...+... | +| tst.go:150:14:150:19 | selection of Form | tst.go:180:27:180:122 | ...+... | nodes -| XPathInjection.go:13:14:13:19 | selection of Form : Values | semmle.label | selection of Form : Values | +| XPathInjection.go:13:14:13:19 | selection of Form | semmle.label | selection of Form | | XPathInjection.go:16:29:16:91 | ...+... | semmle.label | ...+... | -| tst.go:32:14:32:19 | selection of Form : Values | semmle.label | selection of Form : Values | +| tst.go:32:14:32:19 | selection of Form | semmle.label | selection of Form | | tst.go:35:23:35:85 | ...+... | semmle.label | ...+... | | tst.go:38:24:38:86 | ...+... | semmle.label | ...+... | | tst.go:41:24:41:82 | ...+... | semmle.label | ...+... | -| tst.go:46:14:46:19 | selection of Form : Values | semmle.label | selection of Form : Values | +| tst.go:46:14:46:19 | selection of Form | semmle.label | selection of Form | | tst.go:49:26:49:84 | ...+... | semmle.label | ...+... | | tst.go:52:29:52:87 | ...+... | semmle.label | ...+... | | tst.go:55:33:55:91 | ...+... | semmle.label | ...+... | | tst.go:58:30:58:88 | ...+... | semmle.label | ...+... | -| tst.go:63:14:63:19 | selection of Form : Values | semmle.label | selection of Form : Values | +| tst.go:63:14:63:19 | selection of Form | semmle.label | selection of Form | | tst.go:66:25:66:83 | ...+... | semmle.label | ...+... | | tst.go:69:28:69:86 | ...+... | semmle.label | ...+... | | tst.go:72:25:72:83 | ...+... | semmle.label | ...+... | @@ -60,24 +60,24 @@ nodes | tst.go:81:29:81:87 | ...+... | semmle.label | ...+... | | tst.go:84:23:84:85 | ...+... | semmle.label | ...+... | | tst.go:87:22:87:84 | ...+... | semmle.label | ...+... | -| tst.go:92:14:92:19 | selection of Form : Values | semmle.label | selection of Form : Values | +| tst.go:92:14:92:19 | selection of Form | semmle.label | selection of Form | | tst.go:95:26:95:84 | ...+... | semmle.label | ...+... | | tst.go:98:29:98:87 | ...+... | semmle.label | ...+... | | tst.go:101:33:101:91 | ...+... | semmle.label | ...+... | | tst.go:104:30:104:88 | ...+... | semmle.label | ...+... | -| tst.go:109:14:109:19 | selection of Form : Values | semmle.label | selection of Form : Values | +| tst.go:109:14:109:19 | selection of Form | semmle.label | selection of Form | | tst.go:112:25:112:87 | ...+... | semmle.label | ...+... | | tst.go:115:26:115:88 | ...+... | semmle.label | ...+... | -| tst.go:120:14:120:19 | selection of Form : Values | semmle.label | selection of Form : Values | -| tst.go:121:14:121:19 | selection of Form : Values | semmle.label | selection of Form : Values | +| tst.go:120:14:120:19 | selection of Form | semmle.label | selection of Form | +| tst.go:121:14:121:19 | selection of Form | semmle.label | selection of Form | | tst.go:124:23:124:126 | ...+... | semmle.label | ...+... | | tst.go:127:24:127:127 | ...+... | semmle.label | ...+... | | tst.go:130:27:130:122 | ...+... | semmle.label | ...+... | -| tst.go:138:14:138:19 | selection of Form : Values | semmle.label | selection of Form : Values | +| tst.go:138:14:138:19 | selection of Form | semmle.label | selection of Form | | tst.go:141:27:141:89 | ...+... | semmle.label | ...+... | | tst.go:144:28:144:90 | ...+... | semmle.label | ...+... | -| tst.go:149:14:149:19 | selection of Form : Values | semmle.label | selection of Form : Values | -| tst.go:150:14:150:19 | selection of Form : Values | semmle.label | selection of Form : Values | +| tst.go:149:14:149:19 | selection of Form | semmle.label | selection of Form | +| tst.go:150:14:150:19 | selection of Form | semmle.label | selection of Form | | tst.go:153:33:153:136 | ...+... | semmle.label | ...+... | | tst.go:156:18:156:121 | ...+... | semmle.label | ...+... | | tst.go:162:31:162:126 | ...+... | semmle.label | ...+... | @@ -85,43 +85,43 @@ nodes | tst.go:180:27:180:122 | ...+... | semmle.label | ...+... | subpaths #select -| XPathInjection.go:16:29:16:91 | ...+... | XPathInjection.go:13:14:13:19 | selection of Form : Values | XPathInjection.go:16:29:16:91 | ...+... | XPath expression depends on a $@. | XPathInjection.go:13:14:13:19 | selection of Form | user-provided value | -| tst.go:35:23:35:85 | ...+... | tst.go:32:14:32:19 | selection of Form : Values | tst.go:35:23:35:85 | ...+... | XPath expression depends on a $@. | tst.go:32:14:32:19 | selection of Form | user-provided value | -| tst.go:38:24:38:86 | ...+... | tst.go:32:14:32:19 | selection of Form : Values | tst.go:38:24:38:86 | ...+... | XPath expression depends on a $@. | tst.go:32:14:32:19 | selection of Form | user-provided value | -| tst.go:41:24:41:82 | ...+... | tst.go:32:14:32:19 | selection of Form : Values | tst.go:41:24:41:82 | ...+... | XPath expression depends on a $@. | tst.go:32:14:32:19 | selection of Form | user-provided value | -| tst.go:49:26:49:84 | ...+... | tst.go:46:14:46:19 | selection of Form : Values | tst.go:49:26:49:84 | ...+... | XPath expression depends on a $@. | tst.go:46:14:46:19 | selection of Form | user-provided value | -| tst.go:52:29:52:87 | ...+... | tst.go:46:14:46:19 | selection of Form : Values | tst.go:52:29:52:87 | ...+... | XPath expression depends on a $@. | tst.go:46:14:46:19 | selection of Form | user-provided value | -| tst.go:55:33:55:91 | ...+... | tst.go:46:14:46:19 | selection of Form : Values | tst.go:55:33:55:91 | ...+... | XPath expression depends on a $@. | tst.go:46:14:46:19 | selection of Form | user-provided value | -| tst.go:58:30:58:88 | ...+... | tst.go:46:14:46:19 | selection of Form : Values | tst.go:58:30:58:88 | ...+... | XPath expression depends on a $@. | tst.go:46:14:46:19 | selection of Form | user-provided value | -| tst.go:66:25:66:83 | ...+... | tst.go:63:14:63:19 | selection of Form : Values | tst.go:66:25:66:83 | ...+... | XPath expression depends on a $@. | tst.go:63:14:63:19 | selection of Form | user-provided value | -| tst.go:69:28:69:86 | ...+... | tst.go:63:14:63:19 | selection of Form : Values | tst.go:69:28:69:86 | ...+... | XPath expression depends on a $@. | tst.go:63:14:63:19 | selection of Form | user-provided value | -| tst.go:72:25:72:83 | ...+... | tst.go:63:14:63:19 | selection of Form : Values | tst.go:72:25:72:83 | ...+... | XPath expression depends on a $@. | tst.go:63:14:63:19 | selection of Form | user-provided value | -| tst.go:75:34:75:92 | ...+... | tst.go:63:14:63:19 | selection of Form : Values | tst.go:75:34:75:92 | ...+... | XPath expression depends on a $@. | tst.go:63:14:63:19 | selection of Form | user-provided value | -| tst.go:78:32:78:90 | ...+... | tst.go:63:14:63:19 | selection of Form : Values | tst.go:78:32:78:90 | ...+... | XPath expression depends on a $@. | tst.go:63:14:63:19 | selection of Form | user-provided value | -| tst.go:81:29:81:87 | ...+... | tst.go:63:14:63:19 | selection of Form : Values | tst.go:81:29:81:87 | ...+... | XPath expression depends on a $@. | tst.go:63:14:63:19 | selection of Form | user-provided value | -| tst.go:84:23:84:85 | ...+... | tst.go:63:14:63:19 | selection of Form : Values | tst.go:84:23:84:85 | ...+... | XPath expression depends on a $@. | tst.go:63:14:63:19 | selection of Form | user-provided value | -| tst.go:87:22:87:84 | ...+... | tst.go:63:14:63:19 | selection of Form : Values | tst.go:87:22:87:84 | ...+... | XPath expression depends on a $@. | tst.go:63:14:63:19 | selection of Form | user-provided value | -| tst.go:95:26:95:84 | ...+... | tst.go:92:14:92:19 | selection of Form : Values | tst.go:95:26:95:84 | ...+... | XPath expression depends on a $@. | tst.go:92:14:92:19 | selection of Form | user-provided value | -| tst.go:98:29:98:87 | ...+... | tst.go:92:14:92:19 | selection of Form : Values | tst.go:98:29:98:87 | ...+... | XPath expression depends on a $@. | tst.go:92:14:92:19 | selection of Form | user-provided value | -| tst.go:101:33:101:91 | ...+... | tst.go:92:14:92:19 | selection of Form : Values | tst.go:101:33:101:91 | ...+... | XPath expression depends on a $@. | tst.go:92:14:92:19 | selection of Form | user-provided value | -| tst.go:104:30:104:88 | ...+... | tst.go:92:14:92:19 | selection of Form : Values | tst.go:104:30:104:88 | ...+... | XPath expression depends on a $@. | tst.go:92:14:92:19 | selection of Form | user-provided value | -| tst.go:112:25:112:87 | ...+... | tst.go:109:14:109:19 | selection of Form : Values | tst.go:112:25:112:87 | ...+... | XPath expression depends on a $@. | tst.go:109:14:109:19 | selection of Form | user-provided value | -| tst.go:115:26:115:88 | ...+... | tst.go:109:14:109:19 | selection of Form : Values | tst.go:115:26:115:88 | ...+... | XPath expression depends on a $@. | tst.go:109:14:109:19 | selection of Form | user-provided value | -| tst.go:124:23:124:126 | ...+... | tst.go:120:14:120:19 | selection of Form : Values | tst.go:124:23:124:126 | ...+... | XPath expression depends on a $@. | tst.go:120:14:120:19 | selection of Form | user-provided value | -| tst.go:124:23:124:126 | ...+... | tst.go:121:14:121:19 | selection of Form : Values | tst.go:124:23:124:126 | ...+... | XPath expression depends on a $@. | tst.go:121:14:121:19 | selection of Form | user-provided value | -| tst.go:127:24:127:127 | ...+... | tst.go:120:14:120:19 | selection of Form : Values | tst.go:127:24:127:127 | ...+... | XPath expression depends on a $@. | tst.go:120:14:120:19 | selection of Form | user-provided value | -| tst.go:127:24:127:127 | ...+... | tst.go:121:14:121:19 | selection of Form : Values | tst.go:127:24:127:127 | ...+... | XPath expression depends on a $@. | tst.go:121:14:121:19 | selection of Form | user-provided value | -| tst.go:130:27:130:122 | ...+... | tst.go:120:14:120:19 | selection of Form : Values | tst.go:130:27:130:122 | ...+... | XPath expression depends on a $@. | tst.go:120:14:120:19 | selection of Form | user-provided value | -| tst.go:130:27:130:122 | ...+... | tst.go:121:14:121:19 | selection of Form : Values | tst.go:130:27:130:122 | ...+... | XPath expression depends on a $@. | tst.go:121:14:121:19 | selection of Form | user-provided value | -| tst.go:141:27:141:89 | ...+... | tst.go:138:14:138:19 | selection of Form : Values | tst.go:141:27:141:89 | ...+... | XPath expression depends on a $@. | tst.go:138:14:138:19 | selection of Form | user-provided value | -| tst.go:144:28:144:90 | ...+... | tst.go:138:14:138:19 | selection of Form : Values | tst.go:144:28:144:90 | ...+... | XPath expression depends on a $@. | tst.go:138:14:138:19 | selection of Form | user-provided value | -| tst.go:153:33:153:136 | ...+... | tst.go:149:14:149:19 | selection of Form : Values | tst.go:153:33:153:136 | ...+... | XPath expression depends on a $@. | tst.go:149:14:149:19 | selection of Form | user-provided value | -| tst.go:153:33:153:136 | ...+... | tst.go:150:14:150:19 | selection of Form : Values | tst.go:153:33:153:136 | ...+... | XPath expression depends on a $@. | tst.go:150:14:150:19 | selection of Form | user-provided value | -| tst.go:156:18:156:121 | ...+... | tst.go:149:14:149:19 | selection of Form : Values | tst.go:156:18:156:121 | ...+... | XPath expression depends on a $@. | tst.go:149:14:149:19 | selection of Form | user-provided value | -| tst.go:156:18:156:121 | ...+... | tst.go:150:14:150:19 | selection of Form : Values | tst.go:156:18:156:121 | ...+... | XPath expression depends on a $@. | tst.go:150:14:150:19 | selection of Form | user-provided value | -| tst.go:162:31:162:126 | ...+... | tst.go:149:14:149:19 | selection of Form : Values | tst.go:162:31:162:126 | ...+... | XPath expression depends on a $@. | tst.go:149:14:149:19 | selection of Form | user-provided value | -| tst.go:162:31:162:126 | ...+... | tst.go:150:14:150:19 | selection of Form : Values | tst.go:162:31:162:126 | ...+... | XPath expression depends on a $@. | tst.go:150:14:150:19 | selection of Form | user-provided value | -| tst.go:171:21:171:116 | ...+... | tst.go:149:14:149:19 | selection of Form : Values | tst.go:171:21:171:116 | ...+... | XPath expression depends on a $@. | tst.go:149:14:149:19 | selection of Form | user-provided value | -| tst.go:171:21:171:116 | ...+... | tst.go:150:14:150:19 | selection of Form : Values | tst.go:171:21:171:116 | ...+... | XPath expression depends on a $@. | tst.go:150:14:150:19 | selection of Form | user-provided value | -| tst.go:180:27:180:122 | ...+... | tst.go:149:14:149:19 | selection of Form : Values | tst.go:180:27:180:122 | ...+... | XPath expression depends on a $@. | tst.go:149:14:149:19 | selection of Form | user-provided value | -| tst.go:180:27:180:122 | ...+... | tst.go:150:14:150:19 | selection of Form : Values | tst.go:180:27:180:122 | ...+... | XPath expression depends on a $@. | tst.go:150:14:150:19 | selection of Form | user-provided value | +| XPathInjection.go:16:29:16:91 | ...+... | XPathInjection.go:13:14:13:19 | selection of Form | XPathInjection.go:16:29:16:91 | ...+... | XPath expression depends on a $@. | XPathInjection.go:13:14:13:19 | selection of Form | user-provided value | +| tst.go:35:23:35:85 | ...+... | tst.go:32:14:32:19 | selection of Form | tst.go:35:23:35:85 | ...+... | XPath expression depends on a $@. | tst.go:32:14:32:19 | selection of Form | user-provided value | +| tst.go:38:24:38:86 | ...+... | tst.go:32:14:32:19 | selection of Form | tst.go:38:24:38:86 | ...+... | XPath expression depends on a $@. | tst.go:32:14:32:19 | selection of Form | user-provided value | +| tst.go:41:24:41:82 | ...+... | tst.go:32:14:32:19 | selection of Form | tst.go:41:24:41:82 | ...+... | XPath expression depends on a $@. | tst.go:32:14:32:19 | selection of Form | user-provided value | +| tst.go:49:26:49:84 | ...+... | tst.go:46:14:46:19 | selection of Form | tst.go:49:26:49:84 | ...+... | XPath expression depends on a $@. | tst.go:46:14:46:19 | selection of Form | user-provided value | +| tst.go:52:29:52:87 | ...+... | tst.go:46:14:46:19 | selection of Form | tst.go:52:29:52:87 | ...+... | XPath expression depends on a $@. | tst.go:46:14:46:19 | selection of Form | user-provided value | +| tst.go:55:33:55:91 | ...+... | tst.go:46:14:46:19 | selection of Form | tst.go:55:33:55:91 | ...+... | XPath expression depends on a $@. | tst.go:46:14:46:19 | selection of Form | user-provided value | +| tst.go:58:30:58:88 | ...+... | tst.go:46:14:46:19 | selection of Form | tst.go:58:30:58:88 | ...+... | XPath expression depends on a $@. | tst.go:46:14:46:19 | selection of Form | user-provided value | +| tst.go:66:25:66:83 | ...+... | tst.go:63:14:63:19 | selection of Form | tst.go:66:25:66:83 | ...+... | XPath expression depends on a $@. | tst.go:63:14:63:19 | selection of Form | user-provided value | +| tst.go:69:28:69:86 | ...+... | tst.go:63:14:63:19 | selection of Form | tst.go:69:28:69:86 | ...+... | XPath expression depends on a $@. | tst.go:63:14:63:19 | selection of Form | user-provided value | +| tst.go:72:25:72:83 | ...+... | tst.go:63:14:63:19 | selection of Form | tst.go:72:25:72:83 | ...+... | XPath expression depends on a $@. | tst.go:63:14:63:19 | selection of Form | user-provided value | +| tst.go:75:34:75:92 | ...+... | tst.go:63:14:63:19 | selection of Form | tst.go:75:34:75:92 | ...+... | XPath expression depends on a $@. | tst.go:63:14:63:19 | selection of Form | user-provided value | +| tst.go:78:32:78:90 | ...+... | tst.go:63:14:63:19 | selection of Form | tst.go:78:32:78:90 | ...+... | XPath expression depends on a $@. | tst.go:63:14:63:19 | selection of Form | user-provided value | +| tst.go:81:29:81:87 | ...+... | tst.go:63:14:63:19 | selection of Form | tst.go:81:29:81:87 | ...+... | XPath expression depends on a $@. | tst.go:63:14:63:19 | selection of Form | user-provided value | +| tst.go:84:23:84:85 | ...+... | tst.go:63:14:63:19 | selection of Form | tst.go:84:23:84:85 | ...+... | XPath expression depends on a $@. | tst.go:63:14:63:19 | selection of Form | user-provided value | +| tst.go:87:22:87:84 | ...+... | tst.go:63:14:63:19 | selection of Form | tst.go:87:22:87:84 | ...+... | XPath expression depends on a $@. | tst.go:63:14:63:19 | selection of Form | user-provided value | +| tst.go:95:26:95:84 | ...+... | tst.go:92:14:92:19 | selection of Form | tst.go:95:26:95:84 | ...+... | XPath expression depends on a $@. | tst.go:92:14:92:19 | selection of Form | user-provided value | +| tst.go:98:29:98:87 | ...+... | tst.go:92:14:92:19 | selection of Form | tst.go:98:29:98:87 | ...+... | XPath expression depends on a $@. | tst.go:92:14:92:19 | selection of Form | user-provided value | +| tst.go:101:33:101:91 | ...+... | tst.go:92:14:92:19 | selection of Form | tst.go:101:33:101:91 | ...+... | XPath expression depends on a $@. | tst.go:92:14:92:19 | selection of Form | user-provided value | +| tst.go:104:30:104:88 | ...+... | tst.go:92:14:92:19 | selection of Form | tst.go:104:30:104:88 | ...+... | XPath expression depends on a $@. | tst.go:92:14:92:19 | selection of Form | user-provided value | +| tst.go:112:25:112:87 | ...+... | tst.go:109:14:109:19 | selection of Form | tst.go:112:25:112:87 | ...+... | XPath expression depends on a $@. | tst.go:109:14:109:19 | selection of Form | user-provided value | +| tst.go:115:26:115:88 | ...+... | tst.go:109:14:109:19 | selection of Form | tst.go:115:26:115:88 | ...+... | XPath expression depends on a $@. | tst.go:109:14:109:19 | selection of Form | user-provided value | +| tst.go:124:23:124:126 | ...+... | tst.go:120:14:120:19 | selection of Form | tst.go:124:23:124:126 | ...+... | XPath expression depends on a $@. | tst.go:120:14:120:19 | selection of Form | user-provided value | +| tst.go:124:23:124:126 | ...+... | tst.go:121:14:121:19 | selection of Form | tst.go:124:23:124:126 | ...+... | XPath expression depends on a $@. | tst.go:121:14:121:19 | selection of Form | user-provided value | +| tst.go:127:24:127:127 | ...+... | tst.go:120:14:120:19 | selection of Form | tst.go:127:24:127:127 | ...+... | XPath expression depends on a $@. | tst.go:120:14:120:19 | selection of Form | user-provided value | +| tst.go:127:24:127:127 | ...+... | tst.go:121:14:121:19 | selection of Form | tst.go:127:24:127:127 | ...+... | XPath expression depends on a $@. | tst.go:121:14:121:19 | selection of Form | user-provided value | +| tst.go:130:27:130:122 | ...+... | tst.go:120:14:120:19 | selection of Form | tst.go:130:27:130:122 | ...+... | XPath expression depends on a $@. | tst.go:120:14:120:19 | selection of Form | user-provided value | +| tst.go:130:27:130:122 | ...+... | tst.go:121:14:121:19 | selection of Form | tst.go:130:27:130:122 | ...+... | XPath expression depends on a $@. | tst.go:121:14:121:19 | selection of Form | user-provided value | +| tst.go:141:27:141:89 | ...+... | tst.go:138:14:138:19 | selection of Form | tst.go:141:27:141:89 | ...+... | XPath expression depends on a $@. | tst.go:138:14:138:19 | selection of Form | user-provided value | +| tst.go:144:28:144:90 | ...+... | tst.go:138:14:138:19 | selection of Form | tst.go:144:28:144:90 | ...+... | XPath expression depends on a $@. | tst.go:138:14:138:19 | selection of Form | user-provided value | +| tst.go:153:33:153:136 | ...+... | tst.go:149:14:149:19 | selection of Form | tst.go:153:33:153:136 | ...+... | XPath expression depends on a $@. | tst.go:149:14:149:19 | selection of Form | user-provided value | +| tst.go:153:33:153:136 | ...+... | tst.go:150:14:150:19 | selection of Form | tst.go:153:33:153:136 | ...+... | XPath expression depends on a $@. | tst.go:150:14:150:19 | selection of Form | user-provided value | +| tst.go:156:18:156:121 | ...+... | tst.go:149:14:149:19 | selection of Form | tst.go:156:18:156:121 | ...+... | XPath expression depends on a $@. | tst.go:149:14:149:19 | selection of Form | user-provided value | +| tst.go:156:18:156:121 | ...+... | tst.go:150:14:150:19 | selection of Form | tst.go:156:18:156:121 | ...+... | XPath expression depends on a $@. | tst.go:150:14:150:19 | selection of Form | user-provided value | +| tst.go:162:31:162:126 | ...+... | tst.go:149:14:149:19 | selection of Form | tst.go:162:31:162:126 | ...+... | XPath expression depends on a $@. | tst.go:149:14:149:19 | selection of Form | user-provided value | +| tst.go:162:31:162:126 | ...+... | tst.go:150:14:150:19 | selection of Form | tst.go:162:31:162:126 | ...+... | XPath expression depends on a $@. | tst.go:150:14:150:19 | selection of Form | user-provided value | +| tst.go:171:21:171:116 | ...+... | tst.go:149:14:149:19 | selection of Form | tst.go:171:21:171:116 | ...+... | XPath expression depends on a $@. | tst.go:149:14:149:19 | selection of Form | user-provided value | +| tst.go:171:21:171:116 | ...+... | tst.go:150:14:150:19 | selection of Form | tst.go:171:21:171:116 | ...+... | XPath expression depends on a $@. | tst.go:150:14:150:19 | selection of Form | user-provided value | +| tst.go:180:27:180:122 | ...+... | tst.go:149:14:149:19 | selection of Form | tst.go:180:27:180:122 | ...+... | XPath expression depends on a $@. | tst.go:149:14:149:19 | selection of Form | user-provided value | +| tst.go:180:27:180:122 | ...+... | tst.go:150:14:150:19 | selection of Form | tst.go:180:27:180:122 | ...+... | XPath expression depends on a $@. | tst.go:150:14:150:19 | selection of Form | user-provided value | diff --git a/go/ql/test/query-tests/Security/CWE-918/RequestForgery.expected b/go/ql/test/query-tests/Security/CWE-918/RequestForgery.expected index 7751054abbd..d6bb8bbf7af 100644 --- a/go/ql/test/query-tests/Security/CWE-918/RequestForgery.expected +++ b/go/ql/test/query-tests/Security/CWE-918/RequestForgery.expected @@ -1,75 +1,75 @@ edges -| RequestForgery.go:8:12:8:34 | call to FormValue : string | RequestForgery.go:11:24:11:65 | ...+... | -| tst.go:10:13:10:35 | call to FormValue : string | tst.go:14:11:14:17 | tainted | -| tst.go:10:13:10:35 | call to FormValue : string | tst.go:18:12:18:18 | tainted | -| tst.go:10:13:10:35 | call to FormValue : string | tst.go:21:34:21:40 | tainted | -| tst.go:10:13:10:35 | call to FormValue : string | tst.go:24:66:24:72 | tainted | -| tst.go:10:13:10:35 | call to FormValue : string | tst.go:27:11:27:29 | ...+... | -| tst.go:10:13:10:35 | call to FormValue : string | tst.go:29:11:29:40 | ...+... | -| tst.go:10:13:10:35 | call to FormValue : string | tst.go:36:2:36:2 | implicit dereference : URL | -| tst.go:10:13:10:35 | call to FormValue : string | tst.go:37:11:37:20 | call to String | -| tst.go:35:2:35:2 | definition of u [pointer] : URL | tst.go:36:2:36:2 | u [pointer] : URL | -| tst.go:36:2:36:2 | implicit dereference : URL | tst.go:35:2:35:2 | definition of u [pointer] : URL | -| tst.go:36:2:36:2 | implicit dereference : URL | tst.go:36:2:36:2 | implicit dereference : URL | -| tst.go:36:2:36:2 | implicit dereference : URL | tst.go:37:11:37:20 | call to String | -| tst.go:36:2:36:2 | u [pointer] : URL | tst.go:36:2:36:2 | implicit dereference : URL | -| websocket.go:60:21:60:31 | call to Referer : string | websocket.go:65:27:65:40 | untrustedInput | -| websocket.go:74:21:74:31 | call to Referer : string | websocket.go:78:36:78:49 | untrustedInput | -| websocket.go:88:21:88:31 | call to Referer : string | websocket.go:91:31:91:44 | untrustedInput | -| websocket.go:107:21:107:31 | call to Referer : string | websocket.go:110:15:110:28 | untrustedInput | -| websocket.go:126:21:126:31 | call to Referer : string | websocket.go:129:38:129:51 | untrustedInput | -| websocket.go:154:21:154:31 | call to Referer : string | websocket.go:155:31:155:44 | untrustedInput | -| websocket.go:160:21:160:31 | call to Referer : string | websocket.go:162:31:162:44 | untrustedInput | -| websocket.go:195:21:195:31 | call to Referer : string | websocket.go:197:18:197:31 | untrustedInput | -| websocket.go:202:21:202:31 | call to Referer : string | websocket.go:204:11:204:24 | untrustedInput | +| RequestForgery.go:8:12:8:34 | call to FormValue | RequestForgery.go:11:24:11:65 | ...+... | +| tst.go:10:13:10:35 | call to FormValue | tst.go:14:11:14:17 | tainted | +| tst.go:10:13:10:35 | call to FormValue | tst.go:18:12:18:18 | tainted | +| tst.go:10:13:10:35 | call to FormValue | tst.go:21:34:21:40 | tainted | +| tst.go:10:13:10:35 | call to FormValue | tst.go:24:66:24:72 | tainted | +| tst.go:10:13:10:35 | call to FormValue | tst.go:27:11:27:29 | ...+... | +| tst.go:10:13:10:35 | call to FormValue | tst.go:29:11:29:40 | ...+... | +| tst.go:10:13:10:35 | call to FormValue | tst.go:36:2:36:2 | implicit dereference | +| tst.go:10:13:10:35 | call to FormValue | tst.go:37:11:37:20 | call to String | +| tst.go:35:2:35:2 | definition of u [pointer] | tst.go:36:2:36:2 | u [pointer] | +| tst.go:36:2:36:2 | implicit dereference | tst.go:35:2:35:2 | definition of u [pointer] | +| tst.go:36:2:36:2 | implicit dereference | tst.go:36:2:36:2 | implicit dereference | +| tst.go:36:2:36:2 | implicit dereference | tst.go:37:11:37:20 | call to String | +| tst.go:36:2:36:2 | u [pointer] | tst.go:36:2:36:2 | implicit dereference | +| websocket.go:60:21:60:31 | call to Referer | websocket.go:65:27:65:40 | untrustedInput | +| websocket.go:74:21:74:31 | call to Referer | websocket.go:78:36:78:49 | untrustedInput | +| websocket.go:88:21:88:31 | call to Referer | websocket.go:91:31:91:44 | untrustedInput | +| websocket.go:107:21:107:31 | call to Referer | websocket.go:110:15:110:28 | untrustedInput | +| websocket.go:126:21:126:31 | call to Referer | websocket.go:129:38:129:51 | untrustedInput | +| websocket.go:154:21:154:31 | call to Referer | websocket.go:155:31:155:44 | untrustedInput | +| websocket.go:160:21:160:31 | call to Referer | websocket.go:162:31:162:44 | untrustedInput | +| websocket.go:195:21:195:31 | call to Referer | websocket.go:197:18:197:31 | untrustedInput | +| websocket.go:202:21:202:31 | call to Referer | websocket.go:204:11:204:24 | untrustedInput | nodes -| RequestForgery.go:8:12:8:34 | call to FormValue : string | semmle.label | call to FormValue : string | +| RequestForgery.go:8:12:8:34 | call to FormValue | semmle.label | call to FormValue | | RequestForgery.go:11:24:11:65 | ...+... | semmle.label | ...+... | -| tst.go:10:13:10:35 | call to FormValue : string | semmle.label | call to FormValue : string | +| tst.go:10:13:10:35 | call to FormValue | semmle.label | call to FormValue | | tst.go:14:11:14:17 | tainted | semmle.label | tainted | | tst.go:18:12:18:18 | tainted | semmle.label | tainted | | tst.go:21:34:21:40 | tainted | semmle.label | tainted | | tst.go:24:66:24:72 | tainted | semmle.label | tainted | | tst.go:27:11:27:29 | ...+... | semmle.label | ...+... | | tst.go:29:11:29:40 | ...+... | semmle.label | ...+... | -| tst.go:35:2:35:2 | definition of u [pointer] : URL | semmle.label | definition of u [pointer] : URL | -| tst.go:36:2:36:2 | implicit dereference : URL | semmle.label | implicit dereference : URL | -| tst.go:36:2:36:2 | u [pointer] : URL | semmle.label | u [pointer] : URL | +| tst.go:35:2:35:2 | definition of u [pointer] | semmle.label | definition of u [pointer] | +| tst.go:36:2:36:2 | implicit dereference | semmle.label | implicit dereference | +| tst.go:36:2:36:2 | u [pointer] | semmle.label | u [pointer] | | tst.go:37:11:37:20 | call to String | semmle.label | call to String | -| websocket.go:60:21:60:31 | call to Referer : string | semmle.label | call to Referer : string | +| websocket.go:60:21:60:31 | call to Referer | semmle.label | call to Referer | | websocket.go:65:27:65:40 | untrustedInput | semmle.label | untrustedInput | -| websocket.go:74:21:74:31 | call to Referer : string | semmle.label | call to Referer : string | +| websocket.go:74:21:74:31 | call to Referer | semmle.label | call to Referer | | websocket.go:78:36:78:49 | untrustedInput | semmle.label | untrustedInput | -| websocket.go:88:21:88:31 | call to Referer : string | semmle.label | call to Referer : string | +| websocket.go:88:21:88:31 | call to Referer | semmle.label | call to Referer | | websocket.go:91:31:91:44 | untrustedInput | semmle.label | untrustedInput | -| websocket.go:107:21:107:31 | call to Referer : string | semmle.label | call to Referer : string | +| websocket.go:107:21:107:31 | call to Referer | semmle.label | call to Referer | | websocket.go:110:15:110:28 | untrustedInput | semmle.label | untrustedInput | -| websocket.go:126:21:126:31 | call to Referer : string | semmle.label | call to Referer : string | +| websocket.go:126:21:126:31 | call to Referer | semmle.label | call to Referer | | websocket.go:129:38:129:51 | untrustedInput | semmle.label | untrustedInput | -| websocket.go:154:21:154:31 | call to Referer : string | semmle.label | call to Referer : string | +| websocket.go:154:21:154:31 | call to Referer | semmle.label | call to Referer | | websocket.go:155:31:155:44 | untrustedInput | semmle.label | untrustedInput | -| websocket.go:160:21:160:31 | call to Referer : string | semmle.label | call to Referer : string | +| websocket.go:160:21:160:31 | call to Referer | semmle.label | call to Referer | | websocket.go:162:31:162:44 | untrustedInput | semmle.label | untrustedInput | -| websocket.go:195:21:195:31 | call to Referer : string | semmle.label | call to Referer : string | +| websocket.go:195:21:195:31 | call to Referer | semmle.label | call to Referer | | websocket.go:197:18:197:31 | untrustedInput | semmle.label | untrustedInput | -| websocket.go:202:21:202:31 | call to Referer : string | semmle.label | call to Referer : string | +| websocket.go:202:21:202:31 | call to Referer | semmle.label | call to Referer | | websocket.go:204:11:204:24 | untrustedInput | semmle.label | untrustedInput | subpaths #select -| RequestForgery.go:11:15:11:66 | call to Get | RequestForgery.go:8:12:8:34 | call to FormValue : string | RequestForgery.go:11:24:11:65 | ...+... | The $@ of this request depends on a $@. | RequestForgery.go:11:24:11:65 | ...+... | URL | RequestForgery.go:8:12:8:34 | call to FormValue : string | user-provided value | -| tst.go:14:2:14:18 | call to Get | tst.go:10:13:10:35 | call to FormValue : string | tst.go:14:11:14:17 | tainted | The $@ of this request depends on a $@. | tst.go:14:11:14:17 | tainted | URL | tst.go:10:13:10:35 | call to FormValue : string | user-provided value | -| tst.go:18:2:18:38 | call to Post | tst.go:10:13:10:35 | call to FormValue : string | tst.go:18:12:18:18 | tainted | The $@ of this request depends on a $@. | tst.go:18:12:18:18 | tainted | URL | tst.go:10:13:10:35 | call to FormValue : string | user-provided value | -| tst.go:22:2:22:14 | call to Do | tst.go:10:13:10:35 | call to FormValue : string | tst.go:21:34:21:40 | tainted | The $@ of this request depends on a $@. | tst.go:21:34:21:40 | tainted | URL | tst.go:10:13:10:35 | call to FormValue : string | user-provided value | -| tst.go:25:2:25:14 | call to Do | tst.go:10:13:10:35 | call to FormValue : string | tst.go:24:66:24:72 | tainted | The $@ of this request depends on a $@. | tst.go:24:66:24:72 | tainted | URL | tst.go:10:13:10:35 | call to FormValue : string | user-provided value | -| tst.go:27:2:27:30 | call to Get | tst.go:10:13:10:35 | call to FormValue : string | tst.go:27:11:27:29 | ...+... | The $@ of this request depends on a $@. | tst.go:27:11:27:29 | ...+... | URL | tst.go:10:13:10:35 | call to FormValue : string | user-provided value | -| tst.go:29:2:29:41 | call to Get | tst.go:10:13:10:35 | call to FormValue : string | tst.go:29:11:29:40 | ...+... | The $@ of this request depends on a $@. | tst.go:29:11:29:40 | ...+... | URL | tst.go:10:13:10:35 | call to FormValue : string | user-provided value | -| tst.go:37:2:37:21 | call to Get | tst.go:10:13:10:35 | call to FormValue : string | tst.go:37:11:37:20 | call to String | The $@ of this request depends on a $@. | tst.go:37:11:37:20 | call to String | URL | tst.go:10:13:10:35 | call to FormValue : string | user-provided value | -| websocket.go:65:12:65:53 | call to Dial | websocket.go:60:21:60:31 | call to Referer : string | websocket.go:65:27:65:40 | untrustedInput | The $@ of this request depends on a $@. | websocket.go:65:27:65:40 | untrustedInput | WebSocket URL | websocket.go:60:21:60:31 | call to Referer : string | user-provided value | -| websocket.go:79:13:79:40 | call to DialConfig | websocket.go:74:21:74:31 | call to Referer : string | websocket.go:78:36:78:49 | untrustedInput | The $@ of this request depends on a $@. | websocket.go:78:36:78:49 | untrustedInput | WebSocket URL | websocket.go:74:21:74:31 | call to Referer : string | user-provided value | -| websocket.go:91:3:91:50 | call to Dial | websocket.go:88:21:88:31 | call to Referer : string | websocket.go:91:31:91:44 | untrustedInput | The $@ of this request depends on a $@. | websocket.go:91:31:91:44 | untrustedInput | WebSocket URL | websocket.go:88:21:88:31 | call to Referer : string | user-provided value | -| websocket.go:110:3:110:39 | call to Dial | websocket.go:107:21:107:31 | call to Referer : string | websocket.go:110:15:110:28 | untrustedInput | The $@ of this request depends on a $@. | websocket.go:110:15:110:28 | untrustedInput | WebSocket URL | websocket.go:107:21:107:31 | call to Referer : string | user-provided value | -| websocket.go:129:3:129:62 | call to DialContext | websocket.go:126:21:126:31 | call to Referer : string | websocket.go:129:38:129:51 | untrustedInput | The $@ of this request depends on a $@. | websocket.go:129:38:129:51 | untrustedInput | WebSocket URL | websocket.go:126:21:126:31 | call to Referer : string | user-provided value | -| websocket.go:155:3:155:45 | call to Dial | websocket.go:154:21:154:31 | call to Referer : string | websocket.go:155:31:155:44 | untrustedInput | The $@ of this request depends on a $@. | websocket.go:155:31:155:44 | untrustedInput | WebSocket URL | websocket.go:154:21:154:31 | call to Referer : string | user-provided value | -| websocket.go:162:3:162:45 | call to Dial | websocket.go:160:21:160:31 | call to Referer : string | websocket.go:162:31:162:44 | untrustedInput | The $@ of this request depends on a $@. | websocket.go:162:31:162:44 | untrustedInput | WebSocket URL | websocket.go:160:21:160:31 | call to Referer : string | user-provided value | -| websocket.go:197:3:197:32 | call to BuildProxy | websocket.go:195:21:195:31 | call to Referer : string | websocket.go:197:18:197:31 | untrustedInput | The $@ of this request depends on a $@. | websocket.go:197:18:197:31 | untrustedInput | WebSocket URL | websocket.go:195:21:195:31 | call to Referer : string | user-provided value | -| websocket.go:204:3:204:25 | call to New | websocket.go:202:21:202:31 | call to Referer : string | websocket.go:204:11:204:24 | untrustedInput | The $@ of this request depends on a $@. | websocket.go:204:11:204:24 | untrustedInput | WebSocket URL | websocket.go:202:21:202:31 | call to Referer : string | user-provided value | +| RequestForgery.go:11:15:11:66 | call to Get | RequestForgery.go:8:12:8:34 | call to FormValue | RequestForgery.go:11:24:11:65 | ...+... | The $@ of this request depends on a $@. | RequestForgery.go:11:24:11:65 | ...+... | URL | RequestForgery.go:8:12:8:34 | call to FormValue | user-provided value | +| tst.go:14:2:14:18 | call to Get | tst.go:10:13:10:35 | call to FormValue | tst.go:14:11:14:17 | tainted | The $@ of this request depends on a $@. | tst.go:14:11:14:17 | tainted | URL | tst.go:10:13:10:35 | call to FormValue | user-provided value | +| tst.go:18:2:18:38 | call to Post | tst.go:10:13:10:35 | call to FormValue | tst.go:18:12:18:18 | tainted | The $@ of this request depends on a $@. | tst.go:18:12:18:18 | tainted | URL | tst.go:10:13:10:35 | call to FormValue | user-provided value | +| tst.go:22:2:22:14 | call to Do | tst.go:10:13:10:35 | call to FormValue | tst.go:21:34:21:40 | tainted | The $@ of this request depends on a $@. | tst.go:21:34:21:40 | tainted | URL | tst.go:10:13:10:35 | call to FormValue | user-provided value | +| tst.go:25:2:25:14 | call to Do | tst.go:10:13:10:35 | call to FormValue | tst.go:24:66:24:72 | tainted | The $@ of this request depends on a $@. | tst.go:24:66:24:72 | tainted | URL | tst.go:10:13:10:35 | call to FormValue | user-provided value | +| tst.go:27:2:27:30 | call to Get | tst.go:10:13:10:35 | call to FormValue | tst.go:27:11:27:29 | ...+... | The $@ of this request depends on a $@. | tst.go:27:11:27:29 | ...+... | URL | tst.go:10:13:10:35 | call to FormValue | user-provided value | +| tst.go:29:2:29:41 | call to Get | tst.go:10:13:10:35 | call to FormValue | tst.go:29:11:29:40 | ...+... | The $@ of this request depends on a $@. | tst.go:29:11:29:40 | ...+... | URL | tst.go:10:13:10:35 | call to FormValue | user-provided value | +| tst.go:37:2:37:21 | call to Get | tst.go:10:13:10:35 | call to FormValue | tst.go:37:11:37:20 | call to String | The $@ of this request depends on a $@. | tst.go:37:11:37:20 | call to String | URL | tst.go:10:13:10:35 | call to FormValue | user-provided value | +| websocket.go:65:12:65:53 | call to Dial | websocket.go:60:21:60:31 | call to Referer | websocket.go:65:27:65:40 | untrustedInput | The $@ of this request depends on a $@. | websocket.go:65:27:65:40 | untrustedInput | WebSocket URL | websocket.go:60:21:60:31 | call to Referer | user-provided value | +| websocket.go:79:13:79:40 | call to DialConfig | websocket.go:74:21:74:31 | call to Referer | websocket.go:78:36:78:49 | untrustedInput | The $@ of this request depends on a $@. | websocket.go:78:36:78:49 | untrustedInput | WebSocket URL | websocket.go:74:21:74:31 | call to Referer | user-provided value | +| websocket.go:91:3:91:50 | call to Dial | websocket.go:88:21:88:31 | call to Referer | websocket.go:91:31:91:44 | untrustedInput | The $@ of this request depends on a $@. | websocket.go:91:31:91:44 | untrustedInput | WebSocket URL | websocket.go:88:21:88:31 | call to Referer | user-provided value | +| websocket.go:110:3:110:39 | call to Dial | websocket.go:107:21:107:31 | call to Referer | websocket.go:110:15:110:28 | untrustedInput | The $@ of this request depends on a $@. | websocket.go:110:15:110:28 | untrustedInput | WebSocket URL | websocket.go:107:21:107:31 | call to Referer | user-provided value | +| websocket.go:129:3:129:62 | call to DialContext | websocket.go:126:21:126:31 | call to Referer | websocket.go:129:38:129:51 | untrustedInput | The $@ of this request depends on a $@. | websocket.go:129:38:129:51 | untrustedInput | WebSocket URL | websocket.go:126:21:126:31 | call to Referer | user-provided value | +| websocket.go:155:3:155:45 | call to Dial | websocket.go:154:21:154:31 | call to Referer | websocket.go:155:31:155:44 | untrustedInput | The $@ of this request depends on a $@. | websocket.go:155:31:155:44 | untrustedInput | WebSocket URL | websocket.go:154:21:154:31 | call to Referer | user-provided value | +| websocket.go:162:3:162:45 | call to Dial | websocket.go:160:21:160:31 | call to Referer | websocket.go:162:31:162:44 | untrustedInput | The $@ of this request depends on a $@. | websocket.go:162:31:162:44 | untrustedInput | WebSocket URL | websocket.go:160:21:160:31 | call to Referer | user-provided value | +| websocket.go:197:3:197:32 | call to BuildProxy | websocket.go:195:21:195:31 | call to Referer | websocket.go:197:18:197:31 | untrustedInput | The $@ of this request depends on a $@. | websocket.go:197:18:197:31 | untrustedInput | WebSocket URL | websocket.go:195:21:195:31 | call to Referer | user-provided value | +| websocket.go:204:3:204:25 | call to New | websocket.go:202:21:202:31 | call to Referer | websocket.go:204:11:204:24 | untrustedInput | The $@ of this request depends on a $@. | websocket.go:204:11:204:24 | untrustedInput | WebSocket URL | websocket.go:202:21:202:31 | call to Referer | user-provided value | diff --git a/java/ql/integration-tests/all-platforms/kotlin/annotation-id-consistency/qlpack.yml b/java/ql/integration-tests/all-platforms/kotlin/annotation-id-consistency/qlpack.yml index a0c9cdc98a3..74fbac535d7 100644 --- a/java/ql/integration-tests/all-platforms/kotlin/annotation-id-consistency/qlpack.yml +++ b/java/ql/integration-tests/all-platforms/kotlin/annotation-id-consistency/qlpack.yml @@ -5,4 +5,3 @@ dependencies: codeql/java-queries: '*' dataExtensions: ext/*.model.yml - diff --git a/java/ql/integration-tests/all-platforms/kotlin/annotation-id-consistency/ext/test.model.yml b/java/ql/integration-tests/all-platforms/kotlin/annotation-id-consistency/test.ext.yml similarity index 68% rename from java/ql/integration-tests/all-platforms/kotlin/annotation-id-consistency/ext/test.model.yml rename to java/ql/integration-tests/all-platforms/kotlin/annotation-id-consistency/test.ext.yml index 5fb4ebb6c1d..4d7a2e9a149 100644 --- a/java/ql/integration-tests/all-platforms/kotlin/annotation-id-consistency/ext/test.model.yml +++ b/java/ql/integration-tests/all-platforms/kotlin/annotation-id-consistency/test.ext.yml @@ -1,5 +1,5 @@ extensions: - addsTo: pack: integrationtest-annotation-id-consistency - extensible: extNegativeSummaryModel + extensible: neutralModel data: [] diff --git a/java/ql/integration-tests/all-platforms/kotlin/default-parameter-mad-flow/ext/test.model.yml b/java/ql/integration-tests/all-platforms/kotlin/default-parameter-mad-flow/test.ext.yml similarity index 95% rename from java/ql/integration-tests/all-platforms/kotlin/default-parameter-mad-flow/ext/test.model.yml rename to java/ql/integration-tests/all-platforms/kotlin/default-parameter-mad-flow/test.ext.yml index 19ee05fc65f..3553b9fe577 100644 --- a/java/ql/integration-tests/all-platforms/kotlin/default-parameter-mad-flow/ext/test.model.yml +++ b/java/ql/integration-tests/all-platforms/kotlin/default-parameter-mad-flow/test.ext.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: integrationtest-default-parameter-mad-flow - extensible: extSummaryModel + extensible: summaryModel data: - ["", "ConstructorWithDefaults", True, "ConstructorWithDefaults", "(int,int)", "", "Argument[0]", "Argument[-1]", "taint", "manual"] - ["", "LibKt", True, "topLevelWithDefaults", "(int,int)", "", "Argument[0]", "ReturnValue", "value", "manual"] @@ -12,14 +12,14 @@ extensions: - ["", "LibClass", True, "multiParameterExtensionTest", "(int,int,int,int)", "", "Argument[0, 1]", "ReturnValue", "value", "manual"] - addsTo: pack: integrationtest-default-parameter-mad-flow - extensible: extSourceModel + extensible: sourceModel data: - ["", "LibKt", True, "topLevelArgSource", "(SomeToken,int)", "", "Argument[0]", "kotlinMadFlowTest", "manual"] - ["", "LibKt", True, "extensionArgSource", "(String,SomeToken,int)", "", "Argument[1]", "kotlinMadFlowTest", "manual"] - ["", "SourceClass", True, "memberArgSource", "(SomeToken,int)", "", "Argument[0]", "kotlinMadFlowTest", "manual"] - addsTo: pack: integrationtest-default-parameter-mad-flow - extensible: extSinkModel + extensible: sinkModel data: - ["", "SinkClass", True, "SinkClass", "(int,int)", "", "Argument[0]", "kotlinMadFlowTest", "manual"] - ["", "LibKt", True, "topLevelSink", "(int,int)", "", "Argument[0]", "kotlinMadFlowTest", "manual"] diff --git a/java/ql/lib/ext/android.app.model.yml b/java/ql/lib/ext/android.app.model.yml index c96fee8b282..82ed724a418 100644 --- a/java/ql/lib/ext/android.app.model.yml +++ b/java/ql/lib/ext/android.app.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSinkModel + extensible: sinkModel data: - ["android.app", "Activity", True, "bindService", "", "", "Argument[0]", "intent-start", "manual"] - ["android.app", "Activity", True, "bindServiceAsUser", "", "", "Argument[0]", "intent-start", "manual"] @@ -40,7 +40,7 @@ extensions: - ["android.app", "PendingIntent", False, "send", "(Context,int,Intent,OnFinished,Handler,String,Bundle)", "", "Argument[2]", "pending-intent-sent", "manual"] - addsTo: pack: codeql/java-all - extensible: extSummaryModel + extensible: summaryModel data: - ["android.app", "Notification$Action", True, "Action", "(int,CharSequence,PendingIntent)", "", "Argument[2]", "Argument[-1]", "taint", "manual"] - ["android.app", "Notification$Action", True, "getExtras", "", "", "Argument[-1].SyntheticField[android.content.Intent.extras]", "ReturnValue", "value", "manual"] diff --git a/java/ql/lib/ext/android.content.model.yml b/java/ql/lib/ext/android.content.model.yml index a07799665db..292360c550c 100644 --- a/java/ql/lib/ext/android.content.model.yml +++ b/java/ql/lib/ext/android.content.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSourceModel + extensible: sourceModel data: # ContentInterface models are here for backwards compatibility (it was removed in API 28) - ["android.content", "ContentInterface", True, "call", "(String,String,String,Bundle)", "", "Parameter[0..3]", "contentprovider", "manual"] @@ -37,7 +37,7 @@ extensions: - ["android.content", "Context", True, "getExternalFilesDirs", "(String)", "", "ReturnValue", "android-external-storage-dir", "manual"] - addsTo: pack: codeql/java-all - extensible: extSinkModel + extensible: sinkModel data: - ["android.content", "ContentProvider", True, "delete", "(Uri,String,String[])", "", "Argument[1]", "sql", "manual"] - ["android.content", "ContentProvider", True, "query", "(Uri,String[],String,String[],String)", "", "Argument[2]", "sql", "manual"] @@ -65,7 +65,7 @@ extensions: - ["android.content", "Context", True, "startServiceAsUser", "", "", "Argument[0]", "intent-start", "manual"] - addsTo: pack: codeql/java-all - extensible: extSummaryModel + extensible: summaryModel data: - ["android.content", "ComponentName", False, "ComponentName", "(Context,Class)", "", "Argument[1]", "Argument[-1]", "taint", "manual"] - ["android.content", "ComponentName", False, "ComponentName", "(Context,String)", "", "Argument[1]", "Argument[-1]", "taint", "manual"] diff --git a/java/ql/lib/ext/android.database.model.yml b/java/ql/lib/ext/android.database.model.yml index 11aa4a46f74..a7c6e6b1d9b 100644 --- a/java/ql/lib/ext/android.database.model.yml +++ b/java/ql/lib/ext/android.database.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSinkModel + extensible: sinkModel data: - ["android.database", "DatabaseUtils", False, "blobFileDescriptorForQuery", "(SQLiteDatabase,String,String[])", "", "Argument[1]", "sql", "manual"] - ["android.database", "DatabaseUtils", False, "createDbFromSqlStatements", "(Context,String,int,String)", "", "Argument[3]", "sql", "manual"] @@ -12,7 +12,7 @@ extensions: - ["android.database", "DatabaseUtils", False, "stringForQuery", "(SQLiteDatabase,String,String[])", "", "Argument[1]", "sql", "manual"] - addsTo: pack: codeql/java-all - extensible: extSummaryModel + extensible: summaryModel data: - ["android.database", "Cursor", True, "copyStringToBuffer", "", "", "Argument[-1]", "Argument[1]", "taint", "manual"] - ["android.database", "Cursor", True, "getBlob", "", "", "Argument[-1]", "ReturnValue", "taint", "manual"] diff --git a/java/ql/lib/ext/android.database.sqlite.model.yml b/java/ql/lib/ext/android.database.sqlite.model.yml index 09f5b803661..4b775715409 100644 --- a/java/ql/lib/ext/android.database.sqlite.model.yml +++ b/java/ql/lib/ext/android.database.sqlite.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSinkModel + extensible: sinkModel data: - ["android.database.sqlite", "SQLiteDatabase", False, "compileStatement", "(String)", "", "Argument[0]", "sql", "manual"] - ["android.database.sqlite", "SQLiteDatabase", False, "delete", "(String,String,String[])", "", "Argument[0..1]", "sql", "manual"] @@ -57,7 +57,7 @@ extensions: - ["android.database.sqlite", "SQLiteQueryBuilder", True, "update", "(SQLiteDatabase,ContentValues,String,String[])", "", "Argument[2]", "sql", "manual"] - addsTo: pack: codeql/java-all - extensible: extSummaryModel + extensible: summaryModel data: - ["android.database.sqlite", "SQLiteQueryBuilder", True, "appendColumns", "(StringBuilder,String[])", "", "Argument[1].ArrayElement", "Argument[0]", "taint", "manual"] - ["android.database.sqlite", "SQLiteQueryBuilder", True, "appendWhere", "(CharSequence)", "", "Argument[0]", "Argument[-1]", "taint", "manual"] diff --git a/java/ql/lib/ext/android.net.model.yml b/java/ql/lib/ext/android.net.model.yml index 222ef1e0a2e..2cda1efbc75 100644 --- a/java/ql/lib/ext/android.net.model.yml +++ b/java/ql/lib/ext/android.net.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSummaryModel + extensible: summaryModel data: - ["android.net", "Uri", True, "buildUpon", "", "", "Argument[-1]", "ReturnValue", "taint", "manual"] - ["android.net", "Uri", False, "decode", "", "", "Argument[0]", "ReturnValue", "taint", "manual"] diff --git a/java/ql/lib/ext/android.os.model.yml b/java/ql/lib/ext/android.os.model.yml index 32860445cf4..847ac6ce27b 100644 --- a/java/ql/lib/ext/android.os.model.yml +++ b/java/ql/lib/ext/android.os.model.yml @@ -1,13 +1,13 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSourceModel + extensible: sourceModel data: - ["android.os", "Environment", False, "getExternalStorageDirectory", "()", "", "ReturnValue", "android-external-storage-dir", "manual"] - ["android.os", "Environment", False, "getExternalStoragePublicDirectory", "(String)", "", "ReturnValue", "android-external-storage-dir", "manual"] - addsTo: pack: codeql/java-all - extensible: extSummaryModel + extensible: summaryModel data: - ["android.os", "BaseBundle", True, "get", "(String)", "", "Argument[-1].MapValue", "ReturnValue", "value", "manual"] - ["android.os", "BaseBundle", True, "getString", "(String)", "", "Argument[-1].MapValue", "ReturnValue", "value", "manual"] diff --git a/java/ql/lib/ext/android.support.v4.app.model.yml b/java/ql/lib/ext/android.support.v4.app.model.yml index 42df9f0a87a..c99ebd9865e 100644 --- a/java/ql/lib/ext/android.support.v4.app.model.yml +++ b/java/ql/lib/ext/android.support.v4.app.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSinkModel + extensible: sinkModel data: - ["android.support.v4.app", "FragmentTransaction", True, "add", "(Class,Bundle,String)", "", "Argument[0]", "fragment-injection", "manual"] - ["android.support.v4.app", "FragmentTransaction", True, "add", "(Fragment,String)", "", "Argument[0]", "fragment-injection", "manual"] diff --git a/java/ql/lib/ext/android.util.model.yml b/java/ql/lib/ext/android.util.model.yml index 63d0612ea41..b57ff4819a7 100644 --- a/java/ql/lib/ext/android.util.model.yml +++ b/java/ql/lib/ext/android.util.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSourceModel + extensible: sourceModel data: - ["android.util", "AttributeSet", False, "getAttributeBooleanValue", "", "", "ReturnValue", "remote", "manual"] - ["android.util", "AttributeSet", False, "getAttributeCount", "", "", "ReturnValue", "remote", "manual"] @@ -21,7 +21,7 @@ extensions: - ["android.util", "AttributeSet", False, "getStyleAttribute", "", "", "ReturnValue", "remote", "manual"] - addsTo: pack: codeql/java-all - extensible: extSinkModel + extensible: sinkModel data: - ["android.util", "Log", True, "d", "", "", "Argument[1]", "logging", "manual"] - ["android.util", "Log", True, "e", "", "", "Argument[1]", "logging", "manual"] diff --git a/java/ql/lib/ext/android.webkit.model.yml b/java/ql/lib/ext/android.webkit.model.yml index c5a3ed8661f..05058493fe1 100644 --- a/java/ql/lib/ext/android.webkit.model.yml +++ b/java/ql/lib/ext/android.webkit.model.yml @@ -1,13 +1,13 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSourceModel + extensible: sourceModel data: - ["android.webkit", "WebView", False, "getOriginalUrl", "()", "", "ReturnValue", "remote", "manual"] - ["android.webkit", "WebView", False, "getUrl", "()", "", "ReturnValue", "remote", "manual"] - addsTo: pack: codeql/java-all - extensible: extSinkModel + extensible: sinkModel data: # Models representing methods susceptible to XSS attacks. - ["android.webkit", "WebView", False, "evaluateJavascript", "", "", "Argument[0]", "xss", "manual"] diff --git a/java/ql/lib/ext/android.widget.model.yml b/java/ql/lib/ext/android.widget.model.yml index 917167d6156..1b6c94993e0 100644 --- a/java/ql/lib/ext/android.widget.model.yml +++ b/java/ql/lib/ext/android.widget.model.yml @@ -1,11 +1,11 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSourceModel + extensible: sourceModel data: - ["android.widget", "EditText", True, "getText", "", "", "ReturnValue", "android-widget", "manual"] - addsTo: pack: codeql/java-all - extensible: extSummaryModel + extensible: summaryModel data: - ["android.widget", "EditText", True, "getText", "", "", "Argument[-1]", "ReturnValue", "taint", "manual"] diff --git a/java/ql/lib/ext/androidx.core.app.model.yml b/java/ql/lib/ext/androidx.core.app.model.yml index 48a97fbba57..dbf8c0fb082 100644 --- a/java/ql/lib/ext/androidx.core.app.model.yml +++ b/java/ql/lib/ext/androidx.core.app.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSinkModel + extensible: sinkModel data: - ["androidx.core.app", "AlarmManagerCompat", True, "setAlarmClock", "", "", "Argument[2..3]", "pending-intent-sent", "manual"] - ["androidx.core.app", "AlarmManagerCompat", True, "setAndAllowWhileIdle", "", "", "Argument[3]", "pending-intent-sent", "manual"] @@ -11,7 +11,7 @@ extensions: - ["androidx.core.app", "NotificationManagerCompat", True, "notify", "(int,Notification)", "", "Argument[1]", "pending-intent-sent", "manual"] - addsTo: pack: codeql/java-all - extensible: extSummaryModel + extensible: summaryModel data: - ["androidx.core.app", "NotificationCompat$Action", True, "Action", "(IconCompat,CharSequence,PendingIntent)", "", "Argument[2]", "Argument[-1]", "taint", "manual"] - ["androidx.core.app", "NotificationCompat$Action", True, "Action", "(int,CharSequence,PendingIntent)", "", "Argument[2]", "Argument[-1]", "taint", "manual"] diff --git a/java/ql/lib/ext/androidx.fragment.app.model.yml b/java/ql/lib/ext/androidx.fragment.app.model.yml index 8e219640c7d..94c55a75c71 100644 --- a/java/ql/lib/ext/androidx.fragment.app.model.yml +++ b/java/ql/lib/ext/androidx.fragment.app.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSinkModel + extensible: sinkModel data: - ["androidx.fragment.app", "FragmentTransaction", True, "add", "(Class,Bundle,String)", "", "Argument[0]", "fragment-injection", "manual"] - ["androidx.fragment.app", "FragmentTransaction", True, "add", "(Fragment,String)", "", "Argument[0]", "fragment-injection", "manual"] diff --git a/java/ql/lib/ext/androidx.slice.builders.model.yml b/java/ql/lib/ext/androidx.slice.builders.model.yml index 066fae518b2..8b84e7ec341 100644 --- a/java/ql/lib/ext/androidx.slice.builders.model.yml +++ b/java/ql/lib/ext/androidx.slice.builders.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSummaryModel + extensible: summaryModel data: - ["androidx.slice.builders", "ListBuilder", True, "addAction", "", "", "Argument[-1]", "ReturnValue", "value", "manual"] - ["androidx.slice.builders", "ListBuilder", True, "addAction", "", "", "Argument[0].SyntheticField[androidx.slice.Slice.action]", "Argument[-1].SyntheticField[androidx.slice.Slice.action]", "taint", "manual"] diff --git a/java/ql/lib/ext/androidx.slice.model.yml b/java/ql/lib/ext/androidx.slice.model.yml index 770b1797538..97481e886e5 100644 --- a/java/ql/lib/ext/androidx.slice.model.yml +++ b/java/ql/lib/ext/androidx.slice.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSourceModel + extensible: sourceModel data: - ["androidx.slice", "SliceProvider", True, "onBindSlice", "", "", "Parameter[0]", "contentprovider", "manual"] - ["androidx.slice", "SliceProvider", True, "onCreatePermissionRequest", "", "", "Parameter[0]", "contentprovider", "manual"] @@ -10,7 +10,7 @@ extensions: - ["androidx.slice", "SliceProvider", True, "onSliceUnpinned", "", "", "Parameter[0]", "contentprovider", "manual"] - addsTo: pack: codeql/java-all - extensible: extSinkModel + extensible: sinkModel data: - ["androidx.slice", "SliceProvider", True, "onBindSlice", "", "", "ReturnValue", "pending-intent-sent", "manual"] - ["androidx.slice", "SliceProvider", True, "onCreatePermissionRequest", "", "", "ReturnValue", "pending-intent-sent", "manual"] diff --git a/java/ql/lib/ext/cn.hutool.core.codec.model.yml b/java/ql/lib/ext/cn.hutool.core.codec.model.yml index fdd0766ffe4..8d583c144fb 100644 --- a/java/ql/lib/ext/cn.hutool.core.codec.model.yml +++ b/java/ql/lib/ext/cn.hutool.core.codec.model.yml @@ -1,6 +1,6 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSummaryModel + extensible: summaryModel data: - ["cn.hutool.core.codec", "Base64", True, "decode", "", "", "Argument[0]", "ReturnValue", "taint", "manual"] diff --git a/java/ql/lib/ext/com.esotericsoftware.kryo.io.model.yml b/java/ql/lib/ext/com.esotericsoftware.kryo.io.model.yml index 0acf40fe015..b98da490aba 100644 --- a/java/ql/lib/ext/com.esotericsoftware.kryo.io.model.yml +++ b/java/ql/lib/ext/com.esotericsoftware.kryo.io.model.yml @@ -1,6 +1,6 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSummaryModel + extensible: summaryModel data: - ["com.esotericsoftware.kryo.io", "Input", False, "Input", "", "", "Argument[0]", "Argument[-1]", "taint", "manual"] diff --git a/java/ql/lib/ext/com.esotericsoftware.kryo5.io.model.yml b/java/ql/lib/ext/com.esotericsoftware.kryo5.io.model.yml index e71107e7a63..78512602b9f 100644 --- a/java/ql/lib/ext/com.esotericsoftware.kryo5.io.model.yml +++ b/java/ql/lib/ext/com.esotericsoftware.kryo5.io.model.yml @@ -1,6 +1,6 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSummaryModel + extensible: summaryModel data: - ["com.esotericsoftware.kryo5.io", "Input", False, "Input", "", "", "Argument[0]", "Argument[-1]", "taint", "manual"] diff --git a/java/ql/lib/ext/com.fasterxml.jackson.core.model.yml b/java/ql/lib/ext/com.fasterxml.jackson.core.model.yml index 7510d7ed936..640b96f769f 100644 --- a/java/ql/lib/ext/com.fasterxml.jackson.core.model.yml +++ b/java/ql/lib/ext/com.fasterxml.jackson.core.model.yml @@ -1,6 +1,6 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSummaryModel + extensible: summaryModel data: - ["com.fasterxml.jackson.core", "JsonFactory", False, "createParser", "", "", "Argument[0]", "ReturnValue", "taint", "manual"] diff --git a/java/ql/lib/ext/com.fasterxml.jackson.databind.model.yml b/java/ql/lib/ext/com.fasterxml.jackson.databind.model.yml index 880b6bee044..3768007ebe7 100644 --- a/java/ql/lib/ext/com.fasterxml.jackson.databind.model.yml +++ b/java/ql/lib/ext/com.fasterxml.jackson.databind.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSummaryModel + extensible: summaryModel data: - ["com.fasterxml.jackson.databind", "ObjectMapper", True, "convertValue", "", "", "Argument[0]", "ReturnValue", "taint", "manual"] - ["com.fasterxml.jackson.databind", "ObjectMapper", False, "createParser", "", "", "Argument[0]", "ReturnValue", "taint", "manual"] diff --git a/java/ql/lib/ext/com.google.common.base.model.yml b/java/ql/lib/ext/com.google.common.base.model.yml index aaff117fbed..9d7e8491e81 100644 --- a/java/ql/lib/ext/com.google.common.base.model.yml +++ b/java/ql/lib/ext/com.google.common.base.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSinkModel + extensible: sinkModel data: - ["com.google.common.base", "Splitter", False, "onPattern", "(String)", "", "Argument[0]", "regex-use[]", "manual"] - ["com.google.common.base", "Splitter", False, "split", "(CharSequence)", "", "Argument[-1]", "regex-use[0]", "manual"] @@ -9,7 +9,7 @@ extensions: - ["com.google.common.base", "Splitter$MapSplitter", False, "split", "(CharSequence)", "", "Argument[-1]", "regex-use[0]", "manual"] - addsTo: pack: codeql/java-all - extensible: extSummaryModel + extensible: summaryModel data: - ["com.google.common.base", "Ascii", False, "toLowerCase", "(CharSequence)", "", "Argument[0]", "ReturnValue", "taint", "manual"] - ["com.google.common.base", "Ascii", False, "toLowerCase", "(String)", "", "Argument[0]", "ReturnValue", "taint", "manual"] diff --git a/java/ql/lib/ext/com.google.common.cache.model.yml b/java/ql/lib/ext/com.google.common.cache.model.yml index 852542d19d6..f5c88464208 100644 --- a/java/ql/lib/ext/com.google.common.cache.model.yml +++ b/java/ql/lib/ext/com.google.common.cache.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSummaryModel + extensible: summaryModel data: - ["com.google.common.cache", "Cache", True, "asMap", "()", "", "Argument[-1].MapKey", "ReturnValue.MapKey", "value", "manual"] - ["com.google.common.cache", "Cache", True, "asMap", "()", "", "Argument[-1].MapValue", "ReturnValue.MapValue", "value", "manual"] diff --git a/java/ql/lib/ext/com.google.common.collect.model.yml b/java/ql/lib/ext/com.google.common.collect.model.yml index 98124e42679..b6c067fe5e0 100644 --- a/java/ql/lib/ext/com.google.common.collect.model.yml +++ b/java/ql/lib/ext/com.google.common.collect.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSummaryModel + extensible: summaryModel data: # Methods depending on lambda flow are not currently modeled # Methods depending on stronger aliasing properties than we support are also not modeled. diff --git a/java/ql/lib/ext/com.google.common.flogger.model.yml b/java/ql/lib/ext/com.google.common.flogger.model.yml index 21c8b0e9fcb..b9a800b6210 100644 --- a/java/ql/lib/ext/com.google.common.flogger.model.yml +++ b/java/ql/lib/ext/com.google.common.flogger.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSinkModel + extensible: sinkModel data: - ["com.google.common.flogger", "LoggingApi", True, "log", "", "", "Argument[0]", "logging", "manual"] - ["com.google.common.flogger", "LoggingApi", True, "log", "(String,Object)", "", "Argument[1]", "logging", "manual"] diff --git a/java/ql/lib/ext/com.google.common.io.model.yml b/java/ql/lib/ext/com.google.common.io.model.yml index 5cba3d58e12..d08a5604338 100644 --- a/java/ql/lib/ext/com.google.common.io.model.yml +++ b/java/ql/lib/ext/com.google.common.io.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSinkModel + extensible: sinkModel data: - ["com.google.common.io", "Resources", False, "asByteSource", "(URL)", "", "Argument[0]", "url-open-stream", "manual"] - ["com.google.common.io", "Resources", False, "asCharSource", "(URL,Charset)", "", "Argument[0]", "url-open-stream", "manual"] @@ -11,7 +11,7 @@ extensions: - ["com.google.common.io", "Resources", False, "toString", "(URL,Charset)", "", "Argument[0]", "url-open-stream", "manual"] - addsTo: pack: codeql/java-all - extensible: extSummaryModel + extensible: summaryModel data: - ["com.google.common.io", "BaseEncoding", True, "decode", "(CharSequence)", "", "Argument[-1]", "ReturnValue", "taint", "manual"] - ["com.google.common.io", "BaseEncoding", True, "decode", "(CharSequence)", "", "Argument[0]", "ReturnValue", "taint", "manual"] diff --git a/java/ql/lib/ext/com.hubspot.jinjava.model.yml b/java/ql/lib/ext/com.hubspot.jinjava.model.yml index c1a30915e33..2172da483f8 100644 --- a/java/ql/lib/ext/com.hubspot.jinjava.model.yml +++ b/java/ql/lib/ext/com.hubspot.jinjava.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSinkModel + extensible: sinkModel data: - ["com.hubspot.jinjava", "Jinjava", True, "render", "", "", "Argument[0]", "ssti", "manual"] - ["com.hubspot.jinjava", "Jinjava", True, "renderForResult", "", "", "Argument[0]", "ssti", "manual"] diff --git a/java/ql/lib/ext/com.mitchellbosecke.pebble.model.yml b/java/ql/lib/ext/com.mitchellbosecke.pebble.model.yml index a8ae018da3c..74b227da1dd 100644 --- a/java/ql/lib/ext/com.mitchellbosecke.pebble.model.yml +++ b/java/ql/lib/ext/com.mitchellbosecke.pebble.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSinkModel + extensible: sinkModel data: - ["com.mitchellbosecke.pebble", "PebbleEngine", True, "getLiteralTemplate", "", "", "Argument[0]", "ssti", "manual"] - ["com.mitchellbosecke.pebble", "PebbleEngine", True, "getTemplate", "", "", "Argument[0]", "ssti", "manual"] diff --git a/java/ql/lib/ext/com.opensymphony.xwork2.ognl.model.yml b/java/ql/lib/ext/com.opensymphony.xwork2.ognl.model.yml index 60cd1b114d6..58b50652f1b 100644 --- a/java/ql/lib/ext/com.opensymphony.xwork2.ognl.model.yml +++ b/java/ql/lib/ext/com.opensymphony.xwork2.ognl.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSinkModel + extensible: sinkModel data: - ["com.opensymphony.xwork2.ognl", "OgnlUtil", False, "callMethod", "", "", "Argument[0]", "ognl-injection", "manual"] - ["com.opensymphony.xwork2.ognl", "OgnlUtil", False, "getValue", "", "", "Argument[0]", "ognl-injection", "manual"] diff --git a/java/ql/lib/ext/com.rabbitmq.client.impl.model.yml b/java/ql/lib/ext/com.rabbitmq.client.impl.model.yml index cd2a74a741d..9f0e9906e79 100644 --- a/java/ql/lib/ext/com.rabbitmq.client.impl.model.yml +++ b/java/ql/lib/ext/com.rabbitmq.client.impl.model.yml @@ -1,14 +1,14 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSourceModel + extensible: sourceModel data: - ["com.rabbitmq.client.impl", "Frame", True, "getInputStream", "()", "", "ReturnValue", "remote", "manual"] - ["com.rabbitmq.client.impl", "Frame", True, "getPayload", "()", "", "ReturnValue", "remote", "manual"] - ["com.rabbitmq.client.impl", "FrameHandler", True, "readFrame", "()", "", "ReturnValue", "remote", "manual"] - addsTo: pack: codeql/java-all - extensible: extSummaryModel + extensible: summaryModel data: - ["com.rabbitmq.client.impl", "Frame", False, "fromBodyFragment", "(int,byte[],int,int)", "", "Argument[1]", "ReturnValue", "taint", "manual"] - ["com.rabbitmq.client.impl", "Frame", False, "readFrom", "(DataInputStream)", "", "Argument[0]", "ReturnValue", "taint", "manual"] diff --git a/java/ql/lib/ext/com.rabbitmq.client.model.yml b/java/ql/lib/ext/com.rabbitmq.client.model.yml index ef452bf7005..ec313e8ef74 100644 --- a/java/ql/lib/ext/com.rabbitmq.client.model.yml +++ b/java/ql/lib/ext/com.rabbitmq.client.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSourceModel + extensible: sourceModel data: - ["com.rabbitmq.client", "Command", True, "getContentBody", "()", "", "ReturnValue", "remote", "manual"] - ["com.rabbitmq.client", "Command", True, "getContentHeader", "()", "", "ReturnValue", "remote", "manual"] @@ -23,7 +23,7 @@ extensions: - ["com.rabbitmq.client", "StringRpcServer", True, "handleStringCall", "", "", "Parameter[0]", "remote", "manual"] - addsTo: pack: codeql/java-all - extensible: extSummaryModel + extensible: summaryModel data: - ["com.rabbitmq.client", "GetResponse", True, "GetResponse", "", "", "Argument[2]", "Argument[-1]", "taint", "manual"] - ["com.rabbitmq.client", "GetResponse", True, "getBody", "()", "", "Argument[-1]", "ReturnValue", "taint", "manual"] diff --git a/java/ql/lib/ext/com.unboundid.ldap.sdk.model.yml b/java/ql/lib/ext/com.unboundid.ldap.sdk.model.yml index f9d1d872f28..57753bc31d0 100644 --- a/java/ql/lib/ext/com.unboundid.ldap.sdk.model.yml +++ b/java/ql/lib/ext/com.unboundid.ldap.sdk.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSinkModel + extensible: sinkModel data: - ["com.unboundid.ldap.sdk", "LDAPConnection", False, "asyncSearch", "", "", "Argument[0]", "ldap", "manual"] - ["com.unboundid.ldap.sdk", "LDAPConnection", False, "search", "(ReadOnlySearchRequest)", "", "Argument[0]", "ldap", "manual"] diff --git a/java/ql/lib/ext/com.zaxxer.hikari.model.yml b/java/ql/lib/ext/com.zaxxer.hikari.model.yml index fb9f8f3cb80..5fcab32cc7e 100644 --- a/java/ql/lib/ext/com.zaxxer.hikari.model.yml +++ b/java/ql/lib/ext/com.zaxxer.hikari.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSinkModel + extensible: sinkModel data: - ["com.zaxxer.hikari", "HikariConfig", False, "HikariConfig", "(Properties)", "", "Argument[0]", "jdbc-url", "manual"] - ["com.zaxxer.hikari", "HikariConfig", False, "setJdbcUrl", "(String)", "", "Argument[0]", "jdbc-url", "manual"] diff --git a/java/ql/lib/ext/dummy.model.yml b/java/ql/lib/ext/dummy.model.yml index e6139faabcf..0269fe72311 100644 --- a/java/ql/lib/ext/dummy.model.yml +++ b/java/ql/lib/ext/dummy.model.yml @@ -2,17 +2,17 @@ extensions: # Make sure that the extensible model predicates are at least defined as empty. - addsTo: pack: codeql/java-all - extensible: extSourceModel + extensible: sourceModel data: [] - addsTo: pack: codeql/java-all - extensible: extSinkModel + extensible: sinkModel data: [] - addsTo: pack: codeql/java-all - extensible: extSummaryModel + extensible: summaryModel data: [] - addsTo: pack: codeql/java-all - extensible: extNeutralModel + extensible: neutralModel data: [] \ No newline at end of file diff --git a/java/ql/lib/ext/experimental/android.webkit.model.yml b/java/ql/lib/ext/experimental/android.webkit.model.yml index dc2a4b95b64..ce70ae7e87b 100644 --- a/java/ql/lib/ext/experimental/android.webkit.model.yml +++ b/java/ql/lib/ext/experimental/android.webkit.model.yml @@ -1,6 +1,6 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extExperimentalSummaryModel + extensible: experimentalSummaryModel data: - ["android.webkit", "WebResourceRequest", False, "getUrl", "", "", "Argument[-1]", "ReturnValue", "taint", "manual", "android-web-resource-response"] diff --git a/java/ql/lib/ext/experimental/com.auth0.jwt.interfaces.model.yml b/java/ql/lib/ext/experimental/com.auth0.jwt.interfaces.model.yml index 3a4e6a42701..6032a9c8a18 100644 --- a/java/ql/lib/ext/experimental/com.auth0.jwt.interfaces.model.yml +++ b/java/ql/lib/ext/experimental/com.auth0.jwt.interfaces.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extExperimentalSummaryModel + extensible: experimentalSummaryModel data: - ["com.auth0.jwt.interfaces", "Verification", True, "acceptExpiresAt", "", "", "Argument[-1]", "ReturnValue", "value", "manual", "hardcoded-jwt-key"] - ["com.auth0.jwt.interfaces", "Verification", True, "acceptIssuedAt", "", "", "Argument[-1]", "ReturnValue", "value", "manual", "hardcoded-jwt-key"] diff --git a/java/ql/lib/ext/experimental/com.jfinal.core.model.yml b/java/ql/lib/ext/experimental/com.jfinal.core.model.yml index 078e86a4817..b6c7cc438f5 100644 --- a/java/ql/lib/ext/experimental/com.jfinal.core.model.yml +++ b/java/ql/lib/ext/experimental/com.jfinal.core.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extExperimentalSourceModel + extensible: experimentalSourceModel data: - ["com.jfinal.core", "Controller", True, "get", "", "", "ReturnValue", "remote", "manual", "file-path-injection"] - ["com.jfinal.core", "Controller", True, "getBoolean", "", "", "ReturnValue", "remote", "manual", "file-path-injection"] diff --git a/java/ql/lib/ext/experimental/dummy.model.yml b/java/ql/lib/ext/experimental/dummy.model.yml index d1521d27a9c..b43cb611b66 100644 --- a/java/ql/lib/ext/experimental/dummy.model.yml +++ b/java/ql/lib/ext/experimental/dummy.model.yml @@ -3,13 +3,13 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extExperimentalSourceModel + extensible: experimentalSourceModel data: [] - addsTo: pack: codeql/java-all - extensible: extExperimentalSinkModel + extensible: experimentalSinkModel data: [] - addsTo: pack: codeql/java-all - extensible: extExperimentalSummaryModel + extensible: experimentalSummaryModel data: [] diff --git a/java/ql/lib/ext/experimental/io.undertow.server.handlers.resource.model.yml b/java/ql/lib/ext/experimental/io.undertow.server.handlers.resource.model.yml index 222a144acaf..12267dcd845 100644 --- a/java/ql/lib/ext/experimental/io.undertow.server.handlers.resource.model.yml +++ b/java/ql/lib/ext/experimental/io.undertow.server.handlers.resource.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extExperimentalSummaryModel + extensible: experimentalSummaryModel data: - ["io.undertow.server.handlers.resource", "Resource", True, "getFile", "", "", "Argument[-1]", "ReturnValue", "taint", "manual", "unsafe-url-forward"] - ["io.undertow.server.handlers.resource", "Resource", True, "getFilePath", "", "", "Argument[-1]", "ReturnValue", "taint", "manual", "unsafe-url-forward"] diff --git a/java/ql/lib/ext/experimental/jakarta.servlet.http.model.yml b/java/ql/lib/ext/experimental/jakarta.servlet.http.model.yml index 17737495c06..9500beba15b 100644 --- a/java/ql/lib/ext/experimental/jakarta.servlet.http.model.yml +++ b/java/ql/lib/ext/experimental/jakarta.servlet.http.model.yml @@ -1,6 +1,6 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extExperimentalSourceModel + extensible: experimentalSourceModel data: - ["jakarta.servlet.http", "HttpServletRequest", True, "getServletPath", "", "", "ReturnValue", "remote", "manual", "unsafe-url-forward"] diff --git a/java/ql/lib/ext/experimental/java.io.model.yml b/java/ql/lib/ext/experimental/java.io.model.yml index 1b4fd419994..8d6d98ff47d 100644 --- a/java/ql/lib/ext/experimental/java.io.model.yml +++ b/java/ql/lib/ext/experimental/java.io.model.yml @@ -1,6 +1,6 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extExperimentalSummaryModel + extensible: experimentalSummaryModel data: - ["java.io", "FileInputStream", True, "FileInputStream", "", "", "Argument[0]", "Argument[-1]", "taint", "manual", "android-web-resource-response"] diff --git a/java/ql/lib/ext/experimental/java.lang.model.yml b/java/ql/lib/ext/experimental/java.lang.model.yml index 0622356da8e..696a0d9aba3 100644 --- a/java/ql/lib/ext/experimental/java.lang.model.yml +++ b/java/ql/lib/ext/experimental/java.lang.model.yml @@ -1,12 +1,12 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extExperimentalSinkModel + extensible: experimentalSinkModel data: - ["java.lang", "Thread", True, "sleep", "", "", "Argument[0]", "thread-pause", "manual", "thread-resource-abuse"] - addsTo: pack: codeql/java-all - extensible: extExperimentalSummaryModel + extensible: experimentalSummaryModel data: - ["java.lang", "Math", False, "max", "", "", "Argument[0..1]", "ReturnValue", "value", "manual", "thread-resource-abuse"] - ["java.lang", "Math", False, "min", "", "", "Argument[0..1]", "ReturnValue", "value", "manual", "thread-resource-abuse"] diff --git a/java/ql/lib/ext/experimental/java.nio.file.model.yml b/java/ql/lib/ext/experimental/java.nio.file.model.yml index 990a632fae4..d1d0d8d3d6e 100644 --- a/java/ql/lib/ext/experimental/java.nio.file.model.yml +++ b/java/ql/lib/ext/experimental/java.nio.file.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extExperimentalSummaryModel + extensible: experimentalSummaryModel data: - ["java.nio.file", "Path", True, "normalize", "", "", "Argument[-1]", "ReturnValue", "taint", "manual", "unsafe-url-forward"] - ["java.nio.file", "Path", True, "resolve", "", "", "Argument[-1..0]", "ReturnValue", "taint", "manual", "unsafe-url-forward"] diff --git a/java/ql/lib/ext/experimental/java.util.concurrent.model.yml b/java/ql/lib/ext/experimental/java.util.concurrent.model.yml index fbbee520183..82ff0a00570 100644 --- a/java/ql/lib/ext/experimental/java.util.concurrent.model.yml +++ b/java/ql/lib/ext/experimental/java.util.concurrent.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extExperimentalSinkModel + extensible: experimentalSinkModel data: - ["java.util.concurrent", "TimeUnit", True, "sleep", "", "", "Argument[0]", "thread-pause", "manual", "thread-resource-abuse"] - ["java.util.concurrent", "TimeUnit", True, "sleep", "", "", "Argument[0]", "thread-pause", "manual", "unsafe-url-forward"] diff --git a/java/ql/lib/ext/experimental/javax.servlet.http.model.yml b/java/ql/lib/ext/experimental/javax.servlet.http.model.yml index 04098f85f5d..db140149a99 100644 --- a/java/ql/lib/ext/experimental/javax.servlet.http.model.yml +++ b/java/ql/lib/ext/experimental/javax.servlet.http.model.yml @@ -1,12 +1,12 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extExperimentalSourceModel + extensible: experimentalSourceModel data: - ["javax.servlet.http", "HttpServletRequest", True, "getServletPath", "", "", "ReturnValue", "remote", "manual", "unsafe-url-forward"] - addsTo: pack: codeql/java-all - extensible: extExperimentalSourceModel + extensible: experimentalSourceModel data: - ["javax.servlet.http", "HttpServletRequest", False, "getPathInfo", "()", "", "ReturnValue", "uri-path", "manual", "permissive-dot-regex-query"] - ["javax.servlet.http", "HttpServletRequest", False, "getPathTranslated", "()", "", "ReturnValue", "uri-path", "manual", "permissive-dot-regex-query"] diff --git a/java/ql/lib/ext/experimental/org.apache.logging.log4j.message.model.yml b/java/ql/lib/ext/experimental/org.apache.logging.log4j.message.model.yml index 16b401d219d..71839d3abbe 100644 --- a/java/ql/lib/ext/experimental/org.apache.logging.log4j.message.model.yml +++ b/java/ql/lib/ext/experimental/org.apache.logging.log4j.message.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extExperimentalSummaryModel + extensible: experimentalSummaryModel data: - ["org.apache.logging.log4j.message", "MapMessage", True, "put", "", "", "Argument[1]", "Argument[-1]", "taint", "manual", "log4j-injection"] - ["org.apache.logging.log4j.message", "MapMessage", True, "putAll", "", "", "Argument[0].MapValue", "Argument[-1]", "taint", "manual", "log4j-injection"] diff --git a/java/ql/lib/ext/experimental/org.apache.logging.log4j.model.yml b/java/ql/lib/ext/experimental/org.apache.logging.log4j.model.yml index 3c8a2867a65..5b196c272fb 100644 --- a/java/ql/lib/ext/experimental/org.apache.logging.log4j.model.yml +++ b/java/ql/lib/ext/experimental/org.apache.logging.log4j.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extExperimentalSinkModel + extensible: experimentalSinkModel data: - ["org.apache.logging.log4j", "CloseableThreadContext", False, "put", "", "", "Argument[1]", "log4j", "manual", "log4j-injection"] - ["org.apache.logging.log4j", "CloseableThreadContext", False, "putAll", "", "", "Argument[0]", "log4j", "manual", "log4j-injection"] diff --git a/java/ql/lib/ext/experimental/org.springframework.core.io.model.yml b/java/ql/lib/ext/experimental/org.springframework.core.io.model.yml index 8fc74cd24db..1d4d808cdcd 100644 --- a/java/ql/lib/ext/experimental/org.springframework.core.io.model.yml +++ b/java/ql/lib/ext/experimental/org.springframework.core.io.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extExperimentalSinkModel + extensible: experimentalSinkModel data: - ["org.springframework.core.io", "ClassPathResource", True, "getFilename", "", "", "Argument[-1]", "get-resource", "manual", "unsafe-url-forward"] - ["org.springframework.core.io", "ClassPathResource", True, "getPath", "", "", "Argument[-1]", "get-resource", "manual", "unsafe-url-forward"] @@ -9,7 +9,7 @@ extensions: - ["org.springframework.core.io", "ClassPathResource", True, "resolveURL", "", "", "Argument[-1]", "get-resource", "manual", "unsafe-url-forward"] - addsTo: pack: codeql/java-all - extensible: extExperimentalSummaryModel + extensible: experimentalSummaryModel data: - ["org.springframework.core.io", "ClassPathResource", False, "ClassPathResource", "", "", "Argument[0]", "Argument[-1]", "taint", "manual", "unsafe-url-forward"] - ["org.springframework.core.io", "Resource", True, "createRelative", "", "", "Argument[0]", "ReturnValue", "taint", "manual", "unsafe-url-forward"] diff --git a/java/ql/lib/ext/flexjson.model.yml b/java/ql/lib/ext/flexjson.model.yml index af35c167d81..59249214262 100644 --- a/java/ql/lib/ext/flexjson.model.yml +++ b/java/ql/lib/ext/flexjson.model.yml @@ -1,6 +1,6 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSummaryModel + extensible: summaryModel data: - ["flexjson", "JSONDeserializer", True, "use", "", "", "Argument[-1]", "ReturnValue", "value", "manual"] diff --git a/java/ql/lib/ext/freemarker.cache.model.yml b/java/ql/lib/ext/freemarker.cache.model.yml index 031ad7244dd..b65e6386ad6 100644 --- a/java/ql/lib/ext/freemarker.cache.model.yml +++ b/java/ql/lib/ext/freemarker.cache.model.yml @@ -1,6 +1,6 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSinkModel + extensible: sinkModel data: - ["freemarker.cache", "StringTemplateLoader", True, "putTemplate", "", "", "Argument[1]", "ssti", "manual"] diff --git a/java/ql/lib/ext/freemarker.template.model.yml b/java/ql/lib/ext/freemarker.template.model.yml index 10f90c6ea87..96087a2b9ba 100644 --- a/java/ql/lib/ext/freemarker.template.model.yml +++ b/java/ql/lib/ext/freemarker.template.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSinkModel + extensible: sinkModel data: - ["freemarker.template", "Template", True, "Template", "(String,Reader)", "", "Argument[1]", "ssti", "manual"] - ["freemarker.template", "Template", True, "Template", "(String,Reader,Configuration)", "", "Argument[1]", "ssti", "manual"] diff --git a/java/ql/lib/ext/generated/kotlinstdlib.model.yml b/java/ql/lib/ext/generated/kotlinstdlib.model.yml index 4e8a73c048f..be3ee65d162 100644 --- a/java/ql/lib/ext/generated/kotlinstdlib.model.yml +++ b/java/ql/lib/ext/generated/kotlinstdlib.model.yml @@ -4,7 +4,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSinkModel + extensible: sinkModel data: - ["kotlin.io", "FilesKt", false, "appendBytes", "(File,byte[])", "", "Argument[0]", "create-file", "generated"] - ["kotlin.io", "FilesKt", false, "appendText", "(File,String,Charset)", "", "Argument[0]", "create-file", "generated"] @@ -22,7 +22,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSummaryModel + extensible: summaryModel data: - ["kotlin.collections", "AbstractCollection", true, "toString", "()", "", "Argument[-1]", "ReturnValue", "taint", "generated"] - ["kotlin.collections", "ArrayDeque", false, "ArrayDeque", "(Collection)", "", "Argument[0].Element", "Argument[-1]", "taint", "generated"] @@ -1861,7 +1861,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extNeutralModel + extensible: neutralModel data: - ["kotlin.annotation", "AnnotationRetention", "valueOf", "(String)", "generated"] - ["kotlin.annotation", "AnnotationRetention", "values", "()", "generated"] diff --git a/java/ql/lib/ext/generated/org.apache.commons.io.model.yml b/java/ql/lib/ext/generated/org.apache.commons.io.model.yml index 72ba13247bf..c2b6697d812 100644 --- a/java/ql/lib/ext/generated/org.apache.commons.io.model.yml +++ b/java/ql/lib/ext/generated/org.apache.commons.io.model.yml @@ -4,7 +4,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSinkModel + extensible: sinkModel data: - ["org.apache.commons.io.file", "PathFilter", true, "accept", "(Path,BasicFileAttributes)", "", "Argument[0]", "create-file", "generated"] - ["org.apache.commons.io.file", "PathUtils", false, "copyFile", "(URL,Path,CopyOption[])", "", "Argument[0]", "open-url", "generated"] @@ -116,7 +116,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSummaryModel + extensible: summaryModel data: - ["org.apache.commons.io.charset", "CharsetDecoders", true, "toCharsetDecoder", "(CharsetDecoder)", "", "Argument[0]", "ReturnValue", "taint", "generated"] - ["org.apache.commons.io.charset", "CharsetEncoders", true, "toCharsetEncoder", "(CharsetEncoder)", "", "Argument[0]", "ReturnValue", "taint", "generated"] @@ -676,7 +676,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extNeutralModel + extensible: neutralModel data: - ["org.apache.commons.io.charset", "CharsetDecoders", "CharsetDecoders", "()", "generated"] - ["org.apache.commons.io.charset", "CharsetEncoders", "CharsetEncoders", "()", "generated"] diff --git a/java/ql/lib/ext/groovy.lang.model.yml b/java/ql/lib/ext/groovy.lang.model.yml index 5299bf55afa..1c775bdd2e5 100644 --- a/java/ql/lib/ext/groovy.lang.model.yml +++ b/java/ql/lib/ext/groovy.lang.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSinkModel + extensible: sinkModel data: - ["groovy.lang", "GroovyClassLoader", False, "parseClass", "(GroovyCodeSource)", "", "Argument[0]", "groovy", "manual"] - ["groovy.lang", "GroovyClassLoader", False, "parseClass", "(GroovyCodeSource,boolean)", "", "Argument[0]", "groovy", "manual"] diff --git a/java/ql/lib/ext/groovy.util.model.yml b/java/ql/lib/ext/groovy.util.model.yml index 17b3d10ffae..61d1dbb6a05 100644 --- a/java/ql/lib/ext/groovy.util.model.yml +++ b/java/ql/lib/ext/groovy.util.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSinkModel + extensible: sinkModel data: - ["groovy.util", "Eval", False, "me", "(String)", "", "Argument[0]", "groovy", "manual"] - ["groovy.util", "Eval", False, "me", "(String,Object,String)", "", "Argument[2]", "groovy", "manual"] diff --git a/java/ql/lib/ext/jakarta.faces.context.model.yml b/java/ql/lib/ext/jakarta.faces.context.model.yml index 968a15369c9..84a0fd22710 100644 --- a/java/ql/lib/ext/jakarta.faces.context.model.yml +++ b/java/ql/lib/ext/jakarta.faces.context.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSourceModel + extensible: sourceModel data: - ["jakarta.faces.context", "ExternalContext", True, "getRequestCookieMap", "()", "", "ReturnValue", "remote", "manual"] - ["jakarta.faces.context", "ExternalContext", True, "getRequestHeaderMap", "()", "", "ReturnValue", "remote", "manual"] @@ -12,7 +12,7 @@ extensions: - ["jakarta.faces.context", "ExternalContext", True, "getRequestPathInfo", "()", "", "ReturnValue", "remote", "manual"] - addsTo: pack: codeql/java-all - extensible: extSinkModel + extensible: sinkModel data: - ["jakarta.faces.context", "ResponseStream", True, "write", "", "", "Argument[0]", "xss", "manual"] - ["jakarta.faces.context", "ResponseWriter", True, "write", "", "", "Argument[0]", "xss", "manual"] diff --git a/java/ql/lib/ext/jakarta.json.model.yml b/java/ql/lib/ext/jakarta.json.model.yml index 40c2a465fa6..3d4d35ca4f0 100644 --- a/java/ql/lib/ext/jakarta.json.model.yml +++ b/java/ql/lib/ext/jakarta.json.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSummaryModel + extensible: summaryModel data: - ["jakarta.json", "Json", False, "createArrayBuilder", "(Collection)", "", "Argument[0].Element", "ReturnValue", "taint", "manual"] - ["jakarta.json", "Json", False, "createArrayBuilder", "(JsonArray)", "", "Argument[0]", "ReturnValue", "taint", "manual"] diff --git a/java/ql/lib/ext/jakarta.json.stream.model.yml b/java/ql/lib/ext/jakarta.json.stream.model.yml index 1d8a0f2532a..cc6386121d5 100644 --- a/java/ql/lib/ext/jakarta.json.stream.model.yml +++ b/java/ql/lib/ext/jakarta.json.stream.model.yml @@ -1,6 +1,6 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSummaryModel + extensible: summaryModel data: - ["jakarta.json.stream", "JsonParserFactory", False, "createParser", "", "", "Argument[0]", "ReturnValue", "taint", "manual"] diff --git a/java/ql/lib/ext/jakarta.ws.rs.client.model.yml b/java/ql/lib/ext/jakarta.ws.rs.client.model.yml index 37ec5916e86..821ea0ad640 100644 --- a/java/ql/lib/ext/jakarta.ws.rs.client.model.yml +++ b/java/ql/lib/ext/jakarta.ws.rs.client.model.yml @@ -1,6 +1,6 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSinkModel + extensible: sinkModel data: - ["jakarta.ws.rs.client", "Client", True, "target", "", "", "Argument[0]", "open-url", "manual"] diff --git a/java/ql/lib/ext/jakarta.ws.rs.container.model.yml b/java/ql/lib/ext/jakarta.ws.rs.container.model.yml index ac3be002e11..05ccfd62000 100644 --- a/java/ql/lib/ext/jakarta.ws.rs.container.model.yml +++ b/java/ql/lib/ext/jakarta.ws.rs.container.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSourceModel + extensible: sourceModel data: - ["jakarta.ws.rs.container", "ContainerRequestContext", True, "getAcceptableLanguages", "", "", "ReturnValue", "remote", "manual"] - ["jakarta.ws.rs.container", "ContainerRequestContext", True, "getAcceptableMediaTypes", "", "", "ReturnValue", "remote", "manual"] diff --git a/java/ql/lib/ext/jakarta.ws.rs.core.model.yml b/java/ql/lib/ext/jakarta.ws.rs.core.model.yml index 44c8ed66881..593128bd953 100644 --- a/java/ql/lib/ext/jakarta.ws.rs.core.model.yml +++ b/java/ql/lib/ext/jakarta.ws.rs.core.model.yml @@ -1,13 +1,13 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSinkModel + extensible: sinkModel data: - ["jakarta.ws.rs.core", "Response", True, "seeOther", "", "", "Argument[0]", "url-redirect", "manual"] - ["jakarta.ws.rs.core", "Response", True, "temporaryRedirect", "", "", "Argument[0]", "url-redirect", "manual"] - addsTo: pack: codeql/java-all - extensible: extSummaryModel + extensible: summaryModel data: - ["jakarta.ws.rs.core", "AbstractMultivaluedMap", False, "AbstractMultivaluedMap", "", "", "Argument[0].MapKey", "Argument[-1].MapKey", "value", "manual"] - ["jakarta.ws.rs.core", "AbstractMultivaluedMap", False, "AbstractMultivaluedMap", "", "", "Argument[0].MapValue", "Argument[-1].MapValue", "value", "manual"] diff --git a/java/ql/lib/ext/java.beans.model.yml b/java/ql/lib/ext/java.beans.model.yml index 155d1348c35..0d24c372fb0 100644 --- a/java/ql/lib/ext/java.beans.model.yml +++ b/java/ql/lib/ext/java.beans.model.yml @@ -1,6 +1,6 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSummaryModel + extensible: summaryModel data: - ["java.beans", "XMLDecoder", False, "XMLDecoder", "", "", "Argument[0]", "Argument[-1]", "taint", "manual"] diff --git a/java/ql/lib/ext/java.io.model.yml b/java/ql/lib/ext/java.io.model.yml index 33a4e04628d..87d6c6311e7 100644 --- a/java/ql/lib/ext/java.io.model.yml +++ b/java/ql/lib/ext/java.io.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSinkModel + extensible: sinkModel data: - ["java.io", "FileOutputStream", False, "FileOutputStream", "", "", "Argument[0]", "create-file", "manual"] - ["java.io", "FileOutputStream", False, "write", "", "", "Argument[0]", "write-file", "manual"] @@ -42,7 +42,7 @@ extensions: - ["java.io", "Writer", True, "write", "", "", "Argument[0]", "write-file", "manual"] - addsTo: pack: codeql/java-all - extensible: extSummaryModel + extensible: summaryModel data: - ["java.io", "BufferedInputStream", False, "BufferedInputStream", "", "", "Argument[0]", "Argument[-1]", "taint", "manual"] - ["java.io", "BufferedReader", False, "BufferedReader", "", "", "Argument[0]", "Argument[-1]", "taint", "manual"] diff --git a/java/ql/lib/ext/java.lang.model.yml b/java/ql/lib/ext/java.lang.model.yml index 679a99b3e3d..5ec7a1bba7a 100644 --- a/java/ql/lib/ext/java.lang.model.yml +++ b/java/ql/lib/ext/java.lang.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSinkModel + extensible: sinkModel data: - ["java.lang", "String", False, "matches", "(String)", "", "Argument[0]", "regex-use[f-1]", "manual"] - ["java.lang", "String", False, "replaceAll", "(String,String)", "", "Argument[0]", "regex-use[-1]", "manual"] @@ -18,7 +18,7 @@ extensions: - ["java.lang", "System$Logger", True, "log", "(Level,String,Throwable)", "", "Argument[1]", "logging", "manual"] - addsTo: pack: codeql/java-all - extensible: extSummaryModel + extensible: summaryModel data: - ["java.lang", "AbstractStringBuilder", True, "AbstractStringBuilder", "(String)", "", "Argument[0]", "Argument[-1]", "taint", "manual"] - ["java.lang", "AbstractStringBuilder", True, "append", "", "", "Argument[-1]", "ReturnValue", "value", "manual"] diff --git a/java/ql/lib/ext/java.net.http.model.yml b/java/ql/lib/ext/java.net.http.model.yml index fa1222d2e28..d967f46494b 100644 --- a/java/ql/lib/ext/java.net.http.model.yml +++ b/java/ql/lib/ext/java.net.http.model.yml @@ -1,12 +1,12 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSourceModel + extensible: sourceModel data: - ["java.net.http", "WebSocket$Listener", True, "onText", "(WebSocket,CharSequence,boolean)", "", "Parameter[1]", "remote", "manual"] - addsTo: pack: codeql/java-all - extensible: extSinkModel + extensible: sinkModel data: - ["java.net.http", "HttpRequest", False, "newBuilder", "", "", "Argument[0]", "open-url", "manual"] - ["java.net.http", "HttpRequest$Builder", False, "uri", "", "", "Argument[0]", "open-url", "manual"] diff --git a/java/ql/lib/ext/java.net.model.yml b/java/ql/lib/ext/java.net.model.yml index 7042a3e280f..2c153b37a05 100644 --- a/java/ql/lib/ext/java.net.model.yml +++ b/java/ql/lib/ext/java.net.model.yml @@ -1,13 +1,13 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSourceModel + extensible: sourceModel data: - ["java.net", "Socket", False, "getInputStream", "()", "", "ReturnValue", "remote", "manual"] - ["java.net", "URLConnection", False, "getInputStream", "()", "", "ReturnValue", "remote", "manual"] - addsTo: pack: codeql/java-all - extensible: extSinkModel + extensible: sinkModel data: - ["java.net", "URL", False, "openConnection", "", "", "Argument[-1]", "open-url", "manual"] - ["java.net", "URL", False, "openStream", "", "", "Argument[-1]", "open-url", "manual"] @@ -19,7 +19,7 @@ extensions: - ["java.net", "URLClassLoader", False, "newInstance", "", "", "Argument[0]", "open-url", "manual"] - addsTo: pack: codeql/java-all - extensible: extSummaryModel + extensible: summaryModel data: - ["java.net", "URI", False, "URI", "(String)", "", "Argument[0]", "Argument[-1]", "taint", "manual"] - ["java.net", "URI", False, "create", "", "", "Argument[0]", "ReturnValue", "taint", "manual"] diff --git a/java/ql/lib/ext/java.nio.channels.model.yml b/java/ql/lib/ext/java.nio.channels.model.yml index 0e7081567a6..e6b3e301bdf 100644 --- a/java/ql/lib/ext/java.nio.channels.model.yml +++ b/java/ql/lib/ext/java.nio.channels.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSummaryModel + extensible: summaryModel data: - ["java.nio.channels", "Channels", False, "newChannel", "(InputStream)", "", "Argument[0]", "ReturnValue", "taint", "manual"] - ["java.nio.channels", "ReadableByteChannel", True, "read", "(ByteBuffer)", "", "Argument[-1]", "Argument[0]", "taint", "manual"] diff --git a/java/ql/lib/ext/java.nio.file.model.yml b/java/ql/lib/ext/java.nio.file.model.yml index 43c19fedbff..129bf048b96 100644 --- a/java/ql/lib/ext/java.nio.file.model.yml +++ b/java/ql/lib/ext/java.nio.file.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSinkModel + extensible: sinkModel data: - ["java.nio.file", "Files", False, "copy", "", "", "Argument[1]", "create-file", "manual"] - ["java.nio.file", "Files", False, "createDirectories", "", "", "Argument[0]", "create-file", "manual"] @@ -20,7 +20,7 @@ extensions: - ["java.nio.file", "Files", False, "writeString", "", "", "Argument[1]", "write-file", "manual"] - addsTo: pack: codeql/java-all - extensible: extSummaryModel + extensible: summaryModel data: - ["java.nio.file", "FileSystem", True, "getPath", "", "", "Argument[0]", "ReturnValue", "taint", "manual"] - ["java.nio.file", "FileSystem", True, "getRootDirectories", "", "", "Argument[0]", "ReturnValue", "taint", "manual"] diff --git a/java/ql/lib/ext/java.nio.model.yml b/java/ql/lib/ext/java.nio.model.yml index 7864355b4c5..ad03fbe2371 100644 --- a/java/ql/lib/ext/java.nio.model.yml +++ b/java/ql/lib/ext/java.nio.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSummaryModel + extensible: summaryModel data: - ["java.nio", "ByteBuffer", False, "array", "()", "", "Argument[-1]", "ReturnValue", "taint", "manual"] - ["java.nio", "ByteBuffer", False, "get", "", "", "Argument[-1]", "ReturnValue", "taint", "manual"] diff --git a/java/ql/lib/ext/java.sql.model.yml b/java/ql/lib/ext/java.sql.model.yml index 944981e2094..e7017ebd40a 100644 --- a/java/ql/lib/ext/java.sql.model.yml +++ b/java/ql/lib/ext/java.sql.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSinkModel + extensible: sinkModel data: - ["java.sql", "Connection", True, "prepareCall", "", "", "Argument[0]", "sql", "manual"] - ["java.sql", "Connection", True, "prepareStatement", "", "", "Argument[0]", "sql", "manual"] diff --git a/java/ql/lib/ext/java.util.concurrent.model.yml b/java/ql/lib/ext/java.util.concurrent.model.yml index ba34d7e8fea..9c202220dde 100644 --- a/java/ql/lib/ext/java.util.concurrent.model.yml +++ b/java/ql/lib/ext/java.util.concurrent.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSummaryModel + extensible: summaryModel data: - ["java.util.concurrent", "BlockingDeque", True, "offerFirst", "(Object,long,TimeUnit)", "", "Argument[0]", "Argument[-1].Element", "value", "manual"] - ["java.util.concurrent", "BlockingDeque", True, "offerLast", "(Object,long,TimeUnit)", "", "Argument[0]", "Argument[-1].Element", "value", "manual"] diff --git a/java/ql/lib/ext/java.util.function.model.yml b/java/ql/lib/ext/java.util.function.model.yml index b95a50d5119..9a608462a92 100644 --- a/java/ql/lib/ext/java.util.function.model.yml +++ b/java/ql/lib/ext/java.util.function.model.yml @@ -1,6 +1,6 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSinkModel + extensible: sinkModel data: - ["java.util.function", "Predicate", False, "test", "(Object)", "", "Argument[-1]", "regex-use[0]", "manual"] diff --git a/java/ql/lib/ext/java.util.logging.model.yml b/java/ql/lib/ext/java.util.logging.model.yml index 6e90734ae07..4f96b8f28ee 100644 --- a/java/ql/lib/ext/java.util.logging.model.yml +++ b/java/ql/lib/ext/java.util.logging.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSinkModel + extensible: sinkModel data: - ["java.util.logging", "Logger", True, "config", "", "", "Argument[0]", "logging", "manual"] - ["java.util.logging", "Logger", True, "entering", "(String,String)", "", "Argument[0..1]", "logging", "manual"] @@ -39,6 +39,6 @@ extensions: - ["java.util.logging", "Logger", True, "warning", "", "", "Argument[0]", "logging", "manual"] - addsTo: pack: codeql/java-all - extensible: extSummaryModel + extensible: summaryModel data: - ["java.util.logging", "LogRecord", False, "LogRecord", "", "", "Argument[1]", "Argument[-1]", "taint", "manual"] diff --git a/java/ql/lib/ext/java.util.model.yml b/java/ql/lib/ext/java.util.model.yml index 787f0d355be..38368d87bf4 100644 --- a/java/ql/lib/ext/java.util.model.yml +++ b/java/ql/lib/ext/java.util.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSummaryModel + extensible: summaryModel data: - ["java.util", "AbstractMap$SimpleEntry", False, "SimpleEntry", "(Entry)", "", "Argument[0].MapKey", "Argument[-1].MapKey", "value", "manual"] - ["java.util", "AbstractMap$SimpleEntry", False, "SimpleEntry", "(Entry)", "", "Argument[0].MapValue", "Argument[-1].MapValue", "value", "manual"] diff --git a/java/ql/lib/ext/java.util.regex.model.yml b/java/ql/lib/ext/java.util.regex.model.yml index b5c329e7a60..79f50e55e9d 100644 --- a/java/ql/lib/ext/java.util.regex.model.yml +++ b/java/ql/lib/ext/java.util.regex.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSinkModel + extensible: sinkModel data: - ["java.util.regex", "Matcher", False, "matches", "()", "", "Argument[-1]", "regex-use[f]", "manual"] - ["java.util.regex", "Pattern", False, "asMatchPredicate", "()", "", "Argument[-1]", "regex-use[f]", "manual"] @@ -14,7 +14,7 @@ extensions: - ["java.util.regex", "Pattern", False, "splitAsStream", "(CharSequence)", "", "Argument[-1]", "regex-use[0]", "manual"] - addsTo: pack: codeql/java-all - extensible: extSummaryModel + extensible: summaryModel data: - ["java.util.regex", "Matcher", False, "group", "", "", "Argument[-1]", "ReturnValue", "taint", "manual"] - ["java.util.regex", "Matcher", False, "replaceAll", "", "", "Argument[-1]", "ReturnValue", "taint", "manual"] diff --git a/java/ql/lib/ext/java.util.stream.model.yml b/java/ql/lib/ext/java.util.stream.model.yml index ae453444faf..4ce3812336e 100644 --- a/java/ql/lib/ext/java.util.stream.model.yml +++ b/java/ql/lib/ext/java.util.stream.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSummaryModel + extensible: summaryModel data: - ["java.util.stream", "BaseStream", True, "iterator", "()", "", "Argument[-1].Element", "ReturnValue.Element", "value", "manual"] - ["java.util.stream", "BaseStream", True, "onClose", "(Runnable)", "", "Argument[-1].Element", "ReturnValue.Element", "value", "manual"] diff --git a/java/ql/lib/ext/java.util.zip.model.yml b/java/ql/lib/ext/java.util.zip.model.yml index a65be51a58c..fd9c0173016 100644 --- a/java/ql/lib/ext/java.util.zip.model.yml +++ b/java/ql/lib/ext/java.util.zip.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSummaryModel + extensible: summaryModel data: - ["java.util.zip", "GZIPInputStream", False, "GZIPInputStream", "", "", "Argument[0]", "Argument[-1]", "taint", "manual"] - ["java.util.zip", "ZipInputStream", False, "ZipInputStream", "", "", "Argument[0]", "Argument[-1]", "taint", "manual"] diff --git a/java/ql/lib/ext/javax.faces.context.model.yml b/java/ql/lib/ext/javax.faces.context.model.yml index b3d9af75ef6..ad33971c2c3 100644 --- a/java/ql/lib/ext/javax.faces.context.model.yml +++ b/java/ql/lib/ext/javax.faces.context.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSourceModel + extensible: sourceModel data: - ["javax.faces.context", "ExternalContext", True, "getRequestCookieMap", "()", "", "ReturnValue", "remote", "manual"] - ["javax.faces.context", "ExternalContext", True, "getRequestHeaderMap", "()", "", "ReturnValue", "remote", "manual"] @@ -12,7 +12,7 @@ extensions: - ["javax.faces.context", "ExternalContext", True, "getRequestPathInfo", "()", "", "ReturnValue", "remote", "manual"] - addsTo: pack: codeql/java-all - extensible: extSinkModel + extensible: sinkModel data: - ["javax.faces.context", "ResponseStream", True, "write", "", "", "Argument[0]", "xss", "manual"] - ["javax.faces.context", "ResponseWriter", True, "write", "", "", "Argument[0]", "xss", "manual"] diff --git a/java/ql/lib/ext/javax.jms.model.yml b/java/ql/lib/ext/javax.jms.model.yml index 9ccf3e7a379..fed2a255ebd 100644 --- a/java/ql/lib/ext/javax.jms.model.yml +++ b/java/ql/lib/ext/javax.jms.model.yml @@ -6,7 +6,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSourceModel + extensible: sourceModel data: - ["javax.jms", "JMSConsumer", True, "receive", "", "", "ReturnValue", "remote", "manual"] - ["javax.jms", "JMSConsumer", True, "receiveBody", "", "", "ReturnValue", "remote", "manual"] @@ -19,7 +19,7 @@ extensions: - ["javax.jms", "TopicRequestor", True, "request", "(Message)", "", "ReturnValue", "remote", "manual"] - addsTo: pack: codeql/java-all - extensible: extSummaryModel + extensible: summaryModel data: - ["javax.jms", "BytesMessage", True, "readBoolean", "()", "", "Argument[-1]", "ReturnValue", "taint", "manual"] - ["javax.jms", "BytesMessage", True, "readByte", "()", "", "Argument[-1]", "ReturnValue", "taint", "manual"] diff --git a/java/ql/lib/ext/javax.json.model.yml b/java/ql/lib/ext/javax.json.model.yml index 2771ce69f6b..47deffe31b9 100644 --- a/java/ql/lib/ext/javax.json.model.yml +++ b/java/ql/lib/ext/javax.json.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSummaryModel + extensible: summaryModel data: - ["javax.json", "Json", False, "createArrayBuilder", "(Collection)", "", "Argument[0].Element", "ReturnValue", "taint", "manual"] - ["javax.json", "Json", False, "createArrayBuilder", "(JsonArray)", "", "Argument[0]", "ReturnValue", "taint", "manual"] diff --git a/java/ql/lib/ext/javax.json.stream.model.yml b/java/ql/lib/ext/javax.json.stream.model.yml index f354b3bed5b..77d564bfb69 100644 --- a/java/ql/lib/ext/javax.json.stream.model.yml +++ b/java/ql/lib/ext/javax.json.stream.model.yml @@ -1,6 +1,6 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSummaryModel + extensible: summaryModel data: - ["javax.json.stream", "JsonParserFactory", False, "createParser", "", "", "Argument[0]", "ReturnValue", "taint", "manual"] diff --git a/java/ql/lib/ext/javax.management.remote.model.yml b/java/ql/lib/ext/javax.management.remote.model.yml index da3ab68968c..3751017d4e6 100644 --- a/java/ql/lib/ext/javax.management.remote.model.yml +++ b/java/ql/lib/ext/javax.management.remote.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSinkModel + extensible: sinkModel data: - ["javax.management.remote", "JMXConnector", True, "connect", "", "", "Argument[-1]", "jndi-injection", "manual"] - ["javax.management.remote", "JMXConnectorFactory", False, "connect", "", "", "Argument[0]", "jndi-injection", "manual"] diff --git a/java/ql/lib/ext/javax.naming.directory.model.yml b/java/ql/lib/ext/javax.naming.directory.model.yml index d4ff18a773c..bb350a084cb 100644 --- a/java/ql/lib/ext/javax.naming.directory.model.yml +++ b/java/ql/lib/ext/javax.naming.directory.model.yml @@ -1,6 +1,6 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSinkModel + extensible: sinkModel data: - ["javax.naming.directory", "DirContext", True, "search", "", "", "Argument[0..1]", "ldap", "manual"] diff --git a/java/ql/lib/ext/javax.naming.model.yml b/java/ql/lib/ext/javax.naming.model.yml index 7a29b0640a6..c55f76557d6 100644 --- a/java/ql/lib/ext/javax.naming.model.yml +++ b/java/ql/lib/ext/javax.naming.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSinkModel + extensible: sinkModel data: - ["javax.naming", "Context", True, "list", "", "", "Argument[0]", "jndi-injection", "manual"] - ["javax.naming", "Context", True, "listBindings", "", "", "Argument[0]", "jndi-injection", "manual"] diff --git a/java/ql/lib/ext/javax.net.ssl.model.yml b/java/ql/lib/ext/javax.net.ssl.model.yml index f0b7b516595..7cbed92c184 100644 --- a/java/ql/lib/ext/javax.net.ssl.model.yml +++ b/java/ql/lib/ext/javax.net.ssl.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSinkModel + extensible: sinkModel data: - ["javax.net.ssl", "HttpsURLConnection", True, "setDefaultHostnameVerifier", "", "", "Argument[0]", "set-hostname-verifier", "manual"] - ["javax.net.ssl", "HttpsURLConnection", True, "setHostnameVerifier", "", "", "Argument[0]", "set-hostname-verifier", "manual"] diff --git a/java/ql/lib/ext/javax.script.model.yml b/java/ql/lib/ext/javax.script.model.yml index 675055758e1..1ca0311906a 100644 --- a/java/ql/lib/ext/javax.script.model.yml +++ b/java/ql/lib/ext/javax.script.model.yml @@ -1,6 +1,6 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSinkModel + extensible: sinkModel data: - ["javax.script", "CompiledScript", False, "eval", "", "", "Argument[-1]", "mvel", "manual"] diff --git a/java/ql/lib/ext/javax.servlet.http.model.yml b/java/ql/lib/ext/javax.servlet.http.model.yml index 469424e4021..9833d356835 100644 --- a/java/ql/lib/ext/javax.servlet.http.model.yml +++ b/java/ql/lib/ext/javax.servlet.http.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSourceModel + extensible: sourceModel data: - ["javax.servlet.http", "Cookie", False, "getComment", "()", "", "ReturnValue", "remote", "manual"] - ["javax.servlet.http", "Cookie", False, "getName", "()", "", "ReturnValue", "remote", "manual"] @@ -20,7 +20,7 @@ extensions: - ["javax.servlet.http", "HttpServletRequest", False, "getRequestURL", "()", "", "ReturnValue", "remote", "manual"] - addsTo: pack: codeql/java-all - extensible: extSinkModel + extensible: sinkModel data: - ["javax.servlet.http", "HttpServletResponse", False, "addCookie", "", "", "Argument[0]", "header-splitting", "manual"] - ["javax.servlet.http", "HttpServletResponse", False, "addHeader", "", "", "Argument[0..1]", "header-splitting", "manual"] @@ -28,7 +28,7 @@ extensions: - ["javax.servlet.http", "HttpServletResponse", False, "setHeader", "", "", "Argument[0..1]", "header-splitting", "manual"] - addsTo: pack: codeql/java-all - extensible: extSummaryModel + extensible: summaryModel data: - ["javax.servlet.http", "Cookie", False, "Cookie", "", "", "Argument[0]", "Argument[-1]", "taint", "manual"] - ["javax.servlet.http", "Cookie", False, "Cookie", "", "", "Argument[1]", "Argument[-1]", "taint", "manual"] diff --git a/java/ql/lib/ext/javax.servlet.model.yml b/java/ql/lib/ext/javax.servlet.model.yml index accfa736f82..ba850941729 100644 --- a/java/ql/lib/ext/javax.servlet.model.yml +++ b/java/ql/lib/ext/javax.servlet.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSourceModel + extensible: sourceModel data: - ["javax.servlet", "ServletRequest", False, "getInputStream", "()", "", "ReturnValue", "remote", "manual"] - ["javax.servlet", "ServletRequest", False, "getParameter", "(String)", "", "ReturnValue", "remote", "manual"] diff --git a/java/ql/lib/ext/javax.validation.model.yml b/java/ql/lib/ext/javax.validation.model.yml index 464b95dfb11..2f1f3d9a75c 100644 --- a/java/ql/lib/ext/javax.validation.model.yml +++ b/java/ql/lib/ext/javax.validation.model.yml @@ -1,11 +1,11 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSourceModel + extensible: sourceModel data: - ["javax.validation", "ConstraintValidator", True, "isValid", "", "", "Parameter[0]", "remote", "manual"] - addsTo: pack: codeql/java-all - extensible: extSinkModel + extensible: sinkModel data: - ["javax.validation", "ConstraintValidatorContext", True, "buildConstraintViolationWithTemplate", "", "", "Argument[0]", "bean-validation", "manual"] diff --git a/java/ql/lib/ext/javax.ws.rs.client.model.yml b/java/ql/lib/ext/javax.ws.rs.client.model.yml index b2fb8b75ad0..0a5a01c3338 100644 --- a/java/ql/lib/ext/javax.ws.rs.client.model.yml +++ b/java/ql/lib/ext/javax.ws.rs.client.model.yml @@ -1,6 +1,6 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSinkModel + extensible: sinkModel data: - ["javax.ws.rs.client", "Client", True, "target", "", "", "Argument[0]", "open-url", "manual"] diff --git a/java/ql/lib/ext/javax.ws.rs.container.model.yml b/java/ql/lib/ext/javax.ws.rs.container.model.yml index 1277c14a663..a76f848a597 100644 --- a/java/ql/lib/ext/javax.ws.rs.container.model.yml +++ b/java/ql/lib/ext/javax.ws.rs.container.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSourceModel + extensible: sourceModel data: - ["javax.ws.rs.container", "ContainerRequestContext", True, "getAcceptableLanguages", "", "", "ReturnValue", "remote", "manual"] - ["javax.ws.rs.container", "ContainerRequestContext", True, "getAcceptableMediaTypes", "", "", "ReturnValue", "remote", "manual"] diff --git a/java/ql/lib/ext/javax.ws.rs.core.model.yml b/java/ql/lib/ext/javax.ws.rs.core.model.yml index 3c1611970f9..c7fb603d3c4 100644 --- a/java/ql/lib/ext/javax.ws.rs.core.model.yml +++ b/java/ql/lib/ext/javax.ws.rs.core.model.yml @@ -1,14 +1,14 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSinkModel + extensible: sinkModel data: - ["javax.ws.rs.core", "Response", True, "seeOther", "", "", "Argument[0]", "url-redirect", "manual"] - ["javax.ws.rs.core", "Response", True, "temporaryRedirect", "", "", "Argument[0]", "url-redirect", "manual"] - ["javax.ws.rs.core", "ResponseBuilder", False, "header", "", "", "Argument[1]", "header-splitting", "manual"] - addsTo: pack: codeql/java-all - extensible: extSummaryModel + extensible: summaryModel data: - ["javax.ws.rs.core", "AbstractMultivaluedMap", False, "AbstractMultivaluedMap", "", "", "Argument[0].MapKey", "Argument[-1].MapKey", "value", "manual"] - ["javax.ws.rs.core", "AbstractMultivaluedMap", False, "AbstractMultivaluedMap", "", "", "Argument[0].MapValue", "Argument[-1].MapValue", "value", "manual"] diff --git a/java/ql/lib/ext/javax.xml.transform.model.yml b/java/ql/lib/ext/javax.xml.transform.model.yml index 2032ecac6d6..d9123a46fc7 100644 --- a/java/ql/lib/ext/javax.xml.transform.model.yml +++ b/java/ql/lib/ext/javax.xml.transform.model.yml @@ -1,6 +1,6 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSinkModel + extensible: sinkModel data: - ["javax.xml.transform", "Transformer", False, "transform", "", "", "Argument[-1]", "xslt", "manual"] diff --git a/java/ql/lib/ext/javax.xml.transform.sax.model.yml b/java/ql/lib/ext/javax.xml.transform.sax.model.yml index 33765c1678f..90d583b5116 100644 --- a/java/ql/lib/ext/javax.xml.transform.sax.model.yml +++ b/java/ql/lib/ext/javax.xml.transform.sax.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSummaryModel + extensible: summaryModel data: - ["javax.xml.transform.sax", "SAXSource", False, "SAXSource", "(InputSource)", "", "Argument[0]", "Argument[-1]", "taint", "manual"] - ["javax.xml.transform.sax", "SAXSource", False, "SAXSource", "(XMLReader,InputSource)", "", "Argument[1]", "Argument[-1]", "taint", "manual"] diff --git a/java/ql/lib/ext/javax.xml.transform.stream.model.yml b/java/ql/lib/ext/javax.xml.transform.stream.model.yml index 858fbb0ab5a..5098f9badfc 100644 --- a/java/ql/lib/ext/javax.xml.transform.stream.model.yml +++ b/java/ql/lib/ext/javax.xml.transform.stream.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSummaryModel + extensible: summaryModel data: - ["javax.xml.transform.stream", "StreamSource", False, "StreamSource", "", "", "Argument[0]", "Argument[-1]", "taint", "manual"] - ["javax.xml.transform.stream", "StreamSource", False, "getInputStream", "", "", "Argument[-1]", "ReturnValue", "taint", "manual"] diff --git a/java/ql/lib/ext/javax.xml.xpath.model.yml b/java/ql/lib/ext/javax.xml.xpath.model.yml index 24be66eb8e9..68f51a34a2e 100644 --- a/java/ql/lib/ext/javax.xml.xpath.model.yml +++ b/java/ql/lib/ext/javax.xml.xpath.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSinkModel + extensible: sinkModel data: - ["javax.xml.xpath", "XPath", True, "compile", "", "", "Argument[0]", "xpath", "manual"] - ["javax.xml.xpath", "XPath", True, "evaluate", "", "", "Argument[0]", "xpath", "manual"] diff --git a/java/ql/lib/ext/jodd.json.model.yml b/java/ql/lib/ext/jodd.json.model.yml index 6187110797d..cf8005bf909 100644 --- a/java/ql/lib/ext/jodd.json.model.yml +++ b/java/ql/lib/ext/jodd.json.model.yml @@ -7,7 +7,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSummaryModel + extensible: summaryModel data: - ["jodd.json", "JsonParser", False, "allowAllClasses", "", "", "Argument[-1]", "ReturnValue", "value", "manual"] - ["jodd.json", "JsonParser", False, "allowClass", "", "", "Argument[-1]", "ReturnValue", "value", "manual"] diff --git a/java/ql/lib/ext/kotlin.collections.model.yml b/java/ql/lib/ext/kotlin.collections.model.yml index 8336bff3b0a..b854230b9c3 100644 --- a/java/ql/lib/ext/kotlin.collections.model.yml +++ b/java/ql/lib/ext/kotlin.collections.model.yml @@ -1,6 +1,6 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSummaryModel + extensible: summaryModel data: - ["kotlin.collections", "ArraysKt", False, "withIndex", "(Object[])", "", "Argument[0].ArrayElement", "ReturnValue", "taint", "manual"] diff --git a/java/ql/lib/ext/kotlin.jvm.internal.model.yml b/java/ql/lib/ext/kotlin.jvm.internal.model.yml index 40a6b605a53..413642bbeee 100644 --- a/java/ql/lib/ext/kotlin.jvm.internal.model.yml +++ b/java/ql/lib/ext/kotlin.jvm.internal.model.yml @@ -1,6 +1,6 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSummaryModel + extensible: summaryModel data: - ["kotlin.jvm.internal", "ArrayIteratorKt", False, "iterator", "(Object[])", "", "Argument[0].ArrayElement", "ReturnValue.Element", "value", "manual"] diff --git a/java/ql/lib/ext/net.sf.saxon.s9api.model.yml b/java/ql/lib/ext/net.sf.saxon.s9api.model.yml index 7b64bdade8c..cbe916fd018 100644 --- a/java/ql/lib/ext/net.sf.saxon.s9api.model.yml +++ b/java/ql/lib/ext/net.sf.saxon.s9api.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSinkModel + extensible: sinkModel data: - ["net.sf.saxon.s9api", "Xslt30Transformer", False, "applyTemplates", "", "", "Argument[-1]", "xslt", "manual"] - ["net.sf.saxon.s9api", "Xslt30Transformer", False, "callFunction", "", "", "Argument[-1]", "xslt", "manual"] diff --git a/java/ql/lib/ext/ognl.enhance.model.yml b/java/ql/lib/ext/ognl.enhance.model.yml index c3f49d72897..6e3a27f34ae 100644 --- a/java/ql/lib/ext/ognl.enhance.model.yml +++ b/java/ql/lib/ext/ognl.enhance.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSinkModel + extensible: sinkModel data: - ["ognl.enhance", "ExpressionAccessor", True, "get", "", "", "Argument[-1]", "ognl-injection", "manual"] - ["ognl.enhance", "ExpressionAccessor", True, "set", "", "", "Argument[-1]", "ognl-injection", "manual"] diff --git a/java/ql/lib/ext/ognl.model.yml b/java/ql/lib/ext/ognl.model.yml index 133fc36b410..23de976ef98 100644 --- a/java/ql/lib/ext/ognl.model.yml +++ b/java/ql/lib/ext/ognl.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSinkModel + extensible: sinkModel data: - ["ognl", "Node", False, "getValue", "", "", "Argument[-1]", "ognl-injection", "manual"] - ["ognl", "Node", False, "setValue", "", "", "Argument[-1]", "ognl-injection", "manual"] diff --git a/java/ql/lib/ext/okhttp3.model.yml b/java/ql/lib/ext/okhttp3.model.yml index 1c9032c9211..7e8459daedc 100644 --- a/java/ql/lib/ext/okhttp3.model.yml +++ b/java/ql/lib/ext/okhttp3.model.yml @@ -1,13 +1,13 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSinkModel + extensible: sinkModel data: - ["okhttp3", "Request", True, "Request", "", "", "Argument[0]", "open-url", "manual"] - ["okhttp3", "Request$Builder", True, "url", "", "", "Argument[0]", "open-url", "manual"] - addsTo: pack: codeql/java-all - extensible: extSummaryModel + extensible: summaryModel data: - ["okhttp3", "HttpUrl", False, "parse", "", "", "Argument[0]", "ReturnValue", "taint", "manual"] - ["okhttp3", "HttpUrl", False, "uri", "", "", "Argument[-1]", "ReturnValue", "taint", "manual"] diff --git a/java/ql/lib/ext/org.apache.commons.codec.model.yml b/java/ql/lib/ext/org.apache.commons.codec.model.yml index 963aa6ce843..78d41e6e273 100644 --- a/java/ql/lib/ext/org.apache.commons.codec.model.yml +++ b/java/ql/lib/ext/org.apache.commons.codec.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSummaryModel + extensible: summaryModel data: - ["org.apache.commons.codec", "BinaryDecoder", True, "decode", "(byte[])", "", "Argument[0]", "ReturnValue", "taint", "manual"] - ["org.apache.commons.codec", "BinaryEncoder", True, "encode", "(byte[])", "", "Argument[0]", "ReturnValue", "taint", "manual"] diff --git a/java/ql/lib/ext/org.apache.commons.collections.bag.model.yml b/java/ql/lib/ext/org.apache.commons.collections.bag.model.yml index 55ab021d9ff..64994a3567c 100644 --- a/java/ql/lib/ext/org.apache.commons.collections.bag.model.yml +++ b/java/ql/lib/ext/org.apache.commons.collections.bag.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSummaryModel + extensible: summaryModel data: # Note that when lambdas are supported we should have more models for TransformedBag, TransformedSortedBag - ["org.apache.commons.collections.bag", "AbstractBagDecorator", True, "AbstractBagDecorator", "", "", "Argument[0].Element", "Argument[-1].Element", "value", "manual"] diff --git a/java/ql/lib/ext/org.apache.commons.collections.bidimap.model.yml b/java/ql/lib/ext/org.apache.commons.collections.bidimap.model.yml index c47f56654b9..067219984bf 100644 --- a/java/ql/lib/ext/org.apache.commons.collections.bidimap.model.yml +++ b/java/ql/lib/ext/org.apache.commons.collections.bidimap.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSummaryModel + extensible: summaryModel data: - ["org.apache.commons.collections.bidimap", "AbstractBidiMapDecorator", True, "AbstractBidiMapDecorator", "", "", "Argument[0].MapKey", "Argument[-1].MapKey", "value", "manual"] - ["org.apache.commons.collections.bidimap", "AbstractBidiMapDecorator", True, "AbstractBidiMapDecorator", "", "", "Argument[0].MapValue", "Argument[-1].MapValue", "value", "manual"] diff --git a/java/ql/lib/ext/org.apache.commons.collections.collection.model.yml b/java/ql/lib/ext/org.apache.commons.collections.collection.model.yml index a2cdd0a2d80..ce1caf3d473 100644 --- a/java/ql/lib/ext/org.apache.commons.collections.collection.model.yml +++ b/java/ql/lib/ext/org.apache.commons.collections.collection.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSummaryModel + extensible: summaryModel data: # Note that when lambdas are supported we should have more models for TransformedCollection - ["org.apache.commons.collections.collection", "AbstractCollectionDecorator", True, "AbstractCollectionDecorator", "", "", "Argument[0].Element", "Argument[-1].Element", "value", "manual"] diff --git a/java/ql/lib/ext/org.apache.commons.collections.iterators.model.yml b/java/ql/lib/ext/org.apache.commons.collections.iterators.model.yml index d65fc0e6f93..73509f98b1a 100644 --- a/java/ql/lib/ext/org.apache.commons.collections.iterators.model.yml +++ b/java/ql/lib/ext/org.apache.commons.collections.iterators.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSummaryModel + extensible: summaryModel data: # Note that when lambdas are supported we should have more models for TransformIterator - ["org.apache.commons.collections.iterators", "AbstractIteratorDecorator", True, "AbstractIteratorDecorator", "", "", "Argument[0].Element", "Argument[-1].Element", "value", "manual"] diff --git a/java/ql/lib/ext/org.apache.commons.collections.keyvalue.model.yml b/java/ql/lib/ext/org.apache.commons.collections.keyvalue.model.yml index 9c7e0fd4bca..d2c3e5652b5 100644 --- a/java/ql/lib/ext/org.apache.commons.collections.keyvalue.model.yml +++ b/java/ql/lib/ext/org.apache.commons.collections.keyvalue.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSummaryModel + extensible: summaryModel data: # Note that when lambdas are supported we should model the package `org.apache.commons.collections4.functors`, # and when more general callable flow is supported we should model the package diff --git a/java/ql/lib/ext/org.apache.commons.collections.list.model.yml b/java/ql/lib/ext/org.apache.commons.collections.list.model.yml index 53ad3035659..5fd3b418248 100644 --- a/java/ql/lib/ext/org.apache.commons.collections.list.model.yml +++ b/java/ql/lib/ext/org.apache.commons.collections.list.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSummaryModel + extensible: summaryModel data: # Note that when lambdas are supported we should have more models for TransformedList - ["org.apache.commons.collections.list", "AbstractLinkedList", True, "AbstractLinkedList", "", "", "Argument[0].Element", "Argument[-1].Element", "value", "manual"] diff --git a/java/ql/lib/ext/org.apache.commons.collections.map.model.yml b/java/ql/lib/ext/org.apache.commons.collections.map.model.yml index a6280315075..4e0ed31d72f 100644 --- a/java/ql/lib/ext/org.apache.commons.collections.map.model.yml +++ b/java/ql/lib/ext/org.apache.commons.collections.map.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSummaryModel + extensible: summaryModel data: # Note that when lambdas are supported we should have more models for DefaultedMap, LazyMap, TransformedMap, TransformedSortedMap - ["org.apache.commons.collections.map", "AbstractHashedMap", True, "AbstractHashedMap", "(Map)", "", "Argument[0].MapKey", "Argument[-1].MapKey", "value", "manual"] diff --git a/java/ql/lib/ext/org.apache.commons.collections.model.yml b/java/ql/lib/ext/org.apache.commons.collections.model.yml index 5846d092b5c..2df5f5772a4 100644 --- a/java/ql/lib/ext/org.apache.commons.collections.model.yml +++ b/java/ql/lib/ext/org.apache.commons.collections.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSummaryModel + extensible: summaryModel data: # Note that when lambdas are supported we should model things relating to Closure, Factory, Transformer, FluentIterable.forEach, FluentIterable.transform # Note that when lambdas are supported we should model the package `org.apache.commons.collections4.functors`, diff --git a/java/ql/lib/ext/org.apache.commons.collections.multimap.model.yml b/java/ql/lib/ext/org.apache.commons.collections.multimap.model.yml index d1d0b5a885c..97ad092bc08 100644 --- a/java/ql/lib/ext/org.apache.commons.collections.multimap.model.yml +++ b/java/ql/lib/ext/org.apache.commons.collections.multimap.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSummaryModel + extensible: summaryModel data: # Note that when lambdas are supported we should have more models for TransformedMultiValuedMap - ["org.apache.commons.collections.multimap", "ArrayListValuedHashMap", True, "ArrayListValuedHashMap", "(Map)", "", "Argument[0].MapKey", "Argument[-1].MapKey", "value", "manual"] diff --git a/java/ql/lib/ext/org.apache.commons.collections.multiset.model.yml b/java/ql/lib/ext/org.apache.commons.collections.multiset.model.yml index af9e42fb88a..4423d4b1f91 100644 --- a/java/ql/lib/ext/org.apache.commons.collections.multiset.model.yml +++ b/java/ql/lib/ext/org.apache.commons.collections.multiset.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSummaryModel + extensible: summaryModel data: - ["org.apache.commons.collections.multiset", "HashMultiSet", True, "HashMultiSet", "", "", "Argument[0].Element", "Argument[-1].Element", "value", "manual"] - ["org.apache.commons.collections.multiset", "PredicatedMultiSet", True, "predicatedMultiSet", "", "", "Argument[0].Element", "ReturnValue.Element", "value", "manual"] diff --git a/java/ql/lib/ext/org.apache.commons.collections.properties.model.yml b/java/ql/lib/ext/org.apache.commons.collections.properties.model.yml index 0552bb105bb..f149889197e 100644 --- a/java/ql/lib/ext/org.apache.commons.collections.properties.model.yml +++ b/java/ql/lib/ext/org.apache.commons.collections.properties.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSummaryModel + extensible: summaryModel data: - ["org.apache.commons.collections.properties", "AbstractPropertiesFactory", True, "load", "(ClassLoader,String)", "", "Argument[1]", "ReturnValue", "taint", "manual"] - ["org.apache.commons.collections.properties", "AbstractPropertiesFactory", True, "load", "(File)", "", "Argument[0]", "ReturnValue", "taint", "manual"] diff --git a/java/ql/lib/ext/org.apache.commons.collections.queue.model.yml b/java/ql/lib/ext/org.apache.commons.collections.queue.model.yml index 5a9db9599d4..3a88fbf5fa4 100644 --- a/java/ql/lib/ext/org.apache.commons.collections.queue.model.yml +++ b/java/ql/lib/ext/org.apache.commons.collections.queue.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSummaryModel + extensible: summaryModel data: # Note that when lambdas are supported we should have more models for TransformedQueue - ["org.apache.commons.collections.queue", "CircularFifoQueue", True, "CircularFifoQueue", "(Collection)", "", "Argument[0].Element", "Argument[-1].Element", "value", "manual"] diff --git a/java/ql/lib/ext/org.apache.commons.collections.set.model.yml b/java/ql/lib/ext/org.apache.commons.collections.set.model.yml index 019f862568d..c6288adf72c 100644 --- a/java/ql/lib/ext/org.apache.commons.collections.set.model.yml +++ b/java/ql/lib/ext/org.apache.commons.collections.set.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSummaryModel + extensible: summaryModel data: # Note that when lambdas are supported we should have more models for TransformedNavigableSet - ["org.apache.commons.collections.set", "AbstractNavigableSetDecorator", True, "AbstractNavigableSetDecorator", "", "", "Argument[0].Element", "Argument[-1].Element", "value", "manual"] diff --git a/java/ql/lib/ext/org.apache.commons.collections.splitmap.model.yml b/java/ql/lib/ext/org.apache.commons.collections.splitmap.model.yml index 447b3533fbc..65cc1a66fdf 100644 --- a/java/ql/lib/ext/org.apache.commons.collections.splitmap.model.yml +++ b/java/ql/lib/ext/org.apache.commons.collections.splitmap.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSummaryModel + extensible: summaryModel data: # Note that when lambdas are supported we should have more models for TransformedSplitMap - ["org.apache.commons.collections.splitmap", "AbstractIterableGetMapDecorator", True, "AbstractIterableGetMapDecorator", "", "", "Argument[0].MapKey", "Argument[-1].MapKey", "value", "manual"] diff --git a/java/ql/lib/ext/org.apache.commons.collections.trie.model.yml b/java/ql/lib/ext/org.apache.commons.collections.trie.model.yml index 451e0b60bc7..c58ca641902 100644 --- a/java/ql/lib/ext/org.apache.commons.collections.trie.model.yml +++ b/java/ql/lib/ext/org.apache.commons.collections.trie.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSummaryModel + extensible: summaryModel data: # Note that when lambdas are supported we should have more models for TransformedSplitMap - ["org.apache.commons.collections.trie", "AbstractPatriciaTrie", True, "select", "", "", "Argument[-1].MapKey", "ReturnValue.MapKey", "value", "manual"] diff --git a/java/ql/lib/ext/org.apache.commons.collections4.bag.model.yml b/java/ql/lib/ext/org.apache.commons.collections4.bag.model.yml index ddc26f49b7f..9df2c7aba94 100644 --- a/java/ql/lib/ext/org.apache.commons.collections4.bag.model.yml +++ b/java/ql/lib/ext/org.apache.commons.collections4.bag.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSummaryModel + extensible: summaryModel data: # Note that when lambdas are supported we should have more models for TransformedBag, TransformedSortedBag - ["org.apache.commons.collections4.bag", "AbstractBagDecorator", True, "AbstractBagDecorator", "", "", "Argument[0].Element", "Argument[-1].Element", "value", "manual"] diff --git a/java/ql/lib/ext/org.apache.commons.collections4.bidimap.model.yml b/java/ql/lib/ext/org.apache.commons.collections4.bidimap.model.yml index 3be0532ec4d..1a6a3cbab9e 100644 --- a/java/ql/lib/ext/org.apache.commons.collections4.bidimap.model.yml +++ b/java/ql/lib/ext/org.apache.commons.collections4.bidimap.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSummaryModel + extensible: summaryModel data: - ["org.apache.commons.collections4.bidimap", "AbstractBidiMapDecorator", True, "AbstractBidiMapDecorator", "", "", "Argument[0].MapKey", "Argument[-1].MapKey", "value", "manual"] - ["org.apache.commons.collections4.bidimap", "AbstractBidiMapDecorator", True, "AbstractBidiMapDecorator", "", "", "Argument[0].MapValue", "Argument[-1].MapValue", "value", "manual"] diff --git a/java/ql/lib/ext/org.apache.commons.collections4.collection.model.yml b/java/ql/lib/ext/org.apache.commons.collections4.collection.model.yml index f3ac93c242d..7533350620b 100644 --- a/java/ql/lib/ext/org.apache.commons.collections4.collection.model.yml +++ b/java/ql/lib/ext/org.apache.commons.collections4.collection.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSummaryModel + extensible: summaryModel data: # Note that when lambdas are supported we should have more models for TransformedCollection - ["org.apache.commons.collections4.collection", "AbstractCollectionDecorator", True, "AbstractCollectionDecorator", "", "", "Argument[0].Element", "Argument[-1].Element", "value", "manual"] diff --git a/java/ql/lib/ext/org.apache.commons.collections4.iterators.model.yml b/java/ql/lib/ext/org.apache.commons.collections4.iterators.model.yml index f6671a823c4..8fe0e4578f9 100644 --- a/java/ql/lib/ext/org.apache.commons.collections4.iterators.model.yml +++ b/java/ql/lib/ext/org.apache.commons.collections4.iterators.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSummaryModel + extensible: summaryModel data: # Note that when lambdas are supported we should have more models for TransformIterator - ["org.apache.commons.collections4.iterators", "AbstractIteratorDecorator", True, "AbstractIteratorDecorator", "", "", "Argument[0].Element", "Argument[-1].Element", "value", "manual"] diff --git a/java/ql/lib/ext/org.apache.commons.collections4.keyvalue.model.yml b/java/ql/lib/ext/org.apache.commons.collections4.keyvalue.model.yml index aa4a663115e..e662c6348bd 100644 --- a/java/ql/lib/ext/org.apache.commons.collections4.keyvalue.model.yml +++ b/java/ql/lib/ext/org.apache.commons.collections4.keyvalue.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSummaryModel + extensible: summaryModel data: # Note that when lambdas are supported we should model the package `org.apache.commons.collections4.functors`, # and when more general callable flow is supported we should model the package diff --git a/java/ql/lib/ext/org.apache.commons.collections4.list.model.yml b/java/ql/lib/ext/org.apache.commons.collections4.list.model.yml index 7d82ffdcfa5..b0e01ed6929 100644 --- a/java/ql/lib/ext/org.apache.commons.collections4.list.model.yml +++ b/java/ql/lib/ext/org.apache.commons.collections4.list.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSummaryModel + extensible: summaryModel data: # Note that when lambdas are supported we should have more models for TransformedList - ["org.apache.commons.collections4.list", "AbstractLinkedList", True, "AbstractLinkedList", "", "", "Argument[0].Element", "Argument[-1].Element", "value", "manual"] diff --git a/java/ql/lib/ext/org.apache.commons.collections4.map.model.yml b/java/ql/lib/ext/org.apache.commons.collections4.map.model.yml index 52d1221ed1d..385f73050d5 100644 --- a/java/ql/lib/ext/org.apache.commons.collections4.map.model.yml +++ b/java/ql/lib/ext/org.apache.commons.collections4.map.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSummaryModel + extensible: summaryModel data: # Note that when lambdas are supported we should have more models for DefaultedMap, LazyMap, TransformedMap, TransformedSortedMap - ["org.apache.commons.collections4.map", "AbstractHashedMap", True, "AbstractHashedMap", "(Map)", "", "Argument[0].MapKey", "Argument[-1].MapKey", "value", "manual"] diff --git a/java/ql/lib/ext/org.apache.commons.collections4.model.yml b/java/ql/lib/ext/org.apache.commons.collections4.model.yml index ce5fc6b9fe9..218da08ca22 100644 --- a/java/ql/lib/ext/org.apache.commons.collections4.model.yml +++ b/java/ql/lib/ext/org.apache.commons.collections4.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSummaryModel + extensible: summaryModel data: # Note that when lambdas are supported we should model things relating to Closure, Factory, Transformer, FluentIterable.forEach, FluentIterable.transform # Note that when lambdas are supported we should model the package `org.apache.commons.collections4.functors`, diff --git a/java/ql/lib/ext/org.apache.commons.collections4.multimap.model.yml b/java/ql/lib/ext/org.apache.commons.collections4.multimap.model.yml index 3812b6766fd..6bd01379d9e 100644 --- a/java/ql/lib/ext/org.apache.commons.collections4.multimap.model.yml +++ b/java/ql/lib/ext/org.apache.commons.collections4.multimap.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSummaryModel + extensible: summaryModel data: # Note that when lambdas are supported we should have more models for TransformedMultiValuedMap - ["org.apache.commons.collections4.multimap", "ArrayListValuedHashMap", True, "ArrayListValuedHashMap", "(Map)", "", "Argument[0].MapKey", "Argument[-1].MapKey", "value", "manual"] diff --git a/java/ql/lib/ext/org.apache.commons.collections4.multiset.model.yml b/java/ql/lib/ext/org.apache.commons.collections4.multiset.model.yml index b73862089c0..c3da82c1b7a 100644 --- a/java/ql/lib/ext/org.apache.commons.collections4.multiset.model.yml +++ b/java/ql/lib/ext/org.apache.commons.collections4.multiset.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSummaryModel + extensible: summaryModel data: - ["org.apache.commons.collections4.multiset", "HashMultiSet", True, "HashMultiSet", "", "", "Argument[0].Element", "Argument[-1].Element", "value", "manual"] - ["org.apache.commons.collections4.multiset", "PredicatedMultiSet", True, "predicatedMultiSet", "", "", "Argument[0].Element", "ReturnValue.Element", "value", "manual"] diff --git a/java/ql/lib/ext/org.apache.commons.collections4.properties.model.yml b/java/ql/lib/ext/org.apache.commons.collections4.properties.model.yml index 548b50959e1..9187922313a 100644 --- a/java/ql/lib/ext/org.apache.commons.collections4.properties.model.yml +++ b/java/ql/lib/ext/org.apache.commons.collections4.properties.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSummaryModel + extensible: summaryModel data: - ["org.apache.commons.collections4.properties", "AbstractPropertiesFactory", True, "load", "(ClassLoader,String)", "", "Argument[1]", "ReturnValue", "taint", "manual"] - ["org.apache.commons.collections4.properties", "AbstractPropertiesFactory", True, "load", "(File)", "", "Argument[0]", "ReturnValue", "taint", "manual"] diff --git a/java/ql/lib/ext/org.apache.commons.collections4.queue.model.yml b/java/ql/lib/ext/org.apache.commons.collections4.queue.model.yml index f9067b758e9..b2cab2a0594 100644 --- a/java/ql/lib/ext/org.apache.commons.collections4.queue.model.yml +++ b/java/ql/lib/ext/org.apache.commons.collections4.queue.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSummaryModel + extensible: summaryModel data: # Note that when lambdas are supported we should have more models for TransformedQueue - ["org.apache.commons.collections4.queue", "CircularFifoQueue", True, "CircularFifoQueue", "(Collection)", "", "Argument[0].Element", "Argument[-1].Element", "value", "manual"] diff --git a/java/ql/lib/ext/org.apache.commons.collections4.set.model.yml b/java/ql/lib/ext/org.apache.commons.collections4.set.model.yml index 63ac0c91141..deafbdffaaf 100644 --- a/java/ql/lib/ext/org.apache.commons.collections4.set.model.yml +++ b/java/ql/lib/ext/org.apache.commons.collections4.set.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSummaryModel + extensible: summaryModel data: # Note that when lambdas are supported we should have more models for TransformedNavigableSet - ["org.apache.commons.collections4.set", "AbstractNavigableSetDecorator", True, "AbstractNavigableSetDecorator", "", "", "Argument[0].Element", "Argument[-1].Element", "value", "manual"] diff --git a/java/ql/lib/ext/org.apache.commons.collections4.splitmap.model.yml b/java/ql/lib/ext/org.apache.commons.collections4.splitmap.model.yml index 5a1de63ba6a..7190dac37a0 100644 --- a/java/ql/lib/ext/org.apache.commons.collections4.splitmap.model.yml +++ b/java/ql/lib/ext/org.apache.commons.collections4.splitmap.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSummaryModel + extensible: summaryModel data: # Note that when lambdas are supported we should have more models for TransformedSplitMap - ["org.apache.commons.collections4.splitmap", "AbstractIterableGetMapDecorator", True, "AbstractIterableGetMapDecorator", "", "", "Argument[0].MapKey", "Argument[-1].MapKey", "value", "manual"] diff --git a/java/ql/lib/ext/org.apache.commons.collections4.trie.model.yml b/java/ql/lib/ext/org.apache.commons.collections4.trie.model.yml index 1f33d441e18..7c7195d54dc 100644 --- a/java/ql/lib/ext/org.apache.commons.collections4.trie.model.yml +++ b/java/ql/lib/ext/org.apache.commons.collections4.trie.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSummaryModel + extensible: summaryModel data: # Note that when lambdas are supported we should have more models for TransformedSplitMap - ["org.apache.commons.collections4.trie", "AbstractPatriciaTrie", True, "select", "", "", "Argument[-1].MapKey", "ReturnValue.MapKey", "value", "manual"] diff --git a/java/ql/lib/ext/org.apache.commons.io.model.yml b/java/ql/lib/ext/org.apache.commons.io.model.yml index 6cb7aa0b251..d00be2099de 100644 --- a/java/ql/lib/ext/org.apache.commons.io.model.yml +++ b/java/ql/lib/ext/org.apache.commons.io.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSummaryModel + extensible: summaryModel data: # Models that are not yet auto generated or where the generated summaries will # be ignored. diff --git a/java/ql/lib/ext/org.apache.commons.jexl2.model.yml b/java/ql/lib/ext/org.apache.commons.jexl2.model.yml index 7d6e5d070d2..2389ae1d183 100644 --- a/java/ql/lib/ext/org.apache.commons.jexl2.model.yml +++ b/java/ql/lib/ext/org.apache.commons.jexl2.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSinkModel + extensible: sinkModel data: - ["org.apache.commons.jexl2", "Expression", False, "callable", "", "", "Argument[-1]", "jexl", "manual"] - ["org.apache.commons.jexl2", "Expression", False, "evaluate", "", "", "Argument[-1]", "jexl", "manual"] diff --git a/java/ql/lib/ext/org.apache.commons.jexl3.model.yml b/java/ql/lib/ext/org.apache.commons.jexl3.model.yml index a911fe7f22c..206eb79420a 100644 --- a/java/ql/lib/ext/org.apache.commons.jexl3.model.yml +++ b/java/ql/lib/ext/org.apache.commons.jexl3.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSinkModel + extensible: sinkModel data: - ["org.apache.commons.jexl3", "Expression", False, "callable", "", "", "Argument[-1]", "jexl", "manual"] - ["org.apache.commons.jexl3", "Expression", False, "evaluate", "", "", "Argument[-1]", "jexl", "manual"] diff --git a/java/ql/lib/ext/org.apache.commons.lang3.builder.model.yml b/java/ql/lib/ext/org.apache.commons.lang3.builder.model.yml index cf4967b0cb5..88d2bbe4790 100644 --- a/java/ql/lib/ext/org.apache.commons.lang3.builder.model.yml +++ b/java/ql/lib/ext/org.apache.commons.lang3.builder.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSummaryModel + extensible: summaryModel data: - ["org.apache.commons.lang3.builder", "ToStringBuilder", False, "append", "", "", "Argument[-1]", "ReturnValue", "value", "manual"] - ["org.apache.commons.lang3.builder", "ToStringBuilder", False, "append", "(java.lang.Object)", "", "Argument[0]", "Argument[-1]", "taint", "manual"] diff --git a/java/ql/lib/ext/org.apache.commons.lang3.model.yml b/java/ql/lib/ext/org.apache.commons.lang3.model.yml index 3fda3a551af..ad2332fe007 100644 --- a/java/ql/lib/ext/org.apache.commons.lang3.model.yml +++ b/java/ql/lib/ext/org.apache.commons.lang3.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSinkModel + extensible: sinkModel data: - ["org.apache.commons.lang3", "RegExUtils", False, "removeAll", "(String,String)", "", "Argument[1]", "regex-use", "manual"] - ["org.apache.commons.lang3", "RegExUtils", False, "removeFirst", "(String,String)", "", "Argument[1]", "regex-use", "manual"] @@ -11,7 +11,7 @@ extensions: - ["org.apache.commons.lang3", "RegExUtils", False, "replacePattern", "(String,String,String)", "", "Argument[1]", "regex-use", "manual"] - addsTo: pack: codeql/java-all - extensible: extSummaryModel + extensible: summaryModel data: - ["org.apache.commons.lang3", "ArrayUtils", False, "add", "", "", "Argument[0].ArrayElement", "ReturnValue.ArrayElement", "value", "manual"] - ["org.apache.commons.lang3", "ArrayUtils", False, "add", "", "", "Argument[2]", "ReturnValue.ArrayElement", "value", "manual"] diff --git a/java/ql/lib/ext/org.apache.commons.lang3.mutable.model.yml b/java/ql/lib/ext/org.apache.commons.lang3.mutable.model.yml index 0a576393e10..48816a4a9e2 100644 --- a/java/ql/lib/ext/org.apache.commons.lang3.mutable.model.yml +++ b/java/ql/lib/ext/org.apache.commons.lang3.mutable.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSummaryModel + extensible: summaryModel data: - ["org.apache.commons.lang3.mutable", "Mutable", True, "getValue", "", "", "Argument[-1].SyntheticField[org.apache.commons.lang3.mutable.MutableObject.value]", "ReturnValue", "value", "manual"] - ["org.apache.commons.lang3.mutable", "Mutable", True, "setValue", "", "", "Argument[0]", "Argument[-1].SyntheticField[org.apache.commons.lang3.mutable.MutableObject.value]", "value", "manual"] diff --git a/java/ql/lib/ext/org.apache.commons.lang3.text.model.yml b/java/ql/lib/ext/org.apache.commons.lang3.text.model.yml index c31cffeb62c..e11dfbaa34d 100644 --- a/java/ql/lib/ext/org.apache.commons.lang3.text.model.yml +++ b/java/ql/lib/ext/org.apache.commons.lang3.text.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSummaryModel + extensible: summaryModel data: - ["org.apache.commons.lang3.text", "StrBuilder", False, "StrBuilder", "(java.lang.String)", "", "Argument[0]", "Argument[-1]", "taint", "manual"] - ["org.apache.commons.lang3.text", "StrBuilder", False, "append", "", "", "Argument[-1]", "ReturnValue", "taint", "manual"] diff --git a/java/ql/lib/ext/org.apache.commons.lang3.tuple.model.yml b/java/ql/lib/ext/org.apache.commons.lang3.tuple.model.yml index 204c890dd5e..ebd11508343 100644 --- a/java/ql/lib/ext/org.apache.commons.lang3.tuple.model.yml +++ b/java/ql/lib/ext/org.apache.commons.lang3.tuple.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSummaryModel + extensible: summaryModel data: - ["org.apache.commons.lang3.tuple", "ImmutablePair", False, "ImmutablePair", "(java.lang.Object,java.lang.Object)", "", "Argument[0]", "Argument[-1].Field[org.apache.commons.lang3.tuple.ImmutablePair.left]", "value", "manual"] - ["org.apache.commons.lang3.tuple", "ImmutablePair", False, "ImmutablePair", "(java.lang.Object,java.lang.Object)", "", "Argument[1]", "Argument[-1].Field[org.apache.commons.lang3.tuple.ImmutablePair.right]", "value", "manual"] diff --git a/java/ql/lib/ext/org.apache.commons.logging.model.yml b/java/ql/lib/ext/org.apache.commons.logging.model.yml index 252ebf9634a..8f40e26f2a1 100644 --- a/java/ql/lib/ext/org.apache.commons.logging.model.yml +++ b/java/ql/lib/ext/org.apache.commons.logging.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSinkModel + extensible: sinkModel data: - ["org.apache.commons.logging", "Log", True, "debug", "", "", "Argument[0]", "logging", "manual"] - ["org.apache.commons.logging", "Log", True, "error", "", "", "Argument[0]", "logging", "manual"] diff --git a/java/ql/lib/ext/org.apache.commons.ognl.enhance.model.yml b/java/ql/lib/ext/org.apache.commons.ognl.enhance.model.yml index 8f3e1a5a966..790c7640d9b 100644 --- a/java/ql/lib/ext/org.apache.commons.ognl.enhance.model.yml +++ b/java/ql/lib/ext/org.apache.commons.ognl.enhance.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSinkModel + extensible: sinkModel data: - ["org.apache.commons.ognl.enhance", "ExpressionAccessor", True, "get", "", "", "Argument[-1]", "ognl-injection", "manual"] - ["org.apache.commons.ognl.enhance", "ExpressionAccessor", True, "set", "", "", "Argument[-1]", "ognl-injection", "manual"] diff --git a/java/ql/lib/ext/org.apache.commons.ognl.model.yml b/java/ql/lib/ext/org.apache.commons.ognl.model.yml index 4f7190d5342..9b00a781f53 100644 --- a/java/ql/lib/ext/org.apache.commons.ognl.model.yml +++ b/java/ql/lib/ext/org.apache.commons.ognl.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSinkModel + extensible: sinkModel data: - ["org.apache.commons.ognl", "Node", True, "getValue", "", "", "Argument[-1]", "ognl-injection", "manual"] - ["org.apache.commons.ognl", "Node", True, "setValue", "", "", "Argument[-1]", "ognl-injection", "manual"] diff --git a/java/ql/lib/ext/org.apache.commons.text.lookup.model.yml b/java/ql/lib/ext/org.apache.commons.text.lookup.model.yml index 9bea394d619..b89855197f1 100644 --- a/java/ql/lib/ext/org.apache.commons.text.lookup.model.yml +++ b/java/ql/lib/ext/org.apache.commons.text.lookup.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSummaryModel + extensible: summaryModel data: - ["org.apache.commons.text.lookup", "StringLookup", True, "lookup", "", "", "Argument[-1]", "ReturnValue", "taint", "manual"] - ["org.apache.commons.text.lookup", "StringLookupFactory", False, "mapStringLookup", "", "", "Argument[0].MapValue", "ReturnValue", "taint", "manual"] diff --git a/java/ql/lib/ext/org.apache.commons.text.model.yml b/java/ql/lib/ext/org.apache.commons.text.model.yml index 8fd87c79147..c0618224fe4 100644 --- a/java/ql/lib/ext/org.apache.commons.text.model.yml +++ b/java/ql/lib/ext/org.apache.commons.text.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSummaryModel + extensible: summaryModel data: - ["org.apache.commons.text", "StrBuilder", False, "StrBuilder", "(java.lang.String)", "", "Argument[0]", "Argument[-1]", "taint", "manual"] - ["org.apache.commons.text", "StrBuilder", False, "append", "", "", "Argument[-1]", "ReturnValue", "taint", "manual"] diff --git a/java/ql/lib/ext/org.apache.directory.ldap.client.api.model.yml b/java/ql/lib/ext/org.apache.directory.ldap.client.api.model.yml index 5eb28c7c073..14b580383d3 100644 --- a/java/ql/lib/ext/org.apache.directory.ldap.client.api.model.yml +++ b/java/ql/lib/ext/org.apache.directory.ldap.client.api.model.yml @@ -1,6 +1,6 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSinkModel + extensible: sinkModel data: - ["org.apache.directory.ldap.client.api", "LdapConnection", True, "search", "", "", "Argument[0..2]", "ldap", "manual"] diff --git a/java/ql/lib/ext/org.apache.hc.core5.function.model.yml b/java/ql/lib/ext/org.apache.hc.core5.function.model.yml index f001872f720..2763da9cd3d 100644 --- a/java/ql/lib/ext/org.apache.hc.core5.function.model.yml +++ b/java/ql/lib/ext/org.apache.hc.core5.function.model.yml @@ -1,6 +1,6 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSummaryModel + extensible: summaryModel data: - ["org.apache.hc.core5.function", "Supplier", True, "get", "()", "", "Argument[-1]", "ReturnValue", "taint", "manual"] diff --git a/java/ql/lib/ext/org.apache.hc.core5.http.io.entity.model.yml b/java/ql/lib/ext/org.apache.hc.core5.http.io.entity.model.yml index 14ce196044f..2b7b1a4eaf3 100644 --- a/java/ql/lib/ext/org.apache.hc.core5.http.io.entity.model.yml +++ b/java/ql/lib/ext/org.apache.hc.core5.http.io.entity.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSummaryModel + extensible: summaryModel data: - ["org.apache.hc.core5.http.io.entity", "BasicHttpEntity", True, "BasicHttpEntity", "", "", "Argument[0]", "ReturnValue", "taint", "manual"] - ["org.apache.hc.core5.http.io.entity", "BufferedHttpEntity", True, "BufferedHttpEntity", "(HttpEntity)", "", "Argument[0]", "ReturnValue", "taint", "manual"] diff --git a/java/ql/lib/ext/org.apache.hc.core5.http.io.model.yml b/java/ql/lib/ext/org.apache.hc.core5.http.io.model.yml index 9fdf2b1fd2e..8183cb9a3a7 100644 --- a/java/ql/lib/ext/org.apache.hc.core5.http.io.model.yml +++ b/java/ql/lib/ext/org.apache.hc.core5.http.io.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSourceModel + extensible: sourceModel data: - ["org.apache.hc.core5.http.io", "HttpRequestHandler", True, "handle", "(ClassicHttpRequest,ClassicHttpResponse,HttpContext)", "", "Parameter[0]", "remote", "manual"] - ["org.apache.hc.core5.http.io", "HttpServerRequestHandler", True, "handle", "(ClassicHttpRequest,ResponseTrigger,HttpContext)", "", "Parameter[0]", "remote", "manual"] diff --git a/java/ql/lib/ext/org.apache.hc.core5.http.message.model.yml b/java/ql/lib/ext/org.apache.hc.core5.http.message.model.yml index 9d982e54178..bf8ab791ccf 100644 --- a/java/ql/lib/ext/org.apache.hc.core5.http.message.model.yml +++ b/java/ql/lib/ext/org.apache.hc.core5.http.message.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSummaryModel + extensible: summaryModel data: - ["org.apache.hc.core5.http.message", "RequestLine", True, "RequestLine", "(HttpRequest)", "", "Argument[0]", "Argument[-1]", "taint", "manual"] - ["org.apache.hc.core5.http.message", "RequestLine", True, "RequestLine", "(String,String,ProtocolVersion)", "", "Argument[1]", "Argument[-1]", "taint", "manual"] diff --git a/java/ql/lib/ext/org.apache.hc.core5.http.model.yml b/java/ql/lib/ext/org.apache.hc.core5.http.model.yml index 220728fadca..c0fcdc852dc 100644 --- a/java/ql/lib/ext/org.apache.hc.core5.http.model.yml +++ b/java/ql/lib/ext/org.apache.hc.core5.http.model.yml @@ -1,12 +1,12 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSinkModel + extensible: sinkModel data: - ["org.apache.hc.core5.http", "HttpEntityContainer", True, "setEntity", "(HttpEntity)", "", "Argument[0]", "xss", "manual"] - addsTo: pack: codeql/java-all - extensible: extSummaryModel + extensible: summaryModel data: - ["org.apache.hc.core5.http", "EntityDetails", True, "getContentEncoding", "()", "", "Argument[-1]", "ReturnValue", "taint", "manual"] - ["org.apache.hc.core5.http", "EntityDetails", True, "getContentType", "()", "", "Argument[-1]", "ReturnValue", "taint", "manual"] diff --git a/java/ql/lib/ext/org.apache.hc.core5.net.model.yml b/java/ql/lib/ext/org.apache.hc.core5.net.model.yml index 19213c0764f..e16c8b150c3 100644 --- a/java/ql/lib/ext/org.apache.hc.core5.net.model.yml +++ b/java/ql/lib/ext/org.apache.hc.core5.net.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSummaryModel + extensible: summaryModel data: - ["org.apache.hc.core5.net", "URIAuthority", True, "getHostName", "()", "", "Argument[-1]", "ReturnValue", "taint", "manual"] - ["org.apache.hc.core5.net", "URIAuthority", True, "toString", "()", "", "Argument[-1]", "ReturnValue", "taint", "manual"] diff --git a/java/ql/lib/ext/org.apache.hc.core5.util.model.yml b/java/ql/lib/ext/org.apache.hc.core5.util.model.yml index ae9af22ac77..2023ad04f6e 100644 --- a/java/ql/lib/ext/org.apache.hc.core5.util.model.yml +++ b/java/ql/lib/ext/org.apache.hc.core5.util.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSummaryModel + extensible: summaryModel data: - ["org.apache.hc.core5.util", "Args", True, "containsNoBlanks", "(CharSequence,String)", "", "Argument[0]", "ReturnValue", "value", "manual"] - ["org.apache.hc.core5.util", "Args", True, "notBlank", "(CharSequence,String)", "", "Argument[0]", "ReturnValue", "value", "manual"] diff --git a/java/ql/lib/ext/org.apache.http.client.methods.model.yml b/java/ql/lib/ext/org.apache.http.client.methods.model.yml index 99b0a4968cf..c90298bddf8 100644 --- a/java/ql/lib/ext/org.apache.http.client.methods.model.yml +++ b/java/ql/lib/ext/org.apache.http.client.methods.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSinkModel + extensible: sinkModel data: - ["org.apache.http.client.methods", "HttpDelete", False, "HttpDelete", "", "", "Argument[0]", "open-url", "manual"] - ["org.apache.http.client.methods", "HttpGet", False, "HttpGet", "", "", "Argument[0]", "open-url", "manual"] diff --git a/java/ql/lib/ext/org.apache.http.entity.model.yml b/java/ql/lib/ext/org.apache.http.entity.model.yml index 2e299bff5d4..4105b55a634 100644 --- a/java/ql/lib/ext/org.apache.http.entity.model.yml +++ b/java/ql/lib/ext/org.apache.http.entity.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSummaryModel + extensible: summaryModel data: - ["org.apache.http.entity", "BasicHttpEntity", True, "setContent", "(InputStream)", "", "Argument[0]", "Argument[-1]", "taint", "manual"] - ["org.apache.http.entity", "BufferedHttpEntity", True, "BufferedHttpEntity", "(HttpEntity)", "", "Argument[0]", "ReturnValue", "taint", "manual"] diff --git a/java/ql/lib/ext/org.apache.http.message.model.yml b/java/ql/lib/ext/org.apache.http.message.model.yml index b1caf80721b..da798c12017 100644 --- a/java/ql/lib/ext/org.apache.http.message.model.yml +++ b/java/ql/lib/ext/org.apache.http.message.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSinkModel + extensible: sinkModel data: - ["org.apache.http.message", "BasicHttpEntityEnclosingRequest", False, "BasicHttpEntityEnclosingRequest", "(RequestLine)", "", "Argument[0]", "open-url", "manual"] - ["org.apache.http.message", "BasicHttpEntityEnclosingRequest", False, "BasicHttpEntityEnclosingRequest", "(String,String)", "", "Argument[1]", "open-url", "manual"] @@ -11,6 +11,6 @@ extensions: - ["org.apache.http.message", "BasicHttpRequest", False, "BasicHttpRequest", "(String,String,ProtocolVersion)", "", "Argument[1]", "open-url", "manual"] - addsTo: pack: codeql/java-all - extensible: extSummaryModel + extensible: summaryModel data: - ["org.apache.http.message", "BasicRequestLine", False, "BasicRequestLine", "", "", "Argument[1]", "Argument[-1]", "taint", "manual"] diff --git a/java/ql/lib/ext/org.apache.http.model.yml b/java/ql/lib/ext/org.apache.http.model.yml index 76de35242b7..25c5847ad0a 100644 --- a/java/ql/lib/ext/org.apache.http.model.yml +++ b/java/ql/lib/ext/org.apache.http.model.yml @@ -1,19 +1,19 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSourceModel + extensible: sourceModel data: - ["org.apache.http", "HttpEntity", False, "getContent", "()", "", "ReturnValue", "remote", "manual"] - ["org.apache.http", "HttpMessage", False, "getParams", "()", "", "ReturnValue", "remote", "manual"] - addsTo: pack: codeql/java-all - extensible: extSinkModel + extensible: sinkModel data: - ["org.apache.http", "HttpRequest", True, "setURI", "", "", "Argument[0]", "open-url", "manual"] - ["org.apache.http", "HttpResponse", True, "setEntity", "(HttpEntity)", "", "Argument[0]", "xss", "manual"] - addsTo: pack: codeql/java-all - extensible: extSummaryModel + extensible: summaryModel data: - ["org.apache.http", "Header", True, "getElements", "()", "", "Argument[-1]", "ReturnValue", "taint", "manual"] - ["org.apache.http", "HeaderElement", True, "getName", "()", "", "Argument[-1]", "ReturnValue", "taint", "manual"] diff --git a/java/ql/lib/ext/org.apache.http.params.model.yml b/java/ql/lib/ext/org.apache.http.params.model.yml index 0f9facaede8..35cd5b5c8a3 100644 --- a/java/ql/lib/ext/org.apache.http.params.model.yml +++ b/java/ql/lib/ext/org.apache.http.params.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSummaryModel + extensible: summaryModel data: - ["org.apache.http.params", "HttpParams", True, "getDoubleParameter", "(String,double)", "", "Argument[-1]", "ReturnValue", "taint", "manual"] - ["org.apache.http.params", "HttpParams", True, "getDoubleParameter", "(String,double)", "", "Argument[1]", "ReturnValue", "value", "manual"] diff --git a/java/ql/lib/ext/org.apache.http.protocol.model.yml b/java/ql/lib/ext/org.apache.http.protocol.model.yml index fb99d7f6aa1..c5de98c8c68 100644 --- a/java/ql/lib/ext/org.apache.http.protocol.model.yml +++ b/java/ql/lib/ext/org.apache.http.protocol.model.yml @@ -1,6 +1,6 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSourceModel + extensible: sourceModel data: - ["org.apache.http.protocol", "HttpRequestHandler", True, "handle", "(HttpRequest,HttpResponse,HttpContext)", "", "Parameter[0]", "remote", "manual"] diff --git a/java/ql/lib/ext/org.apache.http.util.model.yml b/java/ql/lib/ext/org.apache.http.util.model.yml index e95178e8281..34fb87b5cb9 100644 --- a/java/ql/lib/ext/org.apache.http.util.model.yml +++ b/java/ql/lib/ext/org.apache.http.util.model.yml @@ -1,12 +1,12 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSinkModel + extensible: sinkModel data: - ["org.apache.http.util", "EntityUtils", True, "updateEntity", "(HttpResponse,HttpEntity)", "", "Argument[1]", "xss", "manual"] - addsTo: pack: codeql/java-all - extensible: extSummaryModel + extensible: summaryModel data: - ["org.apache.http.util", "Args", True, "containsNoBlanks", "(CharSequence,String)", "", "Argument[0]", "ReturnValue", "value", "manual"] - ["org.apache.http.util", "Args", True, "notBlank", "(CharSequence,String)", "", "Argument[0]", "ReturnValue", "value", "manual"] diff --git a/java/ql/lib/ext/org.apache.ibatis.jdbc.model.yml b/java/ql/lib/ext/org.apache.ibatis.jdbc.model.yml index 16cfe1404da..05dac3d7f10 100644 --- a/java/ql/lib/ext/org.apache.ibatis.jdbc.model.yml +++ b/java/ql/lib/ext/org.apache.ibatis.jdbc.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSinkModel + extensible: sinkModel data: - ["org.apache.ibatis.jdbc", "SqlRunner", False, "delete", "(String,Object[])", "", "Argument[0]", "sql", "manual"] - ["org.apache.ibatis.jdbc", "SqlRunner", False, "insert", "(String,Object[])", "", "Argument[0]", "sql", "manual"] @@ -11,7 +11,7 @@ extensions: - ["org.apache.ibatis.jdbc", "SqlRunner", False, "update", "(String,Object[])", "", "Argument[0]", "sql", "manual"] - addsTo: pack: codeql/java-all - extensible: extSummaryModel + extensible: summaryModel data: - ["org.apache.ibatis.jdbc", "AbstractSQL", True, "DELETE_FROM", "(String)", "", "Argument[0]", "Argument[-1]", "taint", "manual"] - ["org.apache.ibatis.jdbc", "AbstractSQL", True, "FETCH_FIRST_ROWS_ONLY", "(String)", "", "Argument[0]", "Argument[-1]", "taint", "manual"] diff --git a/java/ql/lib/ext/org.apache.log4j.model.yml b/java/ql/lib/ext/org.apache.log4j.model.yml index 6c10a824dce..309f238111b 100644 --- a/java/ql/lib/ext/org.apache.log4j.model.yml +++ b/java/ql/lib/ext/org.apache.log4j.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSinkModel + extensible: sinkModel data: - ["org.apache.log4j", "Category", True, "assertLog", "", "", "Argument[1]", "logging", "manual"] - ["org.apache.log4j", "Category", True, "debug", "", "", "Argument[0]", "logging", "manual"] diff --git a/java/ql/lib/ext/org.apache.logging.log4j.model.yml b/java/ql/lib/ext/org.apache.logging.log4j.model.yml index c26023c5fdd..5ffe10450a0 100644 --- a/java/ql/lib/ext/org.apache.logging.log4j.model.yml +++ b/java/ql/lib/ext/org.apache.logging.log4j.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSinkModel + extensible: sinkModel data: - ["org.apache.logging.log4j", "LogBuilder", True, "log", "(CharSequence)", "", "Argument[0]", "logging", "manual"] - ["org.apache.logging.log4j", "LogBuilder", True, "log", "(Message)", "", "Argument[0]", "logging", "manual"] @@ -364,7 +364,7 @@ extensions: - ["org.apache.logging.log4j", "Logger", True, "warn", "(Supplier,Throwable)", "", "Argument[0]", "logging", "manual"] - addsTo: pack: codeql/java-all - extensible: extSummaryModel + extensible: summaryModel data: - ["org.apache.logging.log4j", "Logger", True, "traceEntry", "(Message)", "", "Argument[0]", "ReturnValue", "taint", "manual"] - ["org.apache.logging.log4j", "Logger", True, "traceEntry", "(String,Object[])", "", "Argument[0..1]", "ReturnValue", "taint", "manual"] diff --git a/java/ql/lib/ext/org.apache.shiro.codec.model.yml b/java/ql/lib/ext/org.apache.shiro.codec.model.yml index ce779246090..f0a40c8549b 100644 --- a/java/ql/lib/ext/org.apache.shiro.codec.model.yml +++ b/java/ql/lib/ext/org.apache.shiro.codec.model.yml @@ -1,6 +1,6 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSummaryModel + extensible: summaryModel data: - ["org.apache.shiro.codec", "Base64", False, "decode", "(String)", "", "Argument[0]", "ReturnValue", "taint", "manual"] diff --git a/java/ql/lib/ext/org.apache.shiro.jndi.model.yml b/java/ql/lib/ext/org.apache.shiro.jndi.model.yml index 335e4d880ea..6da50e9d0b6 100644 --- a/java/ql/lib/ext/org.apache.shiro.jndi.model.yml +++ b/java/ql/lib/ext/org.apache.shiro.jndi.model.yml @@ -1,6 +1,6 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSinkModel + extensible: sinkModel data: - ["org.apache.shiro.jndi", "JndiTemplate", False, "lookup", "", "", "Argument[0]", "jndi-injection", "manual"] diff --git a/java/ql/lib/ext/org.apache.velocity.app.model.yml b/java/ql/lib/ext/org.apache.velocity.app.model.yml index d29cdea2720..1afc328b882 100644 --- a/java/ql/lib/ext/org.apache.velocity.app.model.yml +++ b/java/ql/lib/ext/org.apache.velocity.app.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSinkModel + extensible: sinkModel data: - ["org.apache.velocity.app", "Velocity", True, "evaluate", "", "", "Argument[3]", "ssti", "manual"] - ["org.apache.velocity.app", "Velocity", True, "mergeTemplate", "", "", "Argument[2]", "ssti", "manual"] diff --git a/java/ql/lib/ext/org.apache.velocity.runtime.model.yml b/java/ql/lib/ext/org.apache.velocity.runtime.model.yml index 732bc9036c8..a8f740a2301 100644 --- a/java/ql/lib/ext/org.apache.velocity.runtime.model.yml +++ b/java/ql/lib/ext/org.apache.velocity.runtime.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSinkModel + extensible: sinkModel data: - ["org.apache.velocity.runtime", "RuntimeServices", True, "evaluate", "", "", "Argument[3]", "ssti", "manual"] - ["org.apache.velocity.runtime", "RuntimeServices", True, "parse", "", "", "Argument[0]", "ssti", "manual"] diff --git a/java/ql/lib/ext/org.apache.velocity.runtime.resource.util.model.yml b/java/ql/lib/ext/org.apache.velocity.runtime.resource.util.model.yml index cfeadc54e91..4d3ce4c37ed 100644 --- a/java/ql/lib/ext/org.apache.velocity.runtime.resource.util.model.yml +++ b/java/ql/lib/ext/org.apache.velocity.runtime.resource.util.model.yml @@ -1,6 +1,6 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSinkModel + extensible: sinkModel data: - ["org.apache.velocity.runtime.resource.util", "StringResourceRepository", True, "putStringResource", "", "", "Argument[1]", "ssti", "manual"] diff --git a/java/ql/lib/ext/org.codehaus.groovy.control.model.yml b/java/ql/lib/ext/org.codehaus.groovy.control.model.yml index 4727e21f82b..77b03818172 100644 --- a/java/ql/lib/ext/org.codehaus.groovy.control.model.yml +++ b/java/ql/lib/ext/org.codehaus.groovy.control.model.yml @@ -1,6 +1,6 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSinkModel + extensible: sinkModel data: - ["org.codehaus.groovy.control", "CompilationUnit", False, "compile", "", "", "Argument[-1]", "groovy", "manual"] diff --git a/java/ql/lib/ext/org.dom4j.model.yml b/java/ql/lib/ext/org.dom4j.model.yml index 4e40f64dc1b..b2e5c2ed379 100644 --- a/java/ql/lib/ext/org.dom4j.model.yml +++ b/java/ql/lib/ext/org.dom4j.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSinkModel + extensible: sinkModel data: - ["org.dom4j", "DocumentFactory", True, "createPattern", "", "", "Argument[0]", "xpath", "manual"] - ["org.dom4j", "DocumentFactory", True, "createXPath", "", "", "Argument[0]", "xpath", "manual"] diff --git a/java/ql/lib/ext/org.dom4j.tree.model.yml b/java/ql/lib/ext/org.dom4j.tree.model.yml index dbad39e0f4c..0896937bb16 100644 --- a/java/ql/lib/ext/org.dom4j.tree.model.yml +++ b/java/ql/lib/ext/org.dom4j.tree.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSinkModel + extensible: sinkModel data: - ["org.dom4j.tree", "AbstractNode", True, "createPattern", "", "", "Argument[0]", "xpath", "manual"] - ["org.dom4j.tree", "AbstractNode", True, "createXPathFilter", "", "", "Argument[0]", "xpath", "manual"] diff --git a/java/ql/lib/ext/org.dom4j.util.model.yml b/java/ql/lib/ext/org.dom4j.util.model.yml index 587a1b68d32..d7dc55cd145 100644 --- a/java/ql/lib/ext/org.dom4j.util.model.yml +++ b/java/ql/lib/ext/org.dom4j.util.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSinkModel + extensible: sinkModel data: - ["org.dom4j.util", "ProxyDocumentFactory", True, "createPattern", "", "", "Argument[0]", "xpath", "manual"] - ["org.dom4j.util", "ProxyDocumentFactory", True, "createXPath", "", "", "Argument[0]", "xpath", "manual"] diff --git a/java/ql/lib/ext/org.hibernate.model.yml b/java/ql/lib/ext/org.hibernate.model.yml index aa550a510e4..bfc232a82a1 100644 --- a/java/ql/lib/ext/org.hibernate.model.yml +++ b/java/ql/lib/ext/org.hibernate.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSinkModel + extensible: sinkModel data: - ["org.hibernate", "QueryProducer", True, "createNativeQuery", "", "", "Argument[0]", "sql", "manual"] - ["org.hibernate", "QueryProducer", True, "createQuery", "", "", "Argument[0]", "sql", "manual"] diff --git a/java/ql/lib/ext/org.jboss.logging.model.yml b/java/ql/lib/ext/org.jboss.logging.model.yml index e0eb0cd3afe..069ae852b77 100644 --- a/java/ql/lib/ext/org.jboss.logging.model.yml +++ b/java/ql/lib/ext/org.jboss.logging.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSinkModel + extensible: sinkModel data: - ["org.jboss.logging", "BasicLogger", True, "debug", "(Object)", "", "Argument[0]", "logging", "manual"] - ["org.jboss.logging", "BasicLogger", True, "debug", "(Object,Object[])", "", "Argument[0..1]", "logging", "manual"] diff --git a/java/ql/lib/ext/org.jdbi.v3.core.model.yml b/java/ql/lib/ext/org.jdbi.v3.core.model.yml index ae662d16dfd..fd7f4e824ac 100644 --- a/java/ql/lib/ext/org.jdbi.v3.core.model.yml +++ b/java/ql/lib/ext/org.jdbi.v3.core.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSinkModel + extensible: sinkModel data: - ["org.jdbi.v3.core", "Jdbi", False, "create", "(String)", "", "Argument[0]", "jdbc-url", "manual"] - ["org.jdbi.v3.core", "Jdbi", False, "create", "(String,Properties)", "", "Argument[0]", "jdbc-url", "manual"] diff --git a/java/ql/lib/ext/org.jooq.model.yml b/java/ql/lib/ext/org.jooq.model.yml index 7de7bdfa6e6..cf7fc22a923 100644 --- a/java/ql/lib/ext/org.jooq.model.yml +++ b/java/ql/lib/ext/org.jooq.model.yml @@ -1,6 +1,6 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSinkModel + extensible: sinkModel data: - ["org.jooq", "PlainSQL", False, "", "", "Annotated", "Argument[0]", "sql", "manual"] diff --git a/java/ql/lib/ext/org.json.model.yml b/java/ql/lib/ext/org.json.model.yml index 98a5bb795de..da97dfadb38 100644 --- a/java/ql/lib/ext/org.json.model.yml +++ b/java/ql/lib/ext/org.json.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSummaryModel + extensible: summaryModel data: - ["org.json", "CDL", False, "rowToJSONArray", "", "", "Argument[0]", "ReturnValue", "taint", "manual"] - ["org.json", "CDL", False, "rowToJSONObject", "", "", "Argument[0..1]", "ReturnValue", "taint", "manual"] diff --git a/java/ql/lib/ext/org.mvel2.compiler.model.yml b/java/ql/lib/ext/org.mvel2.compiler.model.yml index de360871229..0e7f68faea0 100644 --- a/java/ql/lib/ext/org.mvel2.compiler.model.yml +++ b/java/ql/lib/ext/org.mvel2.compiler.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSinkModel + extensible: sinkModel data: - ["org.mvel2.compiler", "Accessor", False, "getValue", "", "", "Argument[-1]", "mvel", "manual"] - ["org.mvel2.compiler", "CompiledAccExpression", False, "getValue", "", "", "Argument[-1]", "mvel", "manual"] diff --git a/java/ql/lib/ext/org.mvel2.jsr223.model.yml b/java/ql/lib/ext/org.mvel2.jsr223.model.yml index a7761277e6c..eeb0cbc7984 100644 --- a/java/ql/lib/ext/org.mvel2.jsr223.model.yml +++ b/java/ql/lib/ext/org.mvel2.jsr223.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSinkModel + extensible: sinkModel data: - ["org.mvel2.jsr223", "MvelCompiledScript", False, "eval", "", "", "Argument[-1]", "mvel", "manual"] - ["org.mvel2.jsr223", "MvelScriptEngine", False, "eval", "", "", "Argument[0]", "mvel", "manual"] diff --git a/java/ql/lib/ext/org.mvel2.model.yml b/java/ql/lib/ext/org.mvel2.model.yml index 895d3a15c8c..fd7778c89a6 100644 --- a/java/ql/lib/ext/org.mvel2.model.yml +++ b/java/ql/lib/ext/org.mvel2.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSinkModel + extensible: sinkModel data: - ["org.mvel2", "MVEL", False, "eval", "", "", "Argument[0]", "mvel", "manual"] - ["org.mvel2", "MVEL", False, "evalToBoolean", "", "", "Argument[0]", "mvel", "manual"] diff --git a/java/ql/lib/ext/org.mvel2.templates.model.yml b/java/ql/lib/ext/org.mvel2.templates.model.yml index fac30dca38a..0e31cee38b0 100644 --- a/java/ql/lib/ext/org.mvel2.templates.model.yml +++ b/java/ql/lib/ext/org.mvel2.templates.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSinkModel + extensible: sinkModel data: - ["org.mvel2.templates", "TemplateRuntime", False, "eval", "", "", "Argument[0]", "mvel", "manual"] - ["org.mvel2.templates", "TemplateRuntime", False, "execute", "", "", "Argument[0]", "mvel", "manual"] diff --git a/java/ql/lib/ext/org.scijava.log.model.yml b/java/ql/lib/ext/org.scijava.log.model.yml index 561de4980f4..303dbae27e2 100644 --- a/java/ql/lib/ext/org.scijava.log.model.yml +++ b/java/ql/lib/ext/org.scijava.log.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSinkModel + extensible: sinkModel data: - ["org.scijava.log", "Logger", True, "alwaysLog", "(int,Object,Throwable)", "", "Argument[1]", "logging", "manual"] - ["org.scijava.log", "Logger", True, "debug", "(Object)", "", "Argument[0]", "logging", "manual"] diff --git a/java/ql/lib/ext/org.slf4j.model.yml b/java/ql/lib/ext/org.slf4j.model.yml index f321c13d1e0..6ff2f31847d 100644 --- a/java/ql/lib/ext/org.slf4j.model.yml +++ b/java/ql/lib/ext/org.slf4j.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSinkModel + extensible: sinkModel data: - ["org.slf4j", "Logger", True, "debug", "(Marker,String)", "", "Argument[1]", "logging", "manual"] - ["org.slf4j", "Logger", True, "debug", "(Marker,String,Object)", "", "Argument[1..2]", "logging", "manual"] diff --git a/java/ql/lib/ext/org.slf4j.spi.model.yml b/java/ql/lib/ext/org.slf4j.spi.model.yml index 2c6c44f0908..59e4d144157 100644 --- a/java/ql/lib/ext/org.slf4j.spi.model.yml +++ b/java/ql/lib/ext/org.slf4j.spi.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSinkModel + extensible: sinkModel data: - ["org.slf4j.spi", "LoggingEventBuilder", True, "log", "", "", "Argument[0]", "logging", "manual"] - ["org.slf4j.spi", "LoggingEventBuilder", True, "log", "(String,Object)", "", "Argument[0..1]", "logging", "manual"] @@ -10,7 +10,7 @@ extensions: - ["org.slf4j.spi", "LoggingEventBuilder", True, "log", "(Supplier)", "", "Argument[0]", "logging", "manual"] - addsTo: pack: codeql/java-all - extensible: extSummaryModel + extensible: summaryModel data: - ["org.slf4j.spi", "LoggingEventBuilder", True, "addArgument", "", "", "Argument[-1]", "ReturnValue", "value", "manual"] - ["org.slf4j.spi", "LoggingEventBuilder", True, "addArgument", "", "", "Argument[1]", "Argument[-1]", "taint", "manual"] diff --git a/java/ql/lib/ext/org.springframework.beans.model.yml b/java/ql/lib/ext/org.springframework.beans.model.yml index 44f6b24ee06..d3579370ec9 100644 --- a/java/ql/lib/ext/org.springframework.beans.model.yml +++ b/java/ql/lib/ext/org.springframework.beans.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSummaryModel + extensible: summaryModel data: - ["org.springframework.beans", "MutablePropertyValues", True, "MutablePropertyValues", "(List)", "", "Argument[0].Element", "Argument[-1].Element", "value", "manual"] - ["org.springframework.beans", "MutablePropertyValues", True, "MutablePropertyValues", "(Map)", "", "Argument[0].MapKey", "Argument[-1].Element.MapKey", "value", "manual"] diff --git a/java/ql/lib/ext/org.springframework.boot.jdbc.model.yml b/java/ql/lib/ext/org.springframework.boot.jdbc.model.yml index 79556f4a285..bd7c5d8c5c1 100644 --- a/java/ql/lib/ext/org.springframework.boot.jdbc.model.yml +++ b/java/ql/lib/ext/org.springframework.boot.jdbc.model.yml @@ -1,6 +1,6 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSinkModel + extensible: sinkModel data: - ["org.springframework.boot.jdbc", "DataSourceBuilder", False, "url", "(String)", "", "Argument[0]", "jdbc-url", "manual"] diff --git a/java/ql/lib/ext/org.springframework.cache.model.yml b/java/ql/lib/ext/org.springframework.cache.model.yml index 450997df83c..6fd3cf4610d 100644 --- a/java/ql/lib/ext/org.springframework.cache.model.yml +++ b/java/ql/lib/ext/org.springframework.cache.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSummaryModel + extensible: summaryModel data: - ["org.springframework.cache", "Cache", True, "get", "(Object)", "", "Argument[-1].MapValue", "ReturnValue.MapValue", "value", "manual"] - ["org.springframework.cache", "Cache", True, "get", "(Object,Callable)", "", "Argument[-1].MapValue", "ReturnValue", "value", "manual"] diff --git a/java/ql/lib/ext/org.springframework.context.model.yml b/java/ql/lib/ext/org.springframework.context.model.yml index adb3431c27c..c4097103179 100644 --- a/java/ql/lib/ext/org.springframework.context.model.yml +++ b/java/ql/lib/ext/org.springframework.context.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSummaryModel + extensible: summaryModel data: - ["org.springframework.context", "MessageSource", True, "getMessage", "(String,Object[],Locale)", "", "Argument[1].ArrayElement", "ReturnValue", "taint", "manual"] - ["org.springframework.context", "MessageSource", True, "getMessage", "(String,Object[],String,Locale)", "", "Argument[1].ArrayElement", "ReturnValue", "taint", "manual"] diff --git a/java/ql/lib/ext/org.springframework.data.repository.model.yml b/java/ql/lib/ext/org.springframework.data.repository.model.yml index ff4f0808118..82a5ba0ec10 100644 --- a/java/ql/lib/ext/org.springframework.data.repository.model.yml +++ b/java/ql/lib/ext/org.springframework.data.repository.model.yml @@ -1,6 +1,6 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSummaryModel + extensible: summaryModel data: - ["org.springframework.data.repository", "CrudRepository", True, "save", "", "", "Argument[0]", "ReturnValue", "value", "manual"] diff --git a/java/ql/lib/ext/org.springframework.http.model.yml b/java/ql/lib/ext/org.springframework.http.model.yml index b8ca57fa10d..2dac7192da2 100644 --- a/java/ql/lib/ext/org.springframework.http.model.yml +++ b/java/ql/lib/ext/org.springframework.http.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSinkModel + extensible: sinkModel data: - ["org.springframework.http", "RequestEntity", False, "RequestEntity", "(HttpMethod,URI)", "", "Argument[1]", "open-url", "manual"] - ["org.springframework.http", "RequestEntity", False, "RequestEntity", "(MultiValueMap,HttpMethod,URI)", "", "Argument[2]", "open-url", "manual"] @@ -19,7 +19,7 @@ extensions: - ["org.springframework.http", "RequestEntity", False, "put", "", "", "Argument[0]", "open-url", "manual"] - addsTo: pack: codeql/java-all - extensible: extSummaryModel + extensible: summaryModel data: - ["org.springframework.http", "HttpEntity", True, "HttpEntity", "(MultiValueMap)", "", "Argument[0].MapKey", "Argument[-1]", "taint", "manual"] - ["org.springframework.http", "HttpEntity", True, "HttpEntity", "(MultiValueMap)", "", "Argument[0].MapValue.Element", "Argument[-1]", "taint", "manual"] diff --git a/java/ql/lib/ext/org.springframework.jdbc.core.model.yml b/java/ql/lib/ext/org.springframework.jdbc.core.model.yml index 36bf98f9ebc..9374293d0bb 100644 --- a/java/ql/lib/ext/org.springframework.jdbc.core.model.yml +++ b/java/ql/lib/ext/org.springframework.jdbc.core.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSinkModel + extensible: sinkModel data: - ["org.springframework.jdbc.core", "JdbcTemplate", False, "batchUpdate", "", "", "Argument[0]", "sql", "manual"] - ["org.springframework.jdbc.core", "JdbcTemplate", False, "batchUpdate", "(String[])", "", "Argument[0]", "sql", "manual"] diff --git a/java/ql/lib/ext/org.springframework.jdbc.datasource.model.yml b/java/ql/lib/ext/org.springframework.jdbc.datasource.model.yml index 54d607485f9..7bb84c37e2c 100644 --- a/java/ql/lib/ext/org.springframework.jdbc.datasource.model.yml +++ b/java/ql/lib/ext/org.springframework.jdbc.datasource.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSinkModel + extensible: sinkModel data: - ["org.springframework.jdbc.datasource", "AbstractDriverBasedDataSource", False, "setUrl", "(String)", "", "Argument[0]", "jdbc-url", "manual"] - ["org.springframework.jdbc.datasource", "DriverManagerDataSource", False, "DriverManagerDataSource", "(String)", "", "Argument[0]", "jdbc-url", "manual"] diff --git a/java/ql/lib/ext/org.springframework.jdbc.object.model.yml b/java/ql/lib/ext/org.springframework.jdbc.object.model.yml index fc15867d36d..74e30d28068 100644 --- a/java/ql/lib/ext/org.springframework.jdbc.object.model.yml +++ b/java/ql/lib/ext/org.springframework.jdbc.object.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSinkModel + extensible: sinkModel data: - ["org.springframework.jdbc.object", "BatchSqlUpdate", False, "BatchSqlUpdate", "", "", "Argument[1]", "sql", "manual"] - ["org.springframework.jdbc.object", "MappingSqlQuery", False, "BatchSqlUpdate", "", "", "Argument[1]", "sql", "manual"] diff --git a/java/ql/lib/ext/org.springframework.jndi.model.yml b/java/ql/lib/ext/org.springframework.jndi.model.yml index 0df0234a379..f0d5f7b692d 100644 --- a/java/ql/lib/ext/org.springframework.jndi.model.yml +++ b/java/ql/lib/ext/org.springframework.jndi.model.yml @@ -1,6 +1,6 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSinkModel + extensible: sinkModel data: - ["org.springframework.jndi", "JndiTemplate", False, "lookup", "", "", "Argument[0]", "jndi-injection", "manual"] diff --git a/java/ql/lib/ext/org.springframework.ldap.core.model.yml b/java/ql/lib/ext/org.springframework.ldap.core.model.yml index bebe96fc14a..962dec40c59 100644 --- a/java/ql/lib/ext/org.springframework.ldap.core.model.yml +++ b/java/ql/lib/ext/org.springframework.ldap.core.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSinkModel + extensible: sinkModel data: - ["org.springframework.ldap.core", "LdapOperations", True, "findByDn", "", "", "Argument[0]", "jndi-injection", "manual"] - ["org.springframework.ldap.core", "LdapOperations", True, "list", "", "", "Argument[0]", "jndi-injection", "manual"] diff --git a/java/ql/lib/ext/org.springframework.ldap.model.yml b/java/ql/lib/ext/org.springframework.ldap.model.yml index 3ce0ad5d6b5..b42e3e85959 100644 --- a/java/ql/lib/ext/org.springframework.ldap.model.yml +++ b/java/ql/lib/ext/org.springframework.ldap.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSinkModel + extensible: sinkModel data: - ["org.springframework.ldap", "LdapOperations", True, "findByDn", "", "", "Argument[0]", "jndi-injection", "manual"] - ["org.springframework.ldap", "LdapOperations", True, "list", "", "", "Argument[0]", "jndi-injection", "manual"] diff --git a/java/ql/lib/ext/org.springframework.security.web.savedrequest.model.yml b/java/ql/lib/ext/org.springframework.security.web.savedrequest.model.yml index 0dd6df9116e..e8d9ab1bef5 100644 --- a/java/ql/lib/ext/org.springframework.security.web.savedrequest.model.yml +++ b/java/ql/lib/ext/org.springframework.security.web.savedrequest.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSourceModel + extensible: sourceModel data: - ["org.springframework.security.web.savedrequest", "SavedRequest", True, "getCookies", "", "", "ReturnValue", "remote", "manual"] - ["org.springframework.security.web.savedrequest", "SavedRequest", True, "getHeaderNames", "", "", "ReturnValue", "remote", "manual"] diff --git a/java/ql/lib/ext/org.springframework.ui.model.yml b/java/ql/lib/ext/org.springframework.ui.model.yml index 0ff23939bed..7e230d11f2f 100644 --- a/java/ql/lib/ext/org.springframework.ui.model.yml +++ b/java/ql/lib/ext/org.springframework.ui.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSummaryModel + extensible: summaryModel data: - ["org.springframework.ui", "ConcurrentModel", False, "ConcurrentModel", "(Object)", "", "Argument[0]", "Argument[-1].MapValue", "value", "manual"] - ["org.springframework.ui", "ConcurrentModel", False, "ConcurrentModel", "(String,Object)", "", "Argument[0]", "Argument[-1].MapKey", "value", "manual"] diff --git a/java/ql/lib/ext/org.springframework.util.model.yml b/java/ql/lib/ext/org.springframework.util.model.yml index 62eb0af5bd1..817f9b43c01 100644 --- a/java/ql/lib/ext/org.springframework.util.model.yml +++ b/java/ql/lib/ext/org.springframework.util.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSummaryModel + extensible: summaryModel data: - ["org.springframework.util", "AntPathMatcher", False, "combine", "", "", "Argument[0..1]", "ReturnValue", "taint", "manual"] - ["org.springframework.util", "AntPathMatcher", False, "doMatch", "", "", "Argument[1]", "Argument[3].MapValue", "taint", "manual"] diff --git a/java/ql/lib/ext/org.springframework.validation.model.yml b/java/ql/lib/ext/org.springframework.validation.model.yml index 46b3c3d016f..190254ad2d1 100644 --- a/java/ql/lib/ext/org.springframework.validation.model.yml +++ b/java/ql/lib/ext/org.springframework.validation.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSummaryModel + extensible: summaryModel data: - ["org.springframework.validation", "Errors", True, "addAllErrors", "", "", "Argument[0]", "Argument[-1]", "taint", "manual"] - ["org.springframework.validation", "Errors", True, "getAllErrors", "", "", "Argument[-1]", "ReturnValue", "taint", "manual"] diff --git a/java/ql/lib/ext/org.springframework.web.client.model.yml b/java/ql/lib/ext/org.springframework.web.client.model.yml index 92f9a558245..69f4cb64fc6 100644 --- a/java/ql/lib/ext/org.springframework.web.client.model.yml +++ b/java/ql/lib/ext/org.springframework.web.client.model.yml @@ -1,14 +1,14 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSourceModel + extensible: sourceModel data: - ["org.springframework.web.client", "RestTemplate", False, "exchange", "", "", "ReturnValue", "remote", "manual"] - ["org.springframework.web.client", "RestTemplate", False, "getForEntity", "", "", "ReturnValue", "remote", "manual"] - ["org.springframework.web.client", "RestTemplate", False, "postForEntity", "", "", "ReturnValue", "remote", "manual"] - addsTo: pack: codeql/java-all - extensible: extSinkModel + extensible: sinkModel data: - ["org.springframework.web.client", "RestTemplate", False, "delete", "", "", "Argument[0]", "open-url", "manual"] - ["org.springframework.web.client", "RestTemplate", False, "doExecute", "", "", "Argument[0]", "open-url", "manual"] diff --git a/java/ql/lib/ext/org.springframework.web.context.request.model.yml b/java/ql/lib/ext/org.springframework.web.context.request.model.yml index 56e276e4cc0..306bb87348e 100644 --- a/java/ql/lib/ext/org.springframework.web.context.request.model.yml +++ b/java/ql/lib/ext/org.springframework.web.context.request.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSourceModel + extensible: sourceModel data: - ["org.springframework.web.context.request", "WebRequest", False, "getDescription", "", "", "ReturnValue", "remote", "manual"] - ["org.springframework.web.context.request", "WebRequest", False, "getHeader", "", "", "ReturnValue", "remote", "manual"] diff --git a/java/ql/lib/ext/org.springframework.web.multipart.model.yml b/java/ql/lib/ext/org.springframework.web.multipart.model.yml index d57d44f8a48..7c0505cbcc4 100644 --- a/java/ql/lib/ext/org.springframework.web.multipart.model.yml +++ b/java/ql/lib/ext/org.springframework.web.multipart.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSourceModel + extensible: sourceModel data: - ["org.springframework.web.multipart", "MultipartFile", True, "getBytes", "()", "", "ReturnValue", "remote", "manual"] - ["org.springframework.web.multipart", "MultipartFile", True, "getContentType", "()", "", "ReturnValue", "remote", "manual"] @@ -17,7 +17,7 @@ extensions: - ["org.springframework.web.multipart", "MultipartRequest", True, "getMultipartContentType", "(String)", "", "ReturnValue", "remote", "manual"] - addsTo: pack: codeql/java-all - extensible: extSummaryModel + extensible: summaryModel data: - ["org.springframework.web.multipart", "MultipartFile", True, "getBytes", "", "", "Argument[-1]", "ReturnValue", "taint", "manual"] - ["org.springframework.web.multipart", "MultipartFile", True, "getInputStream", "", "", "Argument[-1]", "ReturnValue", "taint", "manual"] diff --git a/java/ql/lib/ext/org.springframework.web.reactive.function.client.model.yml b/java/ql/lib/ext/org.springframework.web.reactive.function.client.model.yml index e3ffd17cd7e..cb2d1db4444 100644 --- a/java/ql/lib/ext/org.springframework.web.reactive.function.client.model.yml +++ b/java/ql/lib/ext/org.springframework.web.reactive.function.client.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSinkModel + extensible: sinkModel data: - ["org.springframework.web.reactive.function.client", "WebClient", False, "create", "", "", "Argument[0]", "open-url", "manual"] - ["org.springframework.web.reactive.function.client", "WebClient$Builder", False, "baseUrl", "", "", "Argument[0]", "open-url", "manual"] diff --git a/java/ql/lib/ext/org.springframework.web.util.model.yml b/java/ql/lib/ext/org.springframework.web.util.model.yml index 151be5867e0..336d22b8696 100644 --- a/java/ql/lib/ext/org.springframework.web.util.model.yml +++ b/java/ql/lib/ext/org.springframework.web.util.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSummaryModel + extensible: summaryModel data: - ["org.springframework.web.util", "AbstractUriTemplateHandler", True, "getBaseUrl", "", "", "Argument[-1]", "ReturnValue", "taint", "manual"] - ["org.springframework.web.util", "AbstractUriTemplateHandler", True, "setBaseUrl", "", "", "Argument[0]", "Argument[-1]", "taint", "manual"] diff --git a/java/ql/lib/ext/org.thymeleaf.model.yml b/java/ql/lib/ext/org.thymeleaf.model.yml index a7413343ce4..fb294acafe6 100644 --- a/java/ql/lib/ext/org.thymeleaf.model.yml +++ b/java/ql/lib/ext/org.thymeleaf.model.yml @@ -1,13 +1,13 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSinkModel + extensible: sinkModel data: - ["org.thymeleaf", "ITemplateEngine", True, "process", "", "", "Argument[0]", "ssti", "manual"] - ["org.thymeleaf", "ITemplateEngine", True, "processThrottled", "", "", "Argument[0]", "ssti", "manual"] - addsTo: pack: codeql/java-all - extensible: extSummaryModel + extensible: summaryModel data: - ["org.thymeleaf", "TemplateSpec", False, "TemplateSpec", "", "", "Argument[0]", "Argument[-1]", "taint", "manual"] - ["org.thymeleaf", "TemplateSpec", False, "getTemplate", "", "", "Argument[-1]", "ReturnValue", "taint", "manual"] diff --git a/java/ql/lib/ext/org.xml.sax.model.yml b/java/ql/lib/ext/org.xml.sax.model.yml index ecd2ba3c544..71f1194a94e 100644 --- a/java/ql/lib/ext/org.xml.sax.model.yml +++ b/java/ql/lib/ext/org.xml.sax.model.yml @@ -1,6 +1,6 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSummaryModel + extensible: summaryModel data: - ["org.xml.sax", "InputSource", False, "InputSource", "", "", "Argument[0]", "Argument[-1]", "taint", "manual"] diff --git a/java/ql/lib/ext/org.xmlpull.v1.model.yml b/java/ql/lib/ext/org.xmlpull.v1.model.yml index 01af9ba332b..9002fda11c1 100644 --- a/java/ql/lib/ext/org.xmlpull.v1.model.yml +++ b/java/ql/lib/ext/org.xmlpull.v1.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSourceModel + extensible: sourceModel data: - ["org.xmlpull.v1", "XmlPullParser", False, "getName", "()", "", "ReturnValue", "remote", "manual"] - ["org.xmlpull.v1", "XmlPullParser", False, "getNamespace", "()", "", "ReturnValue", "remote", "manual"] diff --git a/java/ql/lib/ext/play.mvc.model.yml b/java/ql/lib/ext/play.mvc.model.yml index 98e665062a3..a1f8dc60fe0 100644 --- a/java/ql/lib/ext/play.mvc.model.yml +++ b/java/ql/lib/ext/play.mvc.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSourceModel + extensible: sourceModel data: - ["play.mvc", "Http$RequestHeader", False, "getHeader", "", "", "ReturnValue", "remote", "manual"] - ["play.mvc", "Http$RequestHeader", False, "getQueryString", "", "", "ReturnValue", "remote", "manual"] diff --git a/java/ql/lib/ext/ratpack.core.form.model.yml b/java/ql/lib/ext/ratpack.core.form.model.yml index 20d34162ac0..f3df142cf9d 100644 --- a/java/ql/lib/ext/ratpack.core.form.model.yml +++ b/java/ql/lib/ext/ratpack.core.form.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSummaryModel + extensible: summaryModel data: - ["ratpack.core.form", "Form", True, "file", "", "", "Argument[-1]", "ReturnValue", "taint", "manual"] - ["ratpack.core.form", "Form", True, "files", "", "", "Argument[-1]", "ReturnValue", "taint", "manual"] diff --git a/java/ql/lib/ext/ratpack.core.handling.model.yml b/java/ql/lib/ext/ratpack.core.handling.model.yml index 7662cc6c79d..0882d1b983d 100644 --- a/java/ql/lib/ext/ratpack.core.handling.model.yml +++ b/java/ql/lib/ext/ratpack.core.handling.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSourceModel + extensible: sourceModel data: # All Context#parse methods that return a Promise are remote flow sources. - ["ratpack.core.handling", "Context", True, "parse", "(com.google.common.reflect.TypeToken)", "", "ReturnValue", "remote", "manual"] @@ -12,7 +12,7 @@ extensions: - ["ratpack.core.handling", "Context", True, "parse", "(ratpack.parse.Parse)", "", "ReturnValue", "remote", "manual"] - addsTo: pack: codeql/java-all - extensible: extSummaryModel + extensible: summaryModel data: - ["ratpack.core.handling", "Context", True, "parse", "(ratpack.core.http.TypedData,ratpack.core.parse.Parse)", "", "Argument[0]", "ReturnValue", "taint", "manual"] - ["ratpack.core.handling", "Context", True, "parse", "(ratpack.core.http.TypedData,ratpack.core.parse.Parse)", "", "Argument[0]", "ReturnValue.MapKey", "taint", "manual"] diff --git a/java/ql/lib/ext/ratpack.core.http.model.yml b/java/ql/lib/ext/ratpack.core.http.model.yml index 094c90be1bd..2f6bc7fa17c 100644 --- a/java/ql/lib/ext/ratpack.core.http.model.yml +++ b/java/ql/lib/ext/ratpack.core.http.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSourceModel + extensible: sourceModel data: - ["ratpack.core.http", "Request", True, "getBody", "", "", "ReturnValue", "remote", "manual"] - ["ratpack.core.http", "Request", True, "getContentLength", "", "", "ReturnValue", "remote", "manual"] @@ -15,7 +15,7 @@ extensions: - ["ratpack.core.http", "Request", True, "oneCookie", "", "", "ReturnValue", "remote", "manual"] - addsTo: pack: codeql/java-all - extensible: extSummaryModel + extensible: summaryModel data: - ["ratpack.core.http", "Headers", True, "asMultiValueMap", "", "", "Argument[-1]", "ReturnValue", "taint", "manual"] - ["ratpack.core.http", "Headers", True, "get", "", "", "Argument[-1]", "ReturnValue", "taint", "manual"] diff --git a/java/ql/lib/ext/ratpack.exec.model.yml b/java/ql/lib/ext/ratpack.exec.model.yml index 0303f5cfd26..b2c0b2a2922 100644 --- a/java/ql/lib/ext/ratpack.exec.model.yml +++ b/java/ql/lib/ext/ratpack.exec.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSummaryModel + extensible: summaryModel data: - ["ratpack.exec", "Promise", True, "apply", "", "", "Argument[-1].Element", "Argument[0].Parameter[0].Element", "value", "manual"] - ["ratpack.exec", "Promise", True, "apply", "", "", "Argument[0].ReturnValue.Element", "ReturnValue.Element", "value", "manual"] diff --git a/java/ql/lib/ext/ratpack.form.model.yml b/java/ql/lib/ext/ratpack.form.model.yml index c4677cecd8d..3c4f6b2dd2b 100644 --- a/java/ql/lib/ext/ratpack.form.model.yml +++ b/java/ql/lib/ext/ratpack.form.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSummaryModel + extensible: summaryModel data: - ["ratpack.form", "Form", True, "file", "", "", "Argument[-1]", "ReturnValue", "taint", "manual"] - ["ratpack.form", "Form", True, "files", "", "", "Argument[-1]", "ReturnValue", "taint", "manual"] diff --git a/java/ql/lib/ext/ratpack.func.model.yml b/java/ql/lib/ext/ratpack.func.model.yml index 04e5a0cec8c..6cd78dc39d9 100644 --- a/java/ql/lib/ext/ratpack.func.model.yml +++ b/java/ql/lib/ext/ratpack.func.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSummaryModel + extensible: summaryModel data: - ["ratpack.func", "MultiValueMap", True, "asMultimap", "", "", "Argument[-1].MapKey", "ReturnValue.MapKey", "value", "manual"] - ["ratpack.func", "MultiValueMap", True, "asMultimap", "", "", "Argument[-1].MapValue", "ReturnValue.MapValue", "value", "manual"] diff --git a/java/ql/lib/ext/ratpack.handling.model.yml b/java/ql/lib/ext/ratpack.handling.model.yml index 3c2c54d0bba..1552fc7c1fd 100644 --- a/java/ql/lib/ext/ratpack.handling.model.yml +++ b/java/ql/lib/ext/ratpack.handling.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSourceModel + extensible: sourceModel data: # All Context#parse methods that return a Promise are remote flow sources. - ["ratpack.handling", "Context", True, "parse", "(com.google.common.reflect.TypeToken)", "", "ReturnValue", "remote", "manual"] @@ -12,7 +12,7 @@ extensions: - ["ratpack.handling", "Context", True, "parse", "(ratpack.parse.Parse)", "", "ReturnValue", "remote", "manual"] - addsTo: pack: codeql/java-all - extensible: extSummaryModel + extensible: summaryModel data: - ["ratpack.handling", "Context", True, "parse", "(ratpack.core.http.TypedData,ratpack.core.parse.Parse)", "", "Argument[0]", "ReturnValue", "taint", "manual"] - ["ratpack.handling", "Context", True, "parse", "(ratpack.core.http.TypedData,ratpack.core.parse.Parse)", "", "Argument[0]", "ReturnValue.MapKey", "taint", "manual"] diff --git a/java/ql/lib/ext/ratpack.http.model.yml b/java/ql/lib/ext/ratpack.http.model.yml index fc96663138e..340d3d29905 100644 --- a/java/ql/lib/ext/ratpack.http.model.yml +++ b/java/ql/lib/ext/ratpack.http.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSourceModel + extensible: sourceModel data: - ["ratpack.http", "Request", True, "getBody", "", "", "ReturnValue", "remote", "manual"] - ["ratpack.http", "Request", True, "getContentLength", "", "", "ReturnValue", "remote", "manual"] @@ -15,7 +15,7 @@ extensions: - ["ratpack.http", "Request", True, "oneCookie", "", "", "ReturnValue", "remote", "manual"] - addsTo: pack: codeql/java-all - extensible: extSummaryModel + extensible: summaryModel data: - ["ratpack.http", "Headers", True, "asMultiValueMap", "", "", "Argument[-1]", "ReturnValue", "taint", "manual"] - ["ratpack.http", "Headers", True, "get", "", "", "Argument[-1]", "ReturnValue", "taint", "manual"] diff --git a/java/ql/lib/ext/ratpack.util.model.yml b/java/ql/lib/ext/ratpack.util.model.yml index 218a023bcd3..0510897c4c6 100644 --- a/java/ql/lib/ext/ratpack.util.model.yml +++ b/java/ql/lib/ext/ratpack.util.model.yml @@ -1,7 +1,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSummaryModel + extensible: summaryModel data: - ["ratpack.util", "MultiValueMap", True, "asMultimap", "", "", "Argument[-1].MapKey", "ReturnValue.MapKey", "value", "manual"] - ["ratpack.util", "MultiValueMap", True, "asMultimap", "", "", "Argument[-1].MapValue", "ReturnValue.MapValue", "value", "manual"] diff --git a/java/ql/lib/ext/retrofit2.model.yml b/java/ql/lib/ext/retrofit2.model.yml index 7b1a109365a..51c4c0eed83 100644 --- a/java/ql/lib/ext/retrofit2.model.yml +++ b/java/ql/lib/ext/retrofit2.model.yml @@ -1,6 +1,6 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extSinkModel + extensible: sinkModel data: - ["retrofit2", "Retrofit$Builder", True, "baseUrl", "", "", "Argument[0]", "open-url", "manual"] diff --git a/java/ql/lib/semmle/code/java/dataflow/ExternalFlow.qll b/java/ql/lib/semmle/code/java/dataflow/ExternalFlow.qll index 10084c17c8d..02e0953bbc5 100644 --- a/java/ql/lib/semmle/code/java/dataflow/ExternalFlow.qll +++ b/java/ql/lib/semmle/code/java/dataflow/ExternalFlow.qll @@ -78,6 +78,7 @@ private import internal.DataFlowPrivate private import internal.FlowSummaryImpl::Private::External private import internal.FlowSummaryImplSpecific as FlowSummaryImplSpecific private import internal.AccessPathSyntax +private import ExternalFlowExtensions as Extensions private import FlowSummary /** @@ -128,33 +129,6 @@ private predicate summaryModelInternal(string row) { any(SummaryModelCsvInternal private predicate sinkModelInternal(string row) { any(SinkModelCsvInternal s).row(row) } -/** - * Holds if an experimental source model exists for the given parameters. - * This is only for experimental queries. - */ -extensible predicate extExperimentalSourceModel( - string package, string type, boolean subtypes, string name, string signature, string ext, - string output, string kind, string provenance, string filter -); - -/** - * Holds if an experimental sink model exists for the given parameters. - * This is only for experimental queries. - */ -extensible predicate extExperimentalSinkModel( - string package, string type, boolean subtypes, string name, string signature, string ext, - string input, string kind, string provenance, string filter -); - -/** - * Holds if an experimental summary model exists for the given parameters. - * This is only for experimental queries. - */ -extensible predicate extExperimentalSummaryModel( - string package, string type, boolean subtypes, string name, string signature, string ext, - string input, string output, string kind, string provenance, string filter -); - /** * A class for activating additional model rows. * @@ -172,7 +146,7 @@ abstract class ActiveExperimentalModels extends string { string package, string type, boolean subtypes, string name, string signature, string ext, string output, string kind, string provenance ) { - extExperimentalSourceModel(package, type, subtypes, name, signature, ext, output, kind, + Extensions::experimentalSourceModel(package, type, subtypes, name, signature, ext, output, kind, provenance, this) } @@ -183,7 +157,7 @@ abstract class ActiveExperimentalModels extends string { string package, string type, boolean subtypes, string name, string signature, string ext, string output, string kind, string provenance ) { - extExperimentalSinkModel(package, type, subtypes, name, signature, ext, output, kind, + Extensions::experimentalSinkModel(package, type, subtypes, name, signature, ext, output, kind, provenance, this) } @@ -194,19 +168,11 @@ abstract class ActiveExperimentalModels extends string { string package, string type, boolean subtypes, string name, string signature, string ext, string input, string output, string kind, string provenance ) { - extExperimentalSummaryModel(package, type, subtypes, name, signature, ext, input, output, kind, - provenance, this) + Extensions::experimentalSummaryModel(package, type, subtypes, name, signature, ext, input, + output, kind, provenance, this) } } -/** - * Holds if a source model exists for the given parameters. - */ -extensible predicate extSourceModel( - string package, string type, boolean subtypes, string name, string signature, string ext, - string output, string kind, string provenance -); - /** Holds if a source model exists for the given parameters. */ predicate sourceModel( string package, string type, boolean subtypes, string name, string signature, string ext, @@ -226,18 +192,12 @@ predicate sourceModel( row.splitAt(";", 8) = provenance ) or - extSourceModel(package, type, subtypes, name, signature, ext, output, kind, provenance) + Extensions::sourceModel(package, type, subtypes, name, signature, ext, output, kind, provenance) or any(ActiveExperimentalModels q) .sourceModel(package, type, subtypes, name, signature, ext, output, kind, provenance) } -/** Holds if a sink model exists for the given parameters. */ -extensible predicate extSinkModel( - string package, string type, boolean subtypes, string name, string signature, string ext, - string input, string kind, string provenance -); - /** Holds if a sink model exists for the given parameters. */ predicate sinkModel( string package, string type, boolean subtypes, string name, string signature, string ext, @@ -257,18 +217,12 @@ predicate sinkModel( row.splitAt(";", 8) = provenance ) or - extSinkModel(package, type, subtypes, name, signature, ext, input, kind, provenance) + Extensions::sinkModel(package, type, subtypes, name, signature, ext, input, kind, provenance) or any(ActiveExperimentalModels q) .sinkModel(package, type, subtypes, name, signature, ext, input, kind, provenance) } -/** Holds if a summary model exists for the given parameters. */ -extensible predicate extSummaryModel( - string package, string type, boolean subtypes, string name, string signature, string ext, - string input, string output, string kind, string provenance -); - /** Holds if a summary model exists for the given parameters. */ predicate summaryModel( string package, string type, boolean subtypes, string name, string signature, string ext, @@ -289,21 +243,15 @@ predicate summaryModel( row.splitAt(";", 9) = provenance ) or - extSummaryModel(package, type, subtypes, name, signature, ext, input, output, kind, provenance) + Extensions::summaryModel(package, type, subtypes, name, signature, ext, input, output, kind, + provenance) or any(ActiveExperimentalModels q) .summaryModel(package, type, subtypes, name, signature, ext, input, output, kind, provenance) } /** Holds if a neutral model exists indicating there is no flow for the given parameters. */ -extensible predicate extNeutralModel( - string package, string type, string name, string signature, string provenance -); - -/** Holds if a neutral model exists indicating there is no flow for the given parameters. */ -predicate neutralModel(string package, string type, string name, string signature, string provenance) { - extNeutralModel(package, type, name, signature, provenance) -} +predicate neutralModel = Extensions::neutralModel/5; private predicate relevantPackage(string package) { sourceModel(package, _, _, _, _, _, _, _, _) or diff --git a/java/ql/lib/semmle/code/java/dataflow/ExternalFlowExtensions.qll b/java/ql/lib/semmle/code/java/dataflow/ExternalFlowExtensions.qll new file mode 100644 index 00000000000..b06dc92c427 --- /dev/null +++ b/java/ql/lib/semmle/code/java/dataflow/ExternalFlowExtensions.qll @@ -0,0 +1,61 @@ +/** + * This module provides extensible predicates for defining MaD models. + */ + +/** + * Holds if a source model exists for the given parameters. + */ +extensible predicate sourceModel( + string package, string type, boolean subtypes, string name, string signature, string ext, + string output, string kind, string provenance +); + +/** + * Holds if a sink model exists for the given parameters. + */ +extensible predicate sinkModel( + string package, string type, boolean subtypes, string name, string signature, string ext, + string input, string kind, string provenance +); + +/** + * Holds if a summary model exists for the given parameters. + */ +extensible predicate summaryModel( + string package, string type, boolean subtypes, string name, string signature, string ext, + string input, string output, string kind, string provenance +); + +/** + * Holds if a neutral model exists indicating there is no flow for the given parameters. + */ +extensible predicate neutralModel( + string package, string type, string name, string signature, string provenance +); + +/** + * Holds if an experimental source model exists for the given parameters. + * This is only for experimental queries. + */ +extensible predicate experimentalSourceModel( + string package, string type, boolean subtypes, string name, string signature, string ext, + string output, string kind, string provenance, string filter +); + +/** + * Holds if an experimental sink model exists for the given parameters. + * This is only for experimental queries. + */ +extensible predicate experimentalSinkModel( + string package, string type, boolean subtypes, string name, string signature, string ext, + string input, string kind, string provenance, string filter +); + +/** + * Holds if an experimental summary model exists for the given parameters. + * This is only for experimental queries. + */ +extensible predicate experimentalSummaryModel( + string package, string type, boolean subtypes, string name, string signature, string ext, + string input, string output, string kind, string provenance, string filter +); 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 6741ccc2f06..1228d00b6ba 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl.qll @@ -622,7 +622,11 @@ private predicate parameterFlowThroughAllowed(ParamNodeEx p, ReturnKindExt kind) } private module Stage1 implements StageSig { - class Ap = Unit; + class Ap extends int { + // workaround for bad functionality-induced joins (happens when using `Unit`) + pragma[nomagic] + Ap() { this in [0 .. 1] and this < 1 } + } private class Cc = boolean; @@ -1327,8 +1331,8 @@ private module MkStage { */ pragma[nomagic] additional predicate fwdFlow( - NodeEx node, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - Ap ap, ApApprox apa, Configuration config + NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, + ApApprox apa, Configuration config ) { fwdFlow0(node, state, cc, summaryCtx, argAp, ap, apa, config) and PrevStage::revFlow(node, state, apa, config) and @@ -1337,21 +1341,21 @@ private module MkStage { pragma[inline] additional predicate fwdFlow( - NodeEx node, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - Ap ap, Configuration config + NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, + Configuration config ) { fwdFlow(node, state, cc, summaryCtx, argAp, ap, _, config) } pragma[nomagic] private predicate fwdFlow0( - NodeEx node, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - Ap ap, ApApprox apa, Configuration config + NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, + ApApprox apa, Configuration config ) { sourceNode(node, state, config) and (if hasSourceCallCtx(config) then cc = ccSomeCall() else cc = ccNone()) and argAp = apNone() and - summaryCtx = TParameterPositionNone() and + summaryCtx = TParamNodeNone() and ap = getApNil(node) and apa = getApprox(ap) or @@ -1372,7 +1376,7 @@ private module MkStage { fwdFlow(mid, pragma[only_bind_into](state), _, _, _, ap, apa, pragma[only_bind_into](config)) and jumpStep(mid, node, config) and cc = ccNone() and - summaryCtx = TParameterPositionNone() and + summaryCtx = TParamNodeNone() and argAp = apNone() ) or @@ -1380,7 +1384,7 @@ private module MkStage { fwdFlow(mid, state, _, _, _, nil, pragma[only_bind_into](config)) and additionalJumpStep(mid, node, config) and cc = ccNone() and - summaryCtx = TParameterPositionNone() and + summaryCtx = TParamNodeNone() and argAp = apNone() and ap = getApNil(node) and apa = getApprox(ap) @@ -1390,7 +1394,7 @@ private module MkStage { fwdFlow(mid, state0, _, _, _, nil, pragma[only_bind_into](config)) and additionalJumpStateStep(mid, state0, node, state, config) and cc = ccNone() and - summaryCtx = TParameterPositionNone() and + summaryCtx = TParamNodeNone() and argAp = apNone() and ap = getApNil(node) and apa = getApprox(ap) @@ -1414,10 +1418,10 @@ private module MkStage { fwdFlowIn(_, node, state, _, cc, _, _, ap, apa, config) and if PrevStage::parameterMayFlowThrough(node, apa, config) then ( - summaryCtx = TParameterPositionSome(node.(ParamNodeEx).getPosition()) and + summaryCtx = TParamNodeSome(node.asNode()) and argAp = apSome(ap) ) else ( - summaryCtx = TParameterPositionNone() and argAp = apNone() + summaryCtx = TParamNodeNone() and argAp = apNone() ) or // flow out of a callable @@ -1433,16 +1437,19 @@ private module MkStage { ) or // flow through a callable - exists(DataFlowCall call, ParameterPosition summaryCtx0, Ap argAp0 | - fwdFlowOutFromArg(call, node, state, summaryCtx0, argAp0, ap, apa, config) and - fwdFlowIsEntered(call, cc, summaryCtx, argAp, summaryCtx0, argAp0, config) + exists( + DataFlowCall call, CcCall ccc, RetNodeEx ret, boolean allowsFieldFlow, ApApprox innerArgApa + | + fwdFlowThrough(call, cc, state, ccc, summaryCtx, argAp, ap, apa, ret, innerArgApa, config) and + flowThroughOutOfCall(call, ccc, ret, node, allowsFieldFlow, innerArgApa, apa, config) and + if allowsFieldFlow = false then ap instanceof ApNil else any() ) } pragma[nomagic] private predicate fwdFlowStore( NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, FlowState state, Cc cc, - ParameterPositionOption summaryCtx, ApOption argAp, Configuration config + ParamNodeOption summaryCtx, ApOption argAp, Configuration config ) { exists(DataFlowType contentType, ApApprox apa1 | fwdFlow(node1, state, cc, summaryCtx, argAp, ap1, apa1, config) and @@ -1473,8 +1480,8 @@ private module MkStage { pragma[nomagic] private predicate fwdFlowRead0( - NodeEx node1, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - ApNonNil ap, Configuration config + NodeEx node1, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, ApNonNil ap, + Configuration config ) { fwdFlow(node1, state, cc, summaryCtx, argAp, ap, config) and PrevStage::readStepCand(node1, _, _, config) @@ -1483,7 +1490,7 @@ private module MkStage { pragma[nomagic] private predicate fwdFlowRead( Ap ap, Content c, NodeEx node1, NodeEx node2, FlowState state, Cc cc, - ParameterPositionOption summaryCtx, ApOption argAp, Configuration config + ParamNodeOption summaryCtx, ApOption argAp, Configuration config ) { fwdFlowRead0(node1, state, cc, summaryCtx, argAp, ap, config) and PrevStage::readStepCand(node1, c, node2, config) and @@ -1493,7 +1500,7 @@ private module MkStage { pragma[nomagic] private predicate fwdFlowIn( DataFlowCall call, ParamNodeEx p, FlowState state, Cc outercc, CcCall innercc, - ParameterPositionOption summaryCtx, ApOption argAp, Ap ap, ApApprox apa, Configuration config + ParamNodeOption summaryCtx, ApOption argAp, Ap ap, ApApprox apa, Configuration config ) { exists(ArgNodeEx arg, boolean allowsFieldFlow | fwdFlow(arg, state, outercc, summaryCtx, argAp, ap, apa, config) and @@ -1505,64 +1512,38 @@ private module MkStage { pragma[nomagic] private predicate fwdFlowRetFromArg( - RetNodeEx ret, FlowState state, CcCall ccc, ParameterPosition summaryCtx, ParamNodeEx p, - Ap argAp, ApApprox argApa, Ap ap, ApApprox apa, Configuration config + RetNodeEx ret, FlowState state, CcCall ccc, ParamNodeEx summaryCtx, Ap argAp, ApApprox argApa, + Ap ap, ApApprox apa, Configuration config ) { - exists(DataFlowCallable c, ReturnKindExt kind | + exists(ReturnKindExt kind | fwdFlow(pragma[only_bind_into](ret), state, ccc, - TParameterPositionSome(pragma[only_bind_into](summaryCtx)), apSome(argAp), ap, apa, config) and - getApprox(argAp) = argApa and - c = ret.getEnclosingCallable() and + TParamNodeSome(pragma[only_bind_into](summaryCtx.asNode())), + pragma[only_bind_into](apSome(argAp)), ap, pragma[only_bind_into](apa), + pragma[only_bind_into](config)) and kind = ret.getKind() and - p.isParameterOf(c, pragma[only_bind_into](summaryCtx)) and - parameterFlowThroughAllowed(p, kind) + parameterFlowThroughAllowed(summaryCtx, kind) and + argApa = getApprox(argAp) and + PrevStage::returnMayFlowThrough(ret, argApa, apa, kind, pragma[only_bind_into](config)) ) } pragma[inline] - private predicate fwdFlowInMayFlowThrough( - DataFlowCall call, Cc cc, CcCall innerCc, ParameterPositionOption summaryCtx, ApOption argAp, - ParamNodeEx param, Ap ap, ApApprox apa, Configuration config + private predicate fwdFlowThrough0( + DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, + ApOption argAp, Ap ap, ApApprox apa, RetNodeEx ret, ParamNodeEx innerSummaryCtx, + Ap innerArgAp, ApApprox innerArgApa, Configuration config ) { - fwdFlowIn(call, pragma[only_bind_into](param), _, cc, innerCc, summaryCtx, argAp, ap, - pragma[only_bind_into](apa), pragma[only_bind_into](config)) and - PrevStage::parameterMayFlowThrough(param, apa, config) - } - - // dedup before joining with `flowThroughOutOfCall` - pragma[nomagic] - private predicate fwdFlowInMayFlowThroughProj( - DataFlowCall call, CcCall innerCc, ApApprox apa, Configuration config - ) { - fwdFlowInMayFlowThrough(call, _, innerCc, _, _, _, _, apa, config) - } - - /** - * Same as `flowThroughOutOfCall`, but restricted to calls that are reached - * in the flow covered by `fwdFlow`, where data might flow through the target - * callable and back out at `call`. - */ - pragma[nomagic] - private predicate fwdFlowThroughOutOfCall( - DataFlowCall call, CcCall ccc, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow, - ApApprox argApa, ApApprox apa, Configuration config - ) { - fwdFlowInMayFlowThroughProj(call, ccc, argApa, config) and - flowThroughOutOfCall(call, ccc, ret, out, allowsFieldFlow, argApa, apa, config) + fwdFlowRetFromArg(ret, state, ccc, innerSummaryCtx, innerArgAp, innerArgApa, ap, apa, config) and + fwdFlowIsEntered(call, cc, ccc, summaryCtx, argAp, innerSummaryCtx, innerArgAp, config) } pragma[nomagic] - private predicate fwdFlowOutFromArg( - DataFlowCall call, NodeEx out, FlowState state, ParameterPosition summaryCtx, Ap argAp, Ap ap, - ApApprox apa, Configuration config + private predicate fwdFlowThrough( + DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, + ApOption argAp, Ap ap, ApApprox apa, RetNodeEx ret, ApApprox innerArgApa, Configuration config ) { - exists(RetNodeEx ret, boolean allowsFieldFlow, CcCall ccc, ApApprox argApa | - fwdFlowRetFromArg(pragma[only_bind_into](ret), state, pragma[only_bind_into](ccc), - summaryCtx, _, argAp, pragma[only_bind_into](argApa), ap, pragma[only_bind_into](apa), - config) and - fwdFlowThroughOutOfCall(call, ccc, ret, out, allowsFieldFlow, argApa, apa, config) and - (if allowsFieldFlow = false then ap instanceof ApNil else any()) - ) + fwdFlowThrough0(call, cc, state, ccc, summaryCtx, argAp, ap, apa, ret, _, _, innerArgApa, + config) } /** @@ -1571,12 +1552,14 @@ private module MkStage { */ pragma[nomagic] private predicate fwdFlowIsEntered( - DataFlowCall call, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - ParameterPosition pos, Ap ap, Configuration config + DataFlowCall call, Cc cc, CcCall innerCc, ParamNodeOption summaryCtx, ApOption argAp, + ParamNodeEx p, Ap ap, Configuration config ) { - exists(ParamNodeEx param | - fwdFlowInMayFlowThrough(call, cc, _, summaryCtx, argAp, param, ap, _, config) and - pos = param.getPosition() + exists(ApApprox apa | + fwdFlowIn(call, pragma[only_bind_into](p), _, cc, innerCc, summaryCtx, argAp, ap, + pragma[only_bind_into](apa), pragma[only_bind_into](config)) and + PrevStage::parameterMayFlowThrough(p, apa, config) and + PrevStage::callMayFlowThroughRev(call, pragma[only_bind_into](config)) ) } @@ -1596,23 +1579,31 @@ private module MkStage { fwdFlowConsCand(ap1, c, ap2, config) } + pragma[nomagic] + private predicate returnFlowsThrough0( + DataFlowCall call, FlowState state, CcCall ccc, Ap ap, ApApprox apa, RetNodeEx ret, + ParamNodeEx innerSummaryCtx, Ap innerArgAp, ApApprox innerArgApa, Configuration config + ) { + fwdFlowThrough0(call, _, state, ccc, _, _, ap, apa, ret, innerSummaryCtx, innerArgAp, + innerArgApa, config) + } + pragma[nomagic] private predicate returnFlowsThrough( - RetNodeEx ret, ReturnKindExt kind, FlowState state, CcCall ccc, ParamNodeEx p, Ap argAp, + RetNodeEx ret, ReturnPosition pos, FlowState state, CcCall ccc, ParamNodeEx p, Ap argAp, Ap ap, Configuration config ) { - exists(boolean allowsFieldFlow, ApApprox argApa, ApApprox apa | - fwdFlowRetFromArg(pragma[only_bind_into](ret), state, pragma[only_bind_into](ccc), _, p, - argAp, pragma[only_bind_into](argApa), ap, pragma[only_bind_into](apa), config) and - kind = ret.getKind() and - fwdFlowThroughOutOfCall(_, ccc, ret, _, allowsFieldFlow, argApa, apa, config) and - (if allowsFieldFlow = false then ap instanceof ApNil else any()) + exists(DataFlowCall call, ApApprox apa, boolean allowsFieldFlow, ApApprox innerArgApa | + returnFlowsThrough0(call, state, ccc, ap, apa, ret, p, argAp, innerArgApa, config) and + flowThroughOutOfCall(call, ccc, ret, _, allowsFieldFlow, innerArgApa, apa, config) and + pos = ret.getReturnPosition() and + if allowsFieldFlow = false then ap instanceof ApNil else any() ) } pragma[nomagic] private predicate flowThroughIntoCall( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap argAp, + DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap argAp, Ap ap, Configuration config ) { exists(ApApprox argApa | @@ -1620,7 +1611,7 @@ private module MkStage { allowsFieldFlow, argApa, pragma[only_bind_into](config)) and fwdFlow(arg, _, _, _, _, pragma[only_bind_into](argAp), argApa, pragma[only_bind_into](config)) and - returnFlowsThrough(_, _, _, _, p, pragma[only_bind_into](argAp), _, + returnFlowsThrough(_, _, _, _, p, pragma[only_bind_into](argAp), ap, pragma[only_bind_into](config)) and if allowsFieldFlow = false then argAp instanceof ApNil else any() ) @@ -1639,12 +1630,13 @@ private module MkStage { pragma[nomagic] private predicate flowOutOfCallAp( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, boolean allowsFieldFlow, + DataFlowCall call, RetNodeEx ret, ReturnPosition pos, NodeEx out, boolean allowsFieldFlow, Ap ap, Configuration config ) { exists(ApApprox apa | - flowOutOfCallApa(call, ret, kind, out, allowsFieldFlow, apa, config) and - fwdFlow(ret, _, _, _, _, ap, apa, config) + flowOutOfCallApa(call, ret, _, out, allowsFieldFlow, apa, config) and + fwdFlow(ret, _, _, _, _, ap, apa, config) and + pos = ret.getReturnPosition() ) } @@ -1739,17 +1731,17 @@ private module MkStage { ) or // flow through a callable - exists(DataFlowCall call, ReturnKindExt returnKind0, Ap returnAp0 | - revFlowInToReturn(call, node, state, returnKind0, returnAp0, ap, config) and - revFlowIsReturned(call, returnCtx, returnAp, returnKind0, returnAp0, config) + exists(DataFlowCall call, ParamNodeEx p, ReturnPosition pos, Ap innerReturnAp | + revFlowThrough(call, returnCtx, p, state, pos, returnAp, ap, innerReturnAp, config) and + flowThroughIntoCall(call, node, p, _, ap, innerReturnAp, config) ) or // flow out of a callable - exists(ReturnKindExt kind | - revFlowOut(_, node, kind, state, _, _, ap, config) and - if returnFlowsThrough(node, kind, state, _, _, _, ap, config) + exists(ReturnPosition pos | + revFlowOut(_, node, pos, state, _, _, ap, config) and + if returnFlowsThrough(node, pos, state, _, _, _, ap, config) then ( - returnCtx = TReturnCtxMaybeFlowThrough(kind) and + returnCtx = TReturnCtxMaybeFlowThrough(pos) and returnAp = apSome(ap) ) else ( returnCtx = TReturnCtxNoFlowThrough() and returnAp = apNone() @@ -1782,47 +1774,33 @@ private module MkStage { pragma[nomagic] private predicate revFlowOut( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, FlowState state, ReturnCtx returnCtx, + DataFlowCall call, RetNodeEx ret, ReturnPosition pos, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap, Configuration config ) { exists(NodeEx out, boolean allowsFieldFlow | revFlow(out, state, returnCtx, returnAp, ap, config) and - flowOutOfCallAp(call, ret, kind, out, allowsFieldFlow, ap, config) and + flowOutOfCallAp(call, ret, pos, out, allowsFieldFlow, ap, config) and if allowsFieldFlow = false then ap instanceof ApNil else any() ) } - /** - * Same as `flowThroughIntoCall`, but restricted to calls that are reached - * in the flow covered by `revFlow`, where data might flow through the target - * callable and back out at `call`. - */ - pragma[nomagic] - private predicate revFlowThroughIntoCall( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap argAp, - Configuration config - ) { - flowThroughIntoCall(call, arg, p, allowsFieldFlow, argAp, config) and - revFlowIsReturned(call, _, _, _, _, config) - } - pragma[nomagic] private predicate revFlowParamToReturn( - ParamNodeEx p, FlowState state, ReturnKindExt kind, Ap returnAp, Ap ap, Configuration config + ParamNodeEx p, FlowState state, ReturnPosition pos, Ap returnAp, Ap ap, Configuration config ) { - revFlow(p, state, TReturnCtxMaybeFlowThrough(kind), apSome(returnAp), ap, config) and - parameterFlowThroughAllowed(p, kind) + revFlow(pragma[only_bind_into](p), state, TReturnCtxMaybeFlowThrough(pos), apSome(returnAp), + pragma[only_bind_into](ap), pragma[only_bind_into](config)) and + parameterFlowThroughAllowed(p, pos.getKind()) and + PrevStage::parameterMayFlowThrough(p, getApprox(ap), config) } pragma[nomagic] - private predicate revFlowInToReturn( - DataFlowCall call, ArgNodeEx arg, FlowState state, ReturnKindExt kind, Ap returnAp, Ap ap, - Configuration config + private predicate revFlowThrough( + DataFlowCall call, ReturnCtx returnCtx, ParamNodeEx p, FlowState state, ReturnPosition pos, + ApOption returnAp, Ap ap, Ap innerReturnAp, Configuration config ) { - exists(ParamNodeEx p, boolean allowsFieldFlow | - revFlowParamToReturn(p, state, kind, returnAp, ap, config) and - revFlowThroughIntoCall(call, arg, p, allowsFieldFlow, ap, config) - ) + revFlowParamToReturn(p, state, pos, innerReturnAp, ap, config) and + revFlowIsReturned(call, returnCtx, returnAp, pos, innerReturnAp, config) } /** @@ -1832,12 +1810,12 @@ private module MkStage { */ pragma[nomagic] private predicate revFlowIsReturned( - DataFlowCall call, ReturnCtx returnCtx, ApOption returnAp, ReturnKindExt kind, Ap ap, + DataFlowCall call, ReturnCtx returnCtx, ApOption returnAp, ReturnPosition pos, Ap ap, Configuration config ) { exists(RetNodeEx ret, FlowState state, CcCall ccc | - revFlowOut(call, ret, kind, state, returnCtx, returnAp, ap, config) and - returnFlowsThrough(ret, kind, state, ccc, _, _, ap, config) and + revFlowOut(call, ret, pos, state, returnCtx, returnAp, ap, config) and + returnFlowsThrough(ret, pos, state, ccc, _, _, ap, config) and matchesCall(ccc, call) ) } @@ -1915,17 +1893,17 @@ private module MkStage { pragma[nomagic] private predicate parameterFlowsThroughRev( - ParamNodeEx p, Ap ap, ReturnKindExt kind, Ap returnAp, Configuration config + ParamNodeEx p, Ap ap, ReturnPosition pos, Ap returnAp, Configuration config ) { - revFlow(p, _, TReturnCtxMaybeFlowThrough(kind), apSome(returnAp), ap, config) and - parameterFlowThroughAllowed(p, kind) + revFlow(p, _, TReturnCtxMaybeFlowThrough(pos), apSome(returnAp), ap, config) and + parameterFlowThroughAllowed(p, pos.getKind()) } pragma[nomagic] predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap, Configuration config) { - exists(RetNodeEx ret, ReturnKindExt kind | - returnFlowsThrough(ret, kind, _, _, p, ap, _, config) and - parameterFlowsThroughRev(p, ap, kind, _, config) + exists(RetNodeEx ret, ReturnPosition pos | + returnFlowsThrough(ret, pos, _, _, p, ap, _, config) and + parameterFlowsThroughRev(p, ap, pos, _, config) ) } @@ -1933,20 +1911,21 @@ private module MkStage { predicate returnMayFlowThrough( RetNodeEx ret, Ap argAp, Ap ap, ReturnKindExt kind, Configuration config ) { - exists(ParamNodeEx p | - returnFlowsThrough(ret, kind, _, _, p, argAp, ap, config) and - parameterFlowsThroughRev(p, argAp, kind, ap, config) + exists(ParamNodeEx p, ReturnPosition pos | + returnFlowsThrough(ret, pos, _, _, p, argAp, ap, config) and + parameterFlowsThroughRev(p, argAp, pos, ap, config) and + kind = pos.getKind() ) } pragma[nomagic] - predicate revFlowInToReturnIsReturned( + private predicate revFlowThroughArg( DataFlowCall call, ArgNodeEx arg, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap, Configuration config ) { - exists(ReturnKindExt returnKind0, Ap returnAp0 | - revFlowInToReturn(call, arg, state, returnKind0, returnAp0, ap, config) and - revFlowIsReturned(call, returnCtx, returnAp, returnKind0, returnAp0, config) + exists(ParamNodeEx p, ReturnPosition pos, Ap innerReturnAp | + revFlowThrough(call, returnCtx, p, state, pos, returnAp, ap, innerReturnAp, config) and + flowThroughIntoCall(call, arg, p, _, ap, innerReturnAp, config) ) } @@ -1954,7 +1933,7 @@ private module MkStage { predicate callMayFlowThroughRev(DataFlowCall call, Configuration config) { exists(ArgNodeEx arg, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap | revFlow(arg, state, returnCtx, returnAp, ap, config) and - revFlowInToReturnIsReturned(call, arg, state, returnCtx, returnAp, ap, config) + revFlowThroughArg(call, arg, state, returnCtx, returnAp, ap, config) ) } @@ -1967,8 +1946,9 @@ private module MkStage { conscand = count(TypedContent f0, Ap ap | fwdConsCand(f0, ap, config)) and states = count(FlowState state | fwdFlow(_, state, _, _, _, _, config)) and tuples = - count(NodeEx n, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - Ap ap | fwdFlow(n, state, cc, summaryCtx, argAp, ap, config)) + count(NodeEx n, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap | + fwdFlow(n, state, cc, summaryCtx, argAp, ap, config) + ) or fwd = false and nodes = count(NodeEx node | revFlow(node, _, _, _, _, config)) and @@ -2823,13 +2803,12 @@ private Configuration unbindConf(Configuration conf) { pragma[nomagic] private predicate nodeMayUseSummary0( - NodeEx n, DataFlowCallable c, ParameterPosition pos, FlowState state, AccessPathApprox apa, - Configuration config + NodeEx n, ParamNodeEx p, FlowState state, AccessPathApprox apa, Configuration config ) { exists(AccessPathApprox apa0 | - c = n.getEnclosingCallable() and + Stage5::parameterMayFlowThrough(p, _, _) and Stage5::revFlow(n, state, TReturnCtxMaybeFlowThrough(_), _, apa0, config) and - Stage5::fwdFlow(n, state, any(CallContextCall ccc), TParameterPositionSome(pos), + Stage5::fwdFlow(n, state, any(CallContextCall ccc), TParamNodeSome(p.asNode()), TAccessPathApproxSome(apa), apa0, config) ) } @@ -2838,10 +2817,9 @@ pragma[nomagic] private predicate nodeMayUseSummary( NodeEx n, FlowState state, AccessPathApprox apa, Configuration config ) { - exists(DataFlowCallable c, ParameterPosition pos, ParamNodeEx p | + exists(ParamNodeEx p | Stage5::parameterMayFlowThrough(p, apa, config) and - nodeMayUseSummary0(n, c, pos, state, apa, config) and - p.isParameterOf(c, pos) + nodeMayUseSummary0(n, p, state, apa, config) ) } diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl2.qll b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl2.qll index 6741ccc2f06..1228d00b6ba 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl2.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl2.qll @@ -622,7 +622,11 @@ private predicate parameterFlowThroughAllowed(ParamNodeEx p, ReturnKindExt kind) } private module Stage1 implements StageSig { - class Ap = Unit; + class Ap extends int { + // workaround for bad functionality-induced joins (happens when using `Unit`) + pragma[nomagic] + Ap() { this in [0 .. 1] and this < 1 } + } private class Cc = boolean; @@ -1327,8 +1331,8 @@ private module MkStage { */ pragma[nomagic] additional predicate fwdFlow( - NodeEx node, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - Ap ap, ApApprox apa, Configuration config + NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, + ApApprox apa, Configuration config ) { fwdFlow0(node, state, cc, summaryCtx, argAp, ap, apa, config) and PrevStage::revFlow(node, state, apa, config) and @@ -1337,21 +1341,21 @@ private module MkStage { pragma[inline] additional predicate fwdFlow( - NodeEx node, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - Ap ap, Configuration config + NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, + Configuration config ) { fwdFlow(node, state, cc, summaryCtx, argAp, ap, _, config) } pragma[nomagic] private predicate fwdFlow0( - NodeEx node, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - Ap ap, ApApprox apa, Configuration config + NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, + ApApprox apa, Configuration config ) { sourceNode(node, state, config) and (if hasSourceCallCtx(config) then cc = ccSomeCall() else cc = ccNone()) and argAp = apNone() and - summaryCtx = TParameterPositionNone() and + summaryCtx = TParamNodeNone() and ap = getApNil(node) and apa = getApprox(ap) or @@ -1372,7 +1376,7 @@ private module MkStage { fwdFlow(mid, pragma[only_bind_into](state), _, _, _, ap, apa, pragma[only_bind_into](config)) and jumpStep(mid, node, config) and cc = ccNone() and - summaryCtx = TParameterPositionNone() and + summaryCtx = TParamNodeNone() and argAp = apNone() ) or @@ -1380,7 +1384,7 @@ private module MkStage { fwdFlow(mid, state, _, _, _, nil, pragma[only_bind_into](config)) and additionalJumpStep(mid, node, config) and cc = ccNone() and - summaryCtx = TParameterPositionNone() and + summaryCtx = TParamNodeNone() and argAp = apNone() and ap = getApNil(node) and apa = getApprox(ap) @@ -1390,7 +1394,7 @@ private module MkStage { fwdFlow(mid, state0, _, _, _, nil, pragma[only_bind_into](config)) and additionalJumpStateStep(mid, state0, node, state, config) and cc = ccNone() and - summaryCtx = TParameterPositionNone() and + summaryCtx = TParamNodeNone() and argAp = apNone() and ap = getApNil(node) and apa = getApprox(ap) @@ -1414,10 +1418,10 @@ private module MkStage { fwdFlowIn(_, node, state, _, cc, _, _, ap, apa, config) and if PrevStage::parameterMayFlowThrough(node, apa, config) then ( - summaryCtx = TParameterPositionSome(node.(ParamNodeEx).getPosition()) and + summaryCtx = TParamNodeSome(node.asNode()) and argAp = apSome(ap) ) else ( - summaryCtx = TParameterPositionNone() and argAp = apNone() + summaryCtx = TParamNodeNone() and argAp = apNone() ) or // flow out of a callable @@ -1433,16 +1437,19 @@ private module MkStage { ) or // flow through a callable - exists(DataFlowCall call, ParameterPosition summaryCtx0, Ap argAp0 | - fwdFlowOutFromArg(call, node, state, summaryCtx0, argAp0, ap, apa, config) and - fwdFlowIsEntered(call, cc, summaryCtx, argAp, summaryCtx0, argAp0, config) + exists( + DataFlowCall call, CcCall ccc, RetNodeEx ret, boolean allowsFieldFlow, ApApprox innerArgApa + | + fwdFlowThrough(call, cc, state, ccc, summaryCtx, argAp, ap, apa, ret, innerArgApa, config) and + flowThroughOutOfCall(call, ccc, ret, node, allowsFieldFlow, innerArgApa, apa, config) and + if allowsFieldFlow = false then ap instanceof ApNil else any() ) } pragma[nomagic] private predicate fwdFlowStore( NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, FlowState state, Cc cc, - ParameterPositionOption summaryCtx, ApOption argAp, Configuration config + ParamNodeOption summaryCtx, ApOption argAp, Configuration config ) { exists(DataFlowType contentType, ApApprox apa1 | fwdFlow(node1, state, cc, summaryCtx, argAp, ap1, apa1, config) and @@ -1473,8 +1480,8 @@ private module MkStage { pragma[nomagic] private predicate fwdFlowRead0( - NodeEx node1, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - ApNonNil ap, Configuration config + NodeEx node1, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, ApNonNil ap, + Configuration config ) { fwdFlow(node1, state, cc, summaryCtx, argAp, ap, config) and PrevStage::readStepCand(node1, _, _, config) @@ -1483,7 +1490,7 @@ private module MkStage { pragma[nomagic] private predicate fwdFlowRead( Ap ap, Content c, NodeEx node1, NodeEx node2, FlowState state, Cc cc, - ParameterPositionOption summaryCtx, ApOption argAp, Configuration config + ParamNodeOption summaryCtx, ApOption argAp, Configuration config ) { fwdFlowRead0(node1, state, cc, summaryCtx, argAp, ap, config) and PrevStage::readStepCand(node1, c, node2, config) and @@ -1493,7 +1500,7 @@ private module MkStage { pragma[nomagic] private predicate fwdFlowIn( DataFlowCall call, ParamNodeEx p, FlowState state, Cc outercc, CcCall innercc, - ParameterPositionOption summaryCtx, ApOption argAp, Ap ap, ApApprox apa, Configuration config + ParamNodeOption summaryCtx, ApOption argAp, Ap ap, ApApprox apa, Configuration config ) { exists(ArgNodeEx arg, boolean allowsFieldFlow | fwdFlow(arg, state, outercc, summaryCtx, argAp, ap, apa, config) and @@ -1505,64 +1512,38 @@ private module MkStage { pragma[nomagic] private predicate fwdFlowRetFromArg( - RetNodeEx ret, FlowState state, CcCall ccc, ParameterPosition summaryCtx, ParamNodeEx p, - Ap argAp, ApApprox argApa, Ap ap, ApApprox apa, Configuration config + RetNodeEx ret, FlowState state, CcCall ccc, ParamNodeEx summaryCtx, Ap argAp, ApApprox argApa, + Ap ap, ApApprox apa, Configuration config ) { - exists(DataFlowCallable c, ReturnKindExt kind | + exists(ReturnKindExt kind | fwdFlow(pragma[only_bind_into](ret), state, ccc, - TParameterPositionSome(pragma[only_bind_into](summaryCtx)), apSome(argAp), ap, apa, config) and - getApprox(argAp) = argApa and - c = ret.getEnclosingCallable() and + TParamNodeSome(pragma[only_bind_into](summaryCtx.asNode())), + pragma[only_bind_into](apSome(argAp)), ap, pragma[only_bind_into](apa), + pragma[only_bind_into](config)) and kind = ret.getKind() and - p.isParameterOf(c, pragma[only_bind_into](summaryCtx)) and - parameterFlowThroughAllowed(p, kind) + parameterFlowThroughAllowed(summaryCtx, kind) and + argApa = getApprox(argAp) and + PrevStage::returnMayFlowThrough(ret, argApa, apa, kind, pragma[only_bind_into](config)) ) } pragma[inline] - private predicate fwdFlowInMayFlowThrough( - DataFlowCall call, Cc cc, CcCall innerCc, ParameterPositionOption summaryCtx, ApOption argAp, - ParamNodeEx param, Ap ap, ApApprox apa, Configuration config + private predicate fwdFlowThrough0( + DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, + ApOption argAp, Ap ap, ApApprox apa, RetNodeEx ret, ParamNodeEx innerSummaryCtx, + Ap innerArgAp, ApApprox innerArgApa, Configuration config ) { - fwdFlowIn(call, pragma[only_bind_into](param), _, cc, innerCc, summaryCtx, argAp, ap, - pragma[only_bind_into](apa), pragma[only_bind_into](config)) and - PrevStage::parameterMayFlowThrough(param, apa, config) - } - - // dedup before joining with `flowThroughOutOfCall` - pragma[nomagic] - private predicate fwdFlowInMayFlowThroughProj( - DataFlowCall call, CcCall innerCc, ApApprox apa, Configuration config - ) { - fwdFlowInMayFlowThrough(call, _, innerCc, _, _, _, _, apa, config) - } - - /** - * Same as `flowThroughOutOfCall`, but restricted to calls that are reached - * in the flow covered by `fwdFlow`, where data might flow through the target - * callable and back out at `call`. - */ - pragma[nomagic] - private predicate fwdFlowThroughOutOfCall( - DataFlowCall call, CcCall ccc, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow, - ApApprox argApa, ApApprox apa, Configuration config - ) { - fwdFlowInMayFlowThroughProj(call, ccc, argApa, config) and - flowThroughOutOfCall(call, ccc, ret, out, allowsFieldFlow, argApa, apa, config) + fwdFlowRetFromArg(ret, state, ccc, innerSummaryCtx, innerArgAp, innerArgApa, ap, apa, config) and + fwdFlowIsEntered(call, cc, ccc, summaryCtx, argAp, innerSummaryCtx, innerArgAp, config) } pragma[nomagic] - private predicate fwdFlowOutFromArg( - DataFlowCall call, NodeEx out, FlowState state, ParameterPosition summaryCtx, Ap argAp, Ap ap, - ApApprox apa, Configuration config + private predicate fwdFlowThrough( + DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, + ApOption argAp, Ap ap, ApApprox apa, RetNodeEx ret, ApApprox innerArgApa, Configuration config ) { - exists(RetNodeEx ret, boolean allowsFieldFlow, CcCall ccc, ApApprox argApa | - fwdFlowRetFromArg(pragma[only_bind_into](ret), state, pragma[only_bind_into](ccc), - summaryCtx, _, argAp, pragma[only_bind_into](argApa), ap, pragma[only_bind_into](apa), - config) and - fwdFlowThroughOutOfCall(call, ccc, ret, out, allowsFieldFlow, argApa, apa, config) and - (if allowsFieldFlow = false then ap instanceof ApNil else any()) - ) + fwdFlowThrough0(call, cc, state, ccc, summaryCtx, argAp, ap, apa, ret, _, _, innerArgApa, + config) } /** @@ -1571,12 +1552,14 @@ private module MkStage { */ pragma[nomagic] private predicate fwdFlowIsEntered( - DataFlowCall call, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - ParameterPosition pos, Ap ap, Configuration config + DataFlowCall call, Cc cc, CcCall innerCc, ParamNodeOption summaryCtx, ApOption argAp, + ParamNodeEx p, Ap ap, Configuration config ) { - exists(ParamNodeEx param | - fwdFlowInMayFlowThrough(call, cc, _, summaryCtx, argAp, param, ap, _, config) and - pos = param.getPosition() + exists(ApApprox apa | + fwdFlowIn(call, pragma[only_bind_into](p), _, cc, innerCc, summaryCtx, argAp, ap, + pragma[only_bind_into](apa), pragma[only_bind_into](config)) and + PrevStage::parameterMayFlowThrough(p, apa, config) and + PrevStage::callMayFlowThroughRev(call, pragma[only_bind_into](config)) ) } @@ -1596,23 +1579,31 @@ private module MkStage { fwdFlowConsCand(ap1, c, ap2, config) } + pragma[nomagic] + private predicate returnFlowsThrough0( + DataFlowCall call, FlowState state, CcCall ccc, Ap ap, ApApprox apa, RetNodeEx ret, + ParamNodeEx innerSummaryCtx, Ap innerArgAp, ApApprox innerArgApa, Configuration config + ) { + fwdFlowThrough0(call, _, state, ccc, _, _, ap, apa, ret, innerSummaryCtx, innerArgAp, + innerArgApa, config) + } + pragma[nomagic] private predicate returnFlowsThrough( - RetNodeEx ret, ReturnKindExt kind, FlowState state, CcCall ccc, ParamNodeEx p, Ap argAp, + RetNodeEx ret, ReturnPosition pos, FlowState state, CcCall ccc, ParamNodeEx p, Ap argAp, Ap ap, Configuration config ) { - exists(boolean allowsFieldFlow, ApApprox argApa, ApApprox apa | - fwdFlowRetFromArg(pragma[only_bind_into](ret), state, pragma[only_bind_into](ccc), _, p, - argAp, pragma[only_bind_into](argApa), ap, pragma[only_bind_into](apa), config) and - kind = ret.getKind() and - fwdFlowThroughOutOfCall(_, ccc, ret, _, allowsFieldFlow, argApa, apa, config) and - (if allowsFieldFlow = false then ap instanceof ApNil else any()) + exists(DataFlowCall call, ApApprox apa, boolean allowsFieldFlow, ApApprox innerArgApa | + returnFlowsThrough0(call, state, ccc, ap, apa, ret, p, argAp, innerArgApa, config) and + flowThroughOutOfCall(call, ccc, ret, _, allowsFieldFlow, innerArgApa, apa, config) and + pos = ret.getReturnPosition() and + if allowsFieldFlow = false then ap instanceof ApNil else any() ) } pragma[nomagic] private predicate flowThroughIntoCall( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap argAp, + DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap argAp, Ap ap, Configuration config ) { exists(ApApprox argApa | @@ -1620,7 +1611,7 @@ private module MkStage { allowsFieldFlow, argApa, pragma[only_bind_into](config)) and fwdFlow(arg, _, _, _, _, pragma[only_bind_into](argAp), argApa, pragma[only_bind_into](config)) and - returnFlowsThrough(_, _, _, _, p, pragma[only_bind_into](argAp), _, + returnFlowsThrough(_, _, _, _, p, pragma[only_bind_into](argAp), ap, pragma[only_bind_into](config)) and if allowsFieldFlow = false then argAp instanceof ApNil else any() ) @@ -1639,12 +1630,13 @@ private module MkStage { pragma[nomagic] private predicate flowOutOfCallAp( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, boolean allowsFieldFlow, + DataFlowCall call, RetNodeEx ret, ReturnPosition pos, NodeEx out, boolean allowsFieldFlow, Ap ap, Configuration config ) { exists(ApApprox apa | - flowOutOfCallApa(call, ret, kind, out, allowsFieldFlow, apa, config) and - fwdFlow(ret, _, _, _, _, ap, apa, config) + flowOutOfCallApa(call, ret, _, out, allowsFieldFlow, apa, config) and + fwdFlow(ret, _, _, _, _, ap, apa, config) and + pos = ret.getReturnPosition() ) } @@ -1739,17 +1731,17 @@ private module MkStage { ) or // flow through a callable - exists(DataFlowCall call, ReturnKindExt returnKind0, Ap returnAp0 | - revFlowInToReturn(call, node, state, returnKind0, returnAp0, ap, config) and - revFlowIsReturned(call, returnCtx, returnAp, returnKind0, returnAp0, config) + exists(DataFlowCall call, ParamNodeEx p, ReturnPosition pos, Ap innerReturnAp | + revFlowThrough(call, returnCtx, p, state, pos, returnAp, ap, innerReturnAp, config) and + flowThroughIntoCall(call, node, p, _, ap, innerReturnAp, config) ) or // flow out of a callable - exists(ReturnKindExt kind | - revFlowOut(_, node, kind, state, _, _, ap, config) and - if returnFlowsThrough(node, kind, state, _, _, _, ap, config) + exists(ReturnPosition pos | + revFlowOut(_, node, pos, state, _, _, ap, config) and + if returnFlowsThrough(node, pos, state, _, _, _, ap, config) then ( - returnCtx = TReturnCtxMaybeFlowThrough(kind) and + returnCtx = TReturnCtxMaybeFlowThrough(pos) and returnAp = apSome(ap) ) else ( returnCtx = TReturnCtxNoFlowThrough() and returnAp = apNone() @@ -1782,47 +1774,33 @@ private module MkStage { pragma[nomagic] private predicate revFlowOut( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, FlowState state, ReturnCtx returnCtx, + DataFlowCall call, RetNodeEx ret, ReturnPosition pos, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap, Configuration config ) { exists(NodeEx out, boolean allowsFieldFlow | revFlow(out, state, returnCtx, returnAp, ap, config) and - flowOutOfCallAp(call, ret, kind, out, allowsFieldFlow, ap, config) and + flowOutOfCallAp(call, ret, pos, out, allowsFieldFlow, ap, config) and if allowsFieldFlow = false then ap instanceof ApNil else any() ) } - /** - * Same as `flowThroughIntoCall`, but restricted to calls that are reached - * in the flow covered by `revFlow`, where data might flow through the target - * callable and back out at `call`. - */ - pragma[nomagic] - private predicate revFlowThroughIntoCall( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap argAp, - Configuration config - ) { - flowThroughIntoCall(call, arg, p, allowsFieldFlow, argAp, config) and - revFlowIsReturned(call, _, _, _, _, config) - } - pragma[nomagic] private predicate revFlowParamToReturn( - ParamNodeEx p, FlowState state, ReturnKindExt kind, Ap returnAp, Ap ap, Configuration config + ParamNodeEx p, FlowState state, ReturnPosition pos, Ap returnAp, Ap ap, Configuration config ) { - revFlow(p, state, TReturnCtxMaybeFlowThrough(kind), apSome(returnAp), ap, config) and - parameterFlowThroughAllowed(p, kind) + revFlow(pragma[only_bind_into](p), state, TReturnCtxMaybeFlowThrough(pos), apSome(returnAp), + pragma[only_bind_into](ap), pragma[only_bind_into](config)) and + parameterFlowThroughAllowed(p, pos.getKind()) and + PrevStage::parameterMayFlowThrough(p, getApprox(ap), config) } pragma[nomagic] - private predicate revFlowInToReturn( - DataFlowCall call, ArgNodeEx arg, FlowState state, ReturnKindExt kind, Ap returnAp, Ap ap, - Configuration config + private predicate revFlowThrough( + DataFlowCall call, ReturnCtx returnCtx, ParamNodeEx p, FlowState state, ReturnPosition pos, + ApOption returnAp, Ap ap, Ap innerReturnAp, Configuration config ) { - exists(ParamNodeEx p, boolean allowsFieldFlow | - revFlowParamToReturn(p, state, kind, returnAp, ap, config) and - revFlowThroughIntoCall(call, arg, p, allowsFieldFlow, ap, config) - ) + revFlowParamToReturn(p, state, pos, innerReturnAp, ap, config) and + revFlowIsReturned(call, returnCtx, returnAp, pos, innerReturnAp, config) } /** @@ -1832,12 +1810,12 @@ private module MkStage { */ pragma[nomagic] private predicate revFlowIsReturned( - DataFlowCall call, ReturnCtx returnCtx, ApOption returnAp, ReturnKindExt kind, Ap ap, + DataFlowCall call, ReturnCtx returnCtx, ApOption returnAp, ReturnPosition pos, Ap ap, Configuration config ) { exists(RetNodeEx ret, FlowState state, CcCall ccc | - revFlowOut(call, ret, kind, state, returnCtx, returnAp, ap, config) and - returnFlowsThrough(ret, kind, state, ccc, _, _, ap, config) and + revFlowOut(call, ret, pos, state, returnCtx, returnAp, ap, config) and + returnFlowsThrough(ret, pos, state, ccc, _, _, ap, config) and matchesCall(ccc, call) ) } @@ -1915,17 +1893,17 @@ private module MkStage { pragma[nomagic] private predicate parameterFlowsThroughRev( - ParamNodeEx p, Ap ap, ReturnKindExt kind, Ap returnAp, Configuration config + ParamNodeEx p, Ap ap, ReturnPosition pos, Ap returnAp, Configuration config ) { - revFlow(p, _, TReturnCtxMaybeFlowThrough(kind), apSome(returnAp), ap, config) and - parameterFlowThroughAllowed(p, kind) + revFlow(p, _, TReturnCtxMaybeFlowThrough(pos), apSome(returnAp), ap, config) and + parameterFlowThroughAllowed(p, pos.getKind()) } pragma[nomagic] predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap, Configuration config) { - exists(RetNodeEx ret, ReturnKindExt kind | - returnFlowsThrough(ret, kind, _, _, p, ap, _, config) and - parameterFlowsThroughRev(p, ap, kind, _, config) + exists(RetNodeEx ret, ReturnPosition pos | + returnFlowsThrough(ret, pos, _, _, p, ap, _, config) and + parameterFlowsThroughRev(p, ap, pos, _, config) ) } @@ -1933,20 +1911,21 @@ private module MkStage { predicate returnMayFlowThrough( RetNodeEx ret, Ap argAp, Ap ap, ReturnKindExt kind, Configuration config ) { - exists(ParamNodeEx p | - returnFlowsThrough(ret, kind, _, _, p, argAp, ap, config) and - parameterFlowsThroughRev(p, argAp, kind, ap, config) + exists(ParamNodeEx p, ReturnPosition pos | + returnFlowsThrough(ret, pos, _, _, p, argAp, ap, config) and + parameterFlowsThroughRev(p, argAp, pos, ap, config) and + kind = pos.getKind() ) } pragma[nomagic] - predicate revFlowInToReturnIsReturned( + private predicate revFlowThroughArg( DataFlowCall call, ArgNodeEx arg, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap, Configuration config ) { - exists(ReturnKindExt returnKind0, Ap returnAp0 | - revFlowInToReturn(call, arg, state, returnKind0, returnAp0, ap, config) and - revFlowIsReturned(call, returnCtx, returnAp, returnKind0, returnAp0, config) + exists(ParamNodeEx p, ReturnPosition pos, Ap innerReturnAp | + revFlowThrough(call, returnCtx, p, state, pos, returnAp, ap, innerReturnAp, config) and + flowThroughIntoCall(call, arg, p, _, ap, innerReturnAp, config) ) } @@ -1954,7 +1933,7 @@ private module MkStage { predicate callMayFlowThroughRev(DataFlowCall call, Configuration config) { exists(ArgNodeEx arg, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap | revFlow(arg, state, returnCtx, returnAp, ap, config) and - revFlowInToReturnIsReturned(call, arg, state, returnCtx, returnAp, ap, config) + revFlowThroughArg(call, arg, state, returnCtx, returnAp, ap, config) ) } @@ -1967,8 +1946,9 @@ private module MkStage { conscand = count(TypedContent f0, Ap ap | fwdConsCand(f0, ap, config)) and states = count(FlowState state | fwdFlow(_, state, _, _, _, _, config)) and tuples = - count(NodeEx n, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - Ap ap | fwdFlow(n, state, cc, summaryCtx, argAp, ap, config)) + count(NodeEx n, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap | + fwdFlow(n, state, cc, summaryCtx, argAp, ap, config) + ) or fwd = false and nodes = count(NodeEx node | revFlow(node, _, _, _, _, config)) and @@ -2823,13 +2803,12 @@ private Configuration unbindConf(Configuration conf) { pragma[nomagic] private predicate nodeMayUseSummary0( - NodeEx n, DataFlowCallable c, ParameterPosition pos, FlowState state, AccessPathApprox apa, - Configuration config + NodeEx n, ParamNodeEx p, FlowState state, AccessPathApprox apa, Configuration config ) { exists(AccessPathApprox apa0 | - c = n.getEnclosingCallable() and + Stage5::parameterMayFlowThrough(p, _, _) and Stage5::revFlow(n, state, TReturnCtxMaybeFlowThrough(_), _, apa0, config) and - Stage5::fwdFlow(n, state, any(CallContextCall ccc), TParameterPositionSome(pos), + Stage5::fwdFlow(n, state, any(CallContextCall ccc), TParamNodeSome(p.asNode()), TAccessPathApproxSome(apa), apa0, config) ) } @@ -2838,10 +2817,9 @@ pragma[nomagic] private predicate nodeMayUseSummary( NodeEx n, FlowState state, AccessPathApprox apa, Configuration config ) { - exists(DataFlowCallable c, ParameterPosition pos, ParamNodeEx p | + exists(ParamNodeEx p | Stage5::parameterMayFlowThrough(p, apa, config) and - nodeMayUseSummary0(n, c, pos, state, apa, config) and - p.isParameterOf(c, pos) + nodeMayUseSummary0(n, p, state, apa, config) ) } diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl3.qll b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl3.qll index 6741ccc2f06..1228d00b6ba 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl3.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl3.qll @@ -622,7 +622,11 @@ private predicate parameterFlowThroughAllowed(ParamNodeEx p, ReturnKindExt kind) } private module Stage1 implements StageSig { - class Ap = Unit; + class Ap extends int { + // workaround for bad functionality-induced joins (happens when using `Unit`) + pragma[nomagic] + Ap() { this in [0 .. 1] and this < 1 } + } private class Cc = boolean; @@ -1327,8 +1331,8 @@ private module MkStage { */ pragma[nomagic] additional predicate fwdFlow( - NodeEx node, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - Ap ap, ApApprox apa, Configuration config + NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, + ApApprox apa, Configuration config ) { fwdFlow0(node, state, cc, summaryCtx, argAp, ap, apa, config) and PrevStage::revFlow(node, state, apa, config) and @@ -1337,21 +1341,21 @@ private module MkStage { pragma[inline] additional predicate fwdFlow( - NodeEx node, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - Ap ap, Configuration config + NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, + Configuration config ) { fwdFlow(node, state, cc, summaryCtx, argAp, ap, _, config) } pragma[nomagic] private predicate fwdFlow0( - NodeEx node, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - Ap ap, ApApprox apa, Configuration config + NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, + ApApprox apa, Configuration config ) { sourceNode(node, state, config) and (if hasSourceCallCtx(config) then cc = ccSomeCall() else cc = ccNone()) and argAp = apNone() and - summaryCtx = TParameterPositionNone() and + summaryCtx = TParamNodeNone() and ap = getApNil(node) and apa = getApprox(ap) or @@ -1372,7 +1376,7 @@ private module MkStage { fwdFlow(mid, pragma[only_bind_into](state), _, _, _, ap, apa, pragma[only_bind_into](config)) and jumpStep(mid, node, config) and cc = ccNone() and - summaryCtx = TParameterPositionNone() and + summaryCtx = TParamNodeNone() and argAp = apNone() ) or @@ -1380,7 +1384,7 @@ private module MkStage { fwdFlow(mid, state, _, _, _, nil, pragma[only_bind_into](config)) and additionalJumpStep(mid, node, config) and cc = ccNone() and - summaryCtx = TParameterPositionNone() and + summaryCtx = TParamNodeNone() and argAp = apNone() and ap = getApNil(node) and apa = getApprox(ap) @@ -1390,7 +1394,7 @@ private module MkStage { fwdFlow(mid, state0, _, _, _, nil, pragma[only_bind_into](config)) and additionalJumpStateStep(mid, state0, node, state, config) and cc = ccNone() and - summaryCtx = TParameterPositionNone() and + summaryCtx = TParamNodeNone() and argAp = apNone() and ap = getApNil(node) and apa = getApprox(ap) @@ -1414,10 +1418,10 @@ private module MkStage { fwdFlowIn(_, node, state, _, cc, _, _, ap, apa, config) and if PrevStage::parameterMayFlowThrough(node, apa, config) then ( - summaryCtx = TParameterPositionSome(node.(ParamNodeEx).getPosition()) and + summaryCtx = TParamNodeSome(node.asNode()) and argAp = apSome(ap) ) else ( - summaryCtx = TParameterPositionNone() and argAp = apNone() + summaryCtx = TParamNodeNone() and argAp = apNone() ) or // flow out of a callable @@ -1433,16 +1437,19 @@ private module MkStage { ) or // flow through a callable - exists(DataFlowCall call, ParameterPosition summaryCtx0, Ap argAp0 | - fwdFlowOutFromArg(call, node, state, summaryCtx0, argAp0, ap, apa, config) and - fwdFlowIsEntered(call, cc, summaryCtx, argAp, summaryCtx0, argAp0, config) + exists( + DataFlowCall call, CcCall ccc, RetNodeEx ret, boolean allowsFieldFlow, ApApprox innerArgApa + | + fwdFlowThrough(call, cc, state, ccc, summaryCtx, argAp, ap, apa, ret, innerArgApa, config) and + flowThroughOutOfCall(call, ccc, ret, node, allowsFieldFlow, innerArgApa, apa, config) and + if allowsFieldFlow = false then ap instanceof ApNil else any() ) } pragma[nomagic] private predicate fwdFlowStore( NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, FlowState state, Cc cc, - ParameterPositionOption summaryCtx, ApOption argAp, Configuration config + ParamNodeOption summaryCtx, ApOption argAp, Configuration config ) { exists(DataFlowType contentType, ApApprox apa1 | fwdFlow(node1, state, cc, summaryCtx, argAp, ap1, apa1, config) and @@ -1473,8 +1480,8 @@ private module MkStage { pragma[nomagic] private predicate fwdFlowRead0( - NodeEx node1, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - ApNonNil ap, Configuration config + NodeEx node1, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, ApNonNil ap, + Configuration config ) { fwdFlow(node1, state, cc, summaryCtx, argAp, ap, config) and PrevStage::readStepCand(node1, _, _, config) @@ -1483,7 +1490,7 @@ private module MkStage { pragma[nomagic] private predicate fwdFlowRead( Ap ap, Content c, NodeEx node1, NodeEx node2, FlowState state, Cc cc, - ParameterPositionOption summaryCtx, ApOption argAp, Configuration config + ParamNodeOption summaryCtx, ApOption argAp, Configuration config ) { fwdFlowRead0(node1, state, cc, summaryCtx, argAp, ap, config) and PrevStage::readStepCand(node1, c, node2, config) and @@ -1493,7 +1500,7 @@ private module MkStage { pragma[nomagic] private predicate fwdFlowIn( DataFlowCall call, ParamNodeEx p, FlowState state, Cc outercc, CcCall innercc, - ParameterPositionOption summaryCtx, ApOption argAp, Ap ap, ApApprox apa, Configuration config + ParamNodeOption summaryCtx, ApOption argAp, Ap ap, ApApprox apa, Configuration config ) { exists(ArgNodeEx arg, boolean allowsFieldFlow | fwdFlow(arg, state, outercc, summaryCtx, argAp, ap, apa, config) and @@ -1505,64 +1512,38 @@ private module MkStage { pragma[nomagic] private predicate fwdFlowRetFromArg( - RetNodeEx ret, FlowState state, CcCall ccc, ParameterPosition summaryCtx, ParamNodeEx p, - Ap argAp, ApApprox argApa, Ap ap, ApApprox apa, Configuration config + RetNodeEx ret, FlowState state, CcCall ccc, ParamNodeEx summaryCtx, Ap argAp, ApApprox argApa, + Ap ap, ApApprox apa, Configuration config ) { - exists(DataFlowCallable c, ReturnKindExt kind | + exists(ReturnKindExt kind | fwdFlow(pragma[only_bind_into](ret), state, ccc, - TParameterPositionSome(pragma[only_bind_into](summaryCtx)), apSome(argAp), ap, apa, config) and - getApprox(argAp) = argApa and - c = ret.getEnclosingCallable() and + TParamNodeSome(pragma[only_bind_into](summaryCtx.asNode())), + pragma[only_bind_into](apSome(argAp)), ap, pragma[only_bind_into](apa), + pragma[only_bind_into](config)) and kind = ret.getKind() and - p.isParameterOf(c, pragma[only_bind_into](summaryCtx)) and - parameterFlowThroughAllowed(p, kind) + parameterFlowThroughAllowed(summaryCtx, kind) and + argApa = getApprox(argAp) and + PrevStage::returnMayFlowThrough(ret, argApa, apa, kind, pragma[only_bind_into](config)) ) } pragma[inline] - private predicate fwdFlowInMayFlowThrough( - DataFlowCall call, Cc cc, CcCall innerCc, ParameterPositionOption summaryCtx, ApOption argAp, - ParamNodeEx param, Ap ap, ApApprox apa, Configuration config + private predicate fwdFlowThrough0( + DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, + ApOption argAp, Ap ap, ApApprox apa, RetNodeEx ret, ParamNodeEx innerSummaryCtx, + Ap innerArgAp, ApApprox innerArgApa, Configuration config ) { - fwdFlowIn(call, pragma[only_bind_into](param), _, cc, innerCc, summaryCtx, argAp, ap, - pragma[only_bind_into](apa), pragma[only_bind_into](config)) and - PrevStage::parameterMayFlowThrough(param, apa, config) - } - - // dedup before joining with `flowThroughOutOfCall` - pragma[nomagic] - private predicate fwdFlowInMayFlowThroughProj( - DataFlowCall call, CcCall innerCc, ApApprox apa, Configuration config - ) { - fwdFlowInMayFlowThrough(call, _, innerCc, _, _, _, _, apa, config) - } - - /** - * Same as `flowThroughOutOfCall`, but restricted to calls that are reached - * in the flow covered by `fwdFlow`, where data might flow through the target - * callable and back out at `call`. - */ - pragma[nomagic] - private predicate fwdFlowThroughOutOfCall( - DataFlowCall call, CcCall ccc, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow, - ApApprox argApa, ApApprox apa, Configuration config - ) { - fwdFlowInMayFlowThroughProj(call, ccc, argApa, config) and - flowThroughOutOfCall(call, ccc, ret, out, allowsFieldFlow, argApa, apa, config) + fwdFlowRetFromArg(ret, state, ccc, innerSummaryCtx, innerArgAp, innerArgApa, ap, apa, config) and + fwdFlowIsEntered(call, cc, ccc, summaryCtx, argAp, innerSummaryCtx, innerArgAp, config) } pragma[nomagic] - private predicate fwdFlowOutFromArg( - DataFlowCall call, NodeEx out, FlowState state, ParameterPosition summaryCtx, Ap argAp, Ap ap, - ApApprox apa, Configuration config + private predicate fwdFlowThrough( + DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, + ApOption argAp, Ap ap, ApApprox apa, RetNodeEx ret, ApApprox innerArgApa, Configuration config ) { - exists(RetNodeEx ret, boolean allowsFieldFlow, CcCall ccc, ApApprox argApa | - fwdFlowRetFromArg(pragma[only_bind_into](ret), state, pragma[only_bind_into](ccc), - summaryCtx, _, argAp, pragma[only_bind_into](argApa), ap, pragma[only_bind_into](apa), - config) and - fwdFlowThroughOutOfCall(call, ccc, ret, out, allowsFieldFlow, argApa, apa, config) and - (if allowsFieldFlow = false then ap instanceof ApNil else any()) - ) + fwdFlowThrough0(call, cc, state, ccc, summaryCtx, argAp, ap, apa, ret, _, _, innerArgApa, + config) } /** @@ -1571,12 +1552,14 @@ private module MkStage { */ pragma[nomagic] private predicate fwdFlowIsEntered( - DataFlowCall call, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - ParameterPosition pos, Ap ap, Configuration config + DataFlowCall call, Cc cc, CcCall innerCc, ParamNodeOption summaryCtx, ApOption argAp, + ParamNodeEx p, Ap ap, Configuration config ) { - exists(ParamNodeEx param | - fwdFlowInMayFlowThrough(call, cc, _, summaryCtx, argAp, param, ap, _, config) and - pos = param.getPosition() + exists(ApApprox apa | + fwdFlowIn(call, pragma[only_bind_into](p), _, cc, innerCc, summaryCtx, argAp, ap, + pragma[only_bind_into](apa), pragma[only_bind_into](config)) and + PrevStage::parameterMayFlowThrough(p, apa, config) and + PrevStage::callMayFlowThroughRev(call, pragma[only_bind_into](config)) ) } @@ -1596,23 +1579,31 @@ private module MkStage { fwdFlowConsCand(ap1, c, ap2, config) } + pragma[nomagic] + private predicate returnFlowsThrough0( + DataFlowCall call, FlowState state, CcCall ccc, Ap ap, ApApprox apa, RetNodeEx ret, + ParamNodeEx innerSummaryCtx, Ap innerArgAp, ApApprox innerArgApa, Configuration config + ) { + fwdFlowThrough0(call, _, state, ccc, _, _, ap, apa, ret, innerSummaryCtx, innerArgAp, + innerArgApa, config) + } + pragma[nomagic] private predicate returnFlowsThrough( - RetNodeEx ret, ReturnKindExt kind, FlowState state, CcCall ccc, ParamNodeEx p, Ap argAp, + RetNodeEx ret, ReturnPosition pos, FlowState state, CcCall ccc, ParamNodeEx p, Ap argAp, Ap ap, Configuration config ) { - exists(boolean allowsFieldFlow, ApApprox argApa, ApApprox apa | - fwdFlowRetFromArg(pragma[only_bind_into](ret), state, pragma[only_bind_into](ccc), _, p, - argAp, pragma[only_bind_into](argApa), ap, pragma[only_bind_into](apa), config) and - kind = ret.getKind() and - fwdFlowThroughOutOfCall(_, ccc, ret, _, allowsFieldFlow, argApa, apa, config) and - (if allowsFieldFlow = false then ap instanceof ApNil else any()) + exists(DataFlowCall call, ApApprox apa, boolean allowsFieldFlow, ApApprox innerArgApa | + returnFlowsThrough0(call, state, ccc, ap, apa, ret, p, argAp, innerArgApa, config) and + flowThroughOutOfCall(call, ccc, ret, _, allowsFieldFlow, innerArgApa, apa, config) and + pos = ret.getReturnPosition() and + if allowsFieldFlow = false then ap instanceof ApNil else any() ) } pragma[nomagic] private predicate flowThroughIntoCall( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap argAp, + DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap argAp, Ap ap, Configuration config ) { exists(ApApprox argApa | @@ -1620,7 +1611,7 @@ private module MkStage { allowsFieldFlow, argApa, pragma[only_bind_into](config)) and fwdFlow(arg, _, _, _, _, pragma[only_bind_into](argAp), argApa, pragma[only_bind_into](config)) and - returnFlowsThrough(_, _, _, _, p, pragma[only_bind_into](argAp), _, + returnFlowsThrough(_, _, _, _, p, pragma[only_bind_into](argAp), ap, pragma[only_bind_into](config)) and if allowsFieldFlow = false then argAp instanceof ApNil else any() ) @@ -1639,12 +1630,13 @@ private module MkStage { pragma[nomagic] private predicate flowOutOfCallAp( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, boolean allowsFieldFlow, + DataFlowCall call, RetNodeEx ret, ReturnPosition pos, NodeEx out, boolean allowsFieldFlow, Ap ap, Configuration config ) { exists(ApApprox apa | - flowOutOfCallApa(call, ret, kind, out, allowsFieldFlow, apa, config) and - fwdFlow(ret, _, _, _, _, ap, apa, config) + flowOutOfCallApa(call, ret, _, out, allowsFieldFlow, apa, config) and + fwdFlow(ret, _, _, _, _, ap, apa, config) and + pos = ret.getReturnPosition() ) } @@ -1739,17 +1731,17 @@ private module MkStage { ) or // flow through a callable - exists(DataFlowCall call, ReturnKindExt returnKind0, Ap returnAp0 | - revFlowInToReturn(call, node, state, returnKind0, returnAp0, ap, config) and - revFlowIsReturned(call, returnCtx, returnAp, returnKind0, returnAp0, config) + exists(DataFlowCall call, ParamNodeEx p, ReturnPosition pos, Ap innerReturnAp | + revFlowThrough(call, returnCtx, p, state, pos, returnAp, ap, innerReturnAp, config) and + flowThroughIntoCall(call, node, p, _, ap, innerReturnAp, config) ) or // flow out of a callable - exists(ReturnKindExt kind | - revFlowOut(_, node, kind, state, _, _, ap, config) and - if returnFlowsThrough(node, kind, state, _, _, _, ap, config) + exists(ReturnPosition pos | + revFlowOut(_, node, pos, state, _, _, ap, config) and + if returnFlowsThrough(node, pos, state, _, _, _, ap, config) then ( - returnCtx = TReturnCtxMaybeFlowThrough(kind) and + returnCtx = TReturnCtxMaybeFlowThrough(pos) and returnAp = apSome(ap) ) else ( returnCtx = TReturnCtxNoFlowThrough() and returnAp = apNone() @@ -1782,47 +1774,33 @@ private module MkStage { pragma[nomagic] private predicate revFlowOut( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, FlowState state, ReturnCtx returnCtx, + DataFlowCall call, RetNodeEx ret, ReturnPosition pos, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap, Configuration config ) { exists(NodeEx out, boolean allowsFieldFlow | revFlow(out, state, returnCtx, returnAp, ap, config) and - flowOutOfCallAp(call, ret, kind, out, allowsFieldFlow, ap, config) and + flowOutOfCallAp(call, ret, pos, out, allowsFieldFlow, ap, config) and if allowsFieldFlow = false then ap instanceof ApNil else any() ) } - /** - * Same as `flowThroughIntoCall`, but restricted to calls that are reached - * in the flow covered by `revFlow`, where data might flow through the target - * callable and back out at `call`. - */ - pragma[nomagic] - private predicate revFlowThroughIntoCall( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap argAp, - Configuration config - ) { - flowThroughIntoCall(call, arg, p, allowsFieldFlow, argAp, config) and - revFlowIsReturned(call, _, _, _, _, config) - } - pragma[nomagic] private predicate revFlowParamToReturn( - ParamNodeEx p, FlowState state, ReturnKindExt kind, Ap returnAp, Ap ap, Configuration config + ParamNodeEx p, FlowState state, ReturnPosition pos, Ap returnAp, Ap ap, Configuration config ) { - revFlow(p, state, TReturnCtxMaybeFlowThrough(kind), apSome(returnAp), ap, config) and - parameterFlowThroughAllowed(p, kind) + revFlow(pragma[only_bind_into](p), state, TReturnCtxMaybeFlowThrough(pos), apSome(returnAp), + pragma[only_bind_into](ap), pragma[only_bind_into](config)) and + parameterFlowThroughAllowed(p, pos.getKind()) and + PrevStage::parameterMayFlowThrough(p, getApprox(ap), config) } pragma[nomagic] - private predicate revFlowInToReturn( - DataFlowCall call, ArgNodeEx arg, FlowState state, ReturnKindExt kind, Ap returnAp, Ap ap, - Configuration config + private predicate revFlowThrough( + DataFlowCall call, ReturnCtx returnCtx, ParamNodeEx p, FlowState state, ReturnPosition pos, + ApOption returnAp, Ap ap, Ap innerReturnAp, Configuration config ) { - exists(ParamNodeEx p, boolean allowsFieldFlow | - revFlowParamToReturn(p, state, kind, returnAp, ap, config) and - revFlowThroughIntoCall(call, arg, p, allowsFieldFlow, ap, config) - ) + revFlowParamToReturn(p, state, pos, innerReturnAp, ap, config) and + revFlowIsReturned(call, returnCtx, returnAp, pos, innerReturnAp, config) } /** @@ -1832,12 +1810,12 @@ private module MkStage { */ pragma[nomagic] private predicate revFlowIsReturned( - DataFlowCall call, ReturnCtx returnCtx, ApOption returnAp, ReturnKindExt kind, Ap ap, + DataFlowCall call, ReturnCtx returnCtx, ApOption returnAp, ReturnPosition pos, Ap ap, Configuration config ) { exists(RetNodeEx ret, FlowState state, CcCall ccc | - revFlowOut(call, ret, kind, state, returnCtx, returnAp, ap, config) and - returnFlowsThrough(ret, kind, state, ccc, _, _, ap, config) and + revFlowOut(call, ret, pos, state, returnCtx, returnAp, ap, config) and + returnFlowsThrough(ret, pos, state, ccc, _, _, ap, config) and matchesCall(ccc, call) ) } @@ -1915,17 +1893,17 @@ private module MkStage { pragma[nomagic] private predicate parameterFlowsThroughRev( - ParamNodeEx p, Ap ap, ReturnKindExt kind, Ap returnAp, Configuration config + ParamNodeEx p, Ap ap, ReturnPosition pos, Ap returnAp, Configuration config ) { - revFlow(p, _, TReturnCtxMaybeFlowThrough(kind), apSome(returnAp), ap, config) and - parameterFlowThroughAllowed(p, kind) + revFlow(p, _, TReturnCtxMaybeFlowThrough(pos), apSome(returnAp), ap, config) and + parameterFlowThroughAllowed(p, pos.getKind()) } pragma[nomagic] predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap, Configuration config) { - exists(RetNodeEx ret, ReturnKindExt kind | - returnFlowsThrough(ret, kind, _, _, p, ap, _, config) and - parameterFlowsThroughRev(p, ap, kind, _, config) + exists(RetNodeEx ret, ReturnPosition pos | + returnFlowsThrough(ret, pos, _, _, p, ap, _, config) and + parameterFlowsThroughRev(p, ap, pos, _, config) ) } @@ -1933,20 +1911,21 @@ private module MkStage { predicate returnMayFlowThrough( RetNodeEx ret, Ap argAp, Ap ap, ReturnKindExt kind, Configuration config ) { - exists(ParamNodeEx p | - returnFlowsThrough(ret, kind, _, _, p, argAp, ap, config) and - parameterFlowsThroughRev(p, argAp, kind, ap, config) + exists(ParamNodeEx p, ReturnPosition pos | + returnFlowsThrough(ret, pos, _, _, p, argAp, ap, config) and + parameterFlowsThroughRev(p, argAp, pos, ap, config) and + kind = pos.getKind() ) } pragma[nomagic] - predicate revFlowInToReturnIsReturned( + private predicate revFlowThroughArg( DataFlowCall call, ArgNodeEx arg, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap, Configuration config ) { - exists(ReturnKindExt returnKind0, Ap returnAp0 | - revFlowInToReturn(call, arg, state, returnKind0, returnAp0, ap, config) and - revFlowIsReturned(call, returnCtx, returnAp, returnKind0, returnAp0, config) + exists(ParamNodeEx p, ReturnPosition pos, Ap innerReturnAp | + revFlowThrough(call, returnCtx, p, state, pos, returnAp, ap, innerReturnAp, config) and + flowThroughIntoCall(call, arg, p, _, ap, innerReturnAp, config) ) } @@ -1954,7 +1933,7 @@ private module MkStage { predicate callMayFlowThroughRev(DataFlowCall call, Configuration config) { exists(ArgNodeEx arg, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap | revFlow(arg, state, returnCtx, returnAp, ap, config) and - revFlowInToReturnIsReturned(call, arg, state, returnCtx, returnAp, ap, config) + revFlowThroughArg(call, arg, state, returnCtx, returnAp, ap, config) ) } @@ -1967,8 +1946,9 @@ private module MkStage { conscand = count(TypedContent f0, Ap ap | fwdConsCand(f0, ap, config)) and states = count(FlowState state | fwdFlow(_, state, _, _, _, _, config)) and tuples = - count(NodeEx n, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - Ap ap | fwdFlow(n, state, cc, summaryCtx, argAp, ap, config)) + count(NodeEx n, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap | + fwdFlow(n, state, cc, summaryCtx, argAp, ap, config) + ) or fwd = false and nodes = count(NodeEx node | revFlow(node, _, _, _, _, config)) and @@ -2823,13 +2803,12 @@ private Configuration unbindConf(Configuration conf) { pragma[nomagic] private predicate nodeMayUseSummary0( - NodeEx n, DataFlowCallable c, ParameterPosition pos, FlowState state, AccessPathApprox apa, - Configuration config + NodeEx n, ParamNodeEx p, FlowState state, AccessPathApprox apa, Configuration config ) { exists(AccessPathApprox apa0 | - c = n.getEnclosingCallable() and + Stage5::parameterMayFlowThrough(p, _, _) and Stage5::revFlow(n, state, TReturnCtxMaybeFlowThrough(_), _, apa0, config) and - Stage5::fwdFlow(n, state, any(CallContextCall ccc), TParameterPositionSome(pos), + Stage5::fwdFlow(n, state, any(CallContextCall ccc), TParamNodeSome(p.asNode()), TAccessPathApproxSome(apa), apa0, config) ) } @@ -2838,10 +2817,9 @@ pragma[nomagic] private predicate nodeMayUseSummary( NodeEx n, FlowState state, AccessPathApprox apa, Configuration config ) { - exists(DataFlowCallable c, ParameterPosition pos, ParamNodeEx p | + exists(ParamNodeEx p | Stage5::parameterMayFlowThrough(p, apa, config) and - nodeMayUseSummary0(n, c, pos, state, apa, config) and - p.isParameterOf(c, pos) + nodeMayUseSummary0(n, p, state, apa, config) ) } diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl4.qll b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl4.qll index 6741ccc2f06..1228d00b6ba 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl4.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl4.qll @@ -622,7 +622,11 @@ private predicate parameterFlowThroughAllowed(ParamNodeEx p, ReturnKindExt kind) } private module Stage1 implements StageSig { - class Ap = Unit; + class Ap extends int { + // workaround for bad functionality-induced joins (happens when using `Unit`) + pragma[nomagic] + Ap() { this in [0 .. 1] and this < 1 } + } private class Cc = boolean; @@ -1327,8 +1331,8 @@ private module MkStage { */ pragma[nomagic] additional predicate fwdFlow( - NodeEx node, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - Ap ap, ApApprox apa, Configuration config + NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, + ApApprox apa, Configuration config ) { fwdFlow0(node, state, cc, summaryCtx, argAp, ap, apa, config) and PrevStage::revFlow(node, state, apa, config) and @@ -1337,21 +1341,21 @@ private module MkStage { pragma[inline] additional predicate fwdFlow( - NodeEx node, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - Ap ap, Configuration config + NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, + Configuration config ) { fwdFlow(node, state, cc, summaryCtx, argAp, ap, _, config) } pragma[nomagic] private predicate fwdFlow0( - NodeEx node, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - Ap ap, ApApprox apa, Configuration config + NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, + ApApprox apa, Configuration config ) { sourceNode(node, state, config) and (if hasSourceCallCtx(config) then cc = ccSomeCall() else cc = ccNone()) and argAp = apNone() and - summaryCtx = TParameterPositionNone() and + summaryCtx = TParamNodeNone() and ap = getApNil(node) and apa = getApprox(ap) or @@ -1372,7 +1376,7 @@ private module MkStage { fwdFlow(mid, pragma[only_bind_into](state), _, _, _, ap, apa, pragma[only_bind_into](config)) and jumpStep(mid, node, config) and cc = ccNone() and - summaryCtx = TParameterPositionNone() and + summaryCtx = TParamNodeNone() and argAp = apNone() ) or @@ -1380,7 +1384,7 @@ private module MkStage { fwdFlow(mid, state, _, _, _, nil, pragma[only_bind_into](config)) and additionalJumpStep(mid, node, config) and cc = ccNone() and - summaryCtx = TParameterPositionNone() and + summaryCtx = TParamNodeNone() and argAp = apNone() and ap = getApNil(node) and apa = getApprox(ap) @@ -1390,7 +1394,7 @@ private module MkStage { fwdFlow(mid, state0, _, _, _, nil, pragma[only_bind_into](config)) and additionalJumpStateStep(mid, state0, node, state, config) and cc = ccNone() and - summaryCtx = TParameterPositionNone() and + summaryCtx = TParamNodeNone() and argAp = apNone() and ap = getApNil(node) and apa = getApprox(ap) @@ -1414,10 +1418,10 @@ private module MkStage { fwdFlowIn(_, node, state, _, cc, _, _, ap, apa, config) and if PrevStage::parameterMayFlowThrough(node, apa, config) then ( - summaryCtx = TParameterPositionSome(node.(ParamNodeEx).getPosition()) and + summaryCtx = TParamNodeSome(node.asNode()) and argAp = apSome(ap) ) else ( - summaryCtx = TParameterPositionNone() and argAp = apNone() + summaryCtx = TParamNodeNone() and argAp = apNone() ) or // flow out of a callable @@ -1433,16 +1437,19 @@ private module MkStage { ) or // flow through a callable - exists(DataFlowCall call, ParameterPosition summaryCtx0, Ap argAp0 | - fwdFlowOutFromArg(call, node, state, summaryCtx0, argAp0, ap, apa, config) and - fwdFlowIsEntered(call, cc, summaryCtx, argAp, summaryCtx0, argAp0, config) + exists( + DataFlowCall call, CcCall ccc, RetNodeEx ret, boolean allowsFieldFlow, ApApprox innerArgApa + | + fwdFlowThrough(call, cc, state, ccc, summaryCtx, argAp, ap, apa, ret, innerArgApa, config) and + flowThroughOutOfCall(call, ccc, ret, node, allowsFieldFlow, innerArgApa, apa, config) and + if allowsFieldFlow = false then ap instanceof ApNil else any() ) } pragma[nomagic] private predicate fwdFlowStore( NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, FlowState state, Cc cc, - ParameterPositionOption summaryCtx, ApOption argAp, Configuration config + ParamNodeOption summaryCtx, ApOption argAp, Configuration config ) { exists(DataFlowType contentType, ApApprox apa1 | fwdFlow(node1, state, cc, summaryCtx, argAp, ap1, apa1, config) and @@ -1473,8 +1480,8 @@ private module MkStage { pragma[nomagic] private predicate fwdFlowRead0( - NodeEx node1, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - ApNonNil ap, Configuration config + NodeEx node1, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, ApNonNil ap, + Configuration config ) { fwdFlow(node1, state, cc, summaryCtx, argAp, ap, config) and PrevStage::readStepCand(node1, _, _, config) @@ -1483,7 +1490,7 @@ private module MkStage { pragma[nomagic] private predicate fwdFlowRead( Ap ap, Content c, NodeEx node1, NodeEx node2, FlowState state, Cc cc, - ParameterPositionOption summaryCtx, ApOption argAp, Configuration config + ParamNodeOption summaryCtx, ApOption argAp, Configuration config ) { fwdFlowRead0(node1, state, cc, summaryCtx, argAp, ap, config) and PrevStage::readStepCand(node1, c, node2, config) and @@ -1493,7 +1500,7 @@ private module MkStage { pragma[nomagic] private predicate fwdFlowIn( DataFlowCall call, ParamNodeEx p, FlowState state, Cc outercc, CcCall innercc, - ParameterPositionOption summaryCtx, ApOption argAp, Ap ap, ApApprox apa, Configuration config + ParamNodeOption summaryCtx, ApOption argAp, Ap ap, ApApprox apa, Configuration config ) { exists(ArgNodeEx arg, boolean allowsFieldFlow | fwdFlow(arg, state, outercc, summaryCtx, argAp, ap, apa, config) and @@ -1505,64 +1512,38 @@ private module MkStage { pragma[nomagic] private predicate fwdFlowRetFromArg( - RetNodeEx ret, FlowState state, CcCall ccc, ParameterPosition summaryCtx, ParamNodeEx p, - Ap argAp, ApApprox argApa, Ap ap, ApApprox apa, Configuration config + RetNodeEx ret, FlowState state, CcCall ccc, ParamNodeEx summaryCtx, Ap argAp, ApApprox argApa, + Ap ap, ApApprox apa, Configuration config ) { - exists(DataFlowCallable c, ReturnKindExt kind | + exists(ReturnKindExt kind | fwdFlow(pragma[only_bind_into](ret), state, ccc, - TParameterPositionSome(pragma[only_bind_into](summaryCtx)), apSome(argAp), ap, apa, config) and - getApprox(argAp) = argApa and - c = ret.getEnclosingCallable() and + TParamNodeSome(pragma[only_bind_into](summaryCtx.asNode())), + pragma[only_bind_into](apSome(argAp)), ap, pragma[only_bind_into](apa), + pragma[only_bind_into](config)) and kind = ret.getKind() and - p.isParameterOf(c, pragma[only_bind_into](summaryCtx)) and - parameterFlowThroughAllowed(p, kind) + parameterFlowThroughAllowed(summaryCtx, kind) and + argApa = getApprox(argAp) and + PrevStage::returnMayFlowThrough(ret, argApa, apa, kind, pragma[only_bind_into](config)) ) } pragma[inline] - private predicate fwdFlowInMayFlowThrough( - DataFlowCall call, Cc cc, CcCall innerCc, ParameterPositionOption summaryCtx, ApOption argAp, - ParamNodeEx param, Ap ap, ApApprox apa, Configuration config + private predicate fwdFlowThrough0( + DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, + ApOption argAp, Ap ap, ApApprox apa, RetNodeEx ret, ParamNodeEx innerSummaryCtx, + Ap innerArgAp, ApApprox innerArgApa, Configuration config ) { - fwdFlowIn(call, pragma[only_bind_into](param), _, cc, innerCc, summaryCtx, argAp, ap, - pragma[only_bind_into](apa), pragma[only_bind_into](config)) and - PrevStage::parameterMayFlowThrough(param, apa, config) - } - - // dedup before joining with `flowThroughOutOfCall` - pragma[nomagic] - private predicate fwdFlowInMayFlowThroughProj( - DataFlowCall call, CcCall innerCc, ApApprox apa, Configuration config - ) { - fwdFlowInMayFlowThrough(call, _, innerCc, _, _, _, _, apa, config) - } - - /** - * Same as `flowThroughOutOfCall`, but restricted to calls that are reached - * in the flow covered by `fwdFlow`, where data might flow through the target - * callable and back out at `call`. - */ - pragma[nomagic] - private predicate fwdFlowThroughOutOfCall( - DataFlowCall call, CcCall ccc, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow, - ApApprox argApa, ApApprox apa, Configuration config - ) { - fwdFlowInMayFlowThroughProj(call, ccc, argApa, config) and - flowThroughOutOfCall(call, ccc, ret, out, allowsFieldFlow, argApa, apa, config) + fwdFlowRetFromArg(ret, state, ccc, innerSummaryCtx, innerArgAp, innerArgApa, ap, apa, config) and + fwdFlowIsEntered(call, cc, ccc, summaryCtx, argAp, innerSummaryCtx, innerArgAp, config) } pragma[nomagic] - private predicate fwdFlowOutFromArg( - DataFlowCall call, NodeEx out, FlowState state, ParameterPosition summaryCtx, Ap argAp, Ap ap, - ApApprox apa, Configuration config + private predicate fwdFlowThrough( + DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, + ApOption argAp, Ap ap, ApApprox apa, RetNodeEx ret, ApApprox innerArgApa, Configuration config ) { - exists(RetNodeEx ret, boolean allowsFieldFlow, CcCall ccc, ApApprox argApa | - fwdFlowRetFromArg(pragma[only_bind_into](ret), state, pragma[only_bind_into](ccc), - summaryCtx, _, argAp, pragma[only_bind_into](argApa), ap, pragma[only_bind_into](apa), - config) and - fwdFlowThroughOutOfCall(call, ccc, ret, out, allowsFieldFlow, argApa, apa, config) and - (if allowsFieldFlow = false then ap instanceof ApNil else any()) - ) + fwdFlowThrough0(call, cc, state, ccc, summaryCtx, argAp, ap, apa, ret, _, _, innerArgApa, + config) } /** @@ -1571,12 +1552,14 @@ private module MkStage { */ pragma[nomagic] private predicate fwdFlowIsEntered( - DataFlowCall call, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - ParameterPosition pos, Ap ap, Configuration config + DataFlowCall call, Cc cc, CcCall innerCc, ParamNodeOption summaryCtx, ApOption argAp, + ParamNodeEx p, Ap ap, Configuration config ) { - exists(ParamNodeEx param | - fwdFlowInMayFlowThrough(call, cc, _, summaryCtx, argAp, param, ap, _, config) and - pos = param.getPosition() + exists(ApApprox apa | + fwdFlowIn(call, pragma[only_bind_into](p), _, cc, innerCc, summaryCtx, argAp, ap, + pragma[only_bind_into](apa), pragma[only_bind_into](config)) and + PrevStage::parameterMayFlowThrough(p, apa, config) and + PrevStage::callMayFlowThroughRev(call, pragma[only_bind_into](config)) ) } @@ -1596,23 +1579,31 @@ private module MkStage { fwdFlowConsCand(ap1, c, ap2, config) } + pragma[nomagic] + private predicate returnFlowsThrough0( + DataFlowCall call, FlowState state, CcCall ccc, Ap ap, ApApprox apa, RetNodeEx ret, + ParamNodeEx innerSummaryCtx, Ap innerArgAp, ApApprox innerArgApa, Configuration config + ) { + fwdFlowThrough0(call, _, state, ccc, _, _, ap, apa, ret, innerSummaryCtx, innerArgAp, + innerArgApa, config) + } + pragma[nomagic] private predicate returnFlowsThrough( - RetNodeEx ret, ReturnKindExt kind, FlowState state, CcCall ccc, ParamNodeEx p, Ap argAp, + RetNodeEx ret, ReturnPosition pos, FlowState state, CcCall ccc, ParamNodeEx p, Ap argAp, Ap ap, Configuration config ) { - exists(boolean allowsFieldFlow, ApApprox argApa, ApApprox apa | - fwdFlowRetFromArg(pragma[only_bind_into](ret), state, pragma[only_bind_into](ccc), _, p, - argAp, pragma[only_bind_into](argApa), ap, pragma[only_bind_into](apa), config) and - kind = ret.getKind() and - fwdFlowThroughOutOfCall(_, ccc, ret, _, allowsFieldFlow, argApa, apa, config) and - (if allowsFieldFlow = false then ap instanceof ApNil else any()) + exists(DataFlowCall call, ApApprox apa, boolean allowsFieldFlow, ApApprox innerArgApa | + returnFlowsThrough0(call, state, ccc, ap, apa, ret, p, argAp, innerArgApa, config) and + flowThroughOutOfCall(call, ccc, ret, _, allowsFieldFlow, innerArgApa, apa, config) and + pos = ret.getReturnPosition() and + if allowsFieldFlow = false then ap instanceof ApNil else any() ) } pragma[nomagic] private predicate flowThroughIntoCall( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap argAp, + DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap argAp, Ap ap, Configuration config ) { exists(ApApprox argApa | @@ -1620,7 +1611,7 @@ private module MkStage { allowsFieldFlow, argApa, pragma[only_bind_into](config)) and fwdFlow(arg, _, _, _, _, pragma[only_bind_into](argAp), argApa, pragma[only_bind_into](config)) and - returnFlowsThrough(_, _, _, _, p, pragma[only_bind_into](argAp), _, + returnFlowsThrough(_, _, _, _, p, pragma[only_bind_into](argAp), ap, pragma[only_bind_into](config)) and if allowsFieldFlow = false then argAp instanceof ApNil else any() ) @@ -1639,12 +1630,13 @@ private module MkStage { pragma[nomagic] private predicate flowOutOfCallAp( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, boolean allowsFieldFlow, + DataFlowCall call, RetNodeEx ret, ReturnPosition pos, NodeEx out, boolean allowsFieldFlow, Ap ap, Configuration config ) { exists(ApApprox apa | - flowOutOfCallApa(call, ret, kind, out, allowsFieldFlow, apa, config) and - fwdFlow(ret, _, _, _, _, ap, apa, config) + flowOutOfCallApa(call, ret, _, out, allowsFieldFlow, apa, config) and + fwdFlow(ret, _, _, _, _, ap, apa, config) and + pos = ret.getReturnPosition() ) } @@ -1739,17 +1731,17 @@ private module MkStage { ) or // flow through a callable - exists(DataFlowCall call, ReturnKindExt returnKind0, Ap returnAp0 | - revFlowInToReturn(call, node, state, returnKind0, returnAp0, ap, config) and - revFlowIsReturned(call, returnCtx, returnAp, returnKind0, returnAp0, config) + exists(DataFlowCall call, ParamNodeEx p, ReturnPosition pos, Ap innerReturnAp | + revFlowThrough(call, returnCtx, p, state, pos, returnAp, ap, innerReturnAp, config) and + flowThroughIntoCall(call, node, p, _, ap, innerReturnAp, config) ) or // flow out of a callable - exists(ReturnKindExt kind | - revFlowOut(_, node, kind, state, _, _, ap, config) and - if returnFlowsThrough(node, kind, state, _, _, _, ap, config) + exists(ReturnPosition pos | + revFlowOut(_, node, pos, state, _, _, ap, config) and + if returnFlowsThrough(node, pos, state, _, _, _, ap, config) then ( - returnCtx = TReturnCtxMaybeFlowThrough(kind) and + returnCtx = TReturnCtxMaybeFlowThrough(pos) and returnAp = apSome(ap) ) else ( returnCtx = TReturnCtxNoFlowThrough() and returnAp = apNone() @@ -1782,47 +1774,33 @@ private module MkStage { pragma[nomagic] private predicate revFlowOut( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, FlowState state, ReturnCtx returnCtx, + DataFlowCall call, RetNodeEx ret, ReturnPosition pos, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap, Configuration config ) { exists(NodeEx out, boolean allowsFieldFlow | revFlow(out, state, returnCtx, returnAp, ap, config) and - flowOutOfCallAp(call, ret, kind, out, allowsFieldFlow, ap, config) and + flowOutOfCallAp(call, ret, pos, out, allowsFieldFlow, ap, config) and if allowsFieldFlow = false then ap instanceof ApNil else any() ) } - /** - * Same as `flowThroughIntoCall`, but restricted to calls that are reached - * in the flow covered by `revFlow`, where data might flow through the target - * callable and back out at `call`. - */ - pragma[nomagic] - private predicate revFlowThroughIntoCall( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap argAp, - Configuration config - ) { - flowThroughIntoCall(call, arg, p, allowsFieldFlow, argAp, config) and - revFlowIsReturned(call, _, _, _, _, config) - } - pragma[nomagic] private predicate revFlowParamToReturn( - ParamNodeEx p, FlowState state, ReturnKindExt kind, Ap returnAp, Ap ap, Configuration config + ParamNodeEx p, FlowState state, ReturnPosition pos, Ap returnAp, Ap ap, Configuration config ) { - revFlow(p, state, TReturnCtxMaybeFlowThrough(kind), apSome(returnAp), ap, config) and - parameterFlowThroughAllowed(p, kind) + revFlow(pragma[only_bind_into](p), state, TReturnCtxMaybeFlowThrough(pos), apSome(returnAp), + pragma[only_bind_into](ap), pragma[only_bind_into](config)) and + parameterFlowThroughAllowed(p, pos.getKind()) and + PrevStage::parameterMayFlowThrough(p, getApprox(ap), config) } pragma[nomagic] - private predicate revFlowInToReturn( - DataFlowCall call, ArgNodeEx arg, FlowState state, ReturnKindExt kind, Ap returnAp, Ap ap, - Configuration config + private predicate revFlowThrough( + DataFlowCall call, ReturnCtx returnCtx, ParamNodeEx p, FlowState state, ReturnPosition pos, + ApOption returnAp, Ap ap, Ap innerReturnAp, Configuration config ) { - exists(ParamNodeEx p, boolean allowsFieldFlow | - revFlowParamToReturn(p, state, kind, returnAp, ap, config) and - revFlowThroughIntoCall(call, arg, p, allowsFieldFlow, ap, config) - ) + revFlowParamToReturn(p, state, pos, innerReturnAp, ap, config) and + revFlowIsReturned(call, returnCtx, returnAp, pos, innerReturnAp, config) } /** @@ -1832,12 +1810,12 @@ private module MkStage { */ pragma[nomagic] private predicate revFlowIsReturned( - DataFlowCall call, ReturnCtx returnCtx, ApOption returnAp, ReturnKindExt kind, Ap ap, + DataFlowCall call, ReturnCtx returnCtx, ApOption returnAp, ReturnPosition pos, Ap ap, Configuration config ) { exists(RetNodeEx ret, FlowState state, CcCall ccc | - revFlowOut(call, ret, kind, state, returnCtx, returnAp, ap, config) and - returnFlowsThrough(ret, kind, state, ccc, _, _, ap, config) and + revFlowOut(call, ret, pos, state, returnCtx, returnAp, ap, config) and + returnFlowsThrough(ret, pos, state, ccc, _, _, ap, config) and matchesCall(ccc, call) ) } @@ -1915,17 +1893,17 @@ private module MkStage { pragma[nomagic] private predicate parameterFlowsThroughRev( - ParamNodeEx p, Ap ap, ReturnKindExt kind, Ap returnAp, Configuration config + ParamNodeEx p, Ap ap, ReturnPosition pos, Ap returnAp, Configuration config ) { - revFlow(p, _, TReturnCtxMaybeFlowThrough(kind), apSome(returnAp), ap, config) and - parameterFlowThroughAllowed(p, kind) + revFlow(p, _, TReturnCtxMaybeFlowThrough(pos), apSome(returnAp), ap, config) and + parameterFlowThroughAllowed(p, pos.getKind()) } pragma[nomagic] predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap, Configuration config) { - exists(RetNodeEx ret, ReturnKindExt kind | - returnFlowsThrough(ret, kind, _, _, p, ap, _, config) and - parameterFlowsThroughRev(p, ap, kind, _, config) + exists(RetNodeEx ret, ReturnPosition pos | + returnFlowsThrough(ret, pos, _, _, p, ap, _, config) and + parameterFlowsThroughRev(p, ap, pos, _, config) ) } @@ -1933,20 +1911,21 @@ private module MkStage { predicate returnMayFlowThrough( RetNodeEx ret, Ap argAp, Ap ap, ReturnKindExt kind, Configuration config ) { - exists(ParamNodeEx p | - returnFlowsThrough(ret, kind, _, _, p, argAp, ap, config) and - parameterFlowsThroughRev(p, argAp, kind, ap, config) + exists(ParamNodeEx p, ReturnPosition pos | + returnFlowsThrough(ret, pos, _, _, p, argAp, ap, config) and + parameterFlowsThroughRev(p, argAp, pos, ap, config) and + kind = pos.getKind() ) } pragma[nomagic] - predicate revFlowInToReturnIsReturned( + private predicate revFlowThroughArg( DataFlowCall call, ArgNodeEx arg, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap, Configuration config ) { - exists(ReturnKindExt returnKind0, Ap returnAp0 | - revFlowInToReturn(call, arg, state, returnKind0, returnAp0, ap, config) and - revFlowIsReturned(call, returnCtx, returnAp, returnKind0, returnAp0, config) + exists(ParamNodeEx p, ReturnPosition pos, Ap innerReturnAp | + revFlowThrough(call, returnCtx, p, state, pos, returnAp, ap, innerReturnAp, config) and + flowThroughIntoCall(call, arg, p, _, ap, innerReturnAp, config) ) } @@ -1954,7 +1933,7 @@ private module MkStage { predicate callMayFlowThroughRev(DataFlowCall call, Configuration config) { exists(ArgNodeEx arg, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap | revFlow(arg, state, returnCtx, returnAp, ap, config) and - revFlowInToReturnIsReturned(call, arg, state, returnCtx, returnAp, ap, config) + revFlowThroughArg(call, arg, state, returnCtx, returnAp, ap, config) ) } @@ -1967,8 +1946,9 @@ private module MkStage { conscand = count(TypedContent f0, Ap ap | fwdConsCand(f0, ap, config)) and states = count(FlowState state | fwdFlow(_, state, _, _, _, _, config)) and tuples = - count(NodeEx n, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - Ap ap | fwdFlow(n, state, cc, summaryCtx, argAp, ap, config)) + count(NodeEx n, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap | + fwdFlow(n, state, cc, summaryCtx, argAp, ap, config) + ) or fwd = false and nodes = count(NodeEx node | revFlow(node, _, _, _, _, config)) and @@ -2823,13 +2803,12 @@ private Configuration unbindConf(Configuration conf) { pragma[nomagic] private predicate nodeMayUseSummary0( - NodeEx n, DataFlowCallable c, ParameterPosition pos, FlowState state, AccessPathApprox apa, - Configuration config + NodeEx n, ParamNodeEx p, FlowState state, AccessPathApprox apa, Configuration config ) { exists(AccessPathApprox apa0 | - c = n.getEnclosingCallable() and + Stage5::parameterMayFlowThrough(p, _, _) and Stage5::revFlow(n, state, TReturnCtxMaybeFlowThrough(_), _, apa0, config) and - Stage5::fwdFlow(n, state, any(CallContextCall ccc), TParameterPositionSome(pos), + Stage5::fwdFlow(n, state, any(CallContextCall ccc), TParamNodeSome(p.asNode()), TAccessPathApproxSome(apa), apa0, config) ) } @@ -2838,10 +2817,9 @@ pragma[nomagic] private predicate nodeMayUseSummary( NodeEx n, FlowState state, AccessPathApprox apa, Configuration config ) { - exists(DataFlowCallable c, ParameterPosition pos, ParamNodeEx p | + exists(ParamNodeEx p | Stage5::parameterMayFlowThrough(p, apa, config) and - nodeMayUseSummary0(n, c, pos, state, apa, config) and - p.isParameterOf(c, pos) + nodeMayUseSummary0(n, p, state, apa, config) ) } diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl5.qll b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl5.qll index 6741ccc2f06..1228d00b6ba 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl5.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl5.qll @@ -622,7 +622,11 @@ private predicate parameterFlowThroughAllowed(ParamNodeEx p, ReturnKindExt kind) } private module Stage1 implements StageSig { - class Ap = Unit; + class Ap extends int { + // workaround for bad functionality-induced joins (happens when using `Unit`) + pragma[nomagic] + Ap() { this in [0 .. 1] and this < 1 } + } private class Cc = boolean; @@ -1327,8 +1331,8 @@ private module MkStage { */ pragma[nomagic] additional predicate fwdFlow( - NodeEx node, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - Ap ap, ApApprox apa, Configuration config + NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, + ApApprox apa, Configuration config ) { fwdFlow0(node, state, cc, summaryCtx, argAp, ap, apa, config) and PrevStage::revFlow(node, state, apa, config) and @@ -1337,21 +1341,21 @@ private module MkStage { pragma[inline] additional predicate fwdFlow( - NodeEx node, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - Ap ap, Configuration config + NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, + Configuration config ) { fwdFlow(node, state, cc, summaryCtx, argAp, ap, _, config) } pragma[nomagic] private predicate fwdFlow0( - NodeEx node, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - Ap ap, ApApprox apa, Configuration config + NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, + ApApprox apa, Configuration config ) { sourceNode(node, state, config) and (if hasSourceCallCtx(config) then cc = ccSomeCall() else cc = ccNone()) and argAp = apNone() and - summaryCtx = TParameterPositionNone() and + summaryCtx = TParamNodeNone() and ap = getApNil(node) and apa = getApprox(ap) or @@ -1372,7 +1376,7 @@ private module MkStage { fwdFlow(mid, pragma[only_bind_into](state), _, _, _, ap, apa, pragma[only_bind_into](config)) and jumpStep(mid, node, config) and cc = ccNone() and - summaryCtx = TParameterPositionNone() and + summaryCtx = TParamNodeNone() and argAp = apNone() ) or @@ -1380,7 +1384,7 @@ private module MkStage { fwdFlow(mid, state, _, _, _, nil, pragma[only_bind_into](config)) and additionalJumpStep(mid, node, config) and cc = ccNone() and - summaryCtx = TParameterPositionNone() and + summaryCtx = TParamNodeNone() and argAp = apNone() and ap = getApNil(node) and apa = getApprox(ap) @@ -1390,7 +1394,7 @@ private module MkStage { fwdFlow(mid, state0, _, _, _, nil, pragma[only_bind_into](config)) and additionalJumpStateStep(mid, state0, node, state, config) and cc = ccNone() and - summaryCtx = TParameterPositionNone() and + summaryCtx = TParamNodeNone() and argAp = apNone() and ap = getApNil(node) and apa = getApprox(ap) @@ -1414,10 +1418,10 @@ private module MkStage { fwdFlowIn(_, node, state, _, cc, _, _, ap, apa, config) and if PrevStage::parameterMayFlowThrough(node, apa, config) then ( - summaryCtx = TParameterPositionSome(node.(ParamNodeEx).getPosition()) and + summaryCtx = TParamNodeSome(node.asNode()) and argAp = apSome(ap) ) else ( - summaryCtx = TParameterPositionNone() and argAp = apNone() + summaryCtx = TParamNodeNone() and argAp = apNone() ) or // flow out of a callable @@ -1433,16 +1437,19 @@ private module MkStage { ) or // flow through a callable - exists(DataFlowCall call, ParameterPosition summaryCtx0, Ap argAp0 | - fwdFlowOutFromArg(call, node, state, summaryCtx0, argAp0, ap, apa, config) and - fwdFlowIsEntered(call, cc, summaryCtx, argAp, summaryCtx0, argAp0, config) + exists( + DataFlowCall call, CcCall ccc, RetNodeEx ret, boolean allowsFieldFlow, ApApprox innerArgApa + | + fwdFlowThrough(call, cc, state, ccc, summaryCtx, argAp, ap, apa, ret, innerArgApa, config) and + flowThroughOutOfCall(call, ccc, ret, node, allowsFieldFlow, innerArgApa, apa, config) and + if allowsFieldFlow = false then ap instanceof ApNil else any() ) } pragma[nomagic] private predicate fwdFlowStore( NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, FlowState state, Cc cc, - ParameterPositionOption summaryCtx, ApOption argAp, Configuration config + ParamNodeOption summaryCtx, ApOption argAp, Configuration config ) { exists(DataFlowType contentType, ApApprox apa1 | fwdFlow(node1, state, cc, summaryCtx, argAp, ap1, apa1, config) and @@ -1473,8 +1480,8 @@ private module MkStage { pragma[nomagic] private predicate fwdFlowRead0( - NodeEx node1, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - ApNonNil ap, Configuration config + NodeEx node1, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, ApNonNil ap, + Configuration config ) { fwdFlow(node1, state, cc, summaryCtx, argAp, ap, config) and PrevStage::readStepCand(node1, _, _, config) @@ -1483,7 +1490,7 @@ private module MkStage { pragma[nomagic] private predicate fwdFlowRead( Ap ap, Content c, NodeEx node1, NodeEx node2, FlowState state, Cc cc, - ParameterPositionOption summaryCtx, ApOption argAp, Configuration config + ParamNodeOption summaryCtx, ApOption argAp, Configuration config ) { fwdFlowRead0(node1, state, cc, summaryCtx, argAp, ap, config) and PrevStage::readStepCand(node1, c, node2, config) and @@ -1493,7 +1500,7 @@ private module MkStage { pragma[nomagic] private predicate fwdFlowIn( DataFlowCall call, ParamNodeEx p, FlowState state, Cc outercc, CcCall innercc, - ParameterPositionOption summaryCtx, ApOption argAp, Ap ap, ApApprox apa, Configuration config + ParamNodeOption summaryCtx, ApOption argAp, Ap ap, ApApprox apa, Configuration config ) { exists(ArgNodeEx arg, boolean allowsFieldFlow | fwdFlow(arg, state, outercc, summaryCtx, argAp, ap, apa, config) and @@ -1505,64 +1512,38 @@ private module MkStage { pragma[nomagic] private predicate fwdFlowRetFromArg( - RetNodeEx ret, FlowState state, CcCall ccc, ParameterPosition summaryCtx, ParamNodeEx p, - Ap argAp, ApApprox argApa, Ap ap, ApApprox apa, Configuration config + RetNodeEx ret, FlowState state, CcCall ccc, ParamNodeEx summaryCtx, Ap argAp, ApApprox argApa, + Ap ap, ApApprox apa, Configuration config ) { - exists(DataFlowCallable c, ReturnKindExt kind | + exists(ReturnKindExt kind | fwdFlow(pragma[only_bind_into](ret), state, ccc, - TParameterPositionSome(pragma[only_bind_into](summaryCtx)), apSome(argAp), ap, apa, config) and - getApprox(argAp) = argApa and - c = ret.getEnclosingCallable() and + TParamNodeSome(pragma[only_bind_into](summaryCtx.asNode())), + pragma[only_bind_into](apSome(argAp)), ap, pragma[only_bind_into](apa), + pragma[only_bind_into](config)) and kind = ret.getKind() and - p.isParameterOf(c, pragma[only_bind_into](summaryCtx)) and - parameterFlowThroughAllowed(p, kind) + parameterFlowThroughAllowed(summaryCtx, kind) and + argApa = getApprox(argAp) and + PrevStage::returnMayFlowThrough(ret, argApa, apa, kind, pragma[only_bind_into](config)) ) } pragma[inline] - private predicate fwdFlowInMayFlowThrough( - DataFlowCall call, Cc cc, CcCall innerCc, ParameterPositionOption summaryCtx, ApOption argAp, - ParamNodeEx param, Ap ap, ApApprox apa, Configuration config + private predicate fwdFlowThrough0( + DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, + ApOption argAp, Ap ap, ApApprox apa, RetNodeEx ret, ParamNodeEx innerSummaryCtx, + Ap innerArgAp, ApApprox innerArgApa, Configuration config ) { - fwdFlowIn(call, pragma[only_bind_into](param), _, cc, innerCc, summaryCtx, argAp, ap, - pragma[only_bind_into](apa), pragma[only_bind_into](config)) and - PrevStage::parameterMayFlowThrough(param, apa, config) - } - - // dedup before joining with `flowThroughOutOfCall` - pragma[nomagic] - private predicate fwdFlowInMayFlowThroughProj( - DataFlowCall call, CcCall innerCc, ApApprox apa, Configuration config - ) { - fwdFlowInMayFlowThrough(call, _, innerCc, _, _, _, _, apa, config) - } - - /** - * Same as `flowThroughOutOfCall`, but restricted to calls that are reached - * in the flow covered by `fwdFlow`, where data might flow through the target - * callable and back out at `call`. - */ - pragma[nomagic] - private predicate fwdFlowThroughOutOfCall( - DataFlowCall call, CcCall ccc, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow, - ApApprox argApa, ApApprox apa, Configuration config - ) { - fwdFlowInMayFlowThroughProj(call, ccc, argApa, config) and - flowThroughOutOfCall(call, ccc, ret, out, allowsFieldFlow, argApa, apa, config) + fwdFlowRetFromArg(ret, state, ccc, innerSummaryCtx, innerArgAp, innerArgApa, ap, apa, config) and + fwdFlowIsEntered(call, cc, ccc, summaryCtx, argAp, innerSummaryCtx, innerArgAp, config) } pragma[nomagic] - private predicate fwdFlowOutFromArg( - DataFlowCall call, NodeEx out, FlowState state, ParameterPosition summaryCtx, Ap argAp, Ap ap, - ApApprox apa, Configuration config + private predicate fwdFlowThrough( + DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, + ApOption argAp, Ap ap, ApApprox apa, RetNodeEx ret, ApApprox innerArgApa, Configuration config ) { - exists(RetNodeEx ret, boolean allowsFieldFlow, CcCall ccc, ApApprox argApa | - fwdFlowRetFromArg(pragma[only_bind_into](ret), state, pragma[only_bind_into](ccc), - summaryCtx, _, argAp, pragma[only_bind_into](argApa), ap, pragma[only_bind_into](apa), - config) and - fwdFlowThroughOutOfCall(call, ccc, ret, out, allowsFieldFlow, argApa, apa, config) and - (if allowsFieldFlow = false then ap instanceof ApNil else any()) - ) + fwdFlowThrough0(call, cc, state, ccc, summaryCtx, argAp, ap, apa, ret, _, _, innerArgApa, + config) } /** @@ -1571,12 +1552,14 @@ private module MkStage { */ pragma[nomagic] private predicate fwdFlowIsEntered( - DataFlowCall call, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - ParameterPosition pos, Ap ap, Configuration config + DataFlowCall call, Cc cc, CcCall innerCc, ParamNodeOption summaryCtx, ApOption argAp, + ParamNodeEx p, Ap ap, Configuration config ) { - exists(ParamNodeEx param | - fwdFlowInMayFlowThrough(call, cc, _, summaryCtx, argAp, param, ap, _, config) and - pos = param.getPosition() + exists(ApApprox apa | + fwdFlowIn(call, pragma[only_bind_into](p), _, cc, innerCc, summaryCtx, argAp, ap, + pragma[only_bind_into](apa), pragma[only_bind_into](config)) and + PrevStage::parameterMayFlowThrough(p, apa, config) and + PrevStage::callMayFlowThroughRev(call, pragma[only_bind_into](config)) ) } @@ -1596,23 +1579,31 @@ private module MkStage { fwdFlowConsCand(ap1, c, ap2, config) } + pragma[nomagic] + private predicate returnFlowsThrough0( + DataFlowCall call, FlowState state, CcCall ccc, Ap ap, ApApprox apa, RetNodeEx ret, + ParamNodeEx innerSummaryCtx, Ap innerArgAp, ApApprox innerArgApa, Configuration config + ) { + fwdFlowThrough0(call, _, state, ccc, _, _, ap, apa, ret, innerSummaryCtx, innerArgAp, + innerArgApa, config) + } + pragma[nomagic] private predicate returnFlowsThrough( - RetNodeEx ret, ReturnKindExt kind, FlowState state, CcCall ccc, ParamNodeEx p, Ap argAp, + RetNodeEx ret, ReturnPosition pos, FlowState state, CcCall ccc, ParamNodeEx p, Ap argAp, Ap ap, Configuration config ) { - exists(boolean allowsFieldFlow, ApApprox argApa, ApApprox apa | - fwdFlowRetFromArg(pragma[only_bind_into](ret), state, pragma[only_bind_into](ccc), _, p, - argAp, pragma[only_bind_into](argApa), ap, pragma[only_bind_into](apa), config) and - kind = ret.getKind() and - fwdFlowThroughOutOfCall(_, ccc, ret, _, allowsFieldFlow, argApa, apa, config) and - (if allowsFieldFlow = false then ap instanceof ApNil else any()) + exists(DataFlowCall call, ApApprox apa, boolean allowsFieldFlow, ApApprox innerArgApa | + returnFlowsThrough0(call, state, ccc, ap, apa, ret, p, argAp, innerArgApa, config) and + flowThroughOutOfCall(call, ccc, ret, _, allowsFieldFlow, innerArgApa, apa, config) and + pos = ret.getReturnPosition() and + if allowsFieldFlow = false then ap instanceof ApNil else any() ) } pragma[nomagic] private predicate flowThroughIntoCall( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap argAp, + DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap argAp, Ap ap, Configuration config ) { exists(ApApprox argApa | @@ -1620,7 +1611,7 @@ private module MkStage { allowsFieldFlow, argApa, pragma[only_bind_into](config)) and fwdFlow(arg, _, _, _, _, pragma[only_bind_into](argAp), argApa, pragma[only_bind_into](config)) and - returnFlowsThrough(_, _, _, _, p, pragma[only_bind_into](argAp), _, + returnFlowsThrough(_, _, _, _, p, pragma[only_bind_into](argAp), ap, pragma[only_bind_into](config)) and if allowsFieldFlow = false then argAp instanceof ApNil else any() ) @@ -1639,12 +1630,13 @@ private module MkStage { pragma[nomagic] private predicate flowOutOfCallAp( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, boolean allowsFieldFlow, + DataFlowCall call, RetNodeEx ret, ReturnPosition pos, NodeEx out, boolean allowsFieldFlow, Ap ap, Configuration config ) { exists(ApApprox apa | - flowOutOfCallApa(call, ret, kind, out, allowsFieldFlow, apa, config) and - fwdFlow(ret, _, _, _, _, ap, apa, config) + flowOutOfCallApa(call, ret, _, out, allowsFieldFlow, apa, config) and + fwdFlow(ret, _, _, _, _, ap, apa, config) and + pos = ret.getReturnPosition() ) } @@ -1739,17 +1731,17 @@ private module MkStage { ) or // flow through a callable - exists(DataFlowCall call, ReturnKindExt returnKind0, Ap returnAp0 | - revFlowInToReturn(call, node, state, returnKind0, returnAp0, ap, config) and - revFlowIsReturned(call, returnCtx, returnAp, returnKind0, returnAp0, config) + exists(DataFlowCall call, ParamNodeEx p, ReturnPosition pos, Ap innerReturnAp | + revFlowThrough(call, returnCtx, p, state, pos, returnAp, ap, innerReturnAp, config) and + flowThroughIntoCall(call, node, p, _, ap, innerReturnAp, config) ) or // flow out of a callable - exists(ReturnKindExt kind | - revFlowOut(_, node, kind, state, _, _, ap, config) and - if returnFlowsThrough(node, kind, state, _, _, _, ap, config) + exists(ReturnPosition pos | + revFlowOut(_, node, pos, state, _, _, ap, config) and + if returnFlowsThrough(node, pos, state, _, _, _, ap, config) then ( - returnCtx = TReturnCtxMaybeFlowThrough(kind) and + returnCtx = TReturnCtxMaybeFlowThrough(pos) and returnAp = apSome(ap) ) else ( returnCtx = TReturnCtxNoFlowThrough() and returnAp = apNone() @@ -1782,47 +1774,33 @@ private module MkStage { pragma[nomagic] private predicate revFlowOut( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, FlowState state, ReturnCtx returnCtx, + DataFlowCall call, RetNodeEx ret, ReturnPosition pos, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap, Configuration config ) { exists(NodeEx out, boolean allowsFieldFlow | revFlow(out, state, returnCtx, returnAp, ap, config) and - flowOutOfCallAp(call, ret, kind, out, allowsFieldFlow, ap, config) and + flowOutOfCallAp(call, ret, pos, out, allowsFieldFlow, ap, config) and if allowsFieldFlow = false then ap instanceof ApNil else any() ) } - /** - * Same as `flowThroughIntoCall`, but restricted to calls that are reached - * in the flow covered by `revFlow`, where data might flow through the target - * callable and back out at `call`. - */ - pragma[nomagic] - private predicate revFlowThroughIntoCall( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap argAp, - Configuration config - ) { - flowThroughIntoCall(call, arg, p, allowsFieldFlow, argAp, config) and - revFlowIsReturned(call, _, _, _, _, config) - } - pragma[nomagic] private predicate revFlowParamToReturn( - ParamNodeEx p, FlowState state, ReturnKindExt kind, Ap returnAp, Ap ap, Configuration config + ParamNodeEx p, FlowState state, ReturnPosition pos, Ap returnAp, Ap ap, Configuration config ) { - revFlow(p, state, TReturnCtxMaybeFlowThrough(kind), apSome(returnAp), ap, config) and - parameterFlowThroughAllowed(p, kind) + revFlow(pragma[only_bind_into](p), state, TReturnCtxMaybeFlowThrough(pos), apSome(returnAp), + pragma[only_bind_into](ap), pragma[only_bind_into](config)) and + parameterFlowThroughAllowed(p, pos.getKind()) and + PrevStage::parameterMayFlowThrough(p, getApprox(ap), config) } pragma[nomagic] - private predicate revFlowInToReturn( - DataFlowCall call, ArgNodeEx arg, FlowState state, ReturnKindExt kind, Ap returnAp, Ap ap, - Configuration config + private predicate revFlowThrough( + DataFlowCall call, ReturnCtx returnCtx, ParamNodeEx p, FlowState state, ReturnPosition pos, + ApOption returnAp, Ap ap, Ap innerReturnAp, Configuration config ) { - exists(ParamNodeEx p, boolean allowsFieldFlow | - revFlowParamToReturn(p, state, kind, returnAp, ap, config) and - revFlowThroughIntoCall(call, arg, p, allowsFieldFlow, ap, config) - ) + revFlowParamToReturn(p, state, pos, innerReturnAp, ap, config) and + revFlowIsReturned(call, returnCtx, returnAp, pos, innerReturnAp, config) } /** @@ -1832,12 +1810,12 @@ private module MkStage { */ pragma[nomagic] private predicate revFlowIsReturned( - DataFlowCall call, ReturnCtx returnCtx, ApOption returnAp, ReturnKindExt kind, Ap ap, + DataFlowCall call, ReturnCtx returnCtx, ApOption returnAp, ReturnPosition pos, Ap ap, Configuration config ) { exists(RetNodeEx ret, FlowState state, CcCall ccc | - revFlowOut(call, ret, kind, state, returnCtx, returnAp, ap, config) and - returnFlowsThrough(ret, kind, state, ccc, _, _, ap, config) and + revFlowOut(call, ret, pos, state, returnCtx, returnAp, ap, config) and + returnFlowsThrough(ret, pos, state, ccc, _, _, ap, config) and matchesCall(ccc, call) ) } @@ -1915,17 +1893,17 @@ private module MkStage { pragma[nomagic] private predicate parameterFlowsThroughRev( - ParamNodeEx p, Ap ap, ReturnKindExt kind, Ap returnAp, Configuration config + ParamNodeEx p, Ap ap, ReturnPosition pos, Ap returnAp, Configuration config ) { - revFlow(p, _, TReturnCtxMaybeFlowThrough(kind), apSome(returnAp), ap, config) and - parameterFlowThroughAllowed(p, kind) + revFlow(p, _, TReturnCtxMaybeFlowThrough(pos), apSome(returnAp), ap, config) and + parameterFlowThroughAllowed(p, pos.getKind()) } pragma[nomagic] predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap, Configuration config) { - exists(RetNodeEx ret, ReturnKindExt kind | - returnFlowsThrough(ret, kind, _, _, p, ap, _, config) and - parameterFlowsThroughRev(p, ap, kind, _, config) + exists(RetNodeEx ret, ReturnPosition pos | + returnFlowsThrough(ret, pos, _, _, p, ap, _, config) and + parameterFlowsThroughRev(p, ap, pos, _, config) ) } @@ -1933,20 +1911,21 @@ private module MkStage { predicate returnMayFlowThrough( RetNodeEx ret, Ap argAp, Ap ap, ReturnKindExt kind, Configuration config ) { - exists(ParamNodeEx p | - returnFlowsThrough(ret, kind, _, _, p, argAp, ap, config) and - parameterFlowsThroughRev(p, argAp, kind, ap, config) + exists(ParamNodeEx p, ReturnPosition pos | + returnFlowsThrough(ret, pos, _, _, p, argAp, ap, config) and + parameterFlowsThroughRev(p, argAp, pos, ap, config) and + kind = pos.getKind() ) } pragma[nomagic] - predicate revFlowInToReturnIsReturned( + private predicate revFlowThroughArg( DataFlowCall call, ArgNodeEx arg, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap, Configuration config ) { - exists(ReturnKindExt returnKind0, Ap returnAp0 | - revFlowInToReturn(call, arg, state, returnKind0, returnAp0, ap, config) and - revFlowIsReturned(call, returnCtx, returnAp, returnKind0, returnAp0, config) + exists(ParamNodeEx p, ReturnPosition pos, Ap innerReturnAp | + revFlowThrough(call, returnCtx, p, state, pos, returnAp, ap, innerReturnAp, config) and + flowThroughIntoCall(call, arg, p, _, ap, innerReturnAp, config) ) } @@ -1954,7 +1933,7 @@ private module MkStage { predicate callMayFlowThroughRev(DataFlowCall call, Configuration config) { exists(ArgNodeEx arg, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap | revFlow(arg, state, returnCtx, returnAp, ap, config) and - revFlowInToReturnIsReturned(call, arg, state, returnCtx, returnAp, ap, config) + revFlowThroughArg(call, arg, state, returnCtx, returnAp, ap, config) ) } @@ -1967,8 +1946,9 @@ private module MkStage { conscand = count(TypedContent f0, Ap ap | fwdConsCand(f0, ap, config)) and states = count(FlowState state | fwdFlow(_, state, _, _, _, _, config)) and tuples = - count(NodeEx n, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - Ap ap | fwdFlow(n, state, cc, summaryCtx, argAp, ap, config)) + count(NodeEx n, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap | + fwdFlow(n, state, cc, summaryCtx, argAp, ap, config) + ) or fwd = false and nodes = count(NodeEx node | revFlow(node, _, _, _, _, config)) and @@ -2823,13 +2803,12 @@ private Configuration unbindConf(Configuration conf) { pragma[nomagic] private predicate nodeMayUseSummary0( - NodeEx n, DataFlowCallable c, ParameterPosition pos, FlowState state, AccessPathApprox apa, - Configuration config + NodeEx n, ParamNodeEx p, FlowState state, AccessPathApprox apa, Configuration config ) { exists(AccessPathApprox apa0 | - c = n.getEnclosingCallable() and + Stage5::parameterMayFlowThrough(p, _, _) and Stage5::revFlow(n, state, TReturnCtxMaybeFlowThrough(_), _, apa0, config) and - Stage5::fwdFlow(n, state, any(CallContextCall ccc), TParameterPositionSome(pos), + Stage5::fwdFlow(n, state, any(CallContextCall ccc), TParamNodeSome(p.asNode()), TAccessPathApproxSome(apa), apa0, config) ) } @@ -2838,10 +2817,9 @@ pragma[nomagic] private predicate nodeMayUseSummary( NodeEx n, FlowState state, AccessPathApprox apa, Configuration config ) { - exists(DataFlowCallable c, ParameterPosition pos, ParamNodeEx p | + exists(ParamNodeEx p | Stage5::parameterMayFlowThrough(p, apa, config) and - nodeMayUseSummary0(n, c, pos, state, apa, config) and - p.isParameterOf(c, pos) + nodeMayUseSummary0(n, p, state, apa, config) ) } diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl6.qll b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl6.qll index 6741ccc2f06..1228d00b6ba 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl6.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl6.qll @@ -622,7 +622,11 @@ private predicate parameterFlowThroughAllowed(ParamNodeEx p, ReturnKindExt kind) } private module Stage1 implements StageSig { - class Ap = Unit; + class Ap extends int { + // workaround for bad functionality-induced joins (happens when using `Unit`) + pragma[nomagic] + Ap() { this in [0 .. 1] and this < 1 } + } private class Cc = boolean; @@ -1327,8 +1331,8 @@ private module MkStage { */ pragma[nomagic] additional predicate fwdFlow( - NodeEx node, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - Ap ap, ApApprox apa, Configuration config + NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, + ApApprox apa, Configuration config ) { fwdFlow0(node, state, cc, summaryCtx, argAp, ap, apa, config) and PrevStage::revFlow(node, state, apa, config) and @@ -1337,21 +1341,21 @@ private module MkStage { pragma[inline] additional predicate fwdFlow( - NodeEx node, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - Ap ap, Configuration config + NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, + Configuration config ) { fwdFlow(node, state, cc, summaryCtx, argAp, ap, _, config) } pragma[nomagic] private predicate fwdFlow0( - NodeEx node, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - Ap ap, ApApprox apa, Configuration config + NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, + ApApprox apa, Configuration config ) { sourceNode(node, state, config) and (if hasSourceCallCtx(config) then cc = ccSomeCall() else cc = ccNone()) and argAp = apNone() and - summaryCtx = TParameterPositionNone() and + summaryCtx = TParamNodeNone() and ap = getApNil(node) and apa = getApprox(ap) or @@ -1372,7 +1376,7 @@ private module MkStage { fwdFlow(mid, pragma[only_bind_into](state), _, _, _, ap, apa, pragma[only_bind_into](config)) and jumpStep(mid, node, config) and cc = ccNone() and - summaryCtx = TParameterPositionNone() and + summaryCtx = TParamNodeNone() and argAp = apNone() ) or @@ -1380,7 +1384,7 @@ private module MkStage { fwdFlow(mid, state, _, _, _, nil, pragma[only_bind_into](config)) and additionalJumpStep(mid, node, config) and cc = ccNone() and - summaryCtx = TParameterPositionNone() and + summaryCtx = TParamNodeNone() and argAp = apNone() and ap = getApNil(node) and apa = getApprox(ap) @@ -1390,7 +1394,7 @@ private module MkStage { fwdFlow(mid, state0, _, _, _, nil, pragma[only_bind_into](config)) and additionalJumpStateStep(mid, state0, node, state, config) and cc = ccNone() and - summaryCtx = TParameterPositionNone() and + summaryCtx = TParamNodeNone() and argAp = apNone() and ap = getApNil(node) and apa = getApprox(ap) @@ -1414,10 +1418,10 @@ private module MkStage { fwdFlowIn(_, node, state, _, cc, _, _, ap, apa, config) and if PrevStage::parameterMayFlowThrough(node, apa, config) then ( - summaryCtx = TParameterPositionSome(node.(ParamNodeEx).getPosition()) and + summaryCtx = TParamNodeSome(node.asNode()) and argAp = apSome(ap) ) else ( - summaryCtx = TParameterPositionNone() and argAp = apNone() + summaryCtx = TParamNodeNone() and argAp = apNone() ) or // flow out of a callable @@ -1433,16 +1437,19 @@ private module MkStage { ) or // flow through a callable - exists(DataFlowCall call, ParameterPosition summaryCtx0, Ap argAp0 | - fwdFlowOutFromArg(call, node, state, summaryCtx0, argAp0, ap, apa, config) and - fwdFlowIsEntered(call, cc, summaryCtx, argAp, summaryCtx0, argAp0, config) + exists( + DataFlowCall call, CcCall ccc, RetNodeEx ret, boolean allowsFieldFlow, ApApprox innerArgApa + | + fwdFlowThrough(call, cc, state, ccc, summaryCtx, argAp, ap, apa, ret, innerArgApa, config) and + flowThroughOutOfCall(call, ccc, ret, node, allowsFieldFlow, innerArgApa, apa, config) and + if allowsFieldFlow = false then ap instanceof ApNil else any() ) } pragma[nomagic] private predicate fwdFlowStore( NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, FlowState state, Cc cc, - ParameterPositionOption summaryCtx, ApOption argAp, Configuration config + ParamNodeOption summaryCtx, ApOption argAp, Configuration config ) { exists(DataFlowType contentType, ApApprox apa1 | fwdFlow(node1, state, cc, summaryCtx, argAp, ap1, apa1, config) and @@ -1473,8 +1480,8 @@ private module MkStage { pragma[nomagic] private predicate fwdFlowRead0( - NodeEx node1, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - ApNonNil ap, Configuration config + NodeEx node1, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, ApNonNil ap, + Configuration config ) { fwdFlow(node1, state, cc, summaryCtx, argAp, ap, config) and PrevStage::readStepCand(node1, _, _, config) @@ -1483,7 +1490,7 @@ private module MkStage { pragma[nomagic] private predicate fwdFlowRead( Ap ap, Content c, NodeEx node1, NodeEx node2, FlowState state, Cc cc, - ParameterPositionOption summaryCtx, ApOption argAp, Configuration config + ParamNodeOption summaryCtx, ApOption argAp, Configuration config ) { fwdFlowRead0(node1, state, cc, summaryCtx, argAp, ap, config) and PrevStage::readStepCand(node1, c, node2, config) and @@ -1493,7 +1500,7 @@ private module MkStage { pragma[nomagic] private predicate fwdFlowIn( DataFlowCall call, ParamNodeEx p, FlowState state, Cc outercc, CcCall innercc, - ParameterPositionOption summaryCtx, ApOption argAp, Ap ap, ApApprox apa, Configuration config + ParamNodeOption summaryCtx, ApOption argAp, Ap ap, ApApprox apa, Configuration config ) { exists(ArgNodeEx arg, boolean allowsFieldFlow | fwdFlow(arg, state, outercc, summaryCtx, argAp, ap, apa, config) and @@ -1505,64 +1512,38 @@ private module MkStage { pragma[nomagic] private predicate fwdFlowRetFromArg( - RetNodeEx ret, FlowState state, CcCall ccc, ParameterPosition summaryCtx, ParamNodeEx p, - Ap argAp, ApApprox argApa, Ap ap, ApApprox apa, Configuration config + RetNodeEx ret, FlowState state, CcCall ccc, ParamNodeEx summaryCtx, Ap argAp, ApApprox argApa, + Ap ap, ApApprox apa, Configuration config ) { - exists(DataFlowCallable c, ReturnKindExt kind | + exists(ReturnKindExt kind | fwdFlow(pragma[only_bind_into](ret), state, ccc, - TParameterPositionSome(pragma[only_bind_into](summaryCtx)), apSome(argAp), ap, apa, config) and - getApprox(argAp) = argApa and - c = ret.getEnclosingCallable() and + TParamNodeSome(pragma[only_bind_into](summaryCtx.asNode())), + pragma[only_bind_into](apSome(argAp)), ap, pragma[only_bind_into](apa), + pragma[only_bind_into](config)) and kind = ret.getKind() and - p.isParameterOf(c, pragma[only_bind_into](summaryCtx)) and - parameterFlowThroughAllowed(p, kind) + parameterFlowThroughAllowed(summaryCtx, kind) and + argApa = getApprox(argAp) and + PrevStage::returnMayFlowThrough(ret, argApa, apa, kind, pragma[only_bind_into](config)) ) } pragma[inline] - private predicate fwdFlowInMayFlowThrough( - DataFlowCall call, Cc cc, CcCall innerCc, ParameterPositionOption summaryCtx, ApOption argAp, - ParamNodeEx param, Ap ap, ApApprox apa, Configuration config + private predicate fwdFlowThrough0( + DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, + ApOption argAp, Ap ap, ApApprox apa, RetNodeEx ret, ParamNodeEx innerSummaryCtx, + Ap innerArgAp, ApApprox innerArgApa, Configuration config ) { - fwdFlowIn(call, pragma[only_bind_into](param), _, cc, innerCc, summaryCtx, argAp, ap, - pragma[only_bind_into](apa), pragma[only_bind_into](config)) and - PrevStage::parameterMayFlowThrough(param, apa, config) - } - - // dedup before joining with `flowThroughOutOfCall` - pragma[nomagic] - private predicate fwdFlowInMayFlowThroughProj( - DataFlowCall call, CcCall innerCc, ApApprox apa, Configuration config - ) { - fwdFlowInMayFlowThrough(call, _, innerCc, _, _, _, _, apa, config) - } - - /** - * Same as `flowThroughOutOfCall`, but restricted to calls that are reached - * in the flow covered by `fwdFlow`, where data might flow through the target - * callable and back out at `call`. - */ - pragma[nomagic] - private predicate fwdFlowThroughOutOfCall( - DataFlowCall call, CcCall ccc, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow, - ApApprox argApa, ApApprox apa, Configuration config - ) { - fwdFlowInMayFlowThroughProj(call, ccc, argApa, config) and - flowThroughOutOfCall(call, ccc, ret, out, allowsFieldFlow, argApa, apa, config) + fwdFlowRetFromArg(ret, state, ccc, innerSummaryCtx, innerArgAp, innerArgApa, ap, apa, config) and + fwdFlowIsEntered(call, cc, ccc, summaryCtx, argAp, innerSummaryCtx, innerArgAp, config) } pragma[nomagic] - private predicate fwdFlowOutFromArg( - DataFlowCall call, NodeEx out, FlowState state, ParameterPosition summaryCtx, Ap argAp, Ap ap, - ApApprox apa, Configuration config + private predicate fwdFlowThrough( + DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, + ApOption argAp, Ap ap, ApApprox apa, RetNodeEx ret, ApApprox innerArgApa, Configuration config ) { - exists(RetNodeEx ret, boolean allowsFieldFlow, CcCall ccc, ApApprox argApa | - fwdFlowRetFromArg(pragma[only_bind_into](ret), state, pragma[only_bind_into](ccc), - summaryCtx, _, argAp, pragma[only_bind_into](argApa), ap, pragma[only_bind_into](apa), - config) and - fwdFlowThroughOutOfCall(call, ccc, ret, out, allowsFieldFlow, argApa, apa, config) and - (if allowsFieldFlow = false then ap instanceof ApNil else any()) - ) + fwdFlowThrough0(call, cc, state, ccc, summaryCtx, argAp, ap, apa, ret, _, _, innerArgApa, + config) } /** @@ -1571,12 +1552,14 @@ private module MkStage { */ pragma[nomagic] private predicate fwdFlowIsEntered( - DataFlowCall call, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - ParameterPosition pos, Ap ap, Configuration config + DataFlowCall call, Cc cc, CcCall innerCc, ParamNodeOption summaryCtx, ApOption argAp, + ParamNodeEx p, Ap ap, Configuration config ) { - exists(ParamNodeEx param | - fwdFlowInMayFlowThrough(call, cc, _, summaryCtx, argAp, param, ap, _, config) and - pos = param.getPosition() + exists(ApApprox apa | + fwdFlowIn(call, pragma[only_bind_into](p), _, cc, innerCc, summaryCtx, argAp, ap, + pragma[only_bind_into](apa), pragma[only_bind_into](config)) and + PrevStage::parameterMayFlowThrough(p, apa, config) and + PrevStage::callMayFlowThroughRev(call, pragma[only_bind_into](config)) ) } @@ -1596,23 +1579,31 @@ private module MkStage { fwdFlowConsCand(ap1, c, ap2, config) } + pragma[nomagic] + private predicate returnFlowsThrough0( + DataFlowCall call, FlowState state, CcCall ccc, Ap ap, ApApprox apa, RetNodeEx ret, + ParamNodeEx innerSummaryCtx, Ap innerArgAp, ApApprox innerArgApa, Configuration config + ) { + fwdFlowThrough0(call, _, state, ccc, _, _, ap, apa, ret, innerSummaryCtx, innerArgAp, + innerArgApa, config) + } + pragma[nomagic] private predicate returnFlowsThrough( - RetNodeEx ret, ReturnKindExt kind, FlowState state, CcCall ccc, ParamNodeEx p, Ap argAp, + RetNodeEx ret, ReturnPosition pos, FlowState state, CcCall ccc, ParamNodeEx p, Ap argAp, Ap ap, Configuration config ) { - exists(boolean allowsFieldFlow, ApApprox argApa, ApApprox apa | - fwdFlowRetFromArg(pragma[only_bind_into](ret), state, pragma[only_bind_into](ccc), _, p, - argAp, pragma[only_bind_into](argApa), ap, pragma[only_bind_into](apa), config) and - kind = ret.getKind() and - fwdFlowThroughOutOfCall(_, ccc, ret, _, allowsFieldFlow, argApa, apa, config) and - (if allowsFieldFlow = false then ap instanceof ApNil else any()) + exists(DataFlowCall call, ApApprox apa, boolean allowsFieldFlow, ApApprox innerArgApa | + returnFlowsThrough0(call, state, ccc, ap, apa, ret, p, argAp, innerArgApa, config) and + flowThroughOutOfCall(call, ccc, ret, _, allowsFieldFlow, innerArgApa, apa, config) and + pos = ret.getReturnPosition() and + if allowsFieldFlow = false then ap instanceof ApNil else any() ) } pragma[nomagic] private predicate flowThroughIntoCall( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap argAp, + DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap argAp, Ap ap, Configuration config ) { exists(ApApprox argApa | @@ -1620,7 +1611,7 @@ private module MkStage { allowsFieldFlow, argApa, pragma[only_bind_into](config)) and fwdFlow(arg, _, _, _, _, pragma[only_bind_into](argAp), argApa, pragma[only_bind_into](config)) and - returnFlowsThrough(_, _, _, _, p, pragma[only_bind_into](argAp), _, + returnFlowsThrough(_, _, _, _, p, pragma[only_bind_into](argAp), ap, pragma[only_bind_into](config)) and if allowsFieldFlow = false then argAp instanceof ApNil else any() ) @@ -1639,12 +1630,13 @@ private module MkStage { pragma[nomagic] private predicate flowOutOfCallAp( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, boolean allowsFieldFlow, + DataFlowCall call, RetNodeEx ret, ReturnPosition pos, NodeEx out, boolean allowsFieldFlow, Ap ap, Configuration config ) { exists(ApApprox apa | - flowOutOfCallApa(call, ret, kind, out, allowsFieldFlow, apa, config) and - fwdFlow(ret, _, _, _, _, ap, apa, config) + flowOutOfCallApa(call, ret, _, out, allowsFieldFlow, apa, config) and + fwdFlow(ret, _, _, _, _, ap, apa, config) and + pos = ret.getReturnPosition() ) } @@ -1739,17 +1731,17 @@ private module MkStage { ) or // flow through a callable - exists(DataFlowCall call, ReturnKindExt returnKind0, Ap returnAp0 | - revFlowInToReturn(call, node, state, returnKind0, returnAp0, ap, config) and - revFlowIsReturned(call, returnCtx, returnAp, returnKind0, returnAp0, config) + exists(DataFlowCall call, ParamNodeEx p, ReturnPosition pos, Ap innerReturnAp | + revFlowThrough(call, returnCtx, p, state, pos, returnAp, ap, innerReturnAp, config) and + flowThroughIntoCall(call, node, p, _, ap, innerReturnAp, config) ) or // flow out of a callable - exists(ReturnKindExt kind | - revFlowOut(_, node, kind, state, _, _, ap, config) and - if returnFlowsThrough(node, kind, state, _, _, _, ap, config) + exists(ReturnPosition pos | + revFlowOut(_, node, pos, state, _, _, ap, config) and + if returnFlowsThrough(node, pos, state, _, _, _, ap, config) then ( - returnCtx = TReturnCtxMaybeFlowThrough(kind) and + returnCtx = TReturnCtxMaybeFlowThrough(pos) and returnAp = apSome(ap) ) else ( returnCtx = TReturnCtxNoFlowThrough() and returnAp = apNone() @@ -1782,47 +1774,33 @@ private module MkStage { pragma[nomagic] private predicate revFlowOut( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, FlowState state, ReturnCtx returnCtx, + DataFlowCall call, RetNodeEx ret, ReturnPosition pos, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap, Configuration config ) { exists(NodeEx out, boolean allowsFieldFlow | revFlow(out, state, returnCtx, returnAp, ap, config) and - flowOutOfCallAp(call, ret, kind, out, allowsFieldFlow, ap, config) and + flowOutOfCallAp(call, ret, pos, out, allowsFieldFlow, ap, config) and if allowsFieldFlow = false then ap instanceof ApNil else any() ) } - /** - * Same as `flowThroughIntoCall`, but restricted to calls that are reached - * in the flow covered by `revFlow`, where data might flow through the target - * callable and back out at `call`. - */ - pragma[nomagic] - private predicate revFlowThroughIntoCall( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap argAp, - Configuration config - ) { - flowThroughIntoCall(call, arg, p, allowsFieldFlow, argAp, config) and - revFlowIsReturned(call, _, _, _, _, config) - } - pragma[nomagic] private predicate revFlowParamToReturn( - ParamNodeEx p, FlowState state, ReturnKindExt kind, Ap returnAp, Ap ap, Configuration config + ParamNodeEx p, FlowState state, ReturnPosition pos, Ap returnAp, Ap ap, Configuration config ) { - revFlow(p, state, TReturnCtxMaybeFlowThrough(kind), apSome(returnAp), ap, config) and - parameterFlowThroughAllowed(p, kind) + revFlow(pragma[only_bind_into](p), state, TReturnCtxMaybeFlowThrough(pos), apSome(returnAp), + pragma[only_bind_into](ap), pragma[only_bind_into](config)) and + parameterFlowThroughAllowed(p, pos.getKind()) and + PrevStage::parameterMayFlowThrough(p, getApprox(ap), config) } pragma[nomagic] - private predicate revFlowInToReturn( - DataFlowCall call, ArgNodeEx arg, FlowState state, ReturnKindExt kind, Ap returnAp, Ap ap, - Configuration config + private predicate revFlowThrough( + DataFlowCall call, ReturnCtx returnCtx, ParamNodeEx p, FlowState state, ReturnPosition pos, + ApOption returnAp, Ap ap, Ap innerReturnAp, Configuration config ) { - exists(ParamNodeEx p, boolean allowsFieldFlow | - revFlowParamToReturn(p, state, kind, returnAp, ap, config) and - revFlowThroughIntoCall(call, arg, p, allowsFieldFlow, ap, config) - ) + revFlowParamToReturn(p, state, pos, innerReturnAp, ap, config) and + revFlowIsReturned(call, returnCtx, returnAp, pos, innerReturnAp, config) } /** @@ -1832,12 +1810,12 @@ private module MkStage { */ pragma[nomagic] private predicate revFlowIsReturned( - DataFlowCall call, ReturnCtx returnCtx, ApOption returnAp, ReturnKindExt kind, Ap ap, + DataFlowCall call, ReturnCtx returnCtx, ApOption returnAp, ReturnPosition pos, Ap ap, Configuration config ) { exists(RetNodeEx ret, FlowState state, CcCall ccc | - revFlowOut(call, ret, kind, state, returnCtx, returnAp, ap, config) and - returnFlowsThrough(ret, kind, state, ccc, _, _, ap, config) and + revFlowOut(call, ret, pos, state, returnCtx, returnAp, ap, config) and + returnFlowsThrough(ret, pos, state, ccc, _, _, ap, config) and matchesCall(ccc, call) ) } @@ -1915,17 +1893,17 @@ private module MkStage { pragma[nomagic] private predicate parameterFlowsThroughRev( - ParamNodeEx p, Ap ap, ReturnKindExt kind, Ap returnAp, Configuration config + ParamNodeEx p, Ap ap, ReturnPosition pos, Ap returnAp, Configuration config ) { - revFlow(p, _, TReturnCtxMaybeFlowThrough(kind), apSome(returnAp), ap, config) and - parameterFlowThroughAllowed(p, kind) + revFlow(p, _, TReturnCtxMaybeFlowThrough(pos), apSome(returnAp), ap, config) and + parameterFlowThroughAllowed(p, pos.getKind()) } pragma[nomagic] predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap, Configuration config) { - exists(RetNodeEx ret, ReturnKindExt kind | - returnFlowsThrough(ret, kind, _, _, p, ap, _, config) and - parameterFlowsThroughRev(p, ap, kind, _, config) + exists(RetNodeEx ret, ReturnPosition pos | + returnFlowsThrough(ret, pos, _, _, p, ap, _, config) and + parameterFlowsThroughRev(p, ap, pos, _, config) ) } @@ -1933,20 +1911,21 @@ private module MkStage { predicate returnMayFlowThrough( RetNodeEx ret, Ap argAp, Ap ap, ReturnKindExt kind, Configuration config ) { - exists(ParamNodeEx p | - returnFlowsThrough(ret, kind, _, _, p, argAp, ap, config) and - parameterFlowsThroughRev(p, argAp, kind, ap, config) + exists(ParamNodeEx p, ReturnPosition pos | + returnFlowsThrough(ret, pos, _, _, p, argAp, ap, config) and + parameterFlowsThroughRev(p, argAp, pos, ap, config) and + kind = pos.getKind() ) } pragma[nomagic] - predicate revFlowInToReturnIsReturned( + private predicate revFlowThroughArg( DataFlowCall call, ArgNodeEx arg, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap, Configuration config ) { - exists(ReturnKindExt returnKind0, Ap returnAp0 | - revFlowInToReturn(call, arg, state, returnKind0, returnAp0, ap, config) and - revFlowIsReturned(call, returnCtx, returnAp, returnKind0, returnAp0, config) + exists(ParamNodeEx p, ReturnPosition pos, Ap innerReturnAp | + revFlowThrough(call, returnCtx, p, state, pos, returnAp, ap, innerReturnAp, config) and + flowThroughIntoCall(call, arg, p, _, ap, innerReturnAp, config) ) } @@ -1954,7 +1933,7 @@ private module MkStage { predicate callMayFlowThroughRev(DataFlowCall call, Configuration config) { exists(ArgNodeEx arg, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap | revFlow(arg, state, returnCtx, returnAp, ap, config) and - revFlowInToReturnIsReturned(call, arg, state, returnCtx, returnAp, ap, config) + revFlowThroughArg(call, arg, state, returnCtx, returnAp, ap, config) ) } @@ -1967,8 +1946,9 @@ private module MkStage { conscand = count(TypedContent f0, Ap ap | fwdConsCand(f0, ap, config)) and states = count(FlowState state | fwdFlow(_, state, _, _, _, _, config)) and tuples = - count(NodeEx n, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - Ap ap | fwdFlow(n, state, cc, summaryCtx, argAp, ap, config)) + count(NodeEx n, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap | + fwdFlow(n, state, cc, summaryCtx, argAp, ap, config) + ) or fwd = false and nodes = count(NodeEx node | revFlow(node, _, _, _, _, config)) and @@ -2823,13 +2803,12 @@ private Configuration unbindConf(Configuration conf) { pragma[nomagic] private predicate nodeMayUseSummary0( - NodeEx n, DataFlowCallable c, ParameterPosition pos, FlowState state, AccessPathApprox apa, - Configuration config + NodeEx n, ParamNodeEx p, FlowState state, AccessPathApprox apa, Configuration config ) { exists(AccessPathApprox apa0 | - c = n.getEnclosingCallable() and + Stage5::parameterMayFlowThrough(p, _, _) and Stage5::revFlow(n, state, TReturnCtxMaybeFlowThrough(_), _, apa0, config) and - Stage5::fwdFlow(n, state, any(CallContextCall ccc), TParameterPositionSome(pos), + Stage5::fwdFlow(n, state, any(CallContextCall ccc), TParamNodeSome(p.asNode()), TAccessPathApproxSome(apa), apa0, config) ) } @@ -2838,10 +2817,9 @@ pragma[nomagic] private predicate nodeMayUseSummary( NodeEx n, FlowState state, AccessPathApprox apa, Configuration config ) { - exists(DataFlowCallable c, ParameterPosition pos, ParamNodeEx p | + exists(ParamNodeEx p | Stage5::parameterMayFlowThrough(p, apa, config) and - nodeMayUseSummary0(n, c, pos, state, apa, config) and - p.isParameterOf(c, pos) + nodeMayUseSummary0(n, p, state, apa, config) ) } diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplCommon.qll b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplCommon.qll index c66aefced8d..9aa6a529a5b 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplCommon.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplCommon.qll @@ -916,15 +916,15 @@ private module Cached { TDataFlowCallSome(DataFlowCall call) cached - newtype TParameterPositionOption = - TParameterPositionNone() or - TParameterPositionSome(ParameterPosition pos) + newtype TParamNodeOption = + TParamNodeNone() or + TParamNodeSome(ParamNode p) cached newtype TReturnCtx = TReturnCtxNone() or TReturnCtxNoFlowThrough() or - TReturnCtxMaybeFlowThrough(ReturnKindExt kind) + TReturnCtxMaybeFlowThrough(ReturnPosition pos) cached newtype TTypedContentApprox = @@ -1343,15 +1343,15 @@ class DataFlowCallOption extends TDataFlowCallOption { } } -/** An optional `ParameterPosition`. */ -class ParameterPositionOption extends TParameterPositionOption { +/** An optional `ParamNode`. */ +class ParamNodeOption extends TParamNodeOption { string toString() { - this = TParameterPositionNone() and + this = TParamNodeNone() and result = "(none)" or - exists(ParameterPosition pos | - this = TParameterPositionSome(pos) and - result = pos.toString() + exists(ParamNode p | + this = TParamNodeSome(p) and + result = p.toString() ) } } @@ -1363,7 +1363,7 @@ class ParameterPositionOption extends TParameterPositionOption { * * - `TReturnCtxNone()`: no return flow. * - `TReturnCtxNoFlowThrough()`: return flow, but flow through is not possible. - * - `TReturnCtxMaybeFlowThrough(ReturnKindExt kind)`: return flow, of kind `kind`, and + * - `TReturnCtxMaybeFlowThrough(ReturnPosition pos)`: return flow, of kind `pos`, and * flow through may be possible. */ class ReturnCtx extends TReturnCtx { @@ -1374,9 +1374,9 @@ class ReturnCtx extends TReturnCtx { this = TReturnCtxNoFlowThrough() and result = "(no flow through)" or - exists(ReturnKindExt kind | - this = TReturnCtxMaybeFlowThrough(kind) and - result = kind.toString() + exists(ReturnPosition pos | + this = TReturnCtxMaybeFlowThrough(pos) and + result = pos.toString() ) } } diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplForOnActivityResult.qll b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplForOnActivityResult.qll index 6741ccc2f06..1228d00b6ba 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplForOnActivityResult.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplForOnActivityResult.qll @@ -622,7 +622,11 @@ private predicate parameterFlowThroughAllowed(ParamNodeEx p, ReturnKindExt kind) } private module Stage1 implements StageSig { - class Ap = Unit; + class Ap extends int { + // workaround for bad functionality-induced joins (happens when using `Unit`) + pragma[nomagic] + Ap() { this in [0 .. 1] and this < 1 } + } private class Cc = boolean; @@ -1327,8 +1331,8 @@ private module MkStage { */ pragma[nomagic] additional predicate fwdFlow( - NodeEx node, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - Ap ap, ApApprox apa, Configuration config + NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, + ApApprox apa, Configuration config ) { fwdFlow0(node, state, cc, summaryCtx, argAp, ap, apa, config) and PrevStage::revFlow(node, state, apa, config) and @@ -1337,21 +1341,21 @@ private module MkStage { pragma[inline] additional predicate fwdFlow( - NodeEx node, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - Ap ap, Configuration config + NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, + Configuration config ) { fwdFlow(node, state, cc, summaryCtx, argAp, ap, _, config) } pragma[nomagic] private predicate fwdFlow0( - NodeEx node, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - Ap ap, ApApprox apa, Configuration config + NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, + ApApprox apa, Configuration config ) { sourceNode(node, state, config) and (if hasSourceCallCtx(config) then cc = ccSomeCall() else cc = ccNone()) and argAp = apNone() and - summaryCtx = TParameterPositionNone() and + summaryCtx = TParamNodeNone() and ap = getApNil(node) and apa = getApprox(ap) or @@ -1372,7 +1376,7 @@ private module MkStage { fwdFlow(mid, pragma[only_bind_into](state), _, _, _, ap, apa, pragma[only_bind_into](config)) and jumpStep(mid, node, config) and cc = ccNone() and - summaryCtx = TParameterPositionNone() and + summaryCtx = TParamNodeNone() and argAp = apNone() ) or @@ -1380,7 +1384,7 @@ private module MkStage { fwdFlow(mid, state, _, _, _, nil, pragma[only_bind_into](config)) and additionalJumpStep(mid, node, config) and cc = ccNone() and - summaryCtx = TParameterPositionNone() and + summaryCtx = TParamNodeNone() and argAp = apNone() and ap = getApNil(node) and apa = getApprox(ap) @@ -1390,7 +1394,7 @@ private module MkStage { fwdFlow(mid, state0, _, _, _, nil, pragma[only_bind_into](config)) and additionalJumpStateStep(mid, state0, node, state, config) and cc = ccNone() and - summaryCtx = TParameterPositionNone() and + summaryCtx = TParamNodeNone() and argAp = apNone() and ap = getApNil(node) and apa = getApprox(ap) @@ -1414,10 +1418,10 @@ private module MkStage { fwdFlowIn(_, node, state, _, cc, _, _, ap, apa, config) and if PrevStage::parameterMayFlowThrough(node, apa, config) then ( - summaryCtx = TParameterPositionSome(node.(ParamNodeEx).getPosition()) and + summaryCtx = TParamNodeSome(node.asNode()) and argAp = apSome(ap) ) else ( - summaryCtx = TParameterPositionNone() and argAp = apNone() + summaryCtx = TParamNodeNone() and argAp = apNone() ) or // flow out of a callable @@ -1433,16 +1437,19 @@ private module MkStage { ) or // flow through a callable - exists(DataFlowCall call, ParameterPosition summaryCtx0, Ap argAp0 | - fwdFlowOutFromArg(call, node, state, summaryCtx0, argAp0, ap, apa, config) and - fwdFlowIsEntered(call, cc, summaryCtx, argAp, summaryCtx0, argAp0, config) + exists( + DataFlowCall call, CcCall ccc, RetNodeEx ret, boolean allowsFieldFlow, ApApprox innerArgApa + | + fwdFlowThrough(call, cc, state, ccc, summaryCtx, argAp, ap, apa, ret, innerArgApa, config) and + flowThroughOutOfCall(call, ccc, ret, node, allowsFieldFlow, innerArgApa, apa, config) and + if allowsFieldFlow = false then ap instanceof ApNil else any() ) } pragma[nomagic] private predicate fwdFlowStore( NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, FlowState state, Cc cc, - ParameterPositionOption summaryCtx, ApOption argAp, Configuration config + ParamNodeOption summaryCtx, ApOption argAp, Configuration config ) { exists(DataFlowType contentType, ApApprox apa1 | fwdFlow(node1, state, cc, summaryCtx, argAp, ap1, apa1, config) and @@ -1473,8 +1480,8 @@ private module MkStage { pragma[nomagic] private predicate fwdFlowRead0( - NodeEx node1, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - ApNonNil ap, Configuration config + NodeEx node1, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, ApNonNil ap, + Configuration config ) { fwdFlow(node1, state, cc, summaryCtx, argAp, ap, config) and PrevStage::readStepCand(node1, _, _, config) @@ -1483,7 +1490,7 @@ private module MkStage { pragma[nomagic] private predicate fwdFlowRead( Ap ap, Content c, NodeEx node1, NodeEx node2, FlowState state, Cc cc, - ParameterPositionOption summaryCtx, ApOption argAp, Configuration config + ParamNodeOption summaryCtx, ApOption argAp, Configuration config ) { fwdFlowRead0(node1, state, cc, summaryCtx, argAp, ap, config) and PrevStage::readStepCand(node1, c, node2, config) and @@ -1493,7 +1500,7 @@ private module MkStage { pragma[nomagic] private predicate fwdFlowIn( DataFlowCall call, ParamNodeEx p, FlowState state, Cc outercc, CcCall innercc, - ParameterPositionOption summaryCtx, ApOption argAp, Ap ap, ApApprox apa, Configuration config + ParamNodeOption summaryCtx, ApOption argAp, Ap ap, ApApprox apa, Configuration config ) { exists(ArgNodeEx arg, boolean allowsFieldFlow | fwdFlow(arg, state, outercc, summaryCtx, argAp, ap, apa, config) and @@ -1505,64 +1512,38 @@ private module MkStage { pragma[nomagic] private predicate fwdFlowRetFromArg( - RetNodeEx ret, FlowState state, CcCall ccc, ParameterPosition summaryCtx, ParamNodeEx p, - Ap argAp, ApApprox argApa, Ap ap, ApApprox apa, Configuration config + RetNodeEx ret, FlowState state, CcCall ccc, ParamNodeEx summaryCtx, Ap argAp, ApApprox argApa, + Ap ap, ApApprox apa, Configuration config ) { - exists(DataFlowCallable c, ReturnKindExt kind | + exists(ReturnKindExt kind | fwdFlow(pragma[only_bind_into](ret), state, ccc, - TParameterPositionSome(pragma[only_bind_into](summaryCtx)), apSome(argAp), ap, apa, config) and - getApprox(argAp) = argApa and - c = ret.getEnclosingCallable() and + TParamNodeSome(pragma[only_bind_into](summaryCtx.asNode())), + pragma[only_bind_into](apSome(argAp)), ap, pragma[only_bind_into](apa), + pragma[only_bind_into](config)) and kind = ret.getKind() and - p.isParameterOf(c, pragma[only_bind_into](summaryCtx)) and - parameterFlowThroughAllowed(p, kind) + parameterFlowThroughAllowed(summaryCtx, kind) and + argApa = getApprox(argAp) and + PrevStage::returnMayFlowThrough(ret, argApa, apa, kind, pragma[only_bind_into](config)) ) } pragma[inline] - private predicate fwdFlowInMayFlowThrough( - DataFlowCall call, Cc cc, CcCall innerCc, ParameterPositionOption summaryCtx, ApOption argAp, - ParamNodeEx param, Ap ap, ApApprox apa, Configuration config + private predicate fwdFlowThrough0( + DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, + ApOption argAp, Ap ap, ApApprox apa, RetNodeEx ret, ParamNodeEx innerSummaryCtx, + Ap innerArgAp, ApApprox innerArgApa, Configuration config ) { - fwdFlowIn(call, pragma[only_bind_into](param), _, cc, innerCc, summaryCtx, argAp, ap, - pragma[only_bind_into](apa), pragma[only_bind_into](config)) and - PrevStage::parameterMayFlowThrough(param, apa, config) - } - - // dedup before joining with `flowThroughOutOfCall` - pragma[nomagic] - private predicate fwdFlowInMayFlowThroughProj( - DataFlowCall call, CcCall innerCc, ApApprox apa, Configuration config - ) { - fwdFlowInMayFlowThrough(call, _, innerCc, _, _, _, _, apa, config) - } - - /** - * Same as `flowThroughOutOfCall`, but restricted to calls that are reached - * in the flow covered by `fwdFlow`, where data might flow through the target - * callable and back out at `call`. - */ - pragma[nomagic] - private predicate fwdFlowThroughOutOfCall( - DataFlowCall call, CcCall ccc, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow, - ApApprox argApa, ApApprox apa, Configuration config - ) { - fwdFlowInMayFlowThroughProj(call, ccc, argApa, config) and - flowThroughOutOfCall(call, ccc, ret, out, allowsFieldFlow, argApa, apa, config) + fwdFlowRetFromArg(ret, state, ccc, innerSummaryCtx, innerArgAp, innerArgApa, ap, apa, config) and + fwdFlowIsEntered(call, cc, ccc, summaryCtx, argAp, innerSummaryCtx, innerArgAp, config) } pragma[nomagic] - private predicate fwdFlowOutFromArg( - DataFlowCall call, NodeEx out, FlowState state, ParameterPosition summaryCtx, Ap argAp, Ap ap, - ApApprox apa, Configuration config + private predicate fwdFlowThrough( + DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, + ApOption argAp, Ap ap, ApApprox apa, RetNodeEx ret, ApApprox innerArgApa, Configuration config ) { - exists(RetNodeEx ret, boolean allowsFieldFlow, CcCall ccc, ApApprox argApa | - fwdFlowRetFromArg(pragma[only_bind_into](ret), state, pragma[only_bind_into](ccc), - summaryCtx, _, argAp, pragma[only_bind_into](argApa), ap, pragma[only_bind_into](apa), - config) and - fwdFlowThroughOutOfCall(call, ccc, ret, out, allowsFieldFlow, argApa, apa, config) and - (if allowsFieldFlow = false then ap instanceof ApNil else any()) - ) + fwdFlowThrough0(call, cc, state, ccc, summaryCtx, argAp, ap, apa, ret, _, _, innerArgApa, + config) } /** @@ -1571,12 +1552,14 @@ private module MkStage { */ pragma[nomagic] private predicate fwdFlowIsEntered( - DataFlowCall call, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - ParameterPosition pos, Ap ap, Configuration config + DataFlowCall call, Cc cc, CcCall innerCc, ParamNodeOption summaryCtx, ApOption argAp, + ParamNodeEx p, Ap ap, Configuration config ) { - exists(ParamNodeEx param | - fwdFlowInMayFlowThrough(call, cc, _, summaryCtx, argAp, param, ap, _, config) and - pos = param.getPosition() + exists(ApApprox apa | + fwdFlowIn(call, pragma[only_bind_into](p), _, cc, innerCc, summaryCtx, argAp, ap, + pragma[only_bind_into](apa), pragma[only_bind_into](config)) and + PrevStage::parameterMayFlowThrough(p, apa, config) and + PrevStage::callMayFlowThroughRev(call, pragma[only_bind_into](config)) ) } @@ -1596,23 +1579,31 @@ private module MkStage { fwdFlowConsCand(ap1, c, ap2, config) } + pragma[nomagic] + private predicate returnFlowsThrough0( + DataFlowCall call, FlowState state, CcCall ccc, Ap ap, ApApprox apa, RetNodeEx ret, + ParamNodeEx innerSummaryCtx, Ap innerArgAp, ApApprox innerArgApa, Configuration config + ) { + fwdFlowThrough0(call, _, state, ccc, _, _, ap, apa, ret, innerSummaryCtx, innerArgAp, + innerArgApa, config) + } + pragma[nomagic] private predicate returnFlowsThrough( - RetNodeEx ret, ReturnKindExt kind, FlowState state, CcCall ccc, ParamNodeEx p, Ap argAp, + RetNodeEx ret, ReturnPosition pos, FlowState state, CcCall ccc, ParamNodeEx p, Ap argAp, Ap ap, Configuration config ) { - exists(boolean allowsFieldFlow, ApApprox argApa, ApApprox apa | - fwdFlowRetFromArg(pragma[only_bind_into](ret), state, pragma[only_bind_into](ccc), _, p, - argAp, pragma[only_bind_into](argApa), ap, pragma[only_bind_into](apa), config) and - kind = ret.getKind() and - fwdFlowThroughOutOfCall(_, ccc, ret, _, allowsFieldFlow, argApa, apa, config) and - (if allowsFieldFlow = false then ap instanceof ApNil else any()) + exists(DataFlowCall call, ApApprox apa, boolean allowsFieldFlow, ApApprox innerArgApa | + returnFlowsThrough0(call, state, ccc, ap, apa, ret, p, argAp, innerArgApa, config) and + flowThroughOutOfCall(call, ccc, ret, _, allowsFieldFlow, innerArgApa, apa, config) and + pos = ret.getReturnPosition() and + if allowsFieldFlow = false then ap instanceof ApNil else any() ) } pragma[nomagic] private predicate flowThroughIntoCall( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap argAp, + DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap argAp, Ap ap, Configuration config ) { exists(ApApprox argApa | @@ -1620,7 +1611,7 @@ private module MkStage { allowsFieldFlow, argApa, pragma[only_bind_into](config)) and fwdFlow(arg, _, _, _, _, pragma[only_bind_into](argAp), argApa, pragma[only_bind_into](config)) and - returnFlowsThrough(_, _, _, _, p, pragma[only_bind_into](argAp), _, + returnFlowsThrough(_, _, _, _, p, pragma[only_bind_into](argAp), ap, pragma[only_bind_into](config)) and if allowsFieldFlow = false then argAp instanceof ApNil else any() ) @@ -1639,12 +1630,13 @@ private module MkStage { pragma[nomagic] private predicate flowOutOfCallAp( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, boolean allowsFieldFlow, + DataFlowCall call, RetNodeEx ret, ReturnPosition pos, NodeEx out, boolean allowsFieldFlow, Ap ap, Configuration config ) { exists(ApApprox apa | - flowOutOfCallApa(call, ret, kind, out, allowsFieldFlow, apa, config) and - fwdFlow(ret, _, _, _, _, ap, apa, config) + flowOutOfCallApa(call, ret, _, out, allowsFieldFlow, apa, config) and + fwdFlow(ret, _, _, _, _, ap, apa, config) and + pos = ret.getReturnPosition() ) } @@ -1739,17 +1731,17 @@ private module MkStage { ) or // flow through a callable - exists(DataFlowCall call, ReturnKindExt returnKind0, Ap returnAp0 | - revFlowInToReturn(call, node, state, returnKind0, returnAp0, ap, config) and - revFlowIsReturned(call, returnCtx, returnAp, returnKind0, returnAp0, config) + exists(DataFlowCall call, ParamNodeEx p, ReturnPosition pos, Ap innerReturnAp | + revFlowThrough(call, returnCtx, p, state, pos, returnAp, ap, innerReturnAp, config) and + flowThroughIntoCall(call, node, p, _, ap, innerReturnAp, config) ) or // flow out of a callable - exists(ReturnKindExt kind | - revFlowOut(_, node, kind, state, _, _, ap, config) and - if returnFlowsThrough(node, kind, state, _, _, _, ap, config) + exists(ReturnPosition pos | + revFlowOut(_, node, pos, state, _, _, ap, config) and + if returnFlowsThrough(node, pos, state, _, _, _, ap, config) then ( - returnCtx = TReturnCtxMaybeFlowThrough(kind) and + returnCtx = TReturnCtxMaybeFlowThrough(pos) and returnAp = apSome(ap) ) else ( returnCtx = TReturnCtxNoFlowThrough() and returnAp = apNone() @@ -1782,47 +1774,33 @@ private module MkStage { pragma[nomagic] private predicate revFlowOut( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, FlowState state, ReturnCtx returnCtx, + DataFlowCall call, RetNodeEx ret, ReturnPosition pos, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap, Configuration config ) { exists(NodeEx out, boolean allowsFieldFlow | revFlow(out, state, returnCtx, returnAp, ap, config) and - flowOutOfCallAp(call, ret, kind, out, allowsFieldFlow, ap, config) and + flowOutOfCallAp(call, ret, pos, out, allowsFieldFlow, ap, config) and if allowsFieldFlow = false then ap instanceof ApNil else any() ) } - /** - * Same as `flowThroughIntoCall`, but restricted to calls that are reached - * in the flow covered by `revFlow`, where data might flow through the target - * callable and back out at `call`. - */ - pragma[nomagic] - private predicate revFlowThroughIntoCall( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap argAp, - Configuration config - ) { - flowThroughIntoCall(call, arg, p, allowsFieldFlow, argAp, config) and - revFlowIsReturned(call, _, _, _, _, config) - } - pragma[nomagic] private predicate revFlowParamToReturn( - ParamNodeEx p, FlowState state, ReturnKindExt kind, Ap returnAp, Ap ap, Configuration config + ParamNodeEx p, FlowState state, ReturnPosition pos, Ap returnAp, Ap ap, Configuration config ) { - revFlow(p, state, TReturnCtxMaybeFlowThrough(kind), apSome(returnAp), ap, config) and - parameterFlowThroughAllowed(p, kind) + revFlow(pragma[only_bind_into](p), state, TReturnCtxMaybeFlowThrough(pos), apSome(returnAp), + pragma[only_bind_into](ap), pragma[only_bind_into](config)) and + parameterFlowThroughAllowed(p, pos.getKind()) and + PrevStage::parameterMayFlowThrough(p, getApprox(ap), config) } pragma[nomagic] - private predicate revFlowInToReturn( - DataFlowCall call, ArgNodeEx arg, FlowState state, ReturnKindExt kind, Ap returnAp, Ap ap, - Configuration config + private predicate revFlowThrough( + DataFlowCall call, ReturnCtx returnCtx, ParamNodeEx p, FlowState state, ReturnPosition pos, + ApOption returnAp, Ap ap, Ap innerReturnAp, Configuration config ) { - exists(ParamNodeEx p, boolean allowsFieldFlow | - revFlowParamToReturn(p, state, kind, returnAp, ap, config) and - revFlowThroughIntoCall(call, arg, p, allowsFieldFlow, ap, config) - ) + revFlowParamToReturn(p, state, pos, innerReturnAp, ap, config) and + revFlowIsReturned(call, returnCtx, returnAp, pos, innerReturnAp, config) } /** @@ -1832,12 +1810,12 @@ private module MkStage { */ pragma[nomagic] private predicate revFlowIsReturned( - DataFlowCall call, ReturnCtx returnCtx, ApOption returnAp, ReturnKindExt kind, Ap ap, + DataFlowCall call, ReturnCtx returnCtx, ApOption returnAp, ReturnPosition pos, Ap ap, Configuration config ) { exists(RetNodeEx ret, FlowState state, CcCall ccc | - revFlowOut(call, ret, kind, state, returnCtx, returnAp, ap, config) and - returnFlowsThrough(ret, kind, state, ccc, _, _, ap, config) and + revFlowOut(call, ret, pos, state, returnCtx, returnAp, ap, config) and + returnFlowsThrough(ret, pos, state, ccc, _, _, ap, config) and matchesCall(ccc, call) ) } @@ -1915,17 +1893,17 @@ private module MkStage { pragma[nomagic] private predicate parameterFlowsThroughRev( - ParamNodeEx p, Ap ap, ReturnKindExt kind, Ap returnAp, Configuration config + ParamNodeEx p, Ap ap, ReturnPosition pos, Ap returnAp, Configuration config ) { - revFlow(p, _, TReturnCtxMaybeFlowThrough(kind), apSome(returnAp), ap, config) and - parameterFlowThroughAllowed(p, kind) + revFlow(p, _, TReturnCtxMaybeFlowThrough(pos), apSome(returnAp), ap, config) and + parameterFlowThroughAllowed(p, pos.getKind()) } pragma[nomagic] predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap, Configuration config) { - exists(RetNodeEx ret, ReturnKindExt kind | - returnFlowsThrough(ret, kind, _, _, p, ap, _, config) and - parameterFlowsThroughRev(p, ap, kind, _, config) + exists(RetNodeEx ret, ReturnPosition pos | + returnFlowsThrough(ret, pos, _, _, p, ap, _, config) and + parameterFlowsThroughRev(p, ap, pos, _, config) ) } @@ -1933,20 +1911,21 @@ private module MkStage { predicate returnMayFlowThrough( RetNodeEx ret, Ap argAp, Ap ap, ReturnKindExt kind, Configuration config ) { - exists(ParamNodeEx p | - returnFlowsThrough(ret, kind, _, _, p, argAp, ap, config) and - parameterFlowsThroughRev(p, argAp, kind, ap, config) + exists(ParamNodeEx p, ReturnPosition pos | + returnFlowsThrough(ret, pos, _, _, p, argAp, ap, config) and + parameterFlowsThroughRev(p, argAp, pos, ap, config) and + kind = pos.getKind() ) } pragma[nomagic] - predicate revFlowInToReturnIsReturned( + private predicate revFlowThroughArg( DataFlowCall call, ArgNodeEx arg, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap, Configuration config ) { - exists(ReturnKindExt returnKind0, Ap returnAp0 | - revFlowInToReturn(call, arg, state, returnKind0, returnAp0, ap, config) and - revFlowIsReturned(call, returnCtx, returnAp, returnKind0, returnAp0, config) + exists(ParamNodeEx p, ReturnPosition pos, Ap innerReturnAp | + revFlowThrough(call, returnCtx, p, state, pos, returnAp, ap, innerReturnAp, config) and + flowThroughIntoCall(call, arg, p, _, ap, innerReturnAp, config) ) } @@ -1954,7 +1933,7 @@ private module MkStage { predicate callMayFlowThroughRev(DataFlowCall call, Configuration config) { exists(ArgNodeEx arg, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap | revFlow(arg, state, returnCtx, returnAp, ap, config) and - revFlowInToReturnIsReturned(call, arg, state, returnCtx, returnAp, ap, config) + revFlowThroughArg(call, arg, state, returnCtx, returnAp, ap, config) ) } @@ -1967,8 +1946,9 @@ private module MkStage { conscand = count(TypedContent f0, Ap ap | fwdConsCand(f0, ap, config)) and states = count(FlowState state | fwdFlow(_, state, _, _, _, _, config)) and tuples = - count(NodeEx n, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - Ap ap | fwdFlow(n, state, cc, summaryCtx, argAp, ap, config)) + count(NodeEx n, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap | + fwdFlow(n, state, cc, summaryCtx, argAp, ap, config) + ) or fwd = false and nodes = count(NodeEx node | revFlow(node, _, _, _, _, config)) and @@ -2823,13 +2803,12 @@ private Configuration unbindConf(Configuration conf) { pragma[nomagic] private predicate nodeMayUseSummary0( - NodeEx n, DataFlowCallable c, ParameterPosition pos, FlowState state, AccessPathApprox apa, - Configuration config + NodeEx n, ParamNodeEx p, FlowState state, AccessPathApprox apa, Configuration config ) { exists(AccessPathApprox apa0 | - c = n.getEnclosingCallable() and + Stage5::parameterMayFlowThrough(p, _, _) and Stage5::revFlow(n, state, TReturnCtxMaybeFlowThrough(_), _, apa0, config) and - Stage5::fwdFlow(n, state, any(CallContextCall ccc), TParameterPositionSome(pos), + Stage5::fwdFlow(n, state, any(CallContextCall ccc), TParamNodeSome(p.asNode()), TAccessPathApproxSome(apa), apa0, config) ) } @@ -2838,10 +2817,9 @@ pragma[nomagic] private predicate nodeMayUseSummary( NodeEx n, FlowState state, AccessPathApprox apa, Configuration config ) { - exists(DataFlowCallable c, ParameterPosition pos, ParamNodeEx p | + exists(ParamNodeEx p | Stage5::parameterMayFlowThrough(p, apa, config) and - nodeMayUseSummary0(n, c, pos, state, apa, config) and - p.isParameterOf(c, pos) + nodeMayUseSummary0(n, p, state, apa, config) ) } diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplForSerializability.qll b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplForSerializability.qll index 6741ccc2f06..1228d00b6ba 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplForSerializability.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplForSerializability.qll @@ -622,7 +622,11 @@ private predicate parameterFlowThroughAllowed(ParamNodeEx p, ReturnKindExt kind) } private module Stage1 implements StageSig { - class Ap = Unit; + class Ap extends int { + // workaround for bad functionality-induced joins (happens when using `Unit`) + pragma[nomagic] + Ap() { this in [0 .. 1] and this < 1 } + } private class Cc = boolean; @@ -1327,8 +1331,8 @@ private module MkStage { */ pragma[nomagic] additional predicate fwdFlow( - NodeEx node, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - Ap ap, ApApprox apa, Configuration config + NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, + ApApprox apa, Configuration config ) { fwdFlow0(node, state, cc, summaryCtx, argAp, ap, apa, config) and PrevStage::revFlow(node, state, apa, config) and @@ -1337,21 +1341,21 @@ private module MkStage { pragma[inline] additional predicate fwdFlow( - NodeEx node, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - Ap ap, Configuration config + NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, + Configuration config ) { fwdFlow(node, state, cc, summaryCtx, argAp, ap, _, config) } pragma[nomagic] private predicate fwdFlow0( - NodeEx node, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - Ap ap, ApApprox apa, Configuration config + NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, + ApApprox apa, Configuration config ) { sourceNode(node, state, config) and (if hasSourceCallCtx(config) then cc = ccSomeCall() else cc = ccNone()) and argAp = apNone() and - summaryCtx = TParameterPositionNone() and + summaryCtx = TParamNodeNone() and ap = getApNil(node) and apa = getApprox(ap) or @@ -1372,7 +1376,7 @@ private module MkStage { fwdFlow(mid, pragma[only_bind_into](state), _, _, _, ap, apa, pragma[only_bind_into](config)) and jumpStep(mid, node, config) and cc = ccNone() and - summaryCtx = TParameterPositionNone() and + summaryCtx = TParamNodeNone() and argAp = apNone() ) or @@ -1380,7 +1384,7 @@ private module MkStage { fwdFlow(mid, state, _, _, _, nil, pragma[only_bind_into](config)) and additionalJumpStep(mid, node, config) and cc = ccNone() and - summaryCtx = TParameterPositionNone() and + summaryCtx = TParamNodeNone() and argAp = apNone() and ap = getApNil(node) and apa = getApprox(ap) @@ -1390,7 +1394,7 @@ private module MkStage { fwdFlow(mid, state0, _, _, _, nil, pragma[only_bind_into](config)) and additionalJumpStateStep(mid, state0, node, state, config) and cc = ccNone() and - summaryCtx = TParameterPositionNone() and + summaryCtx = TParamNodeNone() and argAp = apNone() and ap = getApNil(node) and apa = getApprox(ap) @@ -1414,10 +1418,10 @@ private module MkStage { fwdFlowIn(_, node, state, _, cc, _, _, ap, apa, config) and if PrevStage::parameterMayFlowThrough(node, apa, config) then ( - summaryCtx = TParameterPositionSome(node.(ParamNodeEx).getPosition()) and + summaryCtx = TParamNodeSome(node.asNode()) and argAp = apSome(ap) ) else ( - summaryCtx = TParameterPositionNone() and argAp = apNone() + summaryCtx = TParamNodeNone() and argAp = apNone() ) or // flow out of a callable @@ -1433,16 +1437,19 @@ private module MkStage { ) or // flow through a callable - exists(DataFlowCall call, ParameterPosition summaryCtx0, Ap argAp0 | - fwdFlowOutFromArg(call, node, state, summaryCtx0, argAp0, ap, apa, config) and - fwdFlowIsEntered(call, cc, summaryCtx, argAp, summaryCtx0, argAp0, config) + exists( + DataFlowCall call, CcCall ccc, RetNodeEx ret, boolean allowsFieldFlow, ApApprox innerArgApa + | + fwdFlowThrough(call, cc, state, ccc, summaryCtx, argAp, ap, apa, ret, innerArgApa, config) and + flowThroughOutOfCall(call, ccc, ret, node, allowsFieldFlow, innerArgApa, apa, config) and + if allowsFieldFlow = false then ap instanceof ApNil else any() ) } pragma[nomagic] private predicate fwdFlowStore( NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, FlowState state, Cc cc, - ParameterPositionOption summaryCtx, ApOption argAp, Configuration config + ParamNodeOption summaryCtx, ApOption argAp, Configuration config ) { exists(DataFlowType contentType, ApApprox apa1 | fwdFlow(node1, state, cc, summaryCtx, argAp, ap1, apa1, config) and @@ -1473,8 +1480,8 @@ private module MkStage { pragma[nomagic] private predicate fwdFlowRead0( - NodeEx node1, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - ApNonNil ap, Configuration config + NodeEx node1, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, ApNonNil ap, + Configuration config ) { fwdFlow(node1, state, cc, summaryCtx, argAp, ap, config) and PrevStage::readStepCand(node1, _, _, config) @@ -1483,7 +1490,7 @@ private module MkStage { pragma[nomagic] private predicate fwdFlowRead( Ap ap, Content c, NodeEx node1, NodeEx node2, FlowState state, Cc cc, - ParameterPositionOption summaryCtx, ApOption argAp, Configuration config + ParamNodeOption summaryCtx, ApOption argAp, Configuration config ) { fwdFlowRead0(node1, state, cc, summaryCtx, argAp, ap, config) and PrevStage::readStepCand(node1, c, node2, config) and @@ -1493,7 +1500,7 @@ private module MkStage { pragma[nomagic] private predicate fwdFlowIn( DataFlowCall call, ParamNodeEx p, FlowState state, Cc outercc, CcCall innercc, - ParameterPositionOption summaryCtx, ApOption argAp, Ap ap, ApApprox apa, Configuration config + ParamNodeOption summaryCtx, ApOption argAp, Ap ap, ApApprox apa, Configuration config ) { exists(ArgNodeEx arg, boolean allowsFieldFlow | fwdFlow(arg, state, outercc, summaryCtx, argAp, ap, apa, config) and @@ -1505,64 +1512,38 @@ private module MkStage { pragma[nomagic] private predicate fwdFlowRetFromArg( - RetNodeEx ret, FlowState state, CcCall ccc, ParameterPosition summaryCtx, ParamNodeEx p, - Ap argAp, ApApprox argApa, Ap ap, ApApprox apa, Configuration config + RetNodeEx ret, FlowState state, CcCall ccc, ParamNodeEx summaryCtx, Ap argAp, ApApprox argApa, + Ap ap, ApApprox apa, Configuration config ) { - exists(DataFlowCallable c, ReturnKindExt kind | + exists(ReturnKindExt kind | fwdFlow(pragma[only_bind_into](ret), state, ccc, - TParameterPositionSome(pragma[only_bind_into](summaryCtx)), apSome(argAp), ap, apa, config) and - getApprox(argAp) = argApa and - c = ret.getEnclosingCallable() and + TParamNodeSome(pragma[only_bind_into](summaryCtx.asNode())), + pragma[only_bind_into](apSome(argAp)), ap, pragma[only_bind_into](apa), + pragma[only_bind_into](config)) and kind = ret.getKind() and - p.isParameterOf(c, pragma[only_bind_into](summaryCtx)) and - parameterFlowThroughAllowed(p, kind) + parameterFlowThroughAllowed(summaryCtx, kind) and + argApa = getApprox(argAp) and + PrevStage::returnMayFlowThrough(ret, argApa, apa, kind, pragma[only_bind_into](config)) ) } pragma[inline] - private predicate fwdFlowInMayFlowThrough( - DataFlowCall call, Cc cc, CcCall innerCc, ParameterPositionOption summaryCtx, ApOption argAp, - ParamNodeEx param, Ap ap, ApApprox apa, Configuration config + private predicate fwdFlowThrough0( + DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, + ApOption argAp, Ap ap, ApApprox apa, RetNodeEx ret, ParamNodeEx innerSummaryCtx, + Ap innerArgAp, ApApprox innerArgApa, Configuration config ) { - fwdFlowIn(call, pragma[only_bind_into](param), _, cc, innerCc, summaryCtx, argAp, ap, - pragma[only_bind_into](apa), pragma[only_bind_into](config)) and - PrevStage::parameterMayFlowThrough(param, apa, config) - } - - // dedup before joining with `flowThroughOutOfCall` - pragma[nomagic] - private predicate fwdFlowInMayFlowThroughProj( - DataFlowCall call, CcCall innerCc, ApApprox apa, Configuration config - ) { - fwdFlowInMayFlowThrough(call, _, innerCc, _, _, _, _, apa, config) - } - - /** - * Same as `flowThroughOutOfCall`, but restricted to calls that are reached - * in the flow covered by `fwdFlow`, where data might flow through the target - * callable and back out at `call`. - */ - pragma[nomagic] - private predicate fwdFlowThroughOutOfCall( - DataFlowCall call, CcCall ccc, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow, - ApApprox argApa, ApApprox apa, Configuration config - ) { - fwdFlowInMayFlowThroughProj(call, ccc, argApa, config) and - flowThroughOutOfCall(call, ccc, ret, out, allowsFieldFlow, argApa, apa, config) + fwdFlowRetFromArg(ret, state, ccc, innerSummaryCtx, innerArgAp, innerArgApa, ap, apa, config) and + fwdFlowIsEntered(call, cc, ccc, summaryCtx, argAp, innerSummaryCtx, innerArgAp, config) } pragma[nomagic] - private predicate fwdFlowOutFromArg( - DataFlowCall call, NodeEx out, FlowState state, ParameterPosition summaryCtx, Ap argAp, Ap ap, - ApApprox apa, Configuration config + private predicate fwdFlowThrough( + DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, + ApOption argAp, Ap ap, ApApprox apa, RetNodeEx ret, ApApprox innerArgApa, Configuration config ) { - exists(RetNodeEx ret, boolean allowsFieldFlow, CcCall ccc, ApApprox argApa | - fwdFlowRetFromArg(pragma[only_bind_into](ret), state, pragma[only_bind_into](ccc), - summaryCtx, _, argAp, pragma[only_bind_into](argApa), ap, pragma[only_bind_into](apa), - config) and - fwdFlowThroughOutOfCall(call, ccc, ret, out, allowsFieldFlow, argApa, apa, config) and - (if allowsFieldFlow = false then ap instanceof ApNil else any()) - ) + fwdFlowThrough0(call, cc, state, ccc, summaryCtx, argAp, ap, apa, ret, _, _, innerArgApa, + config) } /** @@ -1571,12 +1552,14 @@ private module MkStage { */ pragma[nomagic] private predicate fwdFlowIsEntered( - DataFlowCall call, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - ParameterPosition pos, Ap ap, Configuration config + DataFlowCall call, Cc cc, CcCall innerCc, ParamNodeOption summaryCtx, ApOption argAp, + ParamNodeEx p, Ap ap, Configuration config ) { - exists(ParamNodeEx param | - fwdFlowInMayFlowThrough(call, cc, _, summaryCtx, argAp, param, ap, _, config) and - pos = param.getPosition() + exists(ApApprox apa | + fwdFlowIn(call, pragma[only_bind_into](p), _, cc, innerCc, summaryCtx, argAp, ap, + pragma[only_bind_into](apa), pragma[only_bind_into](config)) and + PrevStage::parameterMayFlowThrough(p, apa, config) and + PrevStage::callMayFlowThroughRev(call, pragma[only_bind_into](config)) ) } @@ -1596,23 +1579,31 @@ private module MkStage { fwdFlowConsCand(ap1, c, ap2, config) } + pragma[nomagic] + private predicate returnFlowsThrough0( + DataFlowCall call, FlowState state, CcCall ccc, Ap ap, ApApprox apa, RetNodeEx ret, + ParamNodeEx innerSummaryCtx, Ap innerArgAp, ApApprox innerArgApa, Configuration config + ) { + fwdFlowThrough0(call, _, state, ccc, _, _, ap, apa, ret, innerSummaryCtx, innerArgAp, + innerArgApa, config) + } + pragma[nomagic] private predicate returnFlowsThrough( - RetNodeEx ret, ReturnKindExt kind, FlowState state, CcCall ccc, ParamNodeEx p, Ap argAp, + RetNodeEx ret, ReturnPosition pos, FlowState state, CcCall ccc, ParamNodeEx p, Ap argAp, Ap ap, Configuration config ) { - exists(boolean allowsFieldFlow, ApApprox argApa, ApApprox apa | - fwdFlowRetFromArg(pragma[only_bind_into](ret), state, pragma[only_bind_into](ccc), _, p, - argAp, pragma[only_bind_into](argApa), ap, pragma[only_bind_into](apa), config) and - kind = ret.getKind() and - fwdFlowThroughOutOfCall(_, ccc, ret, _, allowsFieldFlow, argApa, apa, config) and - (if allowsFieldFlow = false then ap instanceof ApNil else any()) + exists(DataFlowCall call, ApApprox apa, boolean allowsFieldFlow, ApApprox innerArgApa | + returnFlowsThrough0(call, state, ccc, ap, apa, ret, p, argAp, innerArgApa, config) and + flowThroughOutOfCall(call, ccc, ret, _, allowsFieldFlow, innerArgApa, apa, config) and + pos = ret.getReturnPosition() and + if allowsFieldFlow = false then ap instanceof ApNil else any() ) } pragma[nomagic] private predicate flowThroughIntoCall( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap argAp, + DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap argAp, Ap ap, Configuration config ) { exists(ApApprox argApa | @@ -1620,7 +1611,7 @@ private module MkStage { allowsFieldFlow, argApa, pragma[only_bind_into](config)) and fwdFlow(arg, _, _, _, _, pragma[only_bind_into](argAp), argApa, pragma[only_bind_into](config)) and - returnFlowsThrough(_, _, _, _, p, pragma[only_bind_into](argAp), _, + returnFlowsThrough(_, _, _, _, p, pragma[only_bind_into](argAp), ap, pragma[only_bind_into](config)) and if allowsFieldFlow = false then argAp instanceof ApNil else any() ) @@ -1639,12 +1630,13 @@ private module MkStage { pragma[nomagic] private predicate flowOutOfCallAp( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, boolean allowsFieldFlow, + DataFlowCall call, RetNodeEx ret, ReturnPosition pos, NodeEx out, boolean allowsFieldFlow, Ap ap, Configuration config ) { exists(ApApprox apa | - flowOutOfCallApa(call, ret, kind, out, allowsFieldFlow, apa, config) and - fwdFlow(ret, _, _, _, _, ap, apa, config) + flowOutOfCallApa(call, ret, _, out, allowsFieldFlow, apa, config) and + fwdFlow(ret, _, _, _, _, ap, apa, config) and + pos = ret.getReturnPosition() ) } @@ -1739,17 +1731,17 @@ private module MkStage { ) or // flow through a callable - exists(DataFlowCall call, ReturnKindExt returnKind0, Ap returnAp0 | - revFlowInToReturn(call, node, state, returnKind0, returnAp0, ap, config) and - revFlowIsReturned(call, returnCtx, returnAp, returnKind0, returnAp0, config) + exists(DataFlowCall call, ParamNodeEx p, ReturnPosition pos, Ap innerReturnAp | + revFlowThrough(call, returnCtx, p, state, pos, returnAp, ap, innerReturnAp, config) and + flowThroughIntoCall(call, node, p, _, ap, innerReturnAp, config) ) or // flow out of a callable - exists(ReturnKindExt kind | - revFlowOut(_, node, kind, state, _, _, ap, config) and - if returnFlowsThrough(node, kind, state, _, _, _, ap, config) + exists(ReturnPosition pos | + revFlowOut(_, node, pos, state, _, _, ap, config) and + if returnFlowsThrough(node, pos, state, _, _, _, ap, config) then ( - returnCtx = TReturnCtxMaybeFlowThrough(kind) and + returnCtx = TReturnCtxMaybeFlowThrough(pos) and returnAp = apSome(ap) ) else ( returnCtx = TReturnCtxNoFlowThrough() and returnAp = apNone() @@ -1782,47 +1774,33 @@ private module MkStage { pragma[nomagic] private predicate revFlowOut( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, FlowState state, ReturnCtx returnCtx, + DataFlowCall call, RetNodeEx ret, ReturnPosition pos, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap, Configuration config ) { exists(NodeEx out, boolean allowsFieldFlow | revFlow(out, state, returnCtx, returnAp, ap, config) and - flowOutOfCallAp(call, ret, kind, out, allowsFieldFlow, ap, config) and + flowOutOfCallAp(call, ret, pos, out, allowsFieldFlow, ap, config) and if allowsFieldFlow = false then ap instanceof ApNil else any() ) } - /** - * Same as `flowThroughIntoCall`, but restricted to calls that are reached - * in the flow covered by `revFlow`, where data might flow through the target - * callable and back out at `call`. - */ - pragma[nomagic] - private predicate revFlowThroughIntoCall( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap argAp, - Configuration config - ) { - flowThroughIntoCall(call, arg, p, allowsFieldFlow, argAp, config) and - revFlowIsReturned(call, _, _, _, _, config) - } - pragma[nomagic] private predicate revFlowParamToReturn( - ParamNodeEx p, FlowState state, ReturnKindExt kind, Ap returnAp, Ap ap, Configuration config + ParamNodeEx p, FlowState state, ReturnPosition pos, Ap returnAp, Ap ap, Configuration config ) { - revFlow(p, state, TReturnCtxMaybeFlowThrough(kind), apSome(returnAp), ap, config) and - parameterFlowThroughAllowed(p, kind) + revFlow(pragma[only_bind_into](p), state, TReturnCtxMaybeFlowThrough(pos), apSome(returnAp), + pragma[only_bind_into](ap), pragma[only_bind_into](config)) and + parameterFlowThroughAllowed(p, pos.getKind()) and + PrevStage::parameterMayFlowThrough(p, getApprox(ap), config) } pragma[nomagic] - private predicate revFlowInToReturn( - DataFlowCall call, ArgNodeEx arg, FlowState state, ReturnKindExt kind, Ap returnAp, Ap ap, - Configuration config + private predicate revFlowThrough( + DataFlowCall call, ReturnCtx returnCtx, ParamNodeEx p, FlowState state, ReturnPosition pos, + ApOption returnAp, Ap ap, Ap innerReturnAp, Configuration config ) { - exists(ParamNodeEx p, boolean allowsFieldFlow | - revFlowParamToReturn(p, state, kind, returnAp, ap, config) and - revFlowThroughIntoCall(call, arg, p, allowsFieldFlow, ap, config) - ) + revFlowParamToReturn(p, state, pos, innerReturnAp, ap, config) and + revFlowIsReturned(call, returnCtx, returnAp, pos, innerReturnAp, config) } /** @@ -1832,12 +1810,12 @@ private module MkStage { */ pragma[nomagic] private predicate revFlowIsReturned( - DataFlowCall call, ReturnCtx returnCtx, ApOption returnAp, ReturnKindExt kind, Ap ap, + DataFlowCall call, ReturnCtx returnCtx, ApOption returnAp, ReturnPosition pos, Ap ap, Configuration config ) { exists(RetNodeEx ret, FlowState state, CcCall ccc | - revFlowOut(call, ret, kind, state, returnCtx, returnAp, ap, config) and - returnFlowsThrough(ret, kind, state, ccc, _, _, ap, config) and + revFlowOut(call, ret, pos, state, returnCtx, returnAp, ap, config) and + returnFlowsThrough(ret, pos, state, ccc, _, _, ap, config) and matchesCall(ccc, call) ) } @@ -1915,17 +1893,17 @@ private module MkStage { pragma[nomagic] private predicate parameterFlowsThroughRev( - ParamNodeEx p, Ap ap, ReturnKindExt kind, Ap returnAp, Configuration config + ParamNodeEx p, Ap ap, ReturnPosition pos, Ap returnAp, Configuration config ) { - revFlow(p, _, TReturnCtxMaybeFlowThrough(kind), apSome(returnAp), ap, config) and - parameterFlowThroughAllowed(p, kind) + revFlow(p, _, TReturnCtxMaybeFlowThrough(pos), apSome(returnAp), ap, config) and + parameterFlowThroughAllowed(p, pos.getKind()) } pragma[nomagic] predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap, Configuration config) { - exists(RetNodeEx ret, ReturnKindExt kind | - returnFlowsThrough(ret, kind, _, _, p, ap, _, config) and - parameterFlowsThroughRev(p, ap, kind, _, config) + exists(RetNodeEx ret, ReturnPosition pos | + returnFlowsThrough(ret, pos, _, _, p, ap, _, config) and + parameterFlowsThroughRev(p, ap, pos, _, config) ) } @@ -1933,20 +1911,21 @@ private module MkStage { predicate returnMayFlowThrough( RetNodeEx ret, Ap argAp, Ap ap, ReturnKindExt kind, Configuration config ) { - exists(ParamNodeEx p | - returnFlowsThrough(ret, kind, _, _, p, argAp, ap, config) and - parameterFlowsThroughRev(p, argAp, kind, ap, config) + exists(ParamNodeEx p, ReturnPosition pos | + returnFlowsThrough(ret, pos, _, _, p, argAp, ap, config) and + parameterFlowsThroughRev(p, argAp, pos, ap, config) and + kind = pos.getKind() ) } pragma[nomagic] - predicate revFlowInToReturnIsReturned( + private predicate revFlowThroughArg( DataFlowCall call, ArgNodeEx arg, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap, Configuration config ) { - exists(ReturnKindExt returnKind0, Ap returnAp0 | - revFlowInToReturn(call, arg, state, returnKind0, returnAp0, ap, config) and - revFlowIsReturned(call, returnCtx, returnAp, returnKind0, returnAp0, config) + exists(ParamNodeEx p, ReturnPosition pos, Ap innerReturnAp | + revFlowThrough(call, returnCtx, p, state, pos, returnAp, ap, innerReturnAp, config) and + flowThroughIntoCall(call, arg, p, _, ap, innerReturnAp, config) ) } @@ -1954,7 +1933,7 @@ private module MkStage { predicate callMayFlowThroughRev(DataFlowCall call, Configuration config) { exists(ArgNodeEx arg, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap | revFlow(arg, state, returnCtx, returnAp, ap, config) and - revFlowInToReturnIsReturned(call, arg, state, returnCtx, returnAp, ap, config) + revFlowThroughArg(call, arg, state, returnCtx, returnAp, ap, config) ) } @@ -1967,8 +1946,9 @@ private module MkStage { conscand = count(TypedContent f0, Ap ap | fwdConsCand(f0, ap, config)) and states = count(FlowState state | fwdFlow(_, state, _, _, _, _, config)) and tuples = - count(NodeEx n, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - Ap ap | fwdFlow(n, state, cc, summaryCtx, argAp, ap, config)) + count(NodeEx n, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap | + fwdFlow(n, state, cc, summaryCtx, argAp, ap, config) + ) or fwd = false and nodes = count(NodeEx node | revFlow(node, _, _, _, _, config)) and @@ -2823,13 +2803,12 @@ private Configuration unbindConf(Configuration conf) { pragma[nomagic] private predicate nodeMayUseSummary0( - NodeEx n, DataFlowCallable c, ParameterPosition pos, FlowState state, AccessPathApprox apa, - Configuration config + NodeEx n, ParamNodeEx p, FlowState state, AccessPathApprox apa, Configuration config ) { exists(AccessPathApprox apa0 | - c = n.getEnclosingCallable() and + Stage5::parameterMayFlowThrough(p, _, _) and Stage5::revFlow(n, state, TReturnCtxMaybeFlowThrough(_), _, apa0, config) and - Stage5::fwdFlow(n, state, any(CallContextCall ccc), TParameterPositionSome(pos), + Stage5::fwdFlow(n, state, any(CallContextCall ccc), TParamNodeSome(p.asNode()), TAccessPathApproxSome(apa), apa0, config) ) } @@ -2838,10 +2817,9 @@ pragma[nomagic] private predicate nodeMayUseSummary( NodeEx n, FlowState state, AccessPathApprox apa, Configuration config ) { - exists(DataFlowCallable c, ParameterPosition pos, ParamNodeEx p | + exists(ParamNodeEx p | Stage5::parameterMayFlowThrough(p, apa, config) and - nodeMayUseSummary0(n, c, pos, state, apa, config) and - p.isParameterOf(c, pos) + nodeMayUseSummary0(n, p, state, apa, config) ) } diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/FlowSummaryImpl.qll b/java/ql/lib/semmle/code/java/dataflow/internal/FlowSummaryImpl.qll index 61c541d8882..b61142c33a7 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/FlowSummaryImpl.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/FlowSummaryImpl.qll @@ -241,9 +241,15 @@ module Public { } /** - * Holds if the summary is auto generated. + * Holds if the summary is auto generated and not manually generated. */ predicate isAutoGenerated() { none() } + + /** + * Holds if the summary has the given provenance where `true` is + * `generated` and `false` is `manual`. + */ + predicate hasProvenance(boolean generated) { none() } } /** A callable where there is no flow via the callable. */ @@ -1012,6 +1018,10 @@ module Private { } override predicate isAutoGenerated() { this.relevantSummaryElementGenerated(_, _, _) } + + override predicate hasProvenance(boolean generated) { + summaryElement(this, _, _, _, generated) + } } /** Holds if component `c` of specification `spec` cannot be parsed. */ diff --git a/java/ql/src/Metrics/Summaries/GeneratedVsManualCoverage.ql b/java/ql/src/Metrics/Summaries/GeneratedVsManualCoverage.ql new file mode 100644 index 00000000000..eb03a785702 --- /dev/null +++ b/java/ql/src/Metrics/Summaries/GeneratedVsManualCoverage.ql @@ -0,0 +1,76 @@ +/** + * @id java/summary/generated-vs-manual-coverage + * @name Metrics of generated versus manual MaD coverage + * @description Expose metrics for the number of API endpoints covered by generated versus manual MaD models. + * @kind table + * @tags summary + */ + +import java +import semmle.code.java.dataflow.FlowSummary +import utils.modelgenerator.internal.CaptureModels + +/** + * Returns the number of `DataFlowTargetApi`s with Summary MaD models + * for a given package and provenance. + */ +bindingset[package] +private int getNumMadModeledApis(string package, string provenance) { + provenance in ["generated", "manual", "both"] and + result = + count(SummarizedCallable sc | + package = sc.asCallable().getCompilationUnit().getPackage().getName() and + sc.asCallable() instanceof DataFlowTargetApi and + ( + // "auto-only" + sc.isAutoGenerated() and + provenance = "generated" + or + // "manual-only" + sc.hasProvenance(false) and + not sc.hasProvenance(true) and + provenance = "manual" + or + // "both" + sc.hasProvenance(false) and + sc.hasProvenance(true) and + provenance = "both" + ) + ) +} + +/** Returns the total number of `DataFlowTargetApi`s for a given package. */ +private int getNumApis(string package) { + result = + strictcount(DataFlowTargetApi dataFlowTargApi | + package = dataFlowTargApi.getCompilationUnit().getPackage().getName() + ) +} + +from + string package, int generatedOnly, int both, int manualOnly, int generated, int manual, int non, + int all, float coverage, float generatedCoverage, float manualCoverage, + float manualCoveredByGenerated, float generatedCoveredByManual, float match +where + // count the number of APIs with generated-only, both, and manual-only MaD models for each package + generatedOnly = getNumMadModeledApis(package, "generated") and + both = getNumMadModeledApis(package, "both") and + manualOnly = getNumMadModeledApis(package, "manual") and + // calculate the total generated and total manual numbers + generated = generatedOnly + both and + manual = manualOnly + both and + // count the total number of `DataFlowTargetApi`s for each package + all = getNumApis(package) and + non = all - (generatedOnly + both + manualOnly) and + // Proportion of coverage + coverage = (generatedOnly + both + manualOnly).(float) / all and + generatedCoverage = generated.(float) / all and + manualCoverage = manual.(float) / all and + // Proportion of manual models covered by generated ones + manualCoveredByGenerated = both.(float) / (both + manualOnly) and + // Proportion of generated models covered by manual ones + generatedCoveredByManual = both.(float) / (both + generatedOnly) and + // Proportion of data points that match + match = (both.(float) + non) / all +select package, generatedOnly, both, manualOnly, non, all, coverage, generatedCoverage, + manualCoverage, manualCoveredByGenerated, generatedCoveredByManual, match order by package diff --git a/java/ql/src/change-notes/2022-12-12-java-mad-metrics-query.md b/java/ql/src/change-notes/2022-12-12-java-mad-metrics-query.md new file mode 100644 index 00000000000..8d4dd5d77e1 --- /dev/null +++ b/java/ql/src/change-notes/2022-12-12-java-mad-metrics-query.md @@ -0,0 +1,4 @@ +--- +category: newQuery +--- +* Added a new query, `java/summary/generated-vs-manual-coverage`, to expose metrics for the number of API endpoints covered by generated versus manual MaD models. diff --git a/java/ql/src/change-notes/2022-12-15-rename-mad-extensibles.md b/java/ql/src/change-notes/2022-12-15-rename-mad-extensibles.md new file mode 100644 index 00000000000..39532da22c8 --- /dev/null +++ b/java/ql/src/change-notes/2022-12-15-rename-mad-extensibles.md @@ -0,0 +1,4 @@ +--- +category: minorAnalysis +--- +* The extensible predicates for Models as Data have been renamed (the `ext` prefix has been removed). As an example `extSummaryModel` has been renamed to `summaryModel`. \ No newline at end of file diff --git a/java/ql/src/utils/flowtestcasegenerator/GenerateFlowTestCase.py b/java/ql/src/utils/flowtestcasegenerator/GenerateFlowTestCase.py index 64a86505db4..fb10c934afd 100755 --- a/java/ql/src/utils/flowtestcasegenerator/GenerateFlowTestCase.py +++ b/java/ql/src/utils/flowtestcasegenerator/GenerateFlowTestCase.py @@ -16,7 +16,7 @@ if any(s == "--help" for s in sys.argv): GenerateFlowTestCase.py specsToTest.csv projectPom.xml outdir [--force] This generates test cases exercising function model specifications found in specsToTest.csv -producing files Test.java, test.ql and test.expected in outdir. +producing files Test.java, test.ql, test.ext.yml and test.expected in outdir. projectPom.xml should be a Maven pom sufficient to resolve the classes named in specsToTest.csv. Typically this means supplying a skeleton POM section that retrieves whatever jars @@ -54,12 +54,11 @@ except Exception as e: resultJava = os.path.join(sys.argv[3], "Test.java") resultQl = os.path.join(sys.argv[3], "test.ql") -resultYml = os.path.join(sys.argv[3], "test.model.yml") -resultPack = os.path.join(sys.argv[3], "qlpack.yml") +resultYml = os.path.join(sys.argv[3], "test.ext.yml") -if not force and (os.path.exists(resultJava) or os.path.exists(resultQl) or os.path.exists(resultYml) or os.path.exists(resultPack)): - print("Won't overwrite existing files '%s', '%s', '%s' or '%s'." % - (resultJava, resultQl, resultYml, resultPack), file=sys.stderr) +if not force and (os.path.exists(resultJava) or os.path.exists(resultQl) or os.path.exists(resultYml)): + print("Won't overwrite existing files '%s', '%s' or '%s'." % + (resultJava, resultQl, resultYml), file=sys.stderr) sys.exit(1) workDir = tempfile.mkdtemp() @@ -226,23 +225,11 @@ if len(supportModelRows) != 0: dataextensions = f"""extensions: - addsTo: pack: codeql/java-tests - extensible: extSummaryModel + extensible: summaryModel data: {models} """ f.write(dataextensions) - # Make a qlpack file such that the extension will be picked up - with open(resultPack, "w") as f: - f.write("""name: example-test-pack -version: 0.0.0 -extractor: java -dependencies: - codeql/java-all: '*' - codeql/java-queries: '*' - codeql/java-tests: '*' -dataExtensions: - - test.model.yml -""") # Make an empty .expected file, since this is an inline-exectations test with open(os.path.join(sys.argv[3], "test.expected"), "w"): diff --git a/java/ql/src/utils/modelgenerator/internal/CaptureModelsSpecific.qll b/java/ql/src/utils/modelgenerator/internal/CaptureModelsSpecific.qll index ced6b703600..e8be963f0dc 100644 --- a/java/ql/src/utils/modelgenerator/internal/CaptureModelsSpecific.qll +++ b/java/ql/src/utils/modelgenerator/internal/CaptureModelsSpecific.qll @@ -65,6 +65,7 @@ private predicate isRelevantForModels(J::Callable api) { not isJdkInternal(api.getCompilationUnit()) and not api instanceof J::MainMethod and not api instanceof J::StaticInitializer and + not exists(J::FunctionalExpr funcExpr | api = funcExpr.asMethod()) and not api.(J::Constructor).isParameterless() } diff --git a/java/ql/test/ext/test.model.yml b/java/ql/test/ext/test.model.yml deleted file mode 100644 index 319ee2b834e..00000000000 --- a/java/ql/test/ext/test.model.yml +++ /dev/null @@ -1,145 +0,0 @@ -extensions: - # Model(s) for Kotlin - dataflow/notnullexpr and dataflow/whenexpr test cases. - - addsTo: - pack: codeql/java-tests - extensible: extSummaryModel - data: - - ["", "Uri", False, "getQueryParameter", "", "", "Argument[-1]", "ReturnValue", "taint", "manual"] - - # Model(s) for Java - dataflow/callback-dispatch test case. - - addsTo: - pack: codeql/java-tests - extensible: extSummaryModel - data: - - ["my.callback.qltest", "A", False, "applyConsumer1", "(Object,Consumer1)", "", "Argument[0]", "Argument[1].Parameter[0]", "value", "manual"] - - ["my.callback.qltest", "A", False, "applyConsumer1Field1Field2", "(A,A,Consumer1)", "", "Argument[0].Field[my.callback.qltest.A.field1]", "Argument[2].Parameter[0]", "value", "manual"] - - ["my.callback.qltest", "A", False, "applyConsumer1Field1Field2", "(A,A,Consumer1)", "", "Argument[1].Field[my.callback.qltest.A.field2]", "Argument[2].Parameter[0]", "value", "manual"] - - ["my.callback.qltest", "A", False, "applyConsumer2", "(Object,Consumer2)", "", "Argument[0]", "Argument[1].Parameter[0]", "value", "manual"] - - ["my.callback.qltest", "A", False, "applyConsumer3", "(Object,Consumer3)", "", "Argument[0]", "Argument[1].Parameter[0]", "value", "manual"] - - ["my.callback.qltest", "A", False, "applyConsumer3_ret_postup", "(Consumer3)", "", "Argument[0].Parameter[0]", "ReturnValue", "value", "manual"] - - ["my.callback.qltest", "A", False, "forEach", "(Object[],Consumer3)", "", "Argument[0].ArrayElement", "Argument[1].Parameter[0]", "value", "manual"] - - ["my.callback.qltest", "A", False, "applyProducer1", "(Producer1)", "", "Argument[0].ReturnValue", "ReturnValue", "value", "manual"] - - ["my.callback.qltest", "A", False, "produceConsume", "(Producer1,Consumer3)", "", "Argument[0].ReturnValue", "Argument[1].Parameter[0]", "value", "manual"] - - ["my.callback.qltest", "A", False, "produceConsume", "(Producer1,Consumer3)", "", "Argument[1].Parameter[0]", "ReturnValue", "value", "manual"] - - ["my.callback.qltest", "A", False, "applyConverter1", "(Object,Converter1)", "", "Argument[0]", "Argument[1].Parameter[0]", "value", "manual"] - - ["my.callback.qltest", "A", False, "applyConverter1", "(Object,Converter1)", "", "Argument[1].ReturnValue", "ReturnValue", "value", "manual"] - - # Model(s) for Java - dataflow/collections test case. - - addsTo: - pack: codeql/java-tests - extensible: extSummaryModel - data: - - ["", "B", False, "readElement", "(Spliterator)", "", "Argument[0].Element", "ReturnValue", "value", "manual"] - - ["", "B", False, "readElement", "(Stream)", "", "Argument[0].Element", "ReturnValue", "value", "manual"] - - # Model(s) for Java - dataflow/external-models test cases. - - addsTo: - pack: codeql/java-tests - extensible: extSourceModel - data: - - ["my.qltest", "A", False, "src1", "()", "", "ReturnValue", "qltest", "manual"] - - ["my.qltest", "A", False, "src1", "(String)", "", "ReturnValue", "qltest", "manual"] - - ["my.qltest", "A", False, "src1", "(java.lang.String)", "", "ReturnValue", "qltest-alt", "manual"] - - ["my.qltest", "A", False, "src1", "", "", "ReturnValue", "qltest-all-overloads", "manual"] - - ["my.qltest", "A", False, "src2", "()", "", "ReturnValue", "qltest", "manual"] - - ["my.qltest", "A", False, "src3", "()", "", "ReturnValue", "qltest", "manual"] - - ["my.qltest", "A", True, "src2", "()", "", "ReturnValue", "qltest-w-subtypes", "manual"] - - ["my.qltest", "A", True, "src3", "()", "", "ReturnValue", "qltest-w-subtypes", "manual"] - - ["my.qltest", "A", False, "srcArg", "(Object)", "", "Argument[0]", "qltest-argnum", "manual"] - - ["my.qltest", "A", False, "srcArg", "(Object)", "", "Argument", "qltest-argany", "manual"] - - ["my.qltest", "A$Handler", True, "handle", "(Object)", "", "Parameter[0]", "qltest-param-override", "manual"] - - ["my.qltest", "A$Tag", False, "", "", "Annotated", "ReturnValue", "qltest-retval", "manual"] - - ["my.qltest", "A$Tag", False, "", "", "Annotated", "Parameter", "qltest-param", "manual"] - - ["my.qltest", "A$Tag", False, "", "", "Annotated", "", "qltest-nospec", "manual"] - - ["my.qltest", "A", False, "srcTwoArg", "(String,String)", "", "ReturnValue", "qltest-shortsig", "manual"] - - ["my.qltest", "A", False, "srcTwoArg", "(java.lang.String,java.lang.String)", "", "ReturnValue", "qltest-longsig", "manual"] - - addsTo: - pack: codeql/java-tests - extensible: extSinkModel - data: - - ["my.qltest", "B", False, "sink1", "(Object)", "", "Argument[0]", "qltest", "manual"] - - ["my.qltest", "B", False, "sinkMethod", "()", "", "ReturnValue", "qltest", "manual"] - - ["my.qltest", "B$Tag", False, "", "", "Annotated", "ReturnValue", "qltest-retval", "manual"] - - ["my.qltest", "B$Tag", False, "", "", "Annotated", "Argument", "qltest-arg", "manual"] - - ["my.qltest", "B$Tag", False, "", "", "Annotated", "", "qltest-nospec", "manual"] - - addsTo: - pack: codeql/java-tests - extensible: extSummaryModel - data: - - ["my.qltest", "C", False, "stepArgRes", "(Object)", "", "Argument[0]", "ReturnValue", "taint", "manual"] - - ["my.qltest", "C", False, "stepArgArg", "(Object,Object)", "", "Argument[0]", "Argument[1]", "taint", "manual"] - - ["my.qltest", "C", False, "stepArgQual", "(Object)", "", "Argument[0]", "Argument[-1]", "taint", "manual"] - - ["my.qltest", "C", False, "stepQualRes", "()", "", "Argument[-1]", "ReturnValue", "taint", "manual"] - - ["my.qltest", "C", False, "stepQualArg", "(Object)", "", "Argument[-1]", "Argument[0]", "taint", "manual"] - - ["my.qltest", "C", False, "stepArgResGenerated", "(Object)", "", "Argument[0]", "ReturnValue", "taint", "generated"] - - ["my.qltest", "C", False, "stepArgResGeneratedIgnored", "(Object,Object)", "", "Argument[0]", "ReturnValue", "taint", "generated"] - - ["my.qltest", "C", False, "stepArgResGeneratedIgnored", "(Object,Object)", "", "Argument[1]", "ReturnValue", "taint", "manual"] - - # Model(s) for Java - dataflow/synth-global test case. - - addsTo: - pack: codeql/java-tests - extensible: extSummaryModel - data: - - ["my.qltest.synth", "A", False, "storeInArray", "(String)", "", "Argument[0]", "SyntheticGlobal[db1].ArrayElement", "value", "manual"] - - ["my.qltest.synth", "A", False, "storeTaintInArray", "(String)", "", "Argument[0]", "SyntheticGlobal[db1].ArrayElement", "taint", "manual"] - - ["my.qltest.synth", "A", False, "storeValue", "(String)", "", "Argument[0]", "SyntheticGlobal[db1]", "value", "manual"] - - ["my.qltest.synth", "A", False, "readValue", "()", "", "SyntheticGlobal[db1]", "ReturnValue", "value", "manual"] - - ["my.qltest.synth", "A", False, "readArray", "()", "", "SyntheticGlobal[db1].ArrayElement", "ReturnValue", "value", "manual"] - - # Model(s) for Java - frameworks/android/content-provider-summaries test case. - - addsTo: - pack: codeql/java-tests - extensible: extSummaryModel - data: - - ["generatedtest", "Test", False, "newWithMapValueDefault", "(Object)", "", "Argument[0]", "ReturnValue.MapValue", "value", "manual"] - - ["generatedtest", "Test", False, "newWithMapKeyDefault", "(Object)", "", "Argument[0]", "ReturnValue.MapKey", "value", "manual"] - - ["generatedtest", "Test", False, "getMapValueDefault", "(Object)", "", "Argument[0].MapValue", "ReturnValue", "value", "manual"] - - ["generatedtest", "Test", False, "getMapKeyDefault", "(Object)", "", "Argument[0].MapKey", "ReturnValue", "value", "manual"] - - # Model(s) for Java - frameworks/android/intent test case. - - addsTo: - pack: codeql/java-tests - extensible: extSummaryModel - data: - - ["generatedtest", "Test", False, "newBundleWithMapValue", "(Object)", "", "Argument[0]", "ReturnValue.MapValue", "value", "manual"] - - ["generatedtest", "Test", False, "newPersistableBundleWithMapValue", "(Object)", "", "Argument[0]", "ReturnValue.MapValue", "value", "manual"] - - ["generatedtest", "Test", False, "getMapValue", "(BaseBundle)", "", "Argument[0].MapValue", "ReturnValue", "value", "manual"] - - ["generatedtest", "Test", False, "newWithIntent_extras", "(Bundle)", "", "Argument[0]", "ReturnValue.SyntheticField[android.content.Intent.extras]", "value", "manual"] - - # Model(s) for Java - frameworks/android/notification test case. - - addsTo: - pack: codeql/java-tests - extensible: extSummaryModel - data: - - ["generatedtest", "Test", False, "getMapKeyDefault", "(Bundle)", "", "Argument[0].MapKey", "ReturnValue", "value", "manual"] - - # Model(s) for Java - frameworks/apache-collections test case. - - addsTo: - pack: codeql/java-tests - extensible: extSummaryModel - data: - - ["generatedtest", "Test", False, "newRBWithMapValue", "", "", "Argument[0]", "ReturnValue.MapValue", "value", "manual"] - - ["generatedtest", "Test", False, "newRBWithMapKey", "", "", "Argument[0]", "ReturnValue.MapKey", "value", "manual"] - - # Model(s) for Java - frameworks/guave/generated/collect test case. - - addsTo: - pack: codeql/java-tests - extensible: extSummaryModel - data: - - ["generatedtest", "Test", False, "newWithElementDefault", "(Object)", "", "Argument[0]", "ReturnValue.Element", "value", "manual"] - - ["generatedtest", "Test", False, "newWithMapKeyDefault", "(Object)", "", "Argument[0]", "ReturnValue.MapKey", "value", "manual"] - - ["generatedtest", "Test", False, "newWithMapValueDefault", "(Object)", "", "Argument[0]", "ReturnValue.MapValue", "value", "manual"] - - # Model(s) for Java - frameworks/stream test case. - - addsTo: - pack: codeql/java-tests - extensible: extSummaryModel - data: - - ["generatedtest", "Test", False, "getElementSpliterator", "(Spliterator)", "", "Argument[0].Element", "ReturnValue", "value", "manual"] - - # Model(s) for Java - frameworks/stream test case. - - addsTo: - pack: codeql/java-tests - extensible: extSummaryModel - data: - - ["generatedtest", "Test", False, "getStreamElement", "", "", "Argument[0].Element", "ReturnValue", "value", "manual"] diff --git a/java/ql/test/kotlin/library-tests/dataflow/notnullexpr/test.ext.yml b/java/ql/test/kotlin/library-tests/dataflow/notnullexpr/test.ext.yml new file mode 100644 index 00000000000..7e049c5de11 --- /dev/null +++ b/java/ql/test/kotlin/library-tests/dataflow/notnullexpr/test.ext.yml @@ -0,0 +1,6 @@ +extensions: + - addsTo: + pack: codeql/java-tests + extensible: summaryModel + data: + - ["", "Uri", False, "getQueryParameter", "", "", "Argument[-1]", "ReturnValue", "taint", "manual"] diff --git a/java/ql/test/kotlin/library-tests/dataflow/whenexpr/test.ext.yml b/java/ql/test/kotlin/library-tests/dataflow/whenexpr/test.ext.yml new file mode 100644 index 00000000000..7e049c5de11 --- /dev/null +++ b/java/ql/test/kotlin/library-tests/dataflow/whenexpr/test.ext.yml @@ -0,0 +1,6 @@ +extensions: + - addsTo: + pack: codeql/java-tests + extensible: summaryModel + data: + - ["", "Uri", False, "getQueryParameter", "", "", "Argument[-1]", "ReturnValue", "taint", "manual"] diff --git a/java/ql/test/library-tests/dataflow/callback-dispatch/test.ext.yml b/java/ql/test/library-tests/dataflow/callback-dispatch/test.ext.yml new file mode 100644 index 00000000000..5f35c923ad0 --- /dev/null +++ b/java/ql/test/library-tests/dataflow/callback-dispatch/test.ext.yml @@ -0,0 +1,18 @@ +extensions: + - addsTo: + pack: codeql/java-tests + extensible: summaryModel + data: + - ["my.callback.qltest", "A", False, "applyConsumer1", "(Object,Consumer1)", "", "Argument[0]", "Argument[1].Parameter[0]", "value", "manual"] + - ["my.callback.qltest", "A", False, "applyConsumer1Field1Field2", "(A,A,Consumer1)", "", "Argument[0].Field[my.callback.qltest.A.field1]", "Argument[2].Parameter[0]", "value", "manual"] + - ["my.callback.qltest", "A", False, "applyConsumer1Field1Field2", "(A,A,Consumer1)", "", "Argument[1].Field[my.callback.qltest.A.field2]", "Argument[2].Parameter[0]", "value", "manual"] + - ["my.callback.qltest", "A", False, "applyConsumer2", "(Object,Consumer2)", "", "Argument[0]", "Argument[1].Parameter[0]", "value", "manual"] + - ["my.callback.qltest", "A", False, "applyConsumer3", "(Object,Consumer3)", "", "Argument[0]", "Argument[1].Parameter[0]", "value", "manual"] + - ["my.callback.qltest", "A", False, "applyConsumer3_ret_postup", "(Consumer3)", "", "Argument[0].Parameter[0]", "ReturnValue", "value", "manual"] + - ["my.callback.qltest", "A", False, "forEach", "(Object[],Consumer3)", "", "Argument[0].ArrayElement", "Argument[1].Parameter[0]", "value", "manual"] + - ["my.callback.qltest", "A", False, "applyProducer1", "(Producer1)", "", "Argument[0].ReturnValue", "ReturnValue", "value", "manual"] + - ["my.callback.qltest", "A", False, "produceConsume", "(Producer1,Consumer3)", "", "Argument[0].ReturnValue", "Argument[1].Parameter[0]", "value", "manual"] + - ["my.callback.qltest", "A", False, "produceConsume", "(Producer1,Consumer3)", "", "Argument[1].Parameter[0]", "ReturnValue", "value", "manual"] + - ["my.callback.qltest", "A", False, "applyConverter1", "(Object,Converter1)", "", "Argument[0]", "Argument[1].Parameter[0]", "value", "manual"] + - ["my.callback.qltest", "A", False, "applyConverter1", "(Object,Converter1)", "", "Argument[1].ReturnValue", "ReturnValue", "value", "manual"] + diff --git a/java/ql/test/library-tests/dataflow/collections/containerflow.ext.yml b/java/ql/test/library-tests/dataflow/collections/containerflow.ext.yml new file mode 100644 index 00000000000..ebe7e3b6ea5 --- /dev/null +++ b/java/ql/test/library-tests/dataflow/collections/containerflow.ext.yml @@ -0,0 +1,7 @@ +extensions: + - addsTo: + pack: codeql/java-tests + extensible: summaryModel + data: + - ["", "B", False, "readElement", "(Spliterator)", "", "Argument[0].Element", "ReturnValue", "value", "manual"] + - ["", "B", False, "readElement", "(Stream)", "", "Argument[0].Element", "ReturnValue", "value", "manual"] diff --git a/java/ql/test/library-tests/dataflow/external-models/sinks.ext.yml b/java/ql/test/library-tests/dataflow/external-models/sinks.ext.yml new file mode 100644 index 00000000000..55a76b79b21 --- /dev/null +++ b/java/ql/test/library-tests/dataflow/external-models/sinks.ext.yml @@ -0,0 +1,10 @@ +extensions: + - addsTo: + pack: codeql/java-tests + extensible: sinkModel + data: + - ["my.qltest", "B", False, "sink1", "(Object)", "", "Argument[0]", "qltest", "manual"] + - ["my.qltest", "B", False, "sinkMethod", "()", "", "ReturnValue", "qltest", "manual"] + - ["my.qltest", "B$Tag", False, "", "", "Annotated", "ReturnValue", "qltest-retval", "manual"] + - ["my.qltest", "B$Tag", False, "", "", "Annotated", "Argument", "qltest-arg", "manual"] + - ["my.qltest", "B$Tag", False, "", "", "Annotated", "", "qltest-nospec", "manual"] diff --git a/java/ql/test/library-tests/dataflow/external-models/srcs.ext.yml b/java/ql/test/library-tests/dataflow/external-models/srcs.ext.yml new file mode 100644 index 00000000000..7730d41e549 --- /dev/null +++ b/java/ql/test/library-tests/dataflow/external-models/srcs.ext.yml @@ -0,0 +1,21 @@ +extensions: + - addsTo: + pack: codeql/java-tests + extensible: sourceModel + data: + - ["my.qltest", "A", False, "src1", "()", "", "ReturnValue", "qltest", "manual"] + - ["my.qltest", "A", False, "src1", "(String)", "", "ReturnValue", "qltest", "manual"] + - ["my.qltest", "A", False, "src1", "(java.lang.String)", "", "ReturnValue", "qltest-alt", "manual"] + - ["my.qltest", "A", False, "src1", "", "", "ReturnValue", "qltest-all-overloads", "manual"] + - ["my.qltest", "A", False, "src2", "()", "", "ReturnValue", "qltest", "manual"] + - ["my.qltest", "A", False, "src3", "()", "", "ReturnValue", "qltest", "manual"] + - ["my.qltest", "A", True, "src2", "()", "", "ReturnValue", "qltest-w-subtypes", "manual"] + - ["my.qltest", "A", True, "src3", "()", "", "ReturnValue", "qltest-w-subtypes", "manual"] + - ["my.qltest", "A", False, "srcArg", "(Object)", "", "Argument[0]", "qltest-argnum", "manual"] + - ["my.qltest", "A", False, "srcArg", "(Object)", "", "Argument", "qltest-argany", "manual"] + - ["my.qltest", "A$Handler", True, "handle", "(Object)", "", "Parameter[0]", "qltest-param-override", "manual"] + - ["my.qltest", "A$Tag", False, "", "", "Annotated", "ReturnValue", "qltest-retval", "manual"] + - ["my.qltest", "A$Tag", False, "", "", "Annotated", "Parameter", "qltest-param", "manual"] + - ["my.qltest", "A$Tag", False, "", "", "Annotated", "", "qltest-nospec", "manual"] + - ["my.qltest", "A", False, "srcTwoArg", "(String,String)", "", "ReturnValue", "qltest-shortsig", "manual"] + - ["my.qltest", "A", False, "srcTwoArg", "(java.lang.String,java.lang.String)", "", "ReturnValue", "qltest-longsig", "manual"] diff --git a/java/ql/test/library-tests/dataflow/external-models/steps.ext.yml b/java/ql/test/library-tests/dataflow/external-models/steps.ext.yml new file mode 100644 index 00000000000..d68e50ce558 --- /dev/null +++ b/java/ql/test/library-tests/dataflow/external-models/steps.ext.yml @@ -0,0 +1,13 @@ +extensions: + - addsTo: + pack: codeql/java-tests + extensible: summaryModel + data: + - ["my.qltest", "C", False, "stepArgRes", "(Object)", "", "Argument[0]", "ReturnValue", "taint", "manual"] + - ["my.qltest", "C", False, "stepArgArg", "(Object,Object)", "", "Argument[0]", "Argument[1]", "taint", "manual"] + - ["my.qltest", "C", False, "stepArgQual", "(Object)", "", "Argument[0]", "Argument[-1]", "taint", "manual"] + - ["my.qltest", "C", False, "stepQualRes", "()", "", "Argument[-1]", "ReturnValue", "taint", "manual"] + - ["my.qltest", "C", False, "stepQualArg", "(Object)", "", "Argument[-1]", "Argument[0]", "taint", "manual"] + - ["my.qltest", "C", False, "stepArgResGenerated", "(Object)", "", "Argument[0]", "ReturnValue", "taint", "generated"] + - ["my.qltest", "C", False, "stepArgResGeneratedIgnored", "(Object,Object)", "", "Argument[0]", "ReturnValue", "taint", "generated"] + - ["my.qltest", "C", False, "stepArgResGeneratedIgnored", "(Object,Object)", "", "Argument[1]", "ReturnValue", "taint", "manual"] diff --git a/java/ql/test/library-tests/dataflow/synth-global/test.ext.yml b/java/ql/test/library-tests/dataflow/synth-global/test.ext.yml new file mode 100644 index 00000000000..3d3bbe9fd47 --- /dev/null +++ b/java/ql/test/library-tests/dataflow/synth-global/test.ext.yml @@ -0,0 +1,10 @@ +extensions: + - addsTo: + pack: codeql/java-tests + extensible: summaryModel + data: + - ["my.qltest.synth", "A", False, "storeInArray", "(String)", "", "Argument[0]", "SyntheticGlobal[db1].ArrayElement", "value", "manual"] + - ["my.qltest.synth", "A", False, "storeTaintInArray", "(String)", "", "Argument[0]", "SyntheticGlobal[db1].ArrayElement", "taint", "manual"] + - ["my.qltest.synth", "A", False, "storeValue", "(String)", "", "Argument[0]", "SyntheticGlobal[db1]", "value", "manual"] + - ["my.qltest.synth", "A", False, "readValue", "()", "", "SyntheticGlobal[db1]", "ReturnValue", "value", "manual"] + - ["my.qltest.synth", "A", False, "readArray", "()", "", "SyntheticGlobal[db1].ArrayElement", "ReturnValue", "value", "manual"] diff --git a/java/ql/test/library-tests/frameworks/android/content-provider-summaries/test.ext.yml b/java/ql/test/library-tests/frameworks/android/content-provider-summaries/test.ext.yml new file mode 100644 index 00000000000..cf5c80bc456 --- /dev/null +++ b/java/ql/test/library-tests/frameworks/android/content-provider-summaries/test.ext.yml @@ -0,0 +1,9 @@ +extensions: + - addsTo: + pack: codeql/java-tests + extensible: summaryModel + data: + - ["generatedtest", "Test", False, "newWithMapValueDefault", "(Object)", "", "Argument[0]", "ReturnValue.MapValue", "value", "manual"] + - ["generatedtest", "Test", False, "newWithMapKeyDefault", "(Object)", "", "Argument[0]", "ReturnValue.MapKey", "value", "manual"] + - ["generatedtest", "Test", False, "getMapValueDefault", "(Object)", "", "Argument[0].MapValue", "ReturnValue", "value", "manual"] + - ["generatedtest", "Test", False, "getMapKeyDefault", "(Object)", "", "Argument[0].MapKey", "ReturnValue", "value", "manual"] diff --git a/java/ql/test/library-tests/frameworks/android/intent/test.ext.yml b/java/ql/test/library-tests/frameworks/android/intent/test.ext.yml new file mode 100644 index 00000000000..31321102a46 --- /dev/null +++ b/java/ql/test/library-tests/frameworks/android/intent/test.ext.yml @@ -0,0 +1,9 @@ +extensions: + - addsTo: + pack: codeql/java-tests + extensible: summaryModel + data: + - ["generatedtest", "Test", False, "newBundleWithMapValue", "(Object)", "", "Argument[0]", "ReturnValue.MapValue", "value", "manual"] + - ["generatedtest", "Test", False, "newPersistableBundleWithMapValue", "(Object)", "", "Argument[0]", "ReturnValue.MapValue", "value", "manual"] + - ["generatedtest", "Test", False, "getMapValue", "(BaseBundle)", "", "Argument[0].MapValue", "ReturnValue", "value", "manual"] + - ["generatedtest", "Test", False, "newWithIntent_extras", "(Bundle)", "", "Argument[0]", "ReturnValue.SyntheticField[android.content.Intent.extras]", "value", "manual"] diff --git a/java/ql/test/library-tests/frameworks/android/notification/test.ext.yml b/java/ql/test/library-tests/frameworks/android/notification/test.ext.yml new file mode 100644 index 00000000000..bd5c804fddc --- /dev/null +++ b/java/ql/test/library-tests/frameworks/android/notification/test.ext.yml @@ -0,0 +1,6 @@ +extensions: + - addsTo: + pack: codeql/java-tests + extensible: summaryModel + data: + - ["generatedtest", "Test", False, "getMapKeyDefault", "(Bundle)", "", "Argument[0].MapKey", "ReturnValue", "value", "manual"] diff --git a/java/ql/test/library-tests/frameworks/apache-collections/test.ext.yml b/java/ql/test/library-tests/frameworks/apache-collections/test.ext.yml new file mode 100644 index 00000000000..a5d1cc8e1ab --- /dev/null +++ b/java/ql/test/library-tests/frameworks/apache-collections/test.ext.yml @@ -0,0 +1,7 @@ +extensions: + - addsTo: + pack: codeql/java-tests + extensible: summaryModel + data: + - ["generatedtest", "Test", False, "newRBWithMapValue", "", "", "Argument[0]", "ReturnValue.MapValue", "value", "manual"] + - ["generatedtest", "Test", False, "newRBWithMapKey", "", "", "Argument[0]", "ReturnValue.MapKey", "value", "manual"] diff --git a/java/ql/test/library-tests/frameworks/guava/generated/collect/test.ext.yml b/java/ql/test/library-tests/frameworks/guava/generated/collect/test.ext.yml new file mode 100644 index 00000000000..153b649a3e6 --- /dev/null +++ b/java/ql/test/library-tests/frameworks/guava/generated/collect/test.ext.yml @@ -0,0 +1,8 @@ +extensions: + - addsTo: + pack: codeql/java-tests + extensible: summaryModel + data: + - ["generatedtest", "Test", False, "newWithElementDefault", "(Object)", "", "Argument[0]", "ReturnValue.Element", "value", "manual"] + - ["generatedtest", "Test", False, "newWithMapKeyDefault", "(Object)", "", "Argument[0]", "ReturnValue.MapKey", "value", "manual"] + - ["generatedtest", "Test", False, "newWithMapValueDefault", "(Object)", "", "Argument[0]", "ReturnValue.MapValue", "value", "manual"] diff --git a/java/ql/test/library-tests/frameworks/stream/test.ext.yml b/java/ql/test/library-tests/frameworks/stream/test.ext.yml new file mode 100644 index 00000000000..4f1cc3e38ac --- /dev/null +++ b/java/ql/test/library-tests/frameworks/stream/test.ext.yml @@ -0,0 +1,6 @@ +extensions: + - addsTo: + pack: codeql/java-tests + extensible: summaryModel + data: + - ["generatedtest", "Test", False, "getElementSpliterator", "(Spliterator)", "", "Argument[0].Element", "ReturnValue", "value", "manual"] diff --git a/java/ql/test/library-tests/optional/test.ext.yml b/java/ql/test/library-tests/optional/test.ext.yml new file mode 100644 index 00000000000..2aebf3bdb97 --- /dev/null +++ b/java/ql/test/library-tests/optional/test.ext.yml @@ -0,0 +1,6 @@ +extensions: + - addsTo: + pack: codeql/java-tests + extensible: summaryModel + data: + - ["generatedtest", "Test", False, "getStreamElement", "", "", "Argument[0].Element", "ReturnValue", "value", "manual"] diff --git a/java/ql/test/qlpack.yml b/java/ql/test/qlpack.yml index 76f524125f5..d1fe5254a38 100644 --- a/java/ql/test/qlpack.yml +++ b/java/ql/test/qlpack.yml @@ -5,5 +5,3 @@ dependencies: codeql/java-queries: ${workspace} extractor: java tests: . -dataExtensions: - - ext/*.model.yml diff --git a/java/ql/test/query-tests/Metrics/GeneratedVsManualCoverage/GeneratedVsManualCoverage.expected b/java/ql/test/query-tests/Metrics/GeneratedVsManualCoverage/GeneratedVsManualCoverage.expected new file mode 100644 index 00000000000..2ce20c00cb4 --- /dev/null +++ b/java/ql/test/query-tests/Metrics/GeneratedVsManualCoverage/GeneratedVsManualCoverage.expected @@ -0,0 +1 @@ +| org.apache.commons.io | 14 | 1 | 1 | 2 | 18 | 0.8888888888888888 | 0.8333333333333334 | 0.1111111111111111 | 0.5 | 0.06666666666666667 | 0.16666666666666666 | diff --git a/java/ql/test/query-tests/Metrics/GeneratedVsManualCoverage/GeneratedVsManualCoverage.qlref b/java/ql/test/query-tests/Metrics/GeneratedVsManualCoverage/GeneratedVsManualCoverage.qlref new file mode 100644 index 00000000000..18e1cb980d9 --- /dev/null +++ b/java/ql/test/query-tests/Metrics/GeneratedVsManualCoverage/GeneratedVsManualCoverage.qlref @@ -0,0 +1 @@ +Metrics/Summaries/GeneratedVsManualCoverage.ql diff --git a/java/ql/test/query-tests/Metrics/GeneratedVsManualCoverage/IOUtils.java b/java/ql/test/query-tests/Metrics/GeneratedVsManualCoverage/IOUtils.java new file mode 100644 index 00000000000..0bd11f545ac --- /dev/null +++ b/java/ql/test/query-tests/Metrics/GeneratedVsManualCoverage/IOUtils.java @@ -0,0 +1,34 @@ +package org.apache.commons.io; +import java.io.*; +import java.util.*; + +public class IOUtils { + + // Generated-only summaries + public static BufferedInputStream buffer(InputStream inputStream) { return null; } + public static void copy(InputStream input, Writer output, String inputEncoding) throws IOException { } + public static long copyLarge(Reader input, Writer output) throws IOException { return 42; } + public static int read(InputStream input, byte[] buffer) throws IOException { return 42; } + public static void readFully(InputStream input, byte[] buffer) throws IOException { } + public static byte[] readFully(InputStream input, int length) throws IOException { return null; } + public static List readLines(InputStream input, String encoding) throws IOException { return null; } + public static BufferedReader toBufferedReader(Reader reader) { return null; } + public static byte[] toByteArray(InputStream input, int size) throws IOException { return null; } + public static char[] toCharArray(InputStream is, String encoding) throws IOException { return null; } + public static InputStream toInputStream(String input, String encoding) throws IOException { return null; } + public static String toString(InputStream input, String encoding) throws IOException { return null; } + public static void write(char[] data, Writer output) throws IOException { } + public static void writeChunked(char[] data, Writer output) throws IOException { } + + // Manual-only summary (generated neutral) + public static InputStream toBufferedInputStream(InputStream input) throws IOException { return null; } + + // Both + public static void writeLines(Collection lines, String lineEnding, Writer writer) throws IOException { } + + // No model + public static void noSummary(String string) throws IOException { } + + // Generated neutral + public static void copy(Reader input, OutputStream output) throws IOException { } +} diff --git a/java/ql/test/query-tests/Metrics/A.java b/java/ql/test/query-tests/Metrics/LinesOfCode/A.java similarity index 100% rename from java/ql/test/query-tests/Metrics/A.java rename to java/ql/test/query-tests/Metrics/LinesOfCode/A.java diff --git a/java/ql/test/query-tests/Metrics/LinesOfCode.expected b/java/ql/test/query-tests/Metrics/LinesOfCode/LinesOfCode.expected similarity index 100% rename from java/ql/test/query-tests/Metrics/LinesOfCode.expected rename to java/ql/test/query-tests/Metrics/LinesOfCode/LinesOfCode.expected diff --git a/java/ql/test/query-tests/Metrics/LinesOfCode.qlref b/java/ql/test/query-tests/Metrics/LinesOfCode/LinesOfCode.qlref similarity index 100% rename from java/ql/test/query-tests/Metrics/LinesOfCode.qlref rename to java/ql/test/query-tests/Metrics/LinesOfCode/LinesOfCode.qlref diff --git a/javascript/ql/lib/change-notes/2022-10-13-restify-framework-support-improvements.md b/javascript/ql/lib/change-notes/2022-10-13-restify-framework-support-improvements.md new file mode 100644 index 00000000000..99e19b51757 --- /dev/null +++ b/javascript/ql/lib/change-notes/2022-10-13-restify-framework-support-improvements.md @@ -0,0 +1,5 @@ +--- +category: feature +--- + +- Improved support for [Restify](http://restify.com/) framework, leading to more results when scanning applications developed with this framework. diff --git a/javascript/ql/lib/change-notes/2022-10-13-spife-framework-support.md b/javascript/ql/lib/change-notes/2022-10-13-spife-framework-support.md new file mode 100644 index 00000000000..52606d44502 --- /dev/null +++ b/javascript/ql/lib/change-notes/2022-10-13-spife-framework-support.md @@ -0,0 +1,5 @@ +--- +category: feature +--- + +- Added support for the [Spife](https://github.com/npm/spife) framework. diff --git a/javascript/ql/lib/semmle/javascript/frameworks/HttpFrameworks.qll b/javascript/ql/lib/semmle/javascript/frameworks/HttpFrameworks.qll index 7568280dcc4..8e91230d3b2 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/HttpFrameworks.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/HttpFrameworks.qll @@ -7,3 +7,4 @@ import semmle.javascript.frameworks.Micro import semmle.javascript.frameworks.Restify import semmle.javascript.frameworks.Connect import semmle.javascript.frameworks.Fastify +import semmle.javascript.frameworks.Spife diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Restify.qll b/javascript/ql/lib/semmle/javascript/frameworks/Restify.qll index 889369c6ea4..190987ba3c9 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/Restify.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/Restify.qll @@ -4,7 +4,11 @@ import javascript import semmle.javascript.frameworks.HTTP +import semmle.javascript.security.dataflow.RequestForgeryCustomizations as RFC +/** + * Provides classes for working with [Restify](https://restify.com/) servers. + */ module Restify { /** * An expression that creates a new Restify server. @@ -19,23 +23,23 @@ module Restify { /** * A Restify route handler. */ - class RouteHandler extends Http::Servers::StandardRouteHandler, DataFlow::ValueNode { - Function function; - - RouteHandler() { - function = astNode and - any(RouteSetup setup).getARouteHandler() = this - } - + abstract class RouteHandler extends Http::Servers::StandardRouteHandler, DataFlow::FunctionNode { /** * Gets the parameter of the route handler that contains the request object. */ - Parameter getRequestParameter() { result = function.getParameter(0) } + DataFlow::ParameterNode getRequestParameter() { result = this.getParameter(0) } /** * Gets the parameter of the route handler that contains the response object. */ - Parameter getResponseParameter() { result = function.getParameter(1) } + DataFlow::ParameterNode getResponseParameter() { result = this.getParameter(1) } + } + + /** + * A standard Restify route handler. + */ + class StandardRouteHandler extends RouteHandler, DataFlow::FunctionNode { + StandardRouteHandler() { any(RouteSetup setup).getARouteHandler() = this } } /** @@ -45,7 +49,7 @@ module Restify { private class ResponseSource extends Http::Servers::ResponseSource { RouteHandler rh; - ResponseSource() { this = DataFlow::parameterNode(rh.getResponseParameter()) } + ResponseSource() { this = rh.getResponseParameter() } /** * Gets the route handler that provides this response. @@ -60,7 +64,7 @@ module Restify { private class RequestSource extends Http::Servers::RequestSource { RouteHandler rh; - RequestSource() { this = DataFlow::parameterNode(rh.getRequestParameter()) } + RequestSource() { this = rh.getRequestParameter() } /** * Gets the route handler that handles this request. @@ -80,7 +84,7 @@ module Restify { * A Node.js HTTP response provided by Restify. */ class ResponseNode extends NodeJSLib::ResponseNode { - ResponseNode() { src instanceof ResponseSource } + ResponseNode() { src instanceof ResponseSource or src instanceof FormatterResponseSource } } /** @@ -95,14 +99,14 @@ module Restify { * A Node.js HTTP request provided by Restify. */ class RequestNode extends NodeJSLib::RequestNode { - RequestNode() { src instanceof RequestSource } + RequestNode() { src instanceof RequestSource or src instanceof FormatterRequestSource } } /** * An access to a user-controlled Restify request input. */ private class RequestInputAccess extends Http::RequestInputAccess { - RequestNode request; + Http::RequestNode request; string kind; RequestInputAccess() { @@ -113,23 +117,17 @@ module Restify { this.(DataFlow::PropRead).accesses(query, _) ) or - exists(string methodName | - // `request.href()` or `request.getPath()` - kind = "url" and - this.(DataFlow::MethodCallNode).calls(request, methodName) - | - methodName = "href" or - methodName = "getPath" + exists(DataFlow::PropRead prop | + // `request.params.` + // `request.query.` + kind = "parameter" and + prop.accesses(request, ["params", "query"]) and + this.(DataFlow::PropRead).accesses(prop, _) ) or - // `request.getContentType()`, `request.userAgent()`, `request.trailer(...)`, `request.header(...)` - kind = "header" and - this.(DataFlow::MethodCallNode) - .calls(request, ["getContentType", "userAgent", "trailer", "header"]) - or - // `req.cookies - kind = "cookie" and - this.(DataFlow::PropRead).accesses(request, "cookies") + // `request.href()` or `request.getPath()` + kind = "url" and + this.(DataFlow::MethodCallNode).calls(request, ["href", "getPath"]) } override RouteHandler getRouteHandler() { result = request.getRouteHandler() } @@ -137,12 +135,35 @@ module Restify { override string getKind() { result = kind } } + /** + * An access to a header on a Restify request. + */ + private class RequestHeaderAccess extends Http::RequestHeaderAccess instanceof DataFlow::MethodCallNode { + RouteHandler rh; + + RequestHeaderAccess() { + // `request.getContentType()`, `request.userAgent()`, `request.trailer(...)`, `request.header(...)` + this = + rh.getARequestSource() + .ref() + .getAMethodCall(["header", "trailer", "userAgent", "getContentType"]) + } + + override string getAHeaderName() { + super.getArgument(0).mayHaveStringValue(any(string s | s.toLowerCase() = result)) + } + + override RouteHandler getRouteHandler() { result = rh } + + override string getKind() { result = "header" } + } + /** * An HTTP header defined in a Restify server. */ private class HeaderDefinition extends Http::Servers::StandardHeaderDefinition { HeaderDefinition() { - // response.header('Cache-Control', 'no-cache') + // res.header('Cache-Control', 'no-cache') this.getReceiver() instanceof ResponseNode and this.getMethodName() = "header" } @@ -150,6 +171,38 @@ module Restify { override RouteHandler getRouteHandler() { this.getReceiver() = result.getAResponseNode() } } + /** + * An invocation that sets any number of headers of the HTTP response. + */ + private class MultipleHeaderDefinitions extends Http::ExplicitHeaderDefinition, + DataFlow::MethodCallNode { + MultipleHeaderDefinitions() { + // res.set({'Cache-Control': 'no-cache'}) + this.getReceiver() instanceof ResponseNode and + this.getMethodName() = "set" + } + + /** + * Gets a reference to the multiple headers object that is to be set. + */ + private DataFlow::ObjectLiteralNode getAHeaderSource() { + result = this.getArgument(0).getALocalSource() + } + + override predicate definesHeaderValue(string headerName, DataFlow::Node headerValue) { + exists(string header | + this.getAHeaderSource().hasPropertyWrite(header, headerValue) and + headerName = header.toLowerCase() + ) + } + + override DataFlow::Node getNameNode() { + result = this.getAHeaderSource().getAPropertyWrite().getPropertyNameExpr().flow() + } + + override RouteHandler getRouteHandler() { this.getReceiver() = result.getAResponseNode() } + } + /** * A call to a Restify method that sets up a route. */ @@ -157,13 +210,256 @@ module Restify { ServerDefinition server; RouteSetup() { - // server.get('/', fun) - // server.head('/', fun) - server.ref().getAMethodCall(any(Http::RequestMethodName m).toLowerCase()) = this + server + .ref() + .getAMethodCall([ + "del", "get", "head", "opts", "post", "put", "patch", "param", "pre", "use", "on" + ]) = this } - override DataFlow::SourceNode getARouteHandler() { result.flowsTo(this.getArgument(1)) } + override DataFlow::SourceNode getARouteHandler() { + exists(DataFlow::Node arg | + // server.get('/', fun) + // server.get('/', fun1, fun2) + // server.get('/', [fun1, fun2]) + // server.param('name', fun) + // server.on('event', fun) + this.getMethodName() = ["del", "get", "head", "opts", "post", "put", "patch", "param", "on"] and + arg = this.getAnArgument() and + not arg = this.getArgument(0) + or + // server.use(fun) + // server.use(fun1, fun2) + // server.use([fun1, fun2]) + this.getMethodName() = ["use", "pre"] and + arg = this.getAnArgument() + | + ( + // server.use(fun1, fun2) + result.flowsTo(arg) and + not arg.getALocalSource() instanceof DataFlow::ArrayCreationNode + or + result.flowsTo(arg.getALocalSource().(DataFlow::ArrayCreationNode).getAnElement()) + ) + ) + } override DataFlow::Node getServer() { result = server } } + + /** + * A call to a Restify's createServer method that sets up a formatter. + */ + class FormatterSetup extends DataFlow::CallNode { + DataFlow::ObjectLiteralNode formatters; + + FormatterSetup() { + // `server = restify.createServer({ formatters: { ... } })` + this = DataFlow::moduleMember("restify", "createServer").getACall() and + this.getArgument(0) + .getALocalSource() + .(DataFlow::ObjectLiteralNode) + .hasPropertyWrite("formatters", formatters) + } + + /** + * Gets the formatter handler installed by this setup. + */ + DataFlow::FunctionNode getAFormatterHandler() { + result = formatters.getAPropertyWrite().getRhs().getALocalSource() + } + } + + /** + * A Restify route handler. + */ + class FormatterHandler extends Http::Servers::StandardRouteHandler, DataFlow::FunctionNode { + FormatterHandler() { any(FormatterSetup setup).getAFormatterHandler() = this } + + /** + * Gets the parameter of the formatter handler that contains the request object. + */ + DataFlow::ParameterNode getRequestParameter() { result = this.getParameter(0) } + + /** + * Gets the parameter of the formatter handler that contains the response object. + */ + DataFlow::ParameterNode getResponseParameter() { result = this.getParameter(1) } + + /** + * Gets the parameter of the formatter handler that contains the body object. + */ + DataFlow::ParameterNode getBodyParameter() { result = this.getParameter(2) } + } + + /** + * A Restify request source, that is, the request parameter of a + * route handler. + */ + private class FormatterRequestSource extends Http::Servers::RequestSource { + FormatterHandler fh; + + FormatterRequestSource() { this = fh.getRequestParameter() } + + /** + * Gets the formatter handler that handles this request. + */ + override RouteHandler getRouteHandler() { result = fh } + } + + /** + * A Restify response source, that is, the response parameter of a + * route handler. + */ + private class FormatterResponseSource extends Http::Servers::ResponseSource { + FormatterHandler fh; + + FormatterResponseSource() { this = fh.getResponseParameter() } + + /** + * Gets the route handler that provides this response. + */ + override RouteHandler getRouteHandler() { result = fh } + } + + /** + * An argument passed to the `send` method of an HTTP response object. + */ + private class ResponseSendArgument extends Http::ResponseSendArgument { + RouteHandler rh; + + ResponseSendArgument() { + this = rh.getAResponseSource().ref().getAMethodCall(["send", "sendRaw"]).getArgument(0) + } + + override RouteHandler getRouteHandler() { result = rh } + } + + /** + * An expression returned by a formatter + */ + private class FormatterOutput extends Http::ResponseSendArgument { + FormatterHandler fh; + + FormatterOutput() { this = fh.getAReturn() } + + override Http::RouteHandler getRouteHandler() { result = fh } + } + + /** + * An invocation of the `redirect` method of an HTTP response object. + */ + private class RedirectInvocation extends Http::RedirectInvocation, DataFlow::MethodCallNode { + RouteHandler rh; + + RedirectInvocation() { this = rh.getAResponseSource().ref().getAMethodCall("redirect") } + + override DataFlow::Node getUrlArgument() { + this.getNumArgument() = 3 and + result = this.getArgument(1) + or + this.getNumArgument() = 2 and + this.getArgument(0).getALocalSource().hasPropertyWrite("hostname", result) + or + this.getNumArgument() = 2 and + result = this.getArgument(0) + } + + override RouteHandler getRouteHandler() { result = rh } + } + + /** + * A function that looks like a Restify route handler. + * + * For example, this could be the function `function(req, res, next){...}`. + */ + class RouteHandlerCandidate extends Http::RouteHandlerCandidate { + RouteHandlerCandidate() { + // heuristic: parameter names match the Restify documentation + astNode.getNumParameter() = [2, 3] and + astNode.getParameter(0).getName() = ["request", "req"] and + astNode.getParameter(1).getName() = ["response", "res"] and + not astNode.getParameter(2).getName() != "next" and + // heuristic: is not invoked (Restify invokes this at a call site we cannot reason precisely about) + not exists(DataFlow::InvokeNode cs | cs.getACallee() = astNode) + } + } + + /** + * The URL of a Restify client, viewed as a sink for request forgery. + */ + class RequestForgerySink extends RFC::RequestForgery::Sink { + RequestForgerySink() { + exists(DataFlow::Node arg | + DataFlow::moduleMember("restify-clients", + ["createClient", "createJsonClient", "createStringClient"]).getACall().getArgument(0) = + arg and + ( + arg.getALocalSource().(DataFlow::ObjectLiteralNode).hasPropertyWrite("url", this) + or + not arg.getALocalSource() instanceof DataFlow::ObjectLiteralNode and + this = arg + ) + ) + } + + override DataFlow::Node getARequest() { + // returning the createClient argument itself since there is no request associated to the client yet. + // `getARequest()` is only used for display purposes + result = this + } + + override string getKind() { result = "host" } + } + + /** + * A header produced by a formatter + */ + private class FormatterContentTypeHeader extends Http::ImplicitHeaderDefinition, + DataFlow::FunctionNode instanceof FormatterHandler { + string contentType; + + FormatterContentTypeHeader() { + exists(DataFlow::PropWrite write | + write.getRhs() = this and + write.getPropertyName() = contentType + ) + } + + override predicate defines(string headerName, string headerValue) { + headerName = "content-type" and headerValue = contentType + } + + override Http::RouteHandler getRouteHandler() { result = this } + } + + /** + * A header produced by a route handler with no explicit declaration of a Content-Type. + */ + private class ContentTypeRouteHandlerHeader extends Http::ImplicitHeaderDefinition, + DataFlow::FunctionNode instanceof RouteHandler { + override predicate defines(string headerName, string headerValue) { + headerName = "content-type" and headerValue = "application/json" + } + + override Http::RouteHandler getRouteHandler() { result = this } + } + + /** A Restify router */ + private class RouterRange extends Routing::Router::Range { + ServerDefinition def; + + RouterRange() { this = def } + + override DataFlow::SourceNode getAReference() { result = def.ref() } + } + + private class RoutingTreeSetup extends Routing::RouteSetup::MethodCall instanceof RouteSetup { + override string getRelativePath() { + not this.getMethodName() = ["use", "pre", "param", "on"] and // do not treat parameter name as a path + result = this.getArgument(0).getStringValue() + } + + override Http::RequestMethodName getHttpMethod() { result.toLowerCase() = this.getMethodName() } + } } diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Spife.qll b/javascript/ql/lib/semmle/javascript/frameworks/Spife.qll new file mode 100644 index 00000000000..7435c23d8c2 --- /dev/null +++ b/javascript/ql/lib/semmle/javascript/frameworks/Spife.qll @@ -0,0 +1,433 @@ +/** + * Provides classes for working with [Spife](https://github.com/npm/spife) applications. + */ + +import javascript +import semmle.javascript.frameworks.HTTP +private import DataFlow + +/** + * Provides classes for working with [Spife](https://github.com/npm/spife) applications. + */ +module Spife { + /** + * A call to a Spife method that sets up a route. + */ + private class RouteSetup extends DataFlow::CallNode, Http::Servers::StandardRouteSetup { + TaggedTemplateExpr template; + + RouteSetup() { + this.getCalleeNode().asExpr() = template and + API::moduleImport(["@npm/spife/routing", "spife/routing"]) + .asSource() + .flowsToExpr(template.getTag()) + } + + private string getRoutePattern() { + // Concatenate the constant parts of the expression + result = + strictconcat(Expr e, int i | + e = template.getTemplate().getElement(i) and exists(e.getStringValue()) + | + e.getStringValue() order by i + ) + } + + private string getARouteLine() { + result = this.getRoutePattern().splitAt("\n").regexpReplaceAll(" +", " ").trim() + } + + private predicate hasLine(string method, string path, string handlerName) { + exists(string line | line = this.getARouteLine() | + line.splitAt(" ", 0) = method and + line.splitAt(" ", 1) = path and + line.splitAt(" ", 2) = handlerName + ) + } + + DataFlow::SourceNode getHandlerDefinitions(TypeBackTracker t) { + t.start() and + result = this.getArgument(0).getALocalSource() + or + exists(TypeBackTracker t2 | result = this.getHandlerDefinitions(t2).backtrack(t2, t)) + } + + DataFlow::SourceNode getHandlerDefinitions() { + result = this.getHandlerDefinitions(TypeBackTracker::end()) + } + + DataFlow::SourceNode getHandlerByName(string name) { + result = this.getHandlerDefinitions().getAPropertySource(name) + } + + DataFlow::SourceNode getHandlerByRoute(string method, string path) { + exists(string handlerName | + this.hasLine(method, path, handlerName) and + result = this.getHandlerByName(handlerName) + ) + } + + override DataFlow::SourceNode getARouteHandler() { + result = this.getHandlerByRoute(_, _).getALocalSource().(DataFlow::FunctionNode) + or + exists(DataFlow::MethodCallNode validation | + validation = this.getHandlerByRoute(_, _).getALocalSource() and + result = validation.getArgument(1).getAFunctionValue() + ) + } + + override DataFlow::Node getServer() { none() } + } + + /** + * A Spife route handler. + */ + abstract class RouteHandler extends Http::Servers::StandardRouteHandler, DataFlow::FunctionNode { + /** + * Gets the parameter of the route handler that contains the request object. + */ + DataFlow::ParameterNode getRequestParameter() { result = this.getParameter(0) } + + /** + * Gets the parameter of the route handler that contains the context object. + */ + DataFlow::ParameterNode getContextParameter() { result = this.getParameter(1) } + } + + /** + * A standard Spife route handler. + */ + private class StandardRouteHandler extends RouteHandler, DataFlow::FunctionNode { + StandardRouteHandler() { any(RouteSetup setup).getARouteHandler() = this } + } + + /** + * A function that looks like a Spife route handler. + * + * For example, this could be the function `function(request, context){...}`. + */ + class RouteHandlerCandidate extends Http::RouteHandlerCandidate { + RouteHandlerCandidate() { + // heuristic: parameter names match the Restify documentation + astNode.getNumParameter() = 2 and + astNode.getParameter(0).getName() = ["request", "req"] and + astNode.getParameter(1).getName() = ["context", "ctx"] + } + } + + /** + * A Spife request source, that is, the request parameter of a + * route handler. + */ + private class RequestSource extends Http::Servers::RequestSource { + RouteHandler rh; + + RequestSource() { this = rh.getRequestParameter() } + + /** + * Gets the route handler that handles this request. + */ + override RouteHandler getRouteHandler() { result = rh } + } + + /** + * A Spife context source, that is, the context the parameter of a + * route handler. + */ + private class ContextSource extends Http::Servers::RequestSource { + RouteHandler rh; + + ContextSource() { this = rh.getContextParameter() } + + /** + * Gets the route handler that handles this request. + */ + override RouteHandler getRouteHandler() { result = rh } + } + + /** + * An access to a user-controlled Spife request input. + */ + private class RequestInputAccess extends Http::RequestInputAccess { + RouteHandler rh; + string kind; + + RequestInputAccess() { + // req.body + this = rh.getARequestSource().ref().getAPropertyRead("body") and + kind = "body" + or + // req.query['foo'] + this = rh.getARequestSource().ref().getAPropertyRead("query").getAPropertyRead() and + kind = "parameter" + or + // req.raw + this = rh.getARequestSource().ref().getAPropertyRead("raw") and + kind = "raw" + or + // req.url + // req.urlObject + this = rh.getARequestSource().ref().getAPropertyRead(["url", "urlObject"]) and + kind = "url" + or + // req.cookie('foo') + // req.cookies() + this = rh.getARequestSource().ref().getAMethodCall() and + this.(DataFlow::MethodCallNode).getMethodName() = ["cookie", "cookies"] and + kind = "cookie" + or + // req.validatedBody.get('foo') + this = + rh.getARequestSource() + .ref() + .getAPropertyRead(any(string s | s.matches("validated%"))) + .getAMethodCall("get") and + kind = "body" + } + + override RouteHandler getRouteHandler() { result = rh } + + override string getKind() { result = kind } + } + + /** + * An access to a user-controlled Spife context input. + */ + private class ContextInputAccess extends Http::RequestInputAccess instanceof DataFlow::MethodCallNode { + ContextSource request; + string kind; + + ContextInputAccess() { + this = request.ref().getAMethodCall("get") and + kind = "path" + } + + override RouteHandler getRouteHandler() { result = request.getRouteHandler() } + + override string getKind() { result = kind } + } + + /** + * An access to a header on a Spife request. + */ + private class RequestHeaderAccess extends Http::RequestHeaderAccess instanceof DataFlow::PropRead { + RouteHandler rh; + + RequestHeaderAccess() { + this = + rh.getARequestSource().ref().getAPropertyRead(["headers", "rawHeaders"]).getAPropertyRead() + } + + override string getAHeaderName() { result = super.getPropertyName().toLowerCase() } + + override RouteHandler getRouteHandler() { result = rh } + + override string getKind() { result = "header" } + } + + /** + * A Spife response source, that is, the response variable used by a + * route handler. + */ + private class ReplyCall extends API::CallNode { + boolean isDirectReplyCall; + + ReplyCall() { + // reply(resp) + this = API::moduleImport(["@npm/spife/reply", "spife/reply"]).getACall() and + isDirectReplyCall = true + or + // reply.header(resp, 'foo', 'bar') + this = API::moduleImport(["@npm/spife/reply", "spife/reply"]).getAMember().getACall() and + isDirectReplyCall = false + } + + predicate isDirectReplyCall() { isDirectReplyCall = true } + + /** + * Gets the route handler that provides this response. + */ + RouteHandler getRouteHandler() { + result.getAReturn() = this.getReturn().getAValueReachableFromSource() + } + } + + /** + * An HTTP header defined in a Spife response. + */ + private class SingleHeaderDefinition extends Http::ExplicitHeaderDefinition instanceof ReplyCall { + SingleHeaderDefinition() { + // reply.header(RESPONSE, 'Cache-Control', 'no-cache') + this.getCalleeName() = "header" and + this.getNumArgument() = 3 + } + + override predicate definesHeaderValue(string headerName, DataFlow::Node headerValue) { + // reply.header(RESPONSE, 'Cache-Control', 'no-cache') + this.getNameNode().mayHaveStringValue(headerName) and + headerValue = super.getArgument(2) + } + + override DataFlow::Node getNameNode() { result = super.getArgument(1) } + + override RouteHandler getRouteHandler() { result = ReplyCall.super.getRouteHandler() } + } + + /** + * An invocation that sets any number of headers of the HTTP response. + */ + private class MultipleHeaderDefinitions extends Http::ExplicitHeaderDefinition instanceof ReplyCall { + MultipleHeaderDefinitions() { + ( + // reply.header(RESPONSE, {'Cache-Control': 'no-cache'}) + this.getCalleeName() = "header" + or + // reply(RESPONSE, {'Cache-Control': 'no-cache'}) + this.isDirectReplyCall() + ) and + this.getAnArgument().getALocalSource() instanceof DataFlow::ObjectLiteralNode + } + + /** + * Gets a reference to the multiple headers object that is to be set. + */ + DataFlow::ObjectLiteralNode getAHeaderSource() { + result = super.getAnArgument().getALocalSource() + } + + override predicate definesHeaderValue(string headerName, DataFlow::Node headerValue) { + exists(string header | + this.getAHeaderSource().hasPropertyWrite(header, headerValue) and + headerName = header.toLowerCase() + ) + } + + override DataFlow::Node getNameNode() { + result = this.getAHeaderSource().getAPropertyWrite().getPropertyNameExpr().flow() + } + + override RouteHandler getRouteHandler() { result = ReplyCall.super.getRouteHandler() } + } + + /** + * A header produced by a route handler with no explicit declaration of a Content-Type. + */ + private class ContentTypeRouteHandlerHeader extends Http::ImplicitHeaderDefinition instanceof RouteHandler { + override predicate defines(string headerName, string headerValue) { + headerName = "content-type" and headerValue = "application/json" + } + + override RouteHandler getRouteHandler() { result = this } + } + + /** + * An HTTP cookie defined in a Spife HTTP response. + */ + private class CookieDefinition extends Http::CookieDefinition instanceof ReplyCall { + CookieDefinition() { + // reply.cookie(RESPONSE, 'TEST', 'FOO', {"maxAge": 1000, "httpOnly": true, "secure": true}) + this.getCalleeName() = "cookie" + } + + // this = any(ReplyCall r).ref().getAMethodCall("cookie") + override DataFlow::Node getNameArgument() { result = super.getArgument(1) } + + override DataFlow::Node getValueArgument() { result = super.getArgument(2) } + + override RouteHandler getRouteHandler() { result = ReplyCall.super.getRouteHandler() } + } + + /** + * A response sent using a method on the `reply` object. + */ + private class ReplyMethodCallArgument extends Http::ResponseSendArgument { + ReplyCall reply; + + ReplyMethodCallArgument() { + // reply.header(RESPONSE, {'Cache-Control': 'no-cache'}) + reply.getCalleeName() = + ["cookie", "link", "header", "headers", "raw", "status", "toStream", "vary"] and + reply.getArgument(0) = this + } + + override RouteHandler getRouteHandler() { result = reply.getRouteHandler() } + } + + /** + * A response sent using the `reply()` method. + */ + private class ReplyCallArgument extends Http::ResponseSendArgument { + ReplyCall reply; + + ReplyCallArgument() { + // reply(RESPONSE, {'Cache-Control': 'no-cache'}) + reply.isDirectReplyCall() and + reply.getArgument(0) = this + } + + override RouteHandler getRouteHandler() { result = reply.getRouteHandler() } + } + + /** + * The return statement for a route handler. + */ + private class RouteHandlerReturn extends Http::ResponseSendArgument { + RouteHandler rh; + + RouteHandlerReturn() { + this = rh.getAReturn() and not this.getALocalSource() instanceof ReplyCall + } + + override RouteHandler getRouteHandler() { result = rh } + } + + /** + * A call to `reply.template('template', { ... })`, seen as a template instantiation. + */ + private class TemplateCall extends Templating::TemplateInstantiation::Range instanceof ReplyCall { + TemplateCall() { this.getCalleeName() = "template" } + + override DataFlow::SourceNode getOutput() { result = this } + + override DataFlow::Node getTemplateFileNode() { result = super.getArgument(0) } + + override DataFlow::Node getTemplateParamsNode() { result = super.getArgument(1) } + } + + /** + * An object passed to the `template` method of the reply object. + */ + private class TemplateObjectInput extends DataFlow::Node { + ReplyCall call; + + TemplateObjectInput() { this = call.getArgument(1) } + + /** + * Gets the route handler that uses this object. + */ + RouteHandler getRouteHandler() { result = call.getRouteHandler() } + } + + /** + * An expression passed to the `template` method of the reply object + * as the value of a template variable. + */ + private class TemplateInput extends Http::ResponseBody { + TemplateObjectInput obj; + + TemplateInput() { obj.getALocalSource().hasPropertyWrite(_, this) } + + override RouteHandler getRouteHandler() { result = obj.getRouteHandler() } + } + + /** + * An invocation of the `redirect` method of an HTTP response object. + */ + private class RedirectInvocation extends Http::RedirectInvocation instanceof ReplyCall { + RedirectInvocation() { this.getCalleeName() = "redirect" } + + override DataFlow::Node getUrlArgument() { result = this.getAnArgument() } + + override RouteHandler getRouteHandler() { result = ReplyCall.super.getRouteHandler() } + } +} diff --git a/javascript/ql/lib/semmle/javascript/heuristics/AdditionalRouteHandlers.qll b/javascript/ql/lib/semmle/javascript/heuristics/AdditionalRouteHandlers.qll index a9b730a5003..a62edc692b3 100644 --- a/javascript/ql/lib/semmle/javascript/heuristics/AdditionalRouteHandlers.qll +++ b/javascript/ql/lib/semmle/javascript/heuristics/AdditionalRouteHandlers.qll @@ -38,3 +38,19 @@ private class PromotedConnectCandidate extends Connect::RouteHandler, result = ConnectExpressShared::getRouteHandlerParameter(this, kind) } } + +/** + * Add `Restify::RouteHandlerCandidate` to the extent of `Restify::RouteHandler`. + */ +private class PromotedRestifyCandidate extends Restify::RouteHandler, + Http::Servers::StandardRouteHandler { + PromotedRestifyCandidate() { this instanceof Restify::RouteHandlerCandidate } +} + +/** + * Add `Spife::RouteHandlerCandidate` to the extent of `Spife::RouteHandler`. + */ +private class PromotedSpifeCandidate extends Spife::RouteHandler, + Http::Servers::StandardRouteHandler { + PromotedSpifeCandidate() { this instanceof Spife::RouteHandlerCandidate } +} diff --git a/javascript/ql/test/library-tests/frameworks/HTTP/RemoteRequestInput.expected b/javascript/ql/test/library-tests/frameworks/HTTP/RemoteRequestInput.expected index c3bd4a86afe..e6c285607c4 100644 --- a/javascript/ql/test/library-tests/frameworks/HTTP/RemoteRequestInput.expected +++ b/javascript/ql/test/library-tests/frameworks/HTTP/RemoteRequestInput.expected @@ -35,4 +35,3 @@ | restify.js:9:5:9:17 | req.trailer() | header | | restify.js:10:5:10:16 | req.header() | header | | restify.js:11:5:11:11 | req.url | url | -| restify.js:12:5:12:15 | req.cookies | cookie | diff --git a/javascript/ql/test/library-tests/frameworks/NodeJSLib/tests.expected b/javascript/ql/test/library-tests/frameworks/NodeJSLib/tests.expected index 7d2d6abfddb..78c2c35309f 100644 --- a/javascript/ql/test/library-tests/frameworks/NodeJSLib/tests.expected +++ b/javascript/ql/test/library-tests/frameworks/NodeJSLib/tests.expected @@ -299,11 +299,13 @@ test_RemoteFlowSources | src/http.js:30:28:30:32 | chunk | | src/http.js:40:23:40:30 | authInfo | | src/http.js:45:23:45:27 | error | +| src/http.js:63:17:63:33 | req.query.myParam | | src/http.js:73:18:73:22 | chunk | | src/http.js:82:18:82:22 | chunk | | src/https.js:6:26:6:32 | req.url | | src/https.js:8:3:8:20 | req.headers.cookie | | src/https.js:9:3:9:17 | req.headers.foo | +| src/indirect2.js:10:12:10:25 | req.params.key | | src/indirect.js:17:28:17:34 | req.url | test_RouteHandler | createServer.js:2:20:2:41 | functio ... res) {} | createServer.js:2:1:2:42 | https.c ... es) {}) | diff --git a/javascript/ql/test/library-tests/frameworks/Restify2/src/index.js b/javascript/ql/test/library-tests/frameworks/Restify2/src/index.js new file mode 100644 index 00000000000..9031aa24564 --- /dev/null +++ b/javascript/ql/test/library-tests/frameworks/Restify2/src/index.js @@ -0,0 +1,214 @@ +var restify = require('restify'); +const restifyPlugins = require('restify-plugins'); +var clients = require('restify-clients'); + +const opts = { + formatters: { + 'text/plain': function(req, res, body) { // test: formatter + if (body instanceof Error) { + return '' + body.message + ''; // test: stackTraceExposureSink + } else { + return '' + body + req.params.name + ''; // test: source, stackTraceExposureSink, !xssSink, !xss + } + } + } +} +const _server = restify.createServer(opts) + +const server = restify.createServer({ + formatters: { + 'text/html': function(req, res, body) { // test: formatter + if (body instanceof Error) { + return '' + body.message + ''; // test: stackTraceExposureSink, xssSink + } else { + return '' + body + req.params.name + ''; // test: source, stackTraceExposureSink, xssSink, xss + } + } + } +}); + +// The pre handler chain is executed before routing. That means these handlers will execute for an incoming request even if it’s for a route that you did not register. +server.pre(restify.plugins.pre.dedupeSlashes()); +server.pre(function(req, res, next) { // test: handler + return next(); +}); + +// The use handler chains is executed after a route has been chosen to service the request. +server.use(restifyPlugins.jsonBodyParser({ mapParams: true })); // TODO: prototype pollution? +server.use(restifyPlugins.acceptParser(server.acceptable)); +server.use(restifyPlugins.queryParser({ mapParams: true })); // TODO: prototype pollution? +server.use(restifyPlugins.fullResponse()); +server.use(function(req, res, next) { // test: handler + return next(); +}); +function filter(req, res, next) { // test: handler + return next(); +} +function filter1(req, res, next) { // test: handler + return next(); +} +function filter2(req, res, next) { // test: handler + return next(); +} +function filter3(req, res, next) { // test: handler + return next(); +} +function filter4(req, res, next) { // test: handler + return next(); +} +function filter5(req, res, next) { // test: handler + return next(); +} +function filter6(req, res, next) { // test: handler + return next(); +} +const handlers = [filter5, filter6]; +server.use(filter); // test: setup +server.use(filter1, filter2); // test: setup +server.use([filter3, filter4]); // test: setup +server.use(handlers); // setup + +function respond(req, res, next) { // test: handler + res.send('hello ' + req.params.name); // test: source, stackTraceExposureSink + res.send('hello ' + req.params["name"]); // test: source, stackTraceExposureSink + res.send('hello ' + req.query.name); // test: source, stackTraceExposureSink + res.send('hello ' + req.params[0]); // test: source, stackTraceExposureSink + + res.redirect({ + hostname: req.params.name, // test: source, redirectSink + pathname: '/bar', + port: 80, + secure: true, + permanent: true, + query: { + a: 1 + } + }, next); + res.redirect(301, req.params.name, next); // test: source, redirectSink + res.redirect(req.params.name, next); // test: source, redirectSink + next(); +} +server.get('/hello/:name', respond); // test: setup +server.head('/hello/:name', respond); // test: setup +server.get('/', function(req, res, next) { // test: setup, handler + res.send('home') + return next(); +}); + +server.get('/foo', // test: setup + function(req, res, next) { // test: handler + req.someData = req.params.name; // test: source + return next(); + }, + function(req, res, next) { // test: handler + res.header("Content-Type", "text/html"); // test: headerDefinition + res.send(req.someData); // test: stackTraceExposureSink, xssSink, xss + return next(); + } +); + +server.get('/foo2', // test: setup + [function(req, res, next) { // test: handler + req.someData = 'foo'; + return next(); + }, + function(req, res, next) { // test: handler + res.send(req.someData); // test: stackTraceExposureSink + return next(); + }] +); + +function xss(req, res, next) { // test: handler + res.header("Content-Type", "text/html"); // test: headerDefinition + res.send('hello ' + req.query.name); // test: source, stackTraceExposureSink, xssSink, xss + next(); +} + +function xss2(req, res, next) { // test: candidateHandler + next() +} + +function xss3(req, res, next) { // test: handler + res.header("Content-Type", "text/html"); // test: headerDefinition + res.send('hello ' + req.header("foo")); // test: source, stackTraceExposureSink, xssSink, !xss + next(); +} + +function xss4(req, res, next) { // test: handler + var body = req.params.name; // test: source + res.writeHead(200, { + 'Content-Length': Buffer.byteLength(body), + 'Content-Type': 'text/html' + }); + res.write(body); // test: stackTraceExposureSink, xssSink, xss + res.end(); + next(); +} + +server["get"]('/xss', xss); // test: setup +["get", "head"].forEach(method => { + server[method]('/xss2', xss2); +}); +server["get"]('/xss3', xss3); // test: setup +server["get"]('/xss4', xss4); // test: setup + + +server.get('/testv2', function(req, res, next) { // test: handler + res.set({ + "Content-Type": "text/html", + "access-control-allow-origin": "*", // test: corsMiconfigurationSink + "access-control-allow-headers": "Content-Type, Authorization, Content-Length, X-Requested-With", + "access-control-allow-methods": "GET, POST, PUT, DELETE, OPTIONS", + "access-control-allow-credentials": "true" + }) + res.send('hello ' + req.params.name); // test: source, stackTraceExposureSink, xssSink, xss + clients.createJsonClient({ + url: req.params.uri, // test: source, ssrfSink + }); + clients.createJsonClient(req.params.uri); // test: source, ssrfSink + + next(); +}) + +server.get('/hello2/:name', restify.plugins.conditionalHandler([ // test: setup + { version: ['2.0.0', '2.1.0', '2.2.0'], handler: sendV2 } +])); + +server.get('/version/test', restify.plugins.conditionalHandler([ //test: setup + { + version: ['2.0.0', '2.1.0', '2.2.0'], + handler: function(req, res, next) { // test: candidateHandler + res.send(200, { + requestedVersion: req.version(), + matchedVersion: req.matchedVersion() + }); + return next(); + } + } +])); + +server.on('InternalServer', function(req, res, err, callback) { // test: setup, handler + return callback(); +}); + +server.on('restifyError', function(req, res, err, callback) { // test: setup, handler + return callback(); +}); +server.on('after', function(req, res, route, error) { // test: setup, handler +}); +server.on('pre', function(req, res) { // test: setup, handler +}); +server.on('routed', function(req, res, route) { // test: setup, handler + res.header("Content-Type", "text/plain") + res.send(req.params.foo) // test: source, !xssSink, !xss +}); +server.on('uncaughtException', function(req, res, route, err) { // test: setup, handler + res.header("Content-Type", "text/html") + res.send(req.params.foo) // test: source, xssSink, xss +}); + + +server.listen(8080, function() { + console.log('%s listening at %s', server.name, server.url); +}); + diff --git a/javascript/ql/test/library-tests/frameworks/Restify2/tests.expected b/javascript/ql/test/library-tests/frameworks/Restify2/tests.expected new file mode 100644 index 00000000000..678104f52a8 --- /dev/null +++ b/javascript/ql/test/library-tests/frameworks/Restify2/tests.expected @@ -0,0 +1,110 @@ +passingPositiveTests +| PASSED | candidateHandler | src/index.js:127:33:127:57 | // test ... Handler | +| PASSED | candidateHandler | src/index.js:180:42:180:66 | // test ... Handler | +| PASSED | corsMiconfigurationSink | src/index.js:159:41:159:72 | // test ... ionSink | +| PASSED | handler | src/index.js:32:39:32:54 | // test: handler | +| PASSED | handler | src/index.js:41:39:41:54 | // test: handler | +| PASSED | handler | src/index.js:44:35:44:50 | // test: handler | +| PASSED | handler | src/index.js:47:36:47:51 | // test: handler | +| PASSED | handler | src/index.js:50:36:50:51 | // test: handler | +| PASSED | handler | src/index.js:53:36:53:51 | // test: handler | +| PASSED | handler | src/index.js:56:36:56:51 | // test: handler | +| PASSED | handler | src/index.js:59:36:59:51 | // test: handler | +| PASSED | handler | src/index.js:62:36:62:51 | // test: handler | +| PASSED | handler | src/index.js:71:36:71:51 | // test: handler | +| PASSED | handler | src/index.js:93:44:93:66 | // test ... handler | +| PASSED | handler | src/index.js:99:30:99:45 | // test: handler | +| PASSED | handler | src/index.js:103:30:103:45 | // test: handler | +| PASSED | handler | src/index.js:111:31:111:46 | // test: handler | +| PASSED | handler | src/index.js:115:30:115:45 | // test: handler | +| PASSED | handler | src/index.js:121:32:121:47 | // test: handler | +| PASSED | handler | src/index.js:131:33:131:48 | // test: handler | +| PASSED | handler | src/index.js:137:33:137:48 | // test: handler | +| PASSED | handler | src/index.js:156:50:156:65 | // test: handler | +| PASSED | handler | src/index.js:190:65:190:87 | // test ... handler | +| PASSED | handler | src/index.js:194:63:194:85 | // test ... handler | +| PASSED | handler | src/index.js:197:55:197:77 | // test ... handler | +| PASSED | handler | src/index.js:199:39:199:61 | // test ... handler | +| PASSED | handler | src/index.js:201:49:201:71 | // test ... handler | +| PASSED | handler | src/index.js:205:65:205:87 | // test ... handler | +| PASSED | headerDefinition | src/index.js:104:46:104:70 | // test ... inition | +| PASSED | headerDefinition | src/index.js:122:44:122:68 | // test ... inition | +| PASSED | headerDefinition | src/index.js:132:44:132:68 | // test ... inition | +| PASSED | redirectSink | src/index.js:78:32:78:60 | // test ... ectSink | +| PASSED | redirectSink | src/index.js:87:45:87:73 | // test ... ectSink | +| PASSED | redirectSink | src/index.js:88:40:88:68 | // test ... ectSink | +| PASSED | setup | src/index.js:66:21:66:34 | // test: setup | +| PASSED | setup | src/index.js:67:31:67:44 | // test: setup | +| PASSED | setup | src/index.js:68:33:68:46 | // test: setup | +| PASSED | setup | src/index.js:91:38:91:51 | // test: setup | +| PASSED | setup | src/index.js:92:39:92:52 | // test: setup | +| PASSED | setup | src/index.js:93:44:93:66 | // test ... handler | +| PASSED | setup | src/index.js:98:20:98:33 | // test: setup | +| PASSED | setup | src/index.js:110:21:110:34 | // test: setup | +| PASSED | setup | src/index.js:148:29:148:42 | // test: setup | +| PASSED | setup | src/index.js:152:31:152:44 | // test: setup | +| PASSED | setup | src/index.js:153:31:153:44 | // test: setup | +| PASSED | setup | src/index.js:173:66:173:79 | // test: setup | +| PASSED | setup | src/index.js:177:66:177:78 | //test: setup | +| PASSED | setup | src/index.js:190:65:190:87 | // test ... handler | +| PASSED | setup | src/index.js:194:63:194:85 | // test ... handler | +| PASSED | setup | src/index.js:197:55:197:77 | // test ... handler | +| PASSED | setup | src/index.js:199:39:199:61 | // test ... handler | +| PASSED | setup | src/index.js:201:49:201:71 | // test ... handler | +| PASSED | setup | src/index.js:205:65:205:87 | // test ... handler | +| PASSED | source | src/index.js:11:76:11:130 | // test ... k, !xss | +| PASSED | source | src/index.js:24:76:24:128 | // test ... nk, xss | +| PASSED | source | src/index.js:72:41:72:80 | // test ... reSink | +| PASSED | source | src/index.js:73:44:73:82 | // test ... ureSink | +| PASSED | source | src/index.js:74:40:74:78 | // test ... ureSink | +| PASSED | source | src/index.js:75:39:75:77 | // test ... ureSink | +| PASSED | source | src/index.js:78:32:78:60 | // test ... ectSink | +| PASSED | source | src/index.js:87:45:87:73 | // test ... ectSink | +| PASSED | source | src/index.js:88:40:88:68 | // test ... ectSink | +| PASSED | source | src/index.js:100:37:100:51 | // test: source | +| PASSED | source | src/index.js:123:40:123:92 | // test ... nk, xss | +| PASSED | source | src/index.js:133:43:133:96 | // test ... k, !xss | +| PASSED | source | src/index.js:138:31:138:45 | // test: source | +| PASSED | source | src/index.js:164:41:164:93 | // test ... nk, xss | +| PASSED | source | src/index.js:166:26:166:50 | // test ... srfSink | +| PASSED | source | src/index.js:168:45:168:69 | // test ... srfSink | +| PASSED | source | src/index.js:203:28:203:58 | // test ... k, !xss | +| PASSED | source | src/index.js:207:28:207:56 | // test ... nk, xss | +| PASSED | ssrfSink | src/index.js:166:26:166:50 | // test ... srfSink | +| PASSED | ssrfSink | src/index.js:168:45:168:69 | // test ... srfSink | +| PASSED | stackTraceExposureSink | src/index.js:9:66:9:96 | // test ... ureSink | +| PASSED | stackTraceExposureSink | src/index.js:11:76:11:130 | // test ... k, !xss | +| PASSED | stackTraceExposureSink | src/index.js:22:66:22:105 | // test ... xssSink | +| PASSED | stackTraceExposureSink | src/index.js:24:76:24:128 | // test ... nk, xss | +| PASSED | stackTraceExposureSink | src/index.js:72:41:72:80 | // test ... reSink | +| PASSED | stackTraceExposureSink | src/index.js:73:44:73:82 | // test ... ureSink | +| PASSED | stackTraceExposureSink | src/index.js:74:40:74:78 | // test ... ureSink | +| PASSED | stackTraceExposureSink | src/index.js:75:39:75:77 | // test ... ureSink | +| PASSED | stackTraceExposureSink | src/index.js:105:29:105:73 | // test ... nk, xss | +| PASSED | stackTraceExposureSink | src/index.js:116:29:116:59 | // test ... ureSink | +| PASSED | stackTraceExposureSink | src/index.js:123:40:123:92 | // test ... nk, xss | +| PASSED | stackTraceExposureSink | src/index.js:133:43:133:96 | // test ... k, !xss | +| PASSED | stackTraceExposureSink | src/index.js:143:20:143:64 | // test ... nk, xss | +| PASSED | stackTraceExposureSink | src/index.js:164:41:164:93 | // test ... nk, xss | +| PASSED | xss | src/index.js:24:76:24:128 | // test ... nk, xss | +| PASSED | xss | src/index.js:105:29:105:73 | // test ... nk, xss | +| PASSED | xss | src/index.js:123:40:123:92 | // test ... nk, xss | +| PASSED | xss | src/index.js:143:20:143:64 | // test ... nk, xss | +| PASSED | xss | src/index.js:164:41:164:93 | // test ... nk, xss | +| PASSED | xss | src/index.js:207:28:207:56 | // test ... nk, xss | +| PASSED | xssSink | src/index.js:22:66:22:105 | // test ... xssSink | +| PASSED | xssSink | src/index.js:24:76:24:128 | // test ... nk, xss | +| PASSED | xssSink | src/index.js:105:29:105:73 | // test ... nk, xss | +| PASSED | xssSink | src/index.js:123:40:123:92 | // test ... nk, xss | +| PASSED | xssSink | src/index.js:133:43:133:96 | // test ... k, !xss | +| PASSED | xssSink | src/index.js:143:20:143:64 | // test ... nk, xss | +| PASSED | xssSink | src/index.js:164:41:164:93 | // test ... nk, xss | +| PASSED | xssSink | src/index.js:207:28:207:56 | // test ... nk, xss | +failingPositiveTests +passingNegativeTests +| PASSED | !xss | src/index.js:11:76:11:130 | // test ... k, !xss | +| PASSED | !xss | src/index.js:133:43:133:96 | // test ... k, !xss | +| PASSED | !xss | src/index.js:203:28:203:58 | // test ... k, !xss | +| PASSED | !xssSink | src/index.js:11:76:11:130 | // test ... k, !xss | +| PASSED | !xssSink | src/index.js:203:28:203:58 | // test ... k, !xss | +failingNegativeTests diff --git a/javascript/ql/test/library-tests/frameworks/Restify2/tests.ql b/javascript/ql/test/library-tests/frameworks/Restify2/tests.ql new file mode 100644 index 00000000000..e385b558458 --- /dev/null +++ b/javascript/ql/test/library-tests/frameworks/Restify2/tests.ql @@ -0,0 +1,229 @@ +import javascript +import semmle.javascript.security.dataflow.CleartextStorageCustomizations +import semmle.javascript.security.dataflow.CorsMisconfigurationForCredentialsCustomizations +import semmle.javascript.security.dataflow.StackTraceExposureCustomizations +import semmle.javascript.security.dataflow.ServerSideUrlRedirectCustomizations +import semmle.javascript.security.dataflow.RequestForgeryCustomizations +import semmle.javascript.security.dataflow.ReflectedXssCustomizations +import semmle.javascript.security.dataflow.ReflectedXssQuery as XssConfig + +class InlineTest extends LineComment { + string tests; + + InlineTest() { tests = this.getText().regexpCapture("\\s*test:(.*)", 1) } + + string getPositiveTest() { + result = tests.trim().splitAt(",").trim() and not result.matches("!%") + } + + string getNegativeTest() { result = tests.trim().splitAt(",").trim() and result.matches("!%") } + + predicate hasPositiveTest(string test) { test = this.getPositiveTest() } + + predicate hasNegativeTest(string test) { test = this.getNegativeTest() } + + predicate inNode(DataFlow::Node n) { + this.getLocation().getFile() = n.getFile() and + this.getLocation().getStartLine() = n.getStartLine() + } +} + +query predicate passingPositiveTests(string res, string expectation, InlineTest t) { + res = "PASSED" and + t.hasPositiveTest(expectation) and + ( + expectation = "headerDefinition" and + exists(Http::HeaderDefinition n | t.inNode(n)) + or + expectation = "cookieDefinition" and + exists(Http::CookieDefinition n | t.inNode(n)) + or + expectation = "templateInstantiation" and + exists(Templating::TemplateInstantiation::Range n | t.inNode(n)) + or + expectation = "source" and + exists(RemoteFlowSource n | t.inNode(n)) + or + expectation = "setup" and + exists(Http::RouteSetup n | t.inNode(n)) + or + expectation = "handler" and + exists(Http::RouteHandler n | t.inNode(n)) + or + expectation = "candidateHandler" and + exists(Http::RouteHandlerCandidate n | t.inNode(n)) + or + expectation = "xssSink" and + exists(ReflectedXss::Sink n | t.inNode(n)) + or + expectation = "xss" and + exists(XssConfig::Configuration cfg, DataFlow::Node sink | + cfg.hasFlow(_, sink) and t.inNode(sink) + ) + or + expectation = "cleartextStorageSink" and + exists(CleartextStorage::Sink n | t.inNode(n)) + or + expectation = "corsMiconfigurationSink" and + exists(CorsMisconfigurationForCredentials::Sink n | t.inNode(n)) + or + expectation = "stackTraceExposureSink" and + exists(StackTraceExposure::Sink n | t.inNode(n)) + or + expectation = "redirectSink" and + exists(ServerSideUrlRedirect::Sink n | t.inNode(n)) + or + expectation = "ssrfSink" and + exists(RequestForgery::Sink n | t.inNode(n)) + ) +} + +query predicate failingPositiveTests(string res, string expectation, InlineTest t) { + res = "FAILED" and + t.hasPositiveTest(expectation) and + ( + expectation = "headerDefinition" and + not exists(Http::HeaderDefinition n | t.inNode(n)) + or + expectation = "cookieDefinition" and + not exists(Http::CookieDefinition n | t.inNode(n)) + or + expectation = "templateInstantiation" and + not exists(Templating::TemplateInstantiation::Range n | t.inNode(n)) + or + expectation = "source" and + not exists(RemoteFlowSource n | t.inNode(n)) + or + expectation = "setup" and + not exists(Http::RouteSetup n | t.inNode(n)) + or + expectation = "handler" and + not exists(Http::RouteHandler n | t.inNode(n)) + or + expectation = "candidateHandler" and + not exists(Http::RouteHandlerCandidate n | t.inNode(n)) + or + expectation = "xssSink" and + not exists(ReflectedXss::Sink n | t.inNode(n)) + or + expectation = "xss" and + not exists(XssConfig::Configuration cfg, DataFlow::Node sink | + cfg.hasFlow(_, sink) and t.inNode(sink) + ) + or + expectation = "cleartextStorageSink" and + not exists(CleartextStorage::Sink n | t.inNode(n)) + or + expectation = "corsMiconfigurationSink" and + not exists(CorsMisconfigurationForCredentials::Sink n | t.inNode(n)) + or + expectation = "stackTraceExposureSink" and + not exists(StackTraceExposure::Sink n | t.inNode(n)) + or + expectation = "redirectSink" and + not exists(ServerSideUrlRedirect::Sink n | t.inNode(n)) + or + expectation = "ssrfSink" and + not exists(RequestForgery::Sink n | t.inNode(n)) + ) +} + +query predicate passingNegativeTests(string res, string expectation, InlineTest t) { + res = "PASSED" and + t.hasNegativeTest(expectation) and + ( + expectation = "!headerDefinition" and + not exists(Http::HeaderDefinition n | t.inNode(n)) + or + expectation = "!cookieDefinition" and + not exists(Http::CookieDefinition n | t.inNode(n)) + or + expectation = "!templateInstantiation" and + not exists(Templating::TemplateInstantiation::Range n | t.inNode(n)) + or + expectation = "!source" and + not exists(RemoteFlowSource n | t.inNode(n)) + or + expectation = "!setup" and + not exists(Http::RouteSetup n | t.inNode(n)) + or + expectation = "!handler" and + not exists(Http::RouteHandler n | t.inNode(n)) + or + expectation = "!candidateHandler" and + not exists(Http::RouteHandlerCandidate n | t.inNode(n)) + or + expectation = "!xssSink" and + not exists(ReflectedXss::Sink n | t.inNode(n)) + or + expectation = "!xss" and + not exists(XssConfig::Configuration cfg, DataFlow::Node sink | + cfg.hasFlow(_, sink) and t.inNode(sink) + ) + or + expectation = "!cleartextStorageSink" and + not exists(CleartextStorage::Sink n | t.inNode(n)) + or + expectation = "!corsMiconfigurationSink" and + not exists(CorsMisconfigurationForCredentials::Sink n | t.inNode(n)) + or + expectation = "!stackTraceExposureSink" and + not exists(StackTraceExposure::Sink n | t.inNode(n)) + or + expectation = "!redirectSink" and + not exists(ServerSideUrlRedirect::Sink n | t.inNode(n)) + or + expectation = "!ssrfSink" and + not exists(RequestForgery::Sink n | t.inNode(n)) + ) +} + +query predicate failingNegativeTests(string res, string expectation, InlineTest t) { + res = "FAILED" and + t.hasNegativeTest(expectation) and + ( + expectation = "!headerDefinition" and + exists(Http::HeaderDefinition n | t.inNode(n)) + or + expectation = "!cookieDefinition" and + exists(Http::CookieDefinition n | t.inNode(n)) + or + expectation = "!templateInstantiation" and + exists(Templating::TemplateInstantiation::Range n | t.inNode(n)) + or + expectation = "!source" and + exists(RemoteFlowSource n | t.inNode(n)) + or + expectation = "!setup" and + exists(Http::RouteSetup n | t.inNode(n)) + or + expectation = "!handler" and + exists(Http::RouteHandler n | t.inNode(n)) + or + expectation = "!candidateHandler" and + exists(Http::RouteHandlerCandidate n | t.inNode(n)) + or + expectation = "!xssSink" and + exists(ReflectedXss::Sink n | t.inNode(n)) + or + expectation = "!xss" and + exists(XssConfig::Configuration cfg, DataFlow::Node sink | + cfg.hasFlow(_, sink) and t.inNode(sink) + ) + or + expectation = "!cleartextStorageSink" and + exists(CleartextStorage::Sink n | t.inNode(n)) + or + expectation = "!corsMiconfigurationSink" and + exists(CorsMisconfigurationForCredentials::Sink n | t.inNode(n)) + or + expectation = "!stackTraceExposureSink" and + exists(StackTraceExposure::Sink n | t.inNode(n)) + or + expectation = "!redirectSink" and + exists(ServerSideUrlRedirect::Sink n | t.inNode(n)) + or + expectation = "!ssrfSink" and + exists(RequestForgery::Sink n | t.inNode(n)) + ) +} diff --git a/javascript/ql/test/library-tests/frameworks/Spife/lib/routes/index.js b/javascript/ql/test/library-tests/frameworks/Spife/lib/routes/index.js new file mode 100644 index 00000000000..cd7ac6340c5 --- /dev/null +++ b/javascript/ql/test/library-tests/frameworks/Spife/lib/routes/index.js @@ -0,0 +1,28 @@ +'use strict' + +const routes = require('@npm/spife/routing') + +module.exports = routes` + GET / homepage + GET /test1 test1 + GET /test1 test2 + GET /test4 test4 + GET /test5 test5 + GET /test6 test6 + GET /raw1 raw1 + GET /raw2 raw2 + POST /body parseBody + GET /redirect/:redirect_url redirect + POST /packages/new createPackage +`(require('../views')) + + +const a = routes`GET /packages/package/${p} viewPackage`(require('../views')) // test:routeSetup + +const b = routes`GET / list`({ ...require('../views'), ...require('../views/orgs') }) // test: routeSetup + +const c = routes`POST /message handleMessage`({ handleMessage: console.log }) // test: routeSetup + +const d = routes`GET /version versionHandler`({ versionHandler: (req, context) => { console.log(req) } }) // test: routeSetup + +const e = routes`GET / handler`({ handler: async (req, context) => { console.log(req) } }) // test: routeSetup diff --git a/javascript/ql/test/library-tests/frameworks/Spife/lib/routes/parameters.js b/javascript/ql/test/library-tests/frameworks/Spife/lib/routes/parameters.js new file mode 100644 index 00000000000..e69de29bb2d diff --git a/javascript/ql/test/library-tests/frameworks/Spife/lib/settings.js b/javascript/ql/test/library-tests/frameworks/Spife/lib/settings.js new file mode 100644 index 00000000000..5d3b9824132 --- /dev/null +++ b/javascript/ql/test/library-tests/frameworks/Spife/lib/settings.js @@ -0,0 +1,46 @@ +'use strict' + +const { Environment, FileSystemLoader } = require('nunjucks') +const Loader = require('@npm/spife/templates/loader') +const path = require('path') + +const isDev = !new Set(['prod', 'production', 'stag', 'staging']).has( + process.env.NODE_ENV +) + +const templateDirs = [path.join(__dirname, '..', 'templates')] +const nunjucksEnv = new Environment(new FileSystemLoader(templateDirs)) +const nunjucksLoader = new Loader({ + dirs: templateDirs, + load (resolved) { + const template = nunjucksEnv.getTemplate(resolved.path, true) + return context => { + return template.render(context) + } + } +}) + +module.exports = { + DEBUG: process.env.DEBUG, + ENABLE_FORM_PARSING: false, + METRICS: process.env.METRICS, + MIDDLEWARE: [ + '@npm/spife/middleware/debug', + ['@npm/spife/middleware/template', [ + nunjucksLoader + ], [ + // template context processors go here + ]], + '@npm/spife/middleware/common', + '@npm/spife/middleware/logging', + '@npm/spife/middleware/metrics', + '@npm/spife/middleware/monitor', + '@npm/spife/middleware/hot-reload', + ['@npm/spife/middleware/csrf', { secureCookie: !isDev }] + ], + NAME: 'nunjucks-example', + NODE_ENV: process.env.NODE_ENV, + PORT: 8124, + ROUTER: './routes/index.js', + HOT: true +} diff --git a/javascript/ql/test/library-tests/frameworks/Spife/lib/views/index.js b/javascript/ql/test/library-tests/frameworks/Spife/lib/views/index.js new file mode 100644 index 00000000000..51fe2622603 --- /dev/null +++ b/javascript/ql/test/library-tests/frameworks/Spife/lib/views/index.js @@ -0,0 +1,115 @@ +'use strict' + +const reply = require('@npm/spife/reply') +const validate = require('@npm/spife/decorators/validate') +const joi = require('@npm/spife/joi') +const concat = require('concat-stream') + +const createPackageSchema = joi.object().keys({ + contents: joi.string().max(200).required(), + destination: joi.any().valid([ + joi.object({ + name: joi.string().max(200).required(), + address: joi.string().max(200).required() + }), + joi.string().min(1) + ]) +}) + +module.exports = { homepage, parseBody, raw1, raw2, test1, test2, test3, test4, test5, test6, redirect, createPackage: validate.body(createPackageSchema, createPackage), } + +function sink(obj) { console.log(obj) } + +function createPackage(req, context) { // test: handler + const tainted = req.validatedBody.get('destination') // test: source + sink(taitned) +} + +function homepage(req, context) { // test: handler + sink(req.cookie("test")) // test: source + sink(req.cookies().test) // test: source + sink(req.headers.test) // test: source + sink(req.rawHeaders[0]) // test: source + sink(req.raw.headers) // test: source + sink(req.url) // test: source + sink(req.urlObject.pathname) // test: source + sink(context.get('package')) // test: source + sink(context) + return reply.template('home', { target: req.query.name }) // test: source, templateInstantiation, stackTraceExposureSink, responseBody +} + +function raw1(req, context) { // test: handler + sink(req.query.name) // test: source + return reply(req.query.name, 200, { // test: source, xssSink, stackTraceExposureSink, xss + "content-type": "text/html", // test: headerDefinition + "access-control-allow-origin": "*", // test: corsMiconfigurationSink, headerDefinition + "access-control-allow-headers": "Content-Type, Authorization, Content-Length, X-Requested-With", // test: headerDefinition + "access-control-allow-methods": "GET, POST, PUT, DELETE, OPTIONS", // test: headerDefinition + "access-control-allow-credentials": "true" //test: headerDefinition + + }) +} + +function redirect(req, context) { // test: handler + return reply.redirect(context.get('redirect_url')) // test: redirectSink, source +} +function raw2(req, context) { // test: handler + return reply.cookie({ "test": req.query.name }, "test", req.query.name, { "httpOnly": false, "secure": false }) // test: source, cleartextStorageSink, stackTraceExposureSink, cookieDefinition +} + +function test1(req, context) { // test: handler + switch (req.accept.type(['json', 'html', 'plain'])) { + case 'json': + return { "some": req.query.name } // test: source, stackTraceExposureSink + case 'html': + return reply.header('

' + req.query.name + '

', 'content-type', 'text/html') // test: source, xssSink, stackTraceExposureSink, xss, headerDefinition + case 'plain': + return reply.header('

' + req.query.name + '

', { 'content-type': 'text/plain' }) // test: source, stackTraceExposureSink, !xssSink, !xss, headerDefinition, headerDefinition + } + return 'well, I guess you just want plaintext.' +} + +function test2(req, context) { // test: handler + switch (req.accept.type(['json', 'html'])) { + case 'json': + return { "some": req.query.name } // test: source, stackTraceExposureSink + case 'html': + return reply.header('

' + req.query.name + '

', { 'content-type': 'text/plain' }) // test: source, stackTraceExposureSink, !xssSink, !xss, headerDefinition + } + return 'well, I guess you just want plaintext.' +} + +function test3(req, context) { // test: candidateHandler + return reply('

' + req.query.name + '

') +} + +function test4(req, context) { // test: handler + const body = req.body // test: source + const newPackument = body['package-json'] + const message = `INFO: User invited to package ${newPackument._id} successfully.` + return reply(message, 200, { 'npm-notice': message }) // test: stackTraceExposureSink, !xssSink, !xss, headerDefinition +} + +function test5(req, context) { // test: handler + const body = req.body // test: source + const newPackument = body['package-json'] + const message = `INFO: User invited to package ${newPackument._id} successfully.` + return reply(message, 200) // test: stackTraceExposureSink, !xssSink, !xss +} + +function test6(req, context) { // test: handler + const body = req.body // test: source + const newPackument = body['package-json'] + const message = `INFO: User invited to package ${newPackument._id} successfully.` + if (message.contains('foo')) { + return reply(message, 200, { 'npm-notice': message }) // test: stackTraceExposureSink, !xssSink, !xss, headerDefinition + } else { + return reply(message, 200, { 'npm-notice': message, 'content-type': 'text/html' }) // test: stackTraceExposureSink, xssSink, xss, headerDefinition + } +} + +function parseBody(req, context) { + return req.body.then(data => { // test: source, stackTraceExposureSink + sink(data.name) + }) +} diff --git a/javascript/ql/test/library-tests/frameworks/Spife/lib/views/orgs.js b/javascript/ql/test/library-tests/frameworks/Spife/lib/views/orgs.js new file mode 100644 index 00000000000..e69de29bb2d diff --git a/javascript/ql/test/library-tests/frameworks/Spife/tests.expected b/javascript/ql/test/library-tests/frameworks/Spife/tests.expected new file mode 100644 index 00000000000..e264b573792 --- /dev/null +++ b/javascript/ql/test/library-tests/frameworks/Spife/tests.expected @@ -0,0 +1,89 @@ +passingPositiveTests +| PASSED | candidateHandler | lib/views/index.js:82:32:82:56 | // test ... Handler | +| PASSED | cleartextStorageSink | lib/views/index.js:57:115:57:193 | // test ... inition | +| PASSED | cookieDefinition | lib/views/index.js:57:115:57:193 | // test ... inition | +| PASSED | corsMiconfigurationSink | lib/views/index.js:45:41:45:90 | // test ... inition | +| PASSED | handler | lib/views/index.js:23:40:23:55 | // test: handler | +| PASSED | handler | lib/views/index.js:28:35:28:50 | // test: handler | +| PASSED | handler | lib/views/index.js:41:31:41:46 | // test: handler | +| PASSED | handler | lib/views/index.js:53:35:53:50 | // test: handler | +| PASSED | handler | lib/views/index.js:56:31:56:46 | // test: handler | +| PASSED | handler | lib/views/index.js:60:32:60:47 | // test: handler | +| PASSED | handler | lib/views/index.js:72:32:72:47 | // test: handler | +| PASSED | handler | lib/views/index.js:86:32:86:47 | // test: handler | +| PASSED | handler | lib/views/index.js:93:32:93:47 | // test: handler | +| PASSED | handler | lib/views/index.js:100:32:100:47 | // test: handler | +| PASSED | headerDefinition | lib/views/index.js:44:34:44:58 | // test ... inition | +| PASSED | headerDefinition | lib/views/index.js:45:41:45:90 | // test ... inition | +| PASSED | headerDefinition | lib/views/index.js:46:102:46:126 | // test ... inition | +| PASSED | headerDefinition | lib/views/index.js:47:72:47:96 | // test ... inition | +| PASSED | headerDefinition | lib/views/index.js:48:48:48:71 | //test: ... inition | +| PASSED | headerDefinition | lib/views/index.js:65:89:65:159 | // test ... inition | +| PASSED | headerDefinition | lib/views/index.js:67:94:67:184 | // test ... inition | +| PASSED | headerDefinition | lib/views/index.js:77:94:77:166 | // test ... inition | +| PASSED | headerDefinition | lib/views/index.js:90:57:90:121 | // test ... inition | +| PASSED | headerDefinition | lib/views/index.js:105:59:105:123 | // test ... inition | +| PASSED | headerDefinition | lib/views/index.js:107:88:107:150 | // test ... inition | +| PASSED | redirectSink | lib/views/index.js:54:54:54:82 | // test ... source | +| PASSED | responseBody | lib/views/index.js:38:61:38:136 | // test ... nseBody | +| PASSED | routeSetup | lib/routes/index.js:20:79:20:96 | // test:routeSetup | +| PASSED | routeSetup | lib/routes/index.js:22:87:22:105 | // test: routeSetup | +| PASSED | routeSetup | lib/routes/index.js:24:81:24:99 | // test: routeSetup | +| PASSED | routeSetup | lib/routes/index.js:26:107:26:125 | // test: routeSetup | +| PASSED | routeSetup | lib/routes/index.js:28:92:28:110 | // test: routeSetup | +| PASSED | source | lib/views/index.js:24:56:24:70 | // test: source | +| PASSED | source | lib/views/index.js:29:28:29:42 | // test: source | +| PASSED | source | lib/views/index.js:30:28:30:42 | // test: source | +| PASSED | source | lib/views/index.js:31:26:31:40 | // test: source | +| PASSED | source | lib/views/index.js:32:27:32:41 | // test: source | +| PASSED | source | lib/views/index.js:33:25:33:39 | // test: source | +| PASSED | source | lib/views/index.js:34:17:34:31 | // test: source | +| PASSED | source | lib/views/index.js:35:32:35:46 | // test: source | +| PASSED | source | lib/views/index.js:36:32:36:46 | // test: source | +| PASSED | source | lib/views/index.js:38:61:38:136 | // test ... nseBody | +| PASSED | source | lib/views/index.js:42:24:42:38 | // test: source | +| PASSED | source | lib/views/index.js:43:39:43:91 | // test ... nk, xss | +| PASSED | source | lib/views/index.js:54:54:54:82 | // test ... source | +| PASSED | source | lib/views/index.js:57:115:57:193 | // test ... inition | +| PASSED | source | lib/views/index.js:63:41:63:79 | // test ... ureSink | +| PASSED | source | lib/views/index.js:65:89:65:159 | // test ... inition | +| PASSED | source | lib/views/index.js:67:94:67:184 | // test ... inition | +| PASSED | source | lib/views/index.js:75:41:75:79 | // test ... ureSink | +| PASSED | source | lib/views/index.js:77:94:77:166 | // test ... inition | +| PASSED | source | lib/views/index.js:87:25:87:39 | // test: source | +| PASSED | source | lib/views/index.js:94:25:94:39 | // test: source | +| PASSED | source | lib/views/index.js:101:25:101:39 | // test: source | +| PASSED | source | lib/views/index.js:112:34:112:72 | // test ... ureSink | +| PASSED | stackTraceExposureSink | lib/views/index.js:38:61:38:136 | // test ... nseBody | +| PASSED | stackTraceExposureSink | lib/views/index.js:43:39:43:91 | // test ... nk, xss | +| PASSED | stackTraceExposureSink | lib/views/index.js:57:115:57:193 | // test ... inition | +| PASSED | stackTraceExposureSink | lib/views/index.js:63:41:63:79 | // test ... ureSink | +| PASSED | stackTraceExposureSink | lib/views/index.js:65:89:65:159 | // test ... inition | +| PASSED | stackTraceExposureSink | lib/views/index.js:67:94:67:184 | // test ... inition | +| PASSED | stackTraceExposureSink | lib/views/index.js:75:41:75:79 | // test ... ureSink | +| PASSED | stackTraceExposureSink | lib/views/index.js:77:94:77:166 | // test ... inition | +| PASSED | stackTraceExposureSink | lib/views/index.js:90:57:90:121 | // test ... inition | +| PASSED | stackTraceExposureSink | lib/views/index.js:97:30:97:76 | // test ... k, !xss | +| PASSED | stackTraceExposureSink | lib/views/index.js:105:59:105:123 | // test ... inition | +| PASSED | stackTraceExposureSink | lib/views/index.js:107:88:107:150 | // test ... inition | +| PASSED | stackTraceExposureSink | lib/views/index.js:112:34:112:72 | // test ... ureSink | +| PASSED | templateInstantiation | lib/views/index.js:38:61:38:136 | // test ... nseBody | +| PASSED | xss | lib/views/index.js:43:39:43:91 | // test ... nk, xss | +| PASSED | xss | lib/views/index.js:65:89:65:159 | // test ... inition | +| PASSED | xss | lib/views/index.js:107:88:107:150 | // test ... inition | +| PASSED | xssSink | lib/views/index.js:43:39:43:91 | // test ... nk, xss | +| PASSED | xssSink | lib/views/index.js:65:89:65:159 | // test ... inition | +| PASSED | xssSink | lib/views/index.js:107:88:107:150 | // test ... inition | +failingPositiveTests +passingNegativeTests +| PASSED | !xss | lib/views/index.js:67:94:67:184 | // test ... inition | +| PASSED | !xss | lib/views/index.js:77:94:77:166 | // test ... inition | +| PASSED | !xss | lib/views/index.js:90:57:90:121 | // test ... inition | +| PASSED | !xss | lib/views/index.js:97:30:97:76 | // test ... k, !xss | +| PASSED | !xss | lib/views/index.js:105:59:105:123 | // test ... inition | +| PASSED | !xssSink | lib/views/index.js:67:94:67:184 | // test ... inition | +| PASSED | !xssSink | lib/views/index.js:77:94:77:166 | // test ... inition | +| PASSED | !xssSink | lib/views/index.js:90:57:90:121 | // test ... inition | +| PASSED | !xssSink | lib/views/index.js:97:30:97:76 | // test ... k, !xss | +| PASSED | !xssSink | lib/views/index.js:105:59:105:123 | // test ... inition | +failingNegativeTests diff --git a/javascript/ql/test/library-tests/frameworks/Spife/tests.ql b/javascript/ql/test/library-tests/frameworks/Spife/tests.ql new file mode 100644 index 00000000000..ef785a2860b --- /dev/null +++ b/javascript/ql/test/library-tests/frameworks/Spife/tests.ql @@ -0,0 +1,253 @@ +import javascript +import semmle.javascript.security.dataflow.CleartextStorageCustomizations +import semmle.javascript.security.dataflow.CorsMisconfigurationForCredentialsCustomizations +import semmle.javascript.security.dataflow.StackTraceExposureCustomizations +import semmle.javascript.security.dataflow.ServerSideUrlRedirectCustomizations +import semmle.javascript.security.dataflow.RequestForgeryCustomizations +import semmle.javascript.security.dataflow.ReflectedXssCustomizations +import semmle.javascript.security.dataflow.ReflectedXssQuery as XssConfig + +class InlineTest extends LineComment { + string tests; + + InlineTest() { tests = this.getText().regexpCapture("\\s*test:(.*)", 1) } + + string getPositiveTest() { + result = tests.trim().splitAt(",").trim() and not result.matches("!%") + } + + string getNegativeTest() { result = tests.trim().splitAt(",").trim() and result.matches("!%") } + + predicate hasPositiveTest(string test) { test = this.getPositiveTest() } + + predicate hasNegativeTest(string test) { test = this.getNegativeTest() } + + predicate inNode(DataFlow::Node n) { + this.getLocation().getFile() = n.getFile() and + this.getLocation().getStartLine() = n.getStartLine() + } +} + +query predicate passingPositiveTests(string res, string expectation, InlineTest t) { + res = "PASSED" and + t.hasPositiveTest(expectation) and + ( + expectation = "responseBody" and + exists(Http::ResponseBody n | t.inNode(n)) + or + expectation = "headerDefinition" and + exists(DataFlow::Node n, Http::ExplicitHeaderDefinition h | + t.inNode(n) and + h.definesHeaderValue(_, n) + ) + or + expectation = "cookieDefinition" and + exists(Http::CookieDefinition n | t.inNode(n)) + or + expectation = "templateInstantiation" and + exists(Templating::TemplateInstantiation::Range n | t.inNode(n)) + or + expectation = "source" and + exists(RemoteFlowSource n | t.inNode(n)) + or + expectation = "routeSetup" and + exists(Http::RouteSetup n | t.inNode(n)) + or + expectation = "handler" and + exists(Http::RouteHandler n | t.inNode(n)) + or + expectation = "candidateHandler" and + exists(Http::RouteHandlerCandidate n | t.inNode(n)) + or + expectation = "xssSink" and + exists(ReflectedXss::Sink n | t.inNode(n)) + or + expectation = "xss" and + exists(XssConfig::Configuration cfg, DataFlow::Node sink | + cfg.hasFlow(_, sink) and t.inNode(sink) + ) + or + expectation = "cleartextStorageSink" and + exists(CleartextStorage::Sink n | t.inNode(n)) + or + expectation = "corsMiconfigurationSink" and + exists(CorsMisconfigurationForCredentials::Sink n | t.inNode(n)) + or + expectation = "stackTraceExposureSink" and + exists(StackTraceExposure::Sink n | t.inNode(n)) + or + expectation = "redirectSink" and + exists(ServerSideUrlRedirect::Sink n | t.inNode(n)) + or + expectation = "ssrfSink" and + exists(RequestForgery::Sink n | t.inNode(n)) + ) +} + +query predicate failingPositiveTests(string res, string expectation, InlineTest t) { + res = "FAILED" and + t.hasPositiveTest(expectation) and + ( + expectation = "responseBody" and + not exists(Http::ResponseBody n | t.inNode(n)) + or + expectation = "headerDefinition" and + not exists(DataFlow::Node n, Http::ExplicitHeaderDefinition h | + t.inNode(n) and + h.definesHeaderValue(_, n) + ) + or + expectation = "cookieDefinition" and + not exists(Http::CookieDefinition n | t.inNode(n)) + or + expectation = "templateInstantiation" and + not exists(Templating::TemplateInstantiation::Range n | t.inNode(n)) + or + expectation = "source" and + not exists(RemoteFlowSource n | t.inNode(n)) + or + expectation = "routeSetup" and + not exists(Http::RouteSetup n | t.inNode(n)) + or + expectation = "handler" and + not exists(Http::RouteHandler n | t.inNode(n)) + or + expectation = "candidateHandler" and + not exists(Http::RouteHandlerCandidate n | t.inNode(n)) + or + expectation = "xssSink" and + not exists(ReflectedXss::Sink n | t.inNode(n)) + or + expectation = "xss" and + not exists(XssConfig::Configuration cfg, DataFlow::Node sink | + cfg.hasFlow(_, sink) and t.inNode(sink) + ) + or + expectation = "cleartextStorageSink" and + not exists(CleartextStorage::Sink n | t.inNode(n)) + or + expectation = "corsMiconfigurationSink" and + not exists(CorsMisconfigurationForCredentials::Sink n | t.inNode(n)) + or + expectation = "stackTraceExposureSink" and + not exists(StackTraceExposure::Sink n | t.inNode(n)) + or + expectation = "redirectSink" and + not exists(ServerSideUrlRedirect::Sink n | t.inNode(n)) + or + expectation = "ssrfSink" and + not exists(RequestForgery::Sink n | t.inNode(n)) + ) +} + +query predicate passingNegativeTests(string res, string expectation, InlineTest t) { + res = "PASSED" and + t.hasNegativeTest(expectation) and + ( + expectation = "!responseBody" and + not exists(Http::ResponseBody n | t.inNode(n)) + or + expectation = "!headerDefinition" and + not exists(DataFlow::Node n, Http::ExplicitHeaderDefinition h | + t.inNode(n) and + h.definesHeaderValue(_, n) + ) + or + expectation = "!cookieDefinition" and + not exists(Http::CookieDefinition n | t.inNode(n)) + or + expectation = "!templateInstantiation" and + not exists(Templating::TemplateInstantiation::Range n | t.inNode(n)) + or + expectation = "!source" and + not exists(RemoteFlowSource n | t.inNode(n)) + or + expectation = "!routeSetup" and + not exists(Http::RouteSetup n | t.inNode(n)) + or + expectation = "!handler" and + not exists(Http::RouteHandler n | t.inNode(n)) + or + expectation = "!candidateHandler" and + not exists(Http::RouteHandlerCandidate n | t.inNode(n)) + or + expectation = "!xssSink" and + not exists(ReflectedXss::Sink n | t.inNode(n)) + or + expectation = "!xss" and + not exists(XssConfig::Configuration cfg, DataFlow::Node sink | + cfg.hasFlow(_, sink) and t.inNode(sink) + ) + or + expectation = "!cleartextStorageSink" and + not exists(CleartextStorage::Sink n | t.inNode(n)) + or + expectation = "!corsMiconfigurationSink" and + not exists(CorsMisconfigurationForCredentials::Sink n | t.inNode(n)) + or + expectation = "!stackTraceExposureSink" and + not exists(StackTraceExposure::Sink n | t.inNode(n)) + or + expectation = "!redirectSink" and + not exists(ServerSideUrlRedirect::Sink n | t.inNode(n)) + or + expectation = "!ssrfSink" and + not exists(RequestForgery::Sink n | t.inNode(n)) + ) +} + +query predicate failingNegativeTests(string res, string expectation, InlineTest t) { + res = "FAILED" and + t.hasNegativeTest(expectation) and + ( + expectation = "!responseBody" and + exists(Http::ResponseBody n | t.inNode(n)) + or + expectation = "!headerDefinition" and + not exists(DataFlow::Node n, Http::ExplicitHeaderDefinition h | + t.inNode(n) and + h.definesHeaderValue(_, n) + ) + or + expectation = "!cookieDefinition" and + exists(Http::CookieDefinition n | t.inNode(n)) + or + expectation = "!templateInstantiation" and + exists(Templating::TemplateInstantiation::Range n | t.inNode(n)) + or + expectation = "!source" and + exists(RemoteFlowSource n | t.inNode(n)) + or + expectation = "!routeSetup" and + exists(Http::RouteSetup n | t.inNode(n)) + or + expectation = "!handler" and + exists(Http::RouteHandler n | t.inNode(n)) + or + expectation = "!candidateHandler" and + exists(Http::RouteHandlerCandidate n | t.inNode(n)) + or + expectation = "!xssSink" and + exists(ReflectedXss::Sink n | t.inNode(n)) + or + expectation = "!xss" and + exists(XssConfig::Configuration cfg, DataFlow::Node sink | + cfg.hasFlow(_, sink) and t.inNode(sink) + ) + or + expectation = "!cleartextStorageSink" and + exists(CleartextStorage::Sink n | t.inNode(n)) + or + expectation = "!corsMiconfigurationSink" and + exists(CorsMisconfigurationForCredentials::Sink n | t.inNode(n)) + or + expectation = "!stackTraceExposureSink" and + exists(StackTraceExposure::Sink n | t.inNode(n)) + or + expectation = "!redirectSink" and + exists(ServerSideUrlRedirect::Sink n | t.inNode(n)) + or + expectation = "!ssrfSink" and + exists(RequestForgery::Sink n | t.inNode(n)) + ) +} diff --git a/javascript/ql/test/library-tests/frameworks/restify/tests.expected b/javascript/ql/test/library-tests/frameworks/restify/tests.expected index 3f26379a3fa..09ccb149eae 100644 --- a/javascript/ql/test/library-tests/frameworks/restify/tests.expected +++ b/javascript/ql/test/library-tests/frameworks/restify/tests.expected @@ -11,10 +11,16 @@ test_RequestInputAccess | src/test.js:19:5:19:26 | request ... ('bar') | header | src/test.js:12:19:22:1 | functio ... okie;\\n} | | src/test.js:20:5:20:25 | request ... ('baz') | header | src/test.js:12:19:22:1 | functio ... okie;\\n} | test_RouteHandler_getAResponseHeader +| src/test.js:6:1:6:21 | functio ... er1(){} | content-type | src/test.js:6:1:6:21 | functio ... er1(){} | +| src/test.js:9:19:11:1 | functio ... ition\\n} | content-type | src/test.js:9:19:11:1 | functio ... ition\\n} | | src/test.js:9:19:11:1 | functio ... ition\\n} | header1 | src/test.js:10:5:10:34 | respons ... 1', '') | +| src/test.js:12:19:22:1 | functio ... okie;\\n} | content-type | src/test.js:12:19:22:1 | functio ... okie;\\n} | | src/test.js:12:19:22:1 | functio ... okie;\\n} | header2 | src/test.js:13:5:13:37 | respons ... 2', '') | test_HeaderDefinition_defines +| src/test.js:6:1:6:21 | functio ... er1(){} | content-type | application/json | +| src/test.js:9:19:11:1 | functio ... ition\\n} | content-type | application/json | | src/test.js:10:5:10:34 | respons ... 1', '') | header1 | | +| src/test.js:12:19:22:1 | functio ... okie;\\n} | content-type | application/json | | src/test.js:13:5:13:37 | respons ... 2', '') | header2 | | test_ResponseExpr | src/test.js:9:46:9:53 | response | src/test.js:9:19:11:1 | functio ... ition\\n} | @@ -24,14 +30,20 @@ test_ResponseExpr | src/test.js:12:46:12:53 | response | src/test.js:12:19:22:1 | functio ... okie;\\n} | | src/test.js:13:5:13:12 | response | src/test.js:12:19:22:1 | functio ... okie;\\n} | test_HeaderDefinition +| src/test.js:6:1:6:21 | functio ... er1(){} | src/test.js:6:1:6:21 | functio ... er1(){} | +| src/test.js:9:19:11:1 | functio ... ition\\n} | src/test.js:9:19:11:1 | functio ... ition\\n} | | src/test.js:10:5:10:34 | respons ... 1', '') | src/test.js:9:19:11:1 | functio ... ition\\n} | +| src/test.js:12:19:22:1 | functio ... okie;\\n} | src/test.js:12:19:22:1 | functio ... okie;\\n} | | src/test.js:13:5:13:37 | respons ... 2', '') | src/test.js:12:19:22:1 | functio ... okie;\\n} | test_RouteSetup_getServer | src/test.js:7:1:7:26 | server2 ... ndler1) | src/test.js:4:15:4:36 | restify ... erver() | | src/test.js:9:1:11:2 | server2 ... tion\\n}) | src/test.js:4:15:4:36 | restify ... erver() | | src/test.js:12:1:22:2 | server2 ... kie;\\n}) | src/test.js:4:15:4:36 | restify ... erver() | test_HeaderDefinition_getAHeaderName +| src/test.js:6:1:6:21 | functio ... er1(){} | content-type | +| src/test.js:9:19:11:1 | functio ... ition\\n} | content-type | | src/test.js:10:5:10:34 | respons ... 1', '') | header1 | +| src/test.js:12:19:22:1 | functio ... okie;\\n} | content-type | | src/test.js:13:5:13:37 | respons ... 2', '') | header2 | test_ServerDefinition | src/test.js:1:15:1:47 | require ... erver() | diff --git a/misc/scripts/models-as-data/helpers.py b/misc/scripts/models-as-data/helpers.py index d26514222ef..58594102037 100644 --- a/misc/scripts/models-as-data/helpers.py +++ b/misc/scripts/models-as-data/helpers.py @@ -4,10 +4,10 @@ import shutil import subprocess # Shared strings. -summaryModelPredicate = "extSummaryModel" -sinkModelPredicate = "extSinkModel" -sourceModelPredicate = "extSourceModel" -neutralModelPredicate = "extNeutralModel" +summaryModelPredicate = "summaryModel" +sinkModelPredicate = "sinkModel" +sourceModelPredicate = "sourceModel" +neutralModelPredicate = "neutralModel" addsToTemplate = """ - addsTo: pack: {0} extensible: {1} 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 6741ccc2f06..1228d00b6ba 100644 --- a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl.qll +++ b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl.qll @@ -622,7 +622,11 @@ private predicate parameterFlowThroughAllowed(ParamNodeEx p, ReturnKindExt kind) } private module Stage1 implements StageSig { - class Ap = Unit; + class Ap extends int { + // workaround for bad functionality-induced joins (happens when using `Unit`) + pragma[nomagic] + Ap() { this in [0 .. 1] and this < 1 } + } private class Cc = boolean; @@ -1327,8 +1331,8 @@ private module MkStage { */ pragma[nomagic] additional predicate fwdFlow( - NodeEx node, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - Ap ap, ApApprox apa, Configuration config + NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, + ApApprox apa, Configuration config ) { fwdFlow0(node, state, cc, summaryCtx, argAp, ap, apa, config) and PrevStage::revFlow(node, state, apa, config) and @@ -1337,21 +1341,21 @@ private module MkStage { pragma[inline] additional predicate fwdFlow( - NodeEx node, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - Ap ap, Configuration config + NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, + Configuration config ) { fwdFlow(node, state, cc, summaryCtx, argAp, ap, _, config) } pragma[nomagic] private predicate fwdFlow0( - NodeEx node, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - Ap ap, ApApprox apa, Configuration config + NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, + ApApprox apa, Configuration config ) { sourceNode(node, state, config) and (if hasSourceCallCtx(config) then cc = ccSomeCall() else cc = ccNone()) and argAp = apNone() and - summaryCtx = TParameterPositionNone() and + summaryCtx = TParamNodeNone() and ap = getApNil(node) and apa = getApprox(ap) or @@ -1372,7 +1376,7 @@ private module MkStage { fwdFlow(mid, pragma[only_bind_into](state), _, _, _, ap, apa, pragma[only_bind_into](config)) and jumpStep(mid, node, config) and cc = ccNone() and - summaryCtx = TParameterPositionNone() and + summaryCtx = TParamNodeNone() and argAp = apNone() ) or @@ -1380,7 +1384,7 @@ private module MkStage { fwdFlow(mid, state, _, _, _, nil, pragma[only_bind_into](config)) and additionalJumpStep(mid, node, config) and cc = ccNone() and - summaryCtx = TParameterPositionNone() and + summaryCtx = TParamNodeNone() and argAp = apNone() and ap = getApNil(node) and apa = getApprox(ap) @@ -1390,7 +1394,7 @@ private module MkStage { fwdFlow(mid, state0, _, _, _, nil, pragma[only_bind_into](config)) and additionalJumpStateStep(mid, state0, node, state, config) and cc = ccNone() and - summaryCtx = TParameterPositionNone() and + summaryCtx = TParamNodeNone() and argAp = apNone() and ap = getApNil(node) and apa = getApprox(ap) @@ -1414,10 +1418,10 @@ private module MkStage { fwdFlowIn(_, node, state, _, cc, _, _, ap, apa, config) and if PrevStage::parameterMayFlowThrough(node, apa, config) then ( - summaryCtx = TParameterPositionSome(node.(ParamNodeEx).getPosition()) and + summaryCtx = TParamNodeSome(node.asNode()) and argAp = apSome(ap) ) else ( - summaryCtx = TParameterPositionNone() and argAp = apNone() + summaryCtx = TParamNodeNone() and argAp = apNone() ) or // flow out of a callable @@ -1433,16 +1437,19 @@ private module MkStage { ) or // flow through a callable - exists(DataFlowCall call, ParameterPosition summaryCtx0, Ap argAp0 | - fwdFlowOutFromArg(call, node, state, summaryCtx0, argAp0, ap, apa, config) and - fwdFlowIsEntered(call, cc, summaryCtx, argAp, summaryCtx0, argAp0, config) + exists( + DataFlowCall call, CcCall ccc, RetNodeEx ret, boolean allowsFieldFlow, ApApprox innerArgApa + | + fwdFlowThrough(call, cc, state, ccc, summaryCtx, argAp, ap, apa, ret, innerArgApa, config) and + flowThroughOutOfCall(call, ccc, ret, node, allowsFieldFlow, innerArgApa, apa, config) and + if allowsFieldFlow = false then ap instanceof ApNil else any() ) } pragma[nomagic] private predicate fwdFlowStore( NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, FlowState state, Cc cc, - ParameterPositionOption summaryCtx, ApOption argAp, Configuration config + ParamNodeOption summaryCtx, ApOption argAp, Configuration config ) { exists(DataFlowType contentType, ApApprox apa1 | fwdFlow(node1, state, cc, summaryCtx, argAp, ap1, apa1, config) and @@ -1473,8 +1480,8 @@ private module MkStage { pragma[nomagic] private predicate fwdFlowRead0( - NodeEx node1, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - ApNonNil ap, Configuration config + NodeEx node1, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, ApNonNil ap, + Configuration config ) { fwdFlow(node1, state, cc, summaryCtx, argAp, ap, config) and PrevStage::readStepCand(node1, _, _, config) @@ -1483,7 +1490,7 @@ private module MkStage { pragma[nomagic] private predicate fwdFlowRead( Ap ap, Content c, NodeEx node1, NodeEx node2, FlowState state, Cc cc, - ParameterPositionOption summaryCtx, ApOption argAp, Configuration config + ParamNodeOption summaryCtx, ApOption argAp, Configuration config ) { fwdFlowRead0(node1, state, cc, summaryCtx, argAp, ap, config) and PrevStage::readStepCand(node1, c, node2, config) and @@ -1493,7 +1500,7 @@ private module MkStage { pragma[nomagic] private predicate fwdFlowIn( DataFlowCall call, ParamNodeEx p, FlowState state, Cc outercc, CcCall innercc, - ParameterPositionOption summaryCtx, ApOption argAp, Ap ap, ApApprox apa, Configuration config + ParamNodeOption summaryCtx, ApOption argAp, Ap ap, ApApprox apa, Configuration config ) { exists(ArgNodeEx arg, boolean allowsFieldFlow | fwdFlow(arg, state, outercc, summaryCtx, argAp, ap, apa, config) and @@ -1505,64 +1512,38 @@ private module MkStage { pragma[nomagic] private predicate fwdFlowRetFromArg( - RetNodeEx ret, FlowState state, CcCall ccc, ParameterPosition summaryCtx, ParamNodeEx p, - Ap argAp, ApApprox argApa, Ap ap, ApApprox apa, Configuration config + RetNodeEx ret, FlowState state, CcCall ccc, ParamNodeEx summaryCtx, Ap argAp, ApApprox argApa, + Ap ap, ApApprox apa, Configuration config ) { - exists(DataFlowCallable c, ReturnKindExt kind | + exists(ReturnKindExt kind | fwdFlow(pragma[only_bind_into](ret), state, ccc, - TParameterPositionSome(pragma[only_bind_into](summaryCtx)), apSome(argAp), ap, apa, config) and - getApprox(argAp) = argApa and - c = ret.getEnclosingCallable() and + TParamNodeSome(pragma[only_bind_into](summaryCtx.asNode())), + pragma[only_bind_into](apSome(argAp)), ap, pragma[only_bind_into](apa), + pragma[only_bind_into](config)) and kind = ret.getKind() and - p.isParameterOf(c, pragma[only_bind_into](summaryCtx)) and - parameterFlowThroughAllowed(p, kind) + parameterFlowThroughAllowed(summaryCtx, kind) and + argApa = getApprox(argAp) and + PrevStage::returnMayFlowThrough(ret, argApa, apa, kind, pragma[only_bind_into](config)) ) } pragma[inline] - private predicate fwdFlowInMayFlowThrough( - DataFlowCall call, Cc cc, CcCall innerCc, ParameterPositionOption summaryCtx, ApOption argAp, - ParamNodeEx param, Ap ap, ApApprox apa, Configuration config + private predicate fwdFlowThrough0( + DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, + ApOption argAp, Ap ap, ApApprox apa, RetNodeEx ret, ParamNodeEx innerSummaryCtx, + Ap innerArgAp, ApApprox innerArgApa, Configuration config ) { - fwdFlowIn(call, pragma[only_bind_into](param), _, cc, innerCc, summaryCtx, argAp, ap, - pragma[only_bind_into](apa), pragma[only_bind_into](config)) and - PrevStage::parameterMayFlowThrough(param, apa, config) - } - - // dedup before joining with `flowThroughOutOfCall` - pragma[nomagic] - private predicate fwdFlowInMayFlowThroughProj( - DataFlowCall call, CcCall innerCc, ApApprox apa, Configuration config - ) { - fwdFlowInMayFlowThrough(call, _, innerCc, _, _, _, _, apa, config) - } - - /** - * Same as `flowThroughOutOfCall`, but restricted to calls that are reached - * in the flow covered by `fwdFlow`, where data might flow through the target - * callable and back out at `call`. - */ - pragma[nomagic] - private predicate fwdFlowThroughOutOfCall( - DataFlowCall call, CcCall ccc, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow, - ApApprox argApa, ApApprox apa, Configuration config - ) { - fwdFlowInMayFlowThroughProj(call, ccc, argApa, config) and - flowThroughOutOfCall(call, ccc, ret, out, allowsFieldFlow, argApa, apa, config) + fwdFlowRetFromArg(ret, state, ccc, innerSummaryCtx, innerArgAp, innerArgApa, ap, apa, config) and + fwdFlowIsEntered(call, cc, ccc, summaryCtx, argAp, innerSummaryCtx, innerArgAp, config) } pragma[nomagic] - private predicate fwdFlowOutFromArg( - DataFlowCall call, NodeEx out, FlowState state, ParameterPosition summaryCtx, Ap argAp, Ap ap, - ApApprox apa, Configuration config + private predicate fwdFlowThrough( + DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, + ApOption argAp, Ap ap, ApApprox apa, RetNodeEx ret, ApApprox innerArgApa, Configuration config ) { - exists(RetNodeEx ret, boolean allowsFieldFlow, CcCall ccc, ApApprox argApa | - fwdFlowRetFromArg(pragma[only_bind_into](ret), state, pragma[only_bind_into](ccc), - summaryCtx, _, argAp, pragma[only_bind_into](argApa), ap, pragma[only_bind_into](apa), - config) and - fwdFlowThroughOutOfCall(call, ccc, ret, out, allowsFieldFlow, argApa, apa, config) and - (if allowsFieldFlow = false then ap instanceof ApNil else any()) - ) + fwdFlowThrough0(call, cc, state, ccc, summaryCtx, argAp, ap, apa, ret, _, _, innerArgApa, + config) } /** @@ -1571,12 +1552,14 @@ private module MkStage { */ pragma[nomagic] private predicate fwdFlowIsEntered( - DataFlowCall call, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - ParameterPosition pos, Ap ap, Configuration config + DataFlowCall call, Cc cc, CcCall innerCc, ParamNodeOption summaryCtx, ApOption argAp, + ParamNodeEx p, Ap ap, Configuration config ) { - exists(ParamNodeEx param | - fwdFlowInMayFlowThrough(call, cc, _, summaryCtx, argAp, param, ap, _, config) and - pos = param.getPosition() + exists(ApApprox apa | + fwdFlowIn(call, pragma[only_bind_into](p), _, cc, innerCc, summaryCtx, argAp, ap, + pragma[only_bind_into](apa), pragma[only_bind_into](config)) and + PrevStage::parameterMayFlowThrough(p, apa, config) and + PrevStage::callMayFlowThroughRev(call, pragma[only_bind_into](config)) ) } @@ -1596,23 +1579,31 @@ private module MkStage { fwdFlowConsCand(ap1, c, ap2, config) } + pragma[nomagic] + private predicate returnFlowsThrough0( + DataFlowCall call, FlowState state, CcCall ccc, Ap ap, ApApprox apa, RetNodeEx ret, + ParamNodeEx innerSummaryCtx, Ap innerArgAp, ApApprox innerArgApa, Configuration config + ) { + fwdFlowThrough0(call, _, state, ccc, _, _, ap, apa, ret, innerSummaryCtx, innerArgAp, + innerArgApa, config) + } + pragma[nomagic] private predicate returnFlowsThrough( - RetNodeEx ret, ReturnKindExt kind, FlowState state, CcCall ccc, ParamNodeEx p, Ap argAp, + RetNodeEx ret, ReturnPosition pos, FlowState state, CcCall ccc, ParamNodeEx p, Ap argAp, Ap ap, Configuration config ) { - exists(boolean allowsFieldFlow, ApApprox argApa, ApApprox apa | - fwdFlowRetFromArg(pragma[only_bind_into](ret), state, pragma[only_bind_into](ccc), _, p, - argAp, pragma[only_bind_into](argApa), ap, pragma[only_bind_into](apa), config) and - kind = ret.getKind() and - fwdFlowThroughOutOfCall(_, ccc, ret, _, allowsFieldFlow, argApa, apa, config) and - (if allowsFieldFlow = false then ap instanceof ApNil else any()) + exists(DataFlowCall call, ApApprox apa, boolean allowsFieldFlow, ApApprox innerArgApa | + returnFlowsThrough0(call, state, ccc, ap, apa, ret, p, argAp, innerArgApa, config) and + flowThroughOutOfCall(call, ccc, ret, _, allowsFieldFlow, innerArgApa, apa, config) and + pos = ret.getReturnPosition() and + if allowsFieldFlow = false then ap instanceof ApNil else any() ) } pragma[nomagic] private predicate flowThroughIntoCall( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap argAp, + DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap argAp, Ap ap, Configuration config ) { exists(ApApprox argApa | @@ -1620,7 +1611,7 @@ private module MkStage { allowsFieldFlow, argApa, pragma[only_bind_into](config)) and fwdFlow(arg, _, _, _, _, pragma[only_bind_into](argAp), argApa, pragma[only_bind_into](config)) and - returnFlowsThrough(_, _, _, _, p, pragma[only_bind_into](argAp), _, + returnFlowsThrough(_, _, _, _, p, pragma[only_bind_into](argAp), ap, pragma[only_bind_into](config)) and if allowsFieldFlow = false then argAp instanceof ApNil else any() ) @@ -1639,12 +1630,13 @@ private module MkStage { pragma[nomagic] private predicate flowOutOfCallAp( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, boolean allowsFieldFlow, + DataFlowCall call, RetNodeEx ret, ReturnPosition pos, NodeEx out, boolean allowsFieldFlow, Ap ap, Configuration config ) { exists(ApApprox apa | - flowOutOfCallApa(call, ret, kind, out, allowsFieldFlow, apa, config) and - fwdFlow(ret, _, _, _, _, ap, apa, config) + flowOutOfCallApa(call, ret, _, out, allowsFieldFlow, apa, config) and + fwdFlow(ret, _, _, _, _, ap, apa, config) and + pos = ret.getReturnPosition() ) } @@ -1739,17 +1731,17 @@ private module MkStage { ) or // flow through a callable - exists(DataFlowCall call, ReturnKindExt returnKind0, Ap returnAp0 | - revFlowInToReturn(call, node, state, returnKind0, returnAp0, ap, config) and - revFlowIsReturned(call, returnCtx, returnAp, returnKind0, returnAp0, config) + exists(DataFlowCall call, ParamNodeEx p, ReturnPosition pos, Ap innerReturnAp | + revFlowThrough(call, returnCtx, p, state, pos, returnAp, ap, innerReturnAp, config) and + flowThroughIntoCall(call, node, p, _, ap, innerReturnAp, config) ) or // flow out of a callable - exists(ReturnKindExt kind | - revFlowOut(_, node, kind, state, _, _, ap, config) and - if returnFlowsThrough(node, kind, state, _, _, _, ap, config) + exists(ReturnPosition pos | + revFlowOut(_, node, pos, state, _, _, ap, config) and + if returnFlowsThrough(node, pos, state, _, _, _, ap, config) then ( - returnCtx = TReturnCtxMaybeFlowThrough(kind) and + returnCtx = TReturnCtxMaybeFlowThrough(pos) and returnAp = apSome(ap) ) else ( returnCtx = TReturnCtxNoFlowThrough() and returnAp = apNone() @@ -1782,47 +1774,33 @@ private module MkStage { pragma[nomagic] private predicate revFlowOut( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, FlowState state, ReturnCtx returnCtx, + DataFlowCall call, RetNodeEx ret, ReturnPosition pos, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap, Configuration config ) { exists(NodeEx out, boolean allowsFieldFlow | revFlow(out, state, returnCtx, returnAp, ap, config) and - flowOutOfCallAp(call, ret, kind, out, allowsFieldFlow, ap, config) and + flowOutOfCallAp(call, ret, pos, out, allowsFieldFlow, ap, config) and if allowsFieldFlow = false then ap instanceof ApNil else any() ) } - /** - * Same as `flowThroughIntoCall`, but restricted to calls that are reached - * in the flow covered by `revFlow`, where data might flow through the target - * callable and back out at `call`. - */ - pragma[nomagic] - private predicate revFlowThroughIntoCall( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap argAp, - Configuration config - ) { - flowThroughIntoCall(call, arg, p, allowsFieldFlow, argAp, config) and - revFlowIsReturned(call, _, _, _, _, config) - } - pragma[nomagic] private predicate revFlowParamToReturn( - ParamNodeEx p, FlowState state, ReturnKindExt kind, Ap returnAp, Ap ap, Configuration config + ParamNodeEx p, FlowState state, ReturnPosition pos, Ap returnAp, Ap ap, Configuration config ) { - revFlow(p, state, TReturnCtxMaybeFlowThrough(kind), apSome(returnAp), ap, config) and - parameterFlowThroughAllowed(p, kind) + revFlow(pragma[only_bind_into](p), state, TReturnCtxMaybeFlowThrough(pos), apSome(returnAp), + pragma[only_bind_into](ap), pragma[only_bind_into](config)) and + parameterFlowThroughAllowed(p, pos.getKind()) and + PrevStage::parameterMayFlowThrough(p, getApprox(ap), config) } pragma[nomagic] - private predicate revFlowInToReturn( - DataFlowCall call, ArgNodeEx arg, FlowState state, ReturnKindExt kind, Ap returnAp, Ap ap, - Configuration config + private predicate revFlowThrough( + DataFlowCall call, ReturnCtx returnCtx, ParamNodeEx p, FlowState state, ReturnPosition pos, + ApOption returnAp, Ap ap, Ap innerReturnAp, Configuration config ) { - exists(ParamNodeEx p, boolean allowsFieldFlow | - revFlowParamToReturn(p, state, kind, returnAp, ap, config) and - revFlowThroughIntoCall(call, arg, p, allowsFieldFlow, ap, config) - ) + revFlowParamToReturn(p, state, pos, innerReturnAp, ap, config) and + revFlowIsReturned(call, returnCtx, returnAp, pos, innerReturnAp, config) } /** @@ -1832,12 +1810,12 @@ private module MkStage { */ pragma[nomagic] private predicate revFlowIsReturned( - DataFlowCall call, ReturnCtx returnCtx, ApOption returnAp, ReturnKindExt kind, Ap ap, + DataFlowCall call, ReturnCtx returnCtx, ApOption returnAp, ReturnPosition pos, Ap ap, Configuration config ) { exists(RetNodeEx ret, FlowState state, CcCall ccc | - revFlowOut(call, ret, kind, state, returnCtx, returnAp, ap, config) and - returnFlowsThrough(ret, kind, state, ccc, _, _, ap, config) and + revFlowOut(call, ret, pos, state, returnCtx, returnAp, ap, config) and + returnFlowsThrough(ret, pos, state, ccc, _, _, ap, config) and matchesCall(ccc, call) ) } @@ -1915,17 +1893,17 @@ private module MkStage { pragma[nomagic] private predicate parameterFlowsThroughRev( - ParamNodeEx p, Ap ap, ReturnKindExt kind, Ap returnAp, Configuration config + ParamNodeEx p, Ap ap, ReturnPosition pos, Ap returnAp, Configuration config ) { - revFlow(p, _, TReturnCtxMaybeFlowThrough(kind), apSome(returnAp), ap, config) and - parameterFlowThroughAllowed(p, kind) + revFlow(p, _, TReturnCtxMaybeFlowThrough(pos), apSome(returnAp), ap, config) and + parameterFlowThroughAllowed(p, pos.getKind()) } pragma[nomagic] predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap, Configuration config) { - exists(RetNodeEx ret, ReturnKindExt kind | - returnFlowsThrough(ret, kind, _, _, p, ap, _, config) and - parameterFlowsThroughRev(p, ap, kind, _, config) + exists(RetNodeEx ret, ReturnPosition pos | + returnFlowsThrough(ret, pos, _, _, p, ap, _, config) and + parameterFlowsThroughRev(p, ap, pos, _, config) ) } @@ -1933,20 +1911,21 @@ private module MkStage { predicate returnMayFlowThrough( RetNodeEx ret, Ap argAp, Ap ap, ReturnKindExt kind, Configuration config ) { - exists(ParamNodeEx p | - returnFlowsThrough(ret, kind, _, _, p, argAp, ap, config) and - parameterFlowsThroughRev(p, argAp, kind, ap, config) + exists(ParamNodeEx p, ReturnPosition pos | + returnFlowsThrough(ret, pos, _, _, p, argAp, ap, config) and + parameterFlowsThroughRev(p, argAp, pos, ap, config) and + kind = pos.getKind() ) } pragma[nomagic] - predicate revFlowInToReturnIsReturned( + private predicate revFlowThroughArg( DataFlowCall call, ArgNodeEx arg, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap, Configuration config ) { - exists(ReturnKindExt returnKind0, Ap returnAp0 | - revFlowInToReturn(call, arg, state, returnKind0, returnAp0, ap, config) and - revFlowIsReturned(call, returnCtx, returnAp, returnKind0, returnAp0, config) + exists(ParamNodeEx p, ReturnPosition pos, Ap innerReturnAp | + revFlowThrough(call, returnCtx, p, state, pos, returnAp, ap, innerReturnAp, config) and + flowThroughIntoCall(call, arg, p, _, ap, innerReturnAp, config) ) } @@ -1954,7 +1933,7 @@ private module MkStage { predicate callMayFlowThroughRev(DataFlowCall call, Configuration config) { exists(ArgNodeEx arg, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap | revFlow(arg, state, returnCtx, returnAp, ap, config) and - revFlowInToReturnIsReturned(call, arg, state, returnCtx, returnAp, ap, config) + revFlowThroughArg(call, arg, state, returnCtx, returnAp, ap, config) ) } @@ -1967,8 +1946,9 @@ private module MkStage { conscand = count(TypedContent f0, Ap ap | fwdConsCand(f0, ap, config)) and states = count(FlowState state | fwdFlow(_, state, _, _, _, _, config)) and tuples = - count(NodeEx n, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - Ap ap | fwdFlow(n, state, cc, summaryCtx, argAp, ap, config)) + count(NodeEx n, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap | + fwdFlow(n, state, cc, summaryCtx, argAp, ap, config) + ) or fwd = false and nodes = count(NodeEx node | revFlow(node, _, _, _, _, config)) and @@ -2823,13 +2803,12 @@ private Configuration unbindConf(Configuration conf) { pragma[nomagic] private predicate nodeMayUseSummary0( - NodeEx n, DataFlowCallable c, ParameterPosition pos, FlowState state, AccessPathApprox apa, - Configuration config + NodeEx n, ParamNodeEx p, FlowState state, AccessPathApprox apa, Configuration config ) { exists(AccessPathApprox apa0 | - c = n.getEnclosingCallable() and + Stage5::parameterMayFlowThrough(p, _, _) and Stage5::revFlow(n, state, TReturnCtxMaybeFlowThrough(_), _, apa0, config) and - Stage5::fwdFlow(n, state, any(CallContextCall ccc), TParameterPositionSome(pos), + Stage5::fwdFlow(n, state, any(CallContextCall ccc), TParamNodeSome(p.asNode()), TAccessPathApproxSome(apa), apa0, config) ) } @@ -2838,10 +2817,9 @@ pragma[nomagic] private predicate nodeMayUseSummary( NodeEx n, FlowState state, AccessPathApprox apa, Configuration config ) { - exists(DataFlowCallable c, ParameterPosition pos, ParamNodeEx p | + exists(ParamNodeEx p | Stage5::parameterMayFlowThrough(p, apa, config) and - nodeMayUseSummary0(n, c, pos, state, apa, config) and - p.isParameterOf(c, pos) + nodeMayUseSummary0(n, p, state, apa, config) ) } diff --git a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl2.qll b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl2.qll index 6741ccc2f06..1228d00b6ba 100644 --- a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl2.qll +++ b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl2.qll @@ -622,7 +622,11 @@ private predicate parameterFlowThroughAllowed(ParamNodeEx p, ReturnKindExt kind) } private module Stage1 implements StageSig { - class Ap = Unit; + class Ap extends int { + // workaround for bad functionality-induced joins (happens when using `Unit`) + pragma[nomagic] + Ap() { this in [0 .. 1] and this < 1 } + } private class Cc = boolean; @@ -1327,8 +1331,8 @@ private module MkStage { */ pragma[nomagic] additional predicate fwdFlow( - NodeEx node, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - Ap ap, ApApprox apa, Configuration config + NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, + ApApprox apa, Configuration config ) { fwdFlow0(node, state, cc, summaryCtx, argAp, ap, apa, config) and PrevStage::revFlow(node, state, apa, config) and @@ -1337,21 +1341,21 @@ private module MkStage { pragma[inline] additional predicate fwdFlow( - NodeEx node, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - Ap ap, Configuration config + NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, + Configuration config ) { fwdFlow(node, state, cc, summaryCtx, argAp, ap, _, config) } pragma[nomagic] private predicate fwdFlow0( - NodeEx node, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - Ap ap, ApApprox apa, Configuration config + NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, + ApApprox apa, Configuration config ) { sourceNode(node, state, config) and (if hasSourceCallCtx(config) then cc = ccSomeCall() else cc = ccNone()) and argAp = apNone() and - summaryCtx = TParameterPositionNone() and + summaryCtx = TParamNodeNone() and ap = getApNil(node) and apa = getApprox(ap) or @@ -1372,7 +1376,7 @@ private module MkStage { fwdFlow(mid, pragma[only_bind_into](state), _, _, _, ap, apa, pragma[only_bind_into](config)) and jumpStep(mid, node, config) and cc = ccNone() and - summaryCtx = TParameterPositionNone() and + summaryCtx = TParamNodeNone() and argAp = apNone() ) or @@ -1380,7 +1384,7 @@ private module MkStage { fwdFlow(mid, state, _, _, _, nil, pragma[only_bind_into](config)) and additionalJumpStep(mid, node, config) and cc = ccNone() and - summaryCtx = TParameterPositionNone() and + summaryCtx = TParamNodeNone() and argAp = apNone() and ap = getApNil(node) and apa = getApprox(ap) @@ -1390,7 +1394,7 @@ private module MkStage { fwdFlow(mid, state0, _, _, _, nil, pragma[only_bind_into](config)) and additionalJumpStateStep(mid, state0, node, state, config) and cc = ccNone() and - summaryCtx = TParameterPositionNone() and + summaryCtx = TParamNodeNone() and argAp = apNone() and ap = getApNil(node) and apa = getApprox(ap) @@ -1414,10 +1418,10 @@ private module MkStage { fwdFlowIn(_, node, state, _, cc, _, _, ap, apa, config) and if PrevStage::parameterMayFlowThrough(node, apa, config) then ( - summaryCtx = TParameterPositionSome(node.(ParamNodeEx).getPosition()) and + summaryCtx = TParamNodeSome(node.asNode()) and argAp = apSome(ap) ) else ( - summaryCtx = TParameterPositionNone() and argAp = apNone() + summaryCtx = TParamNodeNone() and argAp = apNone() ) or // flow out of a callable @@ -1433,16 +1437,19 @@ private module MkStage { ) or // flow through a callable - exists(DataFlowCall call, ParameterPosition summaryCtx0, Ap argAp0 | - fwdFlowOutFromArg(call, node, state, summaryCtx0, argAp0, ap, apa, config) and - fwdFlowIsEntered(call, cc, summaryCtx, argAp, summaryCtx0, argAp0, config) + exists( + DataFlowCall call, CcCall ccc, RetNodeEx ret, boolean allowsFieldFlow, ApApprox innerArgApa + | + fwdFlowThrough(call, cc, state, ccc, summaryCtx, argAp, ap, apa, ret, innerArgApa, config) and + flowThroughOutOfCall(call, ccc, ret, node, allowsFieldFlow, innerArgApa, apa, config) and + if allowsFieldFlow = false then ap instanceof ApNil else any() ) } pragma[nomagic] private predicate fwdFlowStore( NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, FlowState state, Cc cc, - ParameterPositionOption summaryCtx, ApOption argAp, Configuration config + ParamNodeOption summaryCtx, ApOption argAp, Configuration config ) { exists(DataFlowType contentType, ApApprox apa1 | fwdFlow(node1, state, cc, summaryCtx, argAp, ap1, apa1, config) and @@ -1473,8 +1480,8 @@ private module MkStage { pragma[nomagic] private predicate fwdFlowRead0( - NodeEx node1, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - ApNonNil ap, Configuration config + NodeEx node1, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, ApNonNil ap, + Configuration config ) { fwdFlow(node1, state, cc, summaryCtx, argAp, ap, config) and PrevStage::readStepCand(node1, _, _, config) @@ -1483,7 +1490,7 @@ private module MkStage { pragma[nomagic] private predicate fwdFlowRead( Ap ap, Content c, NodeEx node1, NodeEx node2, FlowState state, Cc cc, - ParameterPositionOption summaryCtx, ApOption argAp, Configuration config + ParamNodeOption summaryCtx, ApOption argAp, Configuration config ) { fwdFlowRead0(node1, state, cc, summaryCtx, argAp, ap, config) and PrevStage::readStepCand(node1, c, node2, config) and @@ -1493,7 +1500,7 @@ private module MkStage { pragma[nomagic] private predicate fwdFlowIn( DataFlowCall call, ParamNodeEx p, FlowState state, Cc outercc, CcCall innercc, - ParameterPositionOption summaryCtx, ApOption argAp, Ap ap, ApApprox apa, Configuration config + ParamNodeOption summaryCtx, ApOption argAp, Ap ap, ApApprox apa, Configuration config ) { exists(ArgNodeEx arg, boolean allowsFieldFlow | fwdFlow(arg, state, outercc, summaryCtx, argAp, ap, apa, config) and @@ -1505,64 +1512,38 @@ private module MkStage { pragma[nomagic] private predicate fwdFlowRetFromArg( - RetNodeEx ret, FlowState state, CcCall ccc, ParameterPosition summaryCtx, ParamNodeEx p, - Ap argAp, ApApprox argApa, Ap ap, ApApprox apa, Configuration config + RetNodeEx ret, FlowState state, CcCall ccc, ParamNodeEx summaryCtx, Ap argAp, ApApprox argApa, + Ap ap, ApApprox apa, Configuration config ) { - exists(DataFlowCallable c, ReturnKindExt kind | + exists(ReturnKindExt kind | fwdFlow(pragma[only_bind_into](ret), state, ccc, - TParameterPositionSome(pragma[only_bind_into](summaryCtx)), apSome(argAp), ap, apa, config) and - getApprox(argAp) = argApa and - c = ret.getEnclosingCallable() and + TParamNodeSome(pragma[only_bind_into](summaryCtx.asNode())), + pragma[only_bind_into](apSome(argAp)), ap, pragma[only_bind_into](apa), + pragma[only_bind_into](config)) and kind = ret.getKind() and - p.isParameterOf(c, pragma[only_bind_into](summaryCtx)) and - parameterFlowThroughAllowed(p, kind) + parameterFlowThroughAllowed(summaryCtx, kind) and + argApa = getApprox(argAp) and + PrevStage::returnMayFlowThrough(ret, argApa, apa, kind, pragma[only_bind_into](config)) ) } pragma[inline] - private predicate fwdFlowInMayFlowThrough( - DataFlowCall call, Cc cc, CcCall innerCc, ParameterPositionOption summaryCtx, ApOption argAp, - ParamNodeEx param, Ap ap, ApApprox apa, Configuration config + private predicate fwdFlowThrough0( + DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, + ApOption argAp, Ap ap, ApApprox apa, RetNodeEx ret, ParamNodeEx innerSummaryCtx, + Ap innerArgAp, ApApprox innerArgApa, Configuration config ) { - fwdFlowIn(call, pragma[only_bind_into](param), _, cc, innerCc, summaryCtx, argAp, ap, - pragma[only_bind_into](apa), pragma[only_bind_into](config)) and - PrevStage::parameterMayFlowThrough(param, apa, config) - } - - // dedup before joining with `flowThroughOutOfCall` - pragma[nomagic] - private predicate fwdFlowInMayFlowThroughProj( - DataFlowCall call, CcCall innerCc, ApApprox apa, Configuration config - ) { - fwdFlowInMayFlowThrough(call, _, innerCc, _, _, _, _, apa, config) - } - - /** - * Same as `flowThroughOutOfCall`, but restricted to calls that are reached - * in the flow covered by `fwdFlow`, where data might flow through the target - * callable and back out at `call`. - */ - pragma[nomagic] - private predicate fwdFlowThroughOutOfCall( - DataFlowCall call, CcCall ccc, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow, - ApApprox argApa, ApApprox apa, Configuration config - ) { - fwdFlowInMayFlowThroughProj(call, ccc, argApa, config) and - flowThroughOutOfCall(call, ccc, ret, out, allowsFieldFlow, argApa, apa, config) + fwdFlowRetFromArg(ret, state, ccc, innerSummaryCtx, innerArgAp, innerArgApa, ap, apa, config) and + fwdFlowIsEntered(call, cc, ccc, summaryCtx, argAp, innerSummaryCtx, innerArgAp, config) } pragma[nomagic] - private predicate fwdFlowOutFromArg( - DataFlowCall call, NodeEx out, FlowState state, ParameterPosition summaryCtx, Ap argAp, Ap ap, - ApApprox apa, Configuration config + private predicate fwdFlowThrough( + DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, + ApOption argAp, Ap ap, ApApprox apa, RetNodeEx ret, ApApprox innerArgApa, Configuration config ) { - exists(RetNodeEx ret, boolean allowsFieldFlow, CcCall ccc, ApApprox argApa | - fwdFlowRetFromArg(pragma[only_bind_into](ret), state, pragma[only_bind_into](ccc), - summaryCtx, _, argAp, pragma[only_bind_into](argApa), ap, pragma[only_bind_into](apa), - config) and - fwdFlowThroughOutOfCall(call, ccc, ret, out, allowsFieldFlow, argApa, apa, config) and - (if allowsFieldFlow = false then ap instanceof ApNil else any()) - ) + fwdFlowThrough0(call, cc, state, ccc, summaryCtx, argAp, ap, apa, ret, _, _, innerArgApa, + config) } /** @@ -1571,12 +1552,14 @@ private module MkStage { */ pragma[nomagic] private predicate fwdFlowIsEntered( - DataFlowCall call, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - ParameterPosition pos, Ap ap, Configuration config + DataFlowCall call, Cc cc, CcCall innerCc, ParamNodeOption summaryCtx, ApOption argAp, + ParamNodeEx p, Ap ap, Configuration config ) { - exists(ParamNodeEx param | - fwdFlowInMayFlowThrough(call, cc, _, summaryCtx, argAp, param, ap, _, config) and - pos = param.getPosition() + exists(ApApprox apa | + fwdFlowIn(call, pragma[only_bind_into](p), _, cc, innerCc, summaryCtx, argAp, ap, + pragma[only_bind_into](apa), pragma[only_bind_into](config)) and + PrevStage::parameterMayFlowThrough(p, apa, config) and + PrevStage::callMayFlowThroughRev(call, pragma[only_bind_into](config)) ) } @@ -1596,23 +1579,31 @@ private module MkStage { fwdFlowConsCand(ap1, c, ap2, config) } + pragma[nomagic] + private predicate returnFlowsThrough0( + DataFlowCall call, FlowState state, CcCall ccc, Ap ap, ApApprox apa, RetNodeEx ret, + ParamNodeEx innerSummaryCtx, Ap innerArgAp, ApApprox innerArgApa, Configuration config + ) { + fwdFlowThrough0(call, _, state, ccc, _, _, ap, apa, ret, innerSummaryCtx, innerArgAp, + innerArgApa, config) + } + pragma[nomagic] private predicate returnFlowsThrough( - RetNodeEx ret, ReturnKindExt kind, FlowState state, CcCall ccc, ParamNodeEx p, Ap argAp, + RetNodeEx ret, ReturnPosition pos, FlowState state, CcCall ccc, ParamNodeEx p, Ap argAp, Ap ap, Configuration config ) { - exists(boolean allowsFieldFlow, ApApprox argApa, ApApprox apa | - fwdFlowRetFromArg(pragma[only_bind_into](ret), state, pragma[only_bind_into](ccc), _, p, - argAp, pragma[only_bind_into](argApa), ap, pragma[only_bind_into](apa), config) and - kind = ret.getKind() and - fwdFlowThroughOutOfCall(_, ccc, ret, _, allowsFieldFlow, argApa, apa, config) and - (if allowsFieldFlow = false then ap instanceof ApNil else any()) + exists(DataFlowCall call, ApApprox apa, boolean allowsFieldFlow, ApApprox innerArgApa | + returnFlowsThrough0(call, state, ccc, ap, apa, ret, p, argAp, innerArgApa, config) and + flowThroughOutOfCall(call, ccc, ret, _, allowsFieldFlow, innerArgApa, apa, config) and + pos = ret.getReturnPosition() and + if allowsFieldFlow = false then ap instanceof ApNil else any() ) } pragma[nomagic] private predicate flowThroughIntoCall( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap argAp, + DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap argAp, Ap ap, Configuration config ) { exists(ApApprox argApa | @@ -1620,7 +1611,7 @@ private module MkStage { allowsFieldFlow, argApa, pragma[only_bind_into](config)) and fwdFlow(arg, _, _, _, _, pragma[only_bind_into](argAp), argApa, pragma[only_bind_into](config)) and - returnFlowsThrough(_, _, _, _, p, pragma[only_bind_into](argAp), _, + returnFlowsThrough(_, _, _, _, p, pragma[only_bind_into](argAp), ap, pragma[only_bind_into](config)) and if allowsFieldFlow = false then argAp instanceof ApNil else any() ) @@ -1639,12 +1630,13 @@ private module MkStage { pragma[nomagic] private predicate flowOutOfCallAp( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, boolean allowsFieldFlow, + DataFlowCall call, RetNodeEx ret, ReturnPosition pos, NodeEx out, boolean allowsFieldFlow, Ap ap, Configuration config ) { exists(ApApprox apa | - flowOutOfCallApa(call, ret, kind, out, allowsFieldFlow, apa, config) and - fwdFlow(ret, _, _, _, _, ap, apa, config) + flowOutOfCallApa(call, ret, _, out, allowsFieldFlow, apa, config) and + fwdFlow(ret, _, _, _, _, ap, apa, config) and + pos = ret.getReturnPosition() ) } @@ -1739,17 +1731,17 @@ private module MkStage { ) or // flow through a callable - exists(DataFlowCall call, ReturnKindExt returnKind0, Ap returnAp0 | - revFlowInToReturn(call, node, state, returnKind0, returnAp0, ap, config) and - revFlowIsReturned(call, returnCtx, returnAp, returnKind0, returnAp0, config) + exists(DataFlowCall call, ParamNodeEx p, ReturnPosition pos, Ap innerReturnAp | + revFlowThrough(call, returnCtx, p, state, pos, returnAp, ap, innerReturnAp, config) and + flowThroughIntoCall(call, node, p, _, ap, innerReturnAp, config) ) or // flow out of a callable - exists(ReturnKindExt kind | - revFlowOut(_, node, kind, state, _, _, ap, config) and - if returnFlowsThrough(node, kind, state, _, _, _, ap, config) + exists(ReturnPosition pos | + revFlowOut(_, node, pos, state, _, _, ap, config) and + if returnFlowsThrough(node, pos, state, _, _, _, ap, config) then ( - returnCtx = TReturnCtxMaybeFlowThrough(kind) and + returnCtx = TReturnCtxMaybeFlowThrough(pos) and returnAp = apSome(ap) ) else ( returnCtx = TReturnCtxNoFlowThrough() and returnAp = apNone() @@ -1782,47 +1774,33 @@ private module MkStage { pragma[nomagic] private predicate revFlowOut( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, FlowState state, ReturnCtx returnCtx, + DataFlowCall call, RetNodeEx ret, ReturnPosition pos, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap, Configuration config ) { exists(NodeEx out, boolean allowsFieldFlow | revFlow(out, state, returnCtx, returnAp, ap, config) and - flowOutOfCallAp(call, ret, kind, out, allowsFieldFlow, ap, config) and + flowOutOfCallAp(call, ret, pos, out, allowsFieldFlow, ap, config) and if allowsFieldFlow = false then ap instanceof ApNil else any() ) } - /** - * Same as `flowThroughIntoCall`, but restricted to calls that are reached - * in the flow covered by `revFlow`, where data might flow through the target - * callable and back out at `call`. - */ - pragma[nomagic] - private predicate revFlowThroughIntoCall( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap argAp, - Configuration config - ) { - flowThroughIntoCall(call, arg, p, allowsFieldFlow, argAp, config) and - revFlowIsReturned(call, _, _, _, _, config) - } - pragma[nomagic] private predicate revFlowParamToReturn( - ParamNodeEx p, FlowState state, ReturnKindExt kind, Ap returnAp, Ap ap, Configuration config + ParamNodeEx p, FlowState state, ReturnPosition pos, Ap returnAp, Ap ap, Configuration config ) { - revFlow(p, state, TReturnCtxMaybeFlowThrough(kind), apSome(returnAp), ap, config) and - parameterFlowThroughAllowed(p, kind) + revFlow(pragma[only_bind_into](p), state, TReturnCtxMaybeFlowThrough(pos), apSome(returnAp), + pragma[only_bind_into](ap), pragma[only_bind_into](config)) and + parameterFlowThroughAllowed(p, pos.getKind()) and + PrevStage::parameterMayFlowThrough(p, getApprox(ap), config) } pragma[nomagic] - private predicate revFlowInToReturn( - DataFlowCall call, ArgNodeEx arg, FlowState state, ReturnKindExt kind, Ap returnAp, Ap ap, - Configuration config + private predicate revFlowThrough( + DataFlowCall call, ReturnCtx returnCtx, ParamNodeEx p, FlowState state, ReturnPosition pos, + ApOption returnAp, Ap ap, Ap innerReturnAp, Configuration config ) { - exists(ParamNodeEx p, boolean allowsFieldFlow | - revFlowParamToReturn(p, state, kind, returnAp, ap, config) and - revFlowThroughIntoCall(call, arg, p, allowsFieldFlow, ap, config) - ) + revFlowParamToReturn(p, state, pos, innerReturnAp, ap, config) and + revFlowIsReturned(call, returnCtx, returnAp, pos, innerReturnAp, config) } /** @@ -1832,12 +1810,12 @@ private module MkStage { */ pragma[nomagic] private predicate revFlowIsReturned( - DataFlowCall call, ReturnCtx returnCtx, ApOption returnAp, ReturnKindExt kind, Ap ap, + DataFlowCall call, ReturnCtx returnCtx, ApOption returnAp, ReturnPosition pos, Ap ap, Configuration config ) { exists(RetNodeEx ret, FlowState state, CcCall ccc | - revFlowOut(call, ret, kind, state, returnCtx, returnAp, ap, config) and - returnFlowsThrough(ret, kind, state, ccc, _, _, ap, config) and + revFlowOut(call, ret, pos, state, returnCtx, returnAp, ap, config) and + returnFlowsThrough(ret, pos, state, ccc, _, _, ap, config) and matchesCall(ccc, call) ) } @@ -1915,17 +1893,17 @@ private module MkStage { pragma[nomagic] private predicate parameterFlowsThroughRev( - ParamNodeEx p, Ap ap, ReturnKindExt kind, Ap returnAp, Configuration config + ParamNodeEx p, Ap ap, ReturnPosition pos, Ap returnAp, Configuration config ) { - revFlow(p, _, TReturnCtxMaybeFlowThrough(kind), apSome(returnAp), ap, config) and - parameterFlowThroughAllowed(p, kind) + revFlow(p, _, TReturnCtxMaybeFlowThrough(pos), apSome(returnAp), ap, config) and + parameterFlowThroughAllowed(p, pos.getKind()) } pragma[nomagic] predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap, Configuration config) { - exists(RetNodeEx ret, ReturnKindExt kind | - returnFlowsThrough(ret, kind, _, _, p, ap, _, config) and - parameterFlowsThroughRev(p, ap, kind, _, config) + exists(RetNodeEx ret, ReturnPosition pos | + returnFlowsThrough(ret, pos, _, _, p, ap, _, config) and + parameterFlowsThroughRev(p, ap, pos, _, config) ) } @@ -1933,20 +1911,21 @@ private module MkStage { predicate returnMayFlowThrough( RetNodeEx ret, Ap argAp, Ap ap, ReturnKindExt kind, Configuration config ) { - exists(ParamNodeEx p | - returnFlowsThrough(ret, kind, _, _, p, argAp, ap, config) and - parameterFlowsThroughRev(p, argAp, kind, ap, config) + exists(ParamNodeEx p, ReturnPosition pos | + returnFlowsThrough(ret, pos, _, _, p, argAp, ap, config) and + parameterFlowsThroughRev(p, argAp, pos, ap, config) and + kind = pos.getKind() ) } pragma[nomagic] - predicate revFlowInToReturnIsReturned( + private predicate revFlowThroughArg( DataFlowCall call, ArgNodeEx arg, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap, Configuration config ) { - exists(ReturnKindExt returnKind0, Ap returnAp0 | - revFlowInToReturn(call, arg, state, returnKind0, returnAp0, ap, config) and - revFlowIsReturned(call, returnCtx, returnAp, returnKind0, returnAp0, config) + exists(ParamNodeEx p, ReturnPosition pos, Ap innerReturnAp | + revFlowThrough(call, returnCtx, p, state, pos, returnAp, ap, innerReturnAp, config) and + flowThroughIntoCall(call, arg, p, _, ap, innerReturnAp, config) ) } @@ -1954,7 +1933,7 @@ private module MkStage { predicate callMayFlowThroughRev(DataFlowCall call, Configuration config) { exists(ArgNodeEx arg, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap | revFlow(arg, state, returnCtx, returnAp, ap, config) and - revFlowInToReturnIsReturned(call, arg, state, returnCtx, returnAp, ap, config) + revFlowThroughArg(call, arg, state, returnCtx, returnAp, ap, config) ) } @@ -1967,8 +1946,9 @@ private module MkStage { conscand = count(TypedContent f0, Ap ap | fwdConsCand(f0, ap, config)) and states = count(FlowState state | fwdFlow(_, state, _, _, _, _, config)) and tuples = - count(NodeEx n, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - Ap ap | fwdFlow(n, state, cc, summaryCtx, argAp, ap, config)) + count(NodeEx n, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap | + fwdFlow(n, state, cc, summaryCtx, argAp, ap, config) + ) or fwd = false and nodes = count(NodeEx node | revFlow(node, _, _, _, _, config)) and @@ -2823,13 +2803,12 @@ private Configuration unbindConf(Configuration conf) { pragma[nomagic] private predicate nodeMayUseSummary0( - NodeEx n, DataFlowCallable c, ParameterPosition pos, FlowState state, AccessPathApprox apa, - Configuration config + NodeEx n, ParamNodeEx p, FlowState state, AccessPathApprox apa, Configuration config ) { exists(AccessPathApprox apa0 | - c = n.getEnclosingCallable() and + Stage5::parameterMayFlowThrough(p, _, _) and Stage5::revFlow(n, state, TReturnCtxMaybeFlowThrough(_), _, apa0, config) and - Stage5::fwdFlow(n, state, any(CallContextCall ccc), TParameterPositionSome(pos), + Stage5::fwdFlow(n, state, any(CallContextCall ccc), TParamNodeSome(p.asNode()), TAccessPathApproxSome(apa), apa0, config) ) } @@ -2838,10 +2817,9 @@ pragma[nomagic] private predicate nodeMayUseSummary( NodeEx n, FlowState state, AccessPathApprox apa, Configuration config ) { - exists(DataFlowCallable c, ParameterPosition pos, ParamNodeEx p | + exists(ParamNodeEx p | Stage5::parameterMayFlowThrough(p, apa, config) and - nodeMayUseSummary0(n, c, pos, state, apa, config) and - p.isParameterOf(c, pos) + nodeMayUseSummary0(n, p, state, apa, config) ) } diff --git a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl3.qll b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl3.qll index 6741ccc2f06..1228d00b6ba 100644 --- a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl3.qll +++ b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl3.qll @@ -622,7 +622,11 @@ private predicate parameterFlowThroughAllowed(ParamNodeEx p, ReturnKindExt kind) } private module Stage1 implements StageSig { - class Ap = Unit; + class Ap extends int { + // workaround for bad functionality-induced joins (happens when using `Unit`) + pragma[nomagic] + Ap() { this in [0 .. 1] and this < 1 } + } private class Cc = boolean; @@ -1327,8 +1331,8 @@ private module MkStage { */ pragma[nomagic] additional predicate fwdFlow( - NodeEx node, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - Ap ap, ApApprox apa, Configuration config + NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, + ApApprox apa, Configuration config ) { fwdFlow0(node, state, cc, summaryCtx, argAp, ap, apa, config) and PrevStage::revFlow(node, state, apa, config) and @@ -1337,21 +1341,21 @@ private module MkStage { pragma[inline] additional predicate fwdFlow( - NodeEx node, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - Ap ap, Configuration config + NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, + Configuration config ) { fwdFlow(node, state, cc, summaryCtx, argAp, ap, _, config) } pragma[nomagic] private predicate fwdFlow0( - NodeEx node, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - Ap ap, ApApprox apa, Configuration config + NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, + ApApprox apa, Configuration config ) { sourceNode(node, state, config) and (if hasSourceCallCtx(config) then cc = ccSomeCall() else cc = ccNone()) and argAp = apNone() and - summaryCtx = TParameterPositionNone() and + summaryCtx = TParamNodeNone() and ap = getApNil(node) and apa = getApprox(ap) or @@ -1372,7 +1376,7 @@ private module MkStage { fwdFlow(mid, pragma[only_bind_into](state), _, _, _, ap, apa, pragma[only_bind_into](config)) and jumpStep(mid, node, config) and cc = ccNone() and - summaryCtx = TParameterPositionNone() and + summaryCtx = TParamNodeNone() and argAp = apNone() ) or @@ -1380,7 +1384,7 @@ private module MkStage { fwdFlow(mid, state, _, _, _, nil, pragma[only_bind_into](config)) and additionalJumpStep(mid, node, config) and cc = ccNone() and - summaryCtx = TParameterPositionNone() and + summaryCtx = TParamNodeNone() and argAp = apNone() and ap = getApNil(node) and apa = getApprox(ap) @@ -1390,7 +1394,7 @@ private module MkStage { fwdFlow(mid, state0, _, _, _, nil, pragma[only_bind_into](config)) and additionalJumpStateStep(mid, state0, node, state, config) and cc = ccNone() and - summaryCtx = TParameterPositionNone() and + summaryCtx = TParamNodeNone() and argAp = apNone() and ap = getApNil(node) and apa = getApprox(ap) @@ -1414,10 +1418,10 @@ private module MkStage { fwdFlowIn(_, node, state, _, cc, _, _, ap, apa, config) and if PrevStage::parameterMayFlowThrough(node, apa, config) then ( - summaryCtx = TParameterPositionSome(node.(ParamNodeEx).getPosition()) and + summaryCtx = TParamNodeSome(node.asNode()) and argAp = apSome(ap) ) else ( - summaryCtx = TParameterPositionNone() and argAp = apNone() + summaryCtx = TParamNodeNone() and argAp = apNone() ) or // flow out of a callable @@ -1433,16 +1437,19 @@ private module MkStage { ) or // flow through a callable - exists(DataFlowCall call, ParameterPosition summaryCtx0, Ap argAp0 | - fwdFlowOutFromArg(call, node, state, summaryCtx0, argAp0, ap, apa, config) and - fwdFlowIsEntered(call, cc, summaryCtx, argAp, summaryCtx0, argAp0, config) + exists( + DataFlowCall call, CcCall ccc, RetNodeEx ret, boolean allowsFieldFlow, ApApprox innerArgApa + | + fwdFlowThrough(call, cc, state, ccc, summaryCtx, argAp, ap, apa, ret, innerArgApa, config) and + flowThroughOutOfCall(call, ccc, ret, node, allowsFieldFlow, innerArgApa, apa, config) and + if allowsFieldFlow = false then ap instanceof ApNil else any() ) } pragma[nomagic] private predicate fwdFlowStore( NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, FlowState state, Cc cc, - ParameterPositionOption summaryCtx, ApOption argAp, Configuration config + ParamNodeOption summaryCtx, ApOption argAp, Configuration config ) { exists(DataFlowType contentType, ApApprox apa1 | fwdFlow(node1, state, cc, summaryCtx, argAp, ap1, apa1, config) and @@ -1473,8 +1480,8 @@ private module MkStage { pragma[nomagic] private predicate fwdFlowRead0( - NodeEx node1, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - ApNonNil ap, Configuration config + NodeEx node1, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, ApNonNil ap, + Configuration config ) { fwdFlow(node1, state, cc, summaryCtx, argAp, ap, config) and PrevStage::readStepCand(node1, _, _, config) @@ -1483,7 +1490,7 @@ private module MkStage { pragma[nomagic] private predicate fwdFlowRead( Ap ap, Content c, NodeEx node1, NodeEx node2, FlowState state, Cc cc, - ParameterPositionOption summaryCtx, ApOption argAp, Configuration config + ParamNodeOption summaryCtx, ApOption argAp, Configuration config ) { fwdFlowRead0(node1, state, cc, summaryCtx, argAp, ap, config) and PrevStage::readStepCand(node1, c, node2, config) and @@ -1493,7 +1500,7 @@ private module MkStage { pragma[nomagic] private predicate fwdFlowIn( DataFlowCall call, ParamNodeEx p, FlowState state, Cc outercc, CcCall innercc, - ParameterPositionOption summaryCtx, ApOption argAp, Ap ap, ApApprox apa, Configuration config + ParamNodeOption summaryCtx, ApOption argAp, Ap ap, ApApprox apa, Configuration config ) { exists(ArgNodeEx arg, boolean allowsFieldFlow | fwdFlow(arg, state, outercc, summaryCtx, argAp, ap, apa, config) and @@ -1505,64 +1512,38 @@ private module MkStage { pragma[nomagic] private predicate fwdFlowRetFromArg( - RetNodeEx ret, FlowState state, CcCall ccc, ParameterPosition summaryCtx, ParamNodeEx p, - Ap argAp, ApApprox argApa, Ap ap, ApApprox apa, Configuration config + RetNodeEx ret, FlowState state, CcCall ccc, ParamNodeEx summaryCtx, Ap argAp, ApApprox argApa, + Ap ap, ApApprox apa, Configuration config ) { - exists(DataFlowCallable c, ReturnKindExt kind | + exists(ReturnKindExt kind | fwdFlow(pragma[only_bind_into](ret), state, ccc, - TParameterPositionSome(pragma[only_bind_into](summaryCtx)), apSome(argAp), ap, apa, config) and - getApprox(argAp) = argApa and - c = ret.getEnclosingCallable() and + TParamNodeSome(pragma[only_bind_into](summaryCtx.asNode())), + pragma[only_bind_into](apSome(argAp)), ap, pragma[only_bind_into](apa), + pragma[only_bind_into](config)) and kind = ret.getKind() and - p.isParameterOf(c, pragma[only_bind_into](summaryCtx)) and - parameterFlowThroughAllowed(p, kind) + parameterFlowThroughAllowed(summaryCtx, kind) and + argApa = getApprox(argAp) and + PrevStage::returnMayFlowThrough(ret, argApa, apa, kind, pragma[only_bind_into](config)) ) } pragma[inline] - private predicate fwdFlowInMayFlowThrough( - DataFlowCall call, Cc cc, CcCall innerCc, ParameterPositionOption summaryCtx, ApOption argAp, - ParamNodeEx param, Ap ap, ApApprox apa, Configuration config + private predicate fwdFlowThrough0( + DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, + ApOption argAp, Ap ap, ApApprox apa, RetNodeEx ret, ParamNodeEx innerSummaryCtx, + Ap innerArgAp, ApApprox innerArgApa, Configuration config ) { - fwdFlowIn(call, pragma[only_bind_into](param), _, cc, innerCc, summaryCtx, argAp, ap, - pragma[only_bind_into](apa), pragma[only_bind_into](config)) and - PrevStage::parameterMayFlowThrough(param, apa, config) - } - - // dedup before joining with `flowThroughOutOfCall` - pragma[nomagic] - private predicate fwdFlowInMayFlowThroughProj( - DataFlowCall call, CcCall innerCc, ApApprox apa, Configuration config - ) { - fwdFlowInMayFlowThrough(call, _, innerCc, _, _, _, _, apa, config) - } - - /** - * Same as `flowThroughOutOfCall`, but restricted to calls that are reached - * in the flow covered by `fwdFlow`, where data might flow through the target - * callable and back out at `call`. - */ - pragma[nomagic] - private predicate fwdFlowThroughOutOfCall( - DataFlowCall call, CcCall ccc, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow, - ApApprox argApa, ApApprox apa, Configuration config - ) { - fwdFlowInMayFlowThroughProj(call, ccc, argApa, config) and - flowThroughOutOfCall(call, ccc, ret, out, allowsFieldFlow, argApa, apa, config) + fwdFlowRetFromArg(ret, state, ccc, innerSummaryCtx, innerArgAp, innerArgApa, ap, apa, config) and + fwdFlowIsEntered(call, cc, ccc, summaryCtx, argAp, innerSummaryCtx, innerArgAp, config) } pragma[nomagic] - private predicate fwdFlowOutFromArg( - DataFlowCall call, NodeEx out, FlowState state, ParameterPosition summaryCtx, Ap argAp, Ap ap, - ApApprox apa, Configuration config + private predicate fwdFlowThrough( + DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, + ApOption argAp, Ap ap, ApApprox apa, RetNodeEx ret, ApApprox innerArgApa, Configuration config ) { - exists(RetNodeEx ret, boolean allowsFieldFlow, CcCall ccc, ApApprox argApa | - fwdFlowRetFromArg(pragma[only_bind_into](ret), state, pragma[only_bind_into](ccc), - summaryCtx, _, argAp, pragma[only_bind_into](argApa), ap, pragma[only_bind_into](apa), - config) and - fwdFlowThroughOutOfCall(call, ccc, ret, out, allowsFieldFlow, argApa, apa, config) and - (if allowsFieldFlow = false then ap instanceof ApNil else any()) - ) + fwdFlowThrough0(call, cc, state, ccc, summaryCtx, argAp, ap, apa, ret, _, _, innerArgApa, + config) } /** @@ -1571,12 +1552,14 @@ private module MkStage { */ pragma[nomagic] private predicate fwdFlowIsEntered( - DataFlowCall call, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - ParameterPosition pos, Ap ap, Configuration config + DataFlowCall call, Cc cc, CcCall innerCc, ParamNodeOption summaryCtx, ApOption argAp, + ParamNodeEx p, Ap ap, Configuration config ) { - exists(ParamNodeEx param | - fwdFlowInMayFlowThrough(call, cc, _, summaryCtx, argAp, param, ap, _, config) and - pos = param.getPosition() + exists(ApApprox apa | + fwdFlowIn(call, pragma[only_bind_into](p), _, cc, innerCc, summaryCtx, argAp, ap, + pragma[only_bind_into](apa), pragma[only_bind_into](config)) and + PrevStage::parameterMayFlowThrough(p, apa, config) and + PrevStage::callMayFlowThroughRev(call, pragma[only_bind_into](config)) ) } @@ -1596,23 +1579,31 @@ private module MkStage { fwdFlowConsCand(ap1, c, ap2, config) } + pragma[nomagic] + private predicate returnFlowsThrough0( + DataFlowCall call, FlowState state, CcCall ccc, Ap ap, ApApprox apa, RetNodeEx ret, + ParamNodeEx innerSummaryCtx, Ap innerArgAp, ApApprox innerArgApa, Configuration config + ) { + fwdFlowThrough0(call, _, state, ccc, _, _, ap, apa, ret, innerSummaryCtx, innerArgAp, + innerArgApa, config) + } + pragma[nomagic] private predicate returnFlowsThrough( - RetNodeEx ret, ReturnKindExt kind, FlowState state, CcCall ccc, ParamNodeEx p, Ap argAp, + RetNodeEx ret, ReturnPosition pos, FlowState state, CcCall ccc, ParamNodeEx p, Ap argAp, Ap ap, Configuration config ) { - exists(boolean allowsFieldFlow, ApApprox argApa, ApApprox apa | - fwdFlowRetFromArg(pragma[only_bind_into](ret), state, pragma[only_bind_into](ccc), _, p, - argAp, pragma[only_bind_into](argApa), ap, pragma[only_bind_into](apa), config) and - kind = ret.getKind() and - fwdFlowThroughOutOfCall(_, ccc, ret, _, allowsFieldFlow, argApa, apa, config) and - (if allowsFieldFlow = false then ap instanceof ApNil else any()) + exists(DataFlowCall call, ApApprox apa, boolean allowsFieldFlow, ApApprox innerArgApa | + returnFlowsThrough0(call, state, ccc, ap, apa, ret, p, argAp, innerArgApa, config) and + flowThroughOutOfCall(call, ccc, ret, _, allowsFieldFlow, innerArgApa, apa, config) and + pos = ret.getReturnPosition() and + if allowsFieldFlow = false then ap instanceof ApNil else any() ) } pragma[nomagic] private predicate flowThroughIntoCall( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap argAp, + DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap argAp, Ap ap, Configuration config ) { exists(ApApprox argApa | @@ -1620,7 +1611,7 @@ private module MkStage { allowsFieldFlow, argApa, pragma[only_bind_into](config)) and fwdFlow(arg, _, _, _, _, pragma[only_bind_into](argAp), argApa, pragma[only_bind_into](config)) and - returnFlowsThrough(_, _, _, _, p, pragma[only_bind_into](argAp), _, + returnFlowsThrough(_, _, _, _, p, pragma[only_bind_into](argAp), ap, pragma[only_bind_into](config)) and if allowsFieldFlow = false then argAp instanceof ApNil else any() ) @@ -1639,12 +1630,13 @@ private module MkStage { pragma[nomagic] private predicate flowOutOfCallAp( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, boolean allowsFieldFlow, + DataFlowCall call, RetNodeEx ret, ReturnPosition pos, NodeEx out, boolean allowsFieldFlow, Ap ap, Configuration config ) { exists(ApApprox apa | - flowOutOfCallApa(call, ret, kind, out, allowsFieldFlow, apa, config) and - fwdFlow(ret, _, _, _, _, ap, apa, config) + flowOutOfCallApa(call, ret, _, out, allowsFieldFlow, apa, config) and + fwdFlow(ret, _, _, _, _, ap, apa, config) and + pos = ret.getReturnPosition() ) } @@ -1739,17 +1731,17 @@ private module MkStage { ) or // flow through a callable - exists(DataFlowCall call, ReturnKindExt returnKind0, Ap returnAp0 | - revFlowInToReturn(call, node, state, returnKind0, returnAp0, ap, config) and - revFlowIsReturned(call, returnCtx, returnAp, returnKind0, returnAp0, config) + exists(DataFlowCall call, ParamNodeEx p, ReturnPosition pos, Ap innerReturnAp | + revFlowThrough(call, returnCtx, p, state, pos, returnAp, ap, innerReturnAp, config) and + flowThroughIntoCall(call, node, p, _, ap, innerReturnAp, config) ) or // flow out of a callable - exists(ReturnKindExt kind | - revFlowOut(_, node, kind, state, _, _, ap, config) and - if returnFlowsThrough(node, kind, state, _, _, _, ap, config) + exists(ReturnPosition pos | + revFlowOut(_, node, pos, state, _, _, ap, config) and + if returnFlowsThrough(node, pos, state, _, _, _, ap, config) then ( - returnCtx = TReturnCtxMaybeFlowThrough(kind) and + returnCtx = TReturnCtxMaybeFlowThrough(pos) and returnAp = apSome(ap) ) else ( returnCtx = TReturnCtxNoFlowThrough() and returnAp = apNone() @@ -1782,47 +1774,33 @@ private module MkStage { pragma[nomagic] private predicate revFlowOut( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, FlowState state, ReturnCtx returnCtx, + DataFlowCall call, RetNodeEx ret, ReturnPosition pos, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap, Configuration config ) { exists(NodeEx out, boolean allowsFieldFlow | revFlow(out, state, returnCtx, returnAp, ap, config) and - flowOutOfCallAp(call, ret, kind, out, allowsFieldFlow, ap, config) and + flowOutOfCallAp(call, ret, pos, out, allowsFieldFlow, ap, config) and if allowsFieldFlow = false then ap instanceof ApNil else any() ) } - /** - * Same as `flowThroughIntoCall`, but restricted to calls that are reached - * in the flow covered by `revFlow`, where data might flow through the target - * callable and back out at `call`. - */ - pragma[nomagic] - private predicate revFlowThroughIntoCall( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap argAp, - Configuration config - ) { - flowThroughIntoCall(call, arg, p, allowsFieldFlow, argAp, config) and - revFlowIsReturned(call, _, _, _, _, config) - } - pragma[nomagic] private predicate revFlowParamToReturn( - ParamNodeEx p, FlowState state, ReturnKindExt kind, Ap returnAp, Ap ap, Configuration config + ParamNodeEx p, FlowState state, ReturnPosition pos, Ap returnAp, Ap ap, Configuration config ) { - revFlow(p, state, TReturnCtxMaybeFlowThrough(kind), apSome(returnAp), ap, config) and - parameterFlowThroughAllowed(p, kind) + revFlow(pragma[only_bind_into](p), state, TReturnCtxMaybeFlowThrough(pos), apSome(returnAp), + pragma[only_bind_into](ap), pragma[only_bind_into](config)) and + parameterFlowThroughAllowed(p, pos.getKind()) and + PrevStage::parameterMayFlowThrough(p, getApprox(ap), config) } pragma[nomagic] - private predicate revFlowInToReturn( - DataFlowCall call, ArgNodeEx arg, FlowState state, ReturnKindExt kind, Ap returnAp, Ap ap, - Configuration config + private predicate revFlowThrough( + DataFlowCall call, ReturnCtx returnCtx, ParamNodeEx p, FlowState state, ReturnPosition pos, + ApOption returnAp, Ap ap, Ap innerReturnAp, Configuration config ) { - exists(ParamNodeEx p, boolean allowsFieldFlow | - revFlowParamToReturn(p, state, kind, returnAp, ap, config) and - revFlowThroughIntoCall(call, arg, p, allowsFieldFlow, ap, config) - ) + revFlowParamToReturn(p, state, pos, innerReturnAp, ap, config) and + revFlowIsReturned(call, returnCtx, returnAp, pos, innerReturnAp, config) } /** @@ -1832,12 +1810,12 @@ private module MkStage { */ pragma[nomagic] private predicate revFlowIsReturned( - DataFlowCall call, ReturnCtx returnCtx, ApOption returnAp, ReturnKindExt kind, Ap ap, + DataFlowCall call, ReturnCtx returnCtx, ApOption returnAp, ReturnPosition pos, Ap ap, Configuration config ) { exists(RetNodeEx ret, FlowState state, CcCall ccc | - revFlowOut(call, ret, kind, state, returnCtx, returnAp, ap, config) and - returnFlowsThrough(ret, kind, state, ccc, _, _, ap, config) and + revFlowOut(call, ret, pos, state, returnCtx, returnAp, ap, config) and + returnFlowsThrough(ret, pos, state, ccc, _, _, ap, config) and matchesCall(ccc, call) ) } @@ -1915,17 +1893,17 @@ private module MkStage { pragma[nomagic] private predicate parameterFlowsThroughRev( - ParamNodeEx p, Ap ap, ReturnKindExt kind, Ap returnAp, Configuration config + ParamNodeEx p, Ap ap, ReturnPosition pos, Ap returnAp, Configuration config ) { - revFlow(p, _, TReturnCtxMaybeFlowThrough(kind), apSome(returnAp), ap, config) and - parameterFlowThroughAllowed(p, kind) + revFlow(p, _, TReturnCtxMaybeFlowThrough(pos), apSome(returnAp), ap, config) and + parameterFlowThroughAllowed(p, pos.getKind()) } pragma[nomagic] predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap, Configuration config) { - exists(RetNodeEx ret, ReturnKindExt kind | - returnFlowsThrough(ret, kind, _, _, p, ap, _, config) and - parameterFlowsThroughRev(p, ap, kind, _, config) + exists(RetNodeEx ret, ReturnPosition pos | + returnFlowsThrough(ret, pos, _, _, p, ap, _, config) and + parameterFlowsThroughRev(p, ap, pos, _, config) ) } @@ -1933,20 +1911,21 @@ private module MkStage { predicate returnMayFlowThrough( RetNodeEx ret, Ap argAp, Ap ap, ReturnKindExt kind, Configuration config ) { - exists(ParamNodeEx p | - returnFlowsThrough(ret, kind, _, _, p, argAp, ap, config) and - parameterFlowsThroughRev(p, argAp, kind, ap, config) + exists(ParamNodeEx p, ReturnPosition pos | + returnFlowsThrough(ret, pos, _, _, p, argAp, ap, config) and + parameterFlowsThroughRev(p, argAp, pos, ap, config) and + kind = pos.getKind() ) } pragma[nomagic] - predicate revFlowInToReturnIsReturned( + private predicate revFlowThroughArg( DataFlowCall call, ArgNodeEx arg, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap, Configuration config ) { - exists(ReturnKindExt returnKind0, Ap returnAp0 | - revFlowInToReturn(call, arg, state, returnKind0, returnAp0, ap, config) and - revFlowIsReturned(call, returnCtx, returnAp, returnKind0, returnAp0, config) + exists(ParamNodeEx p, ReturnPosition pos, Ap innerReturnAp | + revFlowThrough(call, returnCtx, p, state, pos, returnAp, ap, innerReturnAp, config) and + flowThroughIntoCall(call, arg, p, _, ap, innerReturnAp, config) ) } @@ -1954,7 +1933,7 @@ private module MkStage { predicate callMayFlowThroughRev(DataFlowCall call, Configuration config) { exists(ArgNodeEx arg, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap | revFlow(arg, state, returnCtx, returnAp, ap, config) and - revFlowInToReturnIsReturned(call, arg, state, returnCtx, returnAp, ap, config) + revFlowThroughArg(call, arg, state, returnCtx, returnAp, ap, config) ) } @@ -1967,8 +1946,9 @@ private module MkStage { conscand = count(TypedContent f0, Ap ap | fwdConsCand(f0, ap, config)) and states = count(FlowState state | fwdFlow(_, state, _, _, _, _, config)) and tuples = - count(NodeEx n, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - Ap ap | fwdFlow(n, state, cc, summaryCtx, argAp, ap, config)) + count(NodeEx n, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap | + fwdFlow(n, state, cc, summaryCtx, argAp, ap, config) + ) or fwd = false and nodes = count(NodeEx node | revFlow(node, _, _, _, _, config)) and @@ -2823,13 +2803,12 @@ private Configuration unbindConf(Configuration conf) { pragma[nomagic] private predicate nodeMayUseSummary0( - NodeEx n, DataFlowCallable c, ParameterPosition pos, FlowState state, AccessPathApprox apa, - Configuration config + NodeEx n, ParamNodeEx p, FlowState state, AccessPathApprox apa, Configuration config ) { exists(AccessPathApprox apa0 | - c = n.getEnclosingCallable() and + Stage5::parameterMayFlowThrough(p, _, _) and Stage5::revFlow(n, state, TReturnCtxMaybeFlowThrough(_), _, apa0, config) and - Stage5::fwdFlow(n, state, any(CallContextCall ccc), TParameterPositionSome(pos), + Stage5::fwdFlow(n, state, any(CallContextCall ccc), TParamNodeSome(p.asNode()), TAccessPathApproxSome(apa), apa0, config) ) } @@ -2838,10 +2817,9 @@ pragma[nomagic] private predicate nodeMayUseSummary( NodeEx n, FlowState state, AccessPathApprox apa, Configuration config ) { - exists(DataFlowCallable c, ParameterPosition pos, ParamNodeEx p | + exists(ParamNodeEx p | Stage5::parameterMayFlowThrough(p, apa, config) and - nodeMayUseSummary0(n, c, pos, state, apa, config) and - p.isParameterOf(c, pos) + nodeMayUseSummary0(n, p, state, apa, config) ) } diff --git a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl4.qll b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl4.qll index 6741ccc2f06..1228d00b6ba 100644 --- a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl4.qll +++ b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl4.qll @@ -622,7 +622,11 @@ private predicate parameterFlowThroughAllowed(ParamNodeEx p, ReturnKindExt kind) } private module Stage1 implements StageSig { - class Ap = Unit; + class Ap extends int { + // workaround for bad functionality-induced joins (happens when using `Unit`) + pragma[nomagic] + Ap() { this in [0 .. 1] and this < 1 } + } private class Cc = boolean; @@ -1327,8 +1331,8 @@ private module MkStage { */ pragma[nomagic] additional predicate fwdFlow( - NodeEx node, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - Ap ap, ApApprox apa, Configuration config + NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, + ApApprox apa, Configuration config ) { fwdFlow0(node, state, cc, summaryCtx, argAp, ap, apa, config) and PrevStage::revFlow(node, state, apa, config) and @@ -1337,21 +1341,21 @@ private module MkStage { pragma[inline] additional predicate fwdFlow( - NodeEx node, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - Ap ap, Configuration config + NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, + Configuration config ) { fwdFlow(node, state, cc, summaryCtx, argAp, ap, _, config) } pragma[nomagic] private predicate fwdFlow0( - NodeEx node, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - Ap ap, ApApprox apa, Configuration config + NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, + ApApprox apa, Configuration config ) { sourceNode(node, state, config) and (if hasSourceCallCtx(config) then cc = ccSomeCall() else cc = ccNone()) and argAp = apNone() and - summaryCtx = TParameterPositionNone() and + summaryCtx = TParamNodeNone() and ap = getApNil(node) and apa = getApprox(ap) or @@ -1372,7 +1376,7 @@ private module MkStage { fwdFlow(mid, pragma[only_bind_into](state), _, _, _, ap, apa, pragma[only_bind_into](config)) and jumpStep(mid, node, config) and cc = ccNone() and - summaryCtx = TParameterPositionNone() and + summaryCtx = TParamNodeNone() and argAp = apNone() ) or @@ -1380,7 +1384,7 @@ private module MkStage { fwdFlow(mid, state, _, _, _, nil, pragma[only_bind_into](config)) and additionalJumpStep(mid, node, config) and cc = ccNone() and - summaryCtx = TParameterPositionNone() and + summaryCtx = TParamNodeNone() and argAp = apNone() and ap = getApNil(node) and apa = getApprox(ap) @@ -1390,7 +1394,7 @@ private module MkStage { fwdFlow(mid, state0, _, _, _, nil, pragma[only_bind_into](config)) and additionalJumpStateStep(mid, state0, node, state, config) and cc = ccNone() and - summaryCtx = TParameterPositionNone() and + summaryCtx = TParamNodeNone() and argAp = apNone() and ap = getApNil(node) and apa = getApprox(ap) @@ -1414,10 +1418,10 @@ private module MkStage { fwdFlowIn(_, node, state, _, cc, _, _, ap, apa, config) and if PrevStage::parameterMayFlowThrough(node, apa, config) then ( - summaryCtx = TParameterPositionSome(node.(ParamNodeEx).getPosition()) and + summaryCtx = TParamNodeSome(node.asNode()) and argAp = apSome(ap) ) else ( - summaryCtx = TParameterPositionNone() and argAp = apNone() + summaryCtx = TParamNodeNone() and argAp = apNone() ) or // flow out of a callable @@ -1433,16 +1437,19 @@ private module MkStage { ) or // flow through a callable - exists(DataFlowCall call, ParameterPosition summaryCtx0, Ap argAp0 | - fwdFlowOutFromArg(call, node, state, summaryCtx0, argAp0, ap, apa, config) and - fwdFlowIsEntered(call, cc, summaryCtx, argAp, summaryCtx0, argAp0, config) + exists( + DataFlowCall call, CcCall ccc, RetNodeEx ret, boolean allowsFieldFlow, ApApprox innerArgApa + | + fwdFlowThrough(call, cc, state, ccc, summaryCtx, argAp, ap, apa, ret, innerArgApa, config) and + flowThroughOutOfCall(call, ccc, ret, node, allowsFieldFlow, innerArgApa, apa, config) and + if allowsFieldFlow = false then ap instanceof ApNil else any() ) } pragma[nomagic] private predicate fwdFlowStore( NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, FlowState state, Cc cc, - ParameterPositionOption summaryCtx, ApOption argAp, Configuration config + ParamNodeOption summaryCtx, ApOption argAp, Configuration config ) { exists(DataFlowType contentType, ApApprox apa1 | fwdFlow(node1, state, cc, summaryCtx, argAp, ap1, apa1, config) and @@ -1473,8 +1480,8 @@ private module MkStage { pragma[nomagic] private predicate fwdFlowRead0( - NodeEx node1, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - ApNonNil ap, Configuration config + NodeEx node1, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, ApNonNil ap, + Configuration config ) { fwdFlow(node1, state, cc, summaryCtx, argAp, ap, config) and PrevStage::readStepCand(node1, _, _, config) @@ -1483,7 +1490,7 @@ private module MkStage { pragma[nomagic] private predicate fwdFlowRead( Ap ap, Content c, NodeEx node1, NodeEx node2, FlowState state, Cc cc, - ParameterPositionOption summaryCtx, ApOption argAp, Configuration config + ParamNodeOption summaryCtx, ApOption argAp, Configuration config ) { fwdFlowRead0(node1, state, cc, summaryCtx, argAp, ap, config) and PrevStage::readStepCand(node1, c, node2, config) and @@ -1493,7 +1500,7 @@ private module MkStage { pragma[nomagic] private predicate fwdFlowIn( DataFlowCall call, ParamNodeEx p, FlowState state, Cc outercc, CcCall innercc, - ParameterPositionOption summaryCtx, ApOption argAp, Ap ap, ApApprox apa, Configuration config + ParamNodeOption summaryCtx, ApOption argAp, Ap ap, ApApprox apa, Configuration config ) { exists(ArgNodeEx arg, boolean allowsFieldFlow | fwdFlow(arg, state, outercc, summaryCtx, argAp, ap, apa, config) and @@ -1505,64 +1512,38 @@ private module MkStage { pragma[nomagic] private predicate fwdFlowRetFromArg( - RetNodeEx ret, FlowState state, CcCall ccc, ParameterPosition summaryCtx, ParamNodeEx p, - Ap argAp, ApApprox argApa, Ap ap, ApApprox apa, Configuration config + RetNodeEx ret, FlowState state, CcCall ccc, ParamNodeEx summaryCtx, Ap argAp, ApApprox argApa, + Ap ap, ApApprox apa, Configuration config ) { - exists(DataFlowCallable c, ReturnKindExt kind | + exists(ReturnKindExt kind | fwdFlow(pragma[only_bind_into](ret), state, ccc, - TParameterPositionSome(pragma[only_bind_into](summaryCtx)), apSome(argAp), ap, apa, config) and - getApprox(argAp) = argApa and - c = ret.getEnclosingCallable() and + TParamNodeSome(pragma[only_bind_into](summaryCtx.asNode())), + pragma[only_bind_into](apSome(argAp)), ap, pragma[only_bind_into](apa), + pragma[only_bind_into](config)) and kind = ret.getKind() and - p.isParameterOf(c, pragma[only_bind_into](summaryCtx)) and - parameterFlowThroughAllowed(p, kind) + parameterFlowThroughAllowed(summaryCtx, kind) and + argApa = getApprox(argAp) and + PrevStage::returnMayFlowThrough(ret, argApa, apa, kind, pragma[only_bind_into](config)) ) } pragma[inline] - private predicate fwdFlowInMayFlowThrough( - DataFlowCall call, Cc cc, CcCall innerCc, ParameterPositionOption summaryCtx, ApOption argAp, - ParamNodeEx param, Ap ap, ApApprox apa, Configuration config + private predicate fwdFlowThrough0( + DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, + ApOption argAp, Ap ap, ApApprox apa, RetNodeEx ret, ParamNodeEx innerSummaryCtx, + Ap innerArgAp, ApApprox innerArgApa, Configuration config ) { - fwdFlowIn(call, pragma[only_bind_into](param), _, cc, innerCc, summaryCtx, argAp, ap, - pragma[only_bind_into](apa), pragma[only_bind_into](config)) and - PrevStage::parameterMayFlowThrough(param, apa, config) - } - - // dedup before joining with `flowThroughOutOfCall` - pragma[nomagic] - private predicate fwdFlowInMayFlowThroughProj( - DataFlowCall call, CcCall innerCc, ApApprox apa, Configuration config - ) { - fwdFlowInMayFlowThrough(call, _, innerCc, _, _, _, _, apa, config) - } - - /** - * Same as `flowThroughOutOfCall`, but restricted to calls that are reached - * in the flow covered by `fwdFlow`, where data might flow through the target - * callable and back out at `call`. - */ - pragma[nomagic] - private predicate fwdFlowThroughOutOfCall( - DataFlowCall call, CcCall ccc, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow, - ApApprox argApa, ApApprox apa, Configuration config - ) { - fwdFlowInMayFlowThroughProj(call, ccc, argApa, config) and - flowThroughOutOfCall(call, ccc, ret, out, allowsFieldFlow, argApa, apa, config) + fwdFlowRetFromArg(ret, state, ccc, innerSummaryCtx, innerArgAp, innerArgApa, ap, apa, config) and + fwdFlowIsEntered(call, cc, ccc, summaryCtx, argAp, innerSummaryCtx, innerArgAp, config) } pragma[nomagic] - private predicate fwdFlowOutFromArg( - DataFlowCall call, NodeEx out, FlowState state, ParameterPosition summaryCtx, Ap argAp, Ap ap, - ApApprox apa, Configuration config + private predicate fwdFlowThrough( + DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, + ApOption argAp, Ap ap, ApApprox apa, RetNodeEx ret, ApApprox innerArgApa, Configuration config ) { - exists(RetNodeEx ret, boolean allowsFieldFlow, CcCall ccc, ApApprox argApa | - fwdFlowRetFromArg(pragma[only_bind_into](ret), state, pragma[only_bind_into](ccc), - summaryCtx, _, argAp, pragma[only_bind_into](argApa), ap, pragma[only_bind_into](apa), - config) and - fwdFlowThroughOutOfCall(call, ccc, ret, out, allowsFieldFlow, argApa, apa, config) and - (if allowsFieldFlow = false then ap instanceof ApNil else any()) - ) + fwdFlowThrough0(call, cc, state, ccc, summaryCtx, argAp, ap, apa, ret, _, _, innerArgApa, + config) } /** @@ -1571,12 +1552,14 @@ private module MkStage { */ pragma[nomagic] private predicate fwdFlowIsEntered( - DataFlowCall call, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - ParameterPosition pos, Ap ap, Configuration config + DataFlowCall call, Cc cc, CcCall innerCc, ParamNodeOption summaryCtx, ApOption argAp, + ParamNodeEx p, Ap ap, Configuration config ) { - exists(ParamNodeEx param | - fwdFlowInMayFlowThrough(call, cc, _, summaryCtx, argAp, param, ap, _, config) and - pos = param.getPosition() + exists(ApApprox apa | + fwdFlowIn(call, pragma[only_bind_into](p), _, cc, innerCc, summaryCtx, argAp, ap, + pragma[only_bind_into](apa), pragma[only_bind_into](config)) and + PrevStage::parameterMayFlowThrough(p, apa, config) and + PrevStage::callMayFlowThroughRev(call, pragma[only_bind_into](config)) ) } @@ -1596,23 +1579,31 @@ private module MkStage { fwdFlowConsCand(ap1, c, ap2, config) } + pragma[nomagic] + private predicate returnFlowsThrough0( + DataFlowCall call, FlowState state, CcCall ccc, Ap ap, ApApprox apa, RetNodeEx ret, + ParamNodeEx innerSummaryCtx, Ap innerArgAp, ApApprox innerArgApa, Configuration config + ) { + fwdFlowThrough0(call, _, state, ccc, _, _, ap, apa, ret, innerSummaryCtx, innerArgAp, + innerArgApa, config) + } + pragma[nomagic] private predicate returnFlowsThrough( - RetNodeEx ret, ReturnKindExt kind, FlowState state, CcCall ccc, ParamNodeEx p, Ap argAp, + RetNodeEx ret, ReturnPosition pos, FlowState state, CcCall ccc, ParamNodeEx p, Ap argAp, Ap ap, Configuration config ) { - exists(boolean allowsFieldFlow, ApApprox argApa, ApApprox apa | - fwdFlowRetFromArg(pragma[only_bind_into](ret), state, pragma[only_bind_into](ccc), _, p, - argAp, pragma[only_bind_into](argApa), ap, pragma[only_bind_into](apa), config) and - kind = ret.getKind() and - fwdFlowThroughOutOfCall(_, ccc, ret, _, allowsFieldFlow, argApa, apa, config) and - (if allowsFieldFlow = false then ap instanceof ApNil else any()) + exists(DataFlowCall call, ApApprox apa, boolean allowsFieldFlow, ApApprox innerArgApa | + returnFlowsThrough0(call, state, ccc, ap, apa, ret, p, argAp, innerArgApa, config) and + flowThroughOutOfCall(call, ccc, ret, _, allowsFieldFlow, innerArgApa, apa, config) and + pos = ret.getReturnPosition() and + if allowsFieldFlow = false then ap instanceof ApNil else any() ) } pragma[nomagic] private predicate flowThroughIntoCall( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap argAp, + DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap argAp, Ap ap, Configuration config ) { exists(ApApprox argApa | @@ -1620,7 +1611,7 @@ private module MkStage { allowsFieldFlow, argApa, pragma[only_bind_into](config)) and fwdFlow(arg, _, _, _, _, pragma[only_bind_into](argAp), argApa, pragma[only_bind_into](config)) and - returnFlowsThrough(_, _, _, _, p, pragma[only_bind_into](argAp), _, + returnFlowsThrough(_, _, _, _, p, pragma[only_bind_into](argAp), ap, pragma[only_bind_into](config)) and if allowsFieldFlow = false then argAp instanceof ApNil else any() ) @@ -1639,12 +1630,13 @@ private module MkStage { pragma[nomagic] private predicate flowOutOfCallAp( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, boolean allowsFieldFlow, + DataFlowCall call, RetNodeEx ret, ReturnPosition pos, NodeEx out, boolean allowsFieldFlow, Ap ap, Configuration config ) { exists(ApApprox apa | - flowOutOfCallApa(call, ret, kind, out, allowsFieldFlow, apa, config) and - fwdFlow(ret, _, _, _, _, ap, apa, config) + flowOutOfCallApa(call, ret, _, out, allowsFieldFlow, apa, config) and + fwdFlow(ret, _, _, _, _, ap, apa, config) and + pos = ret.getReturnPosition() ) } @@ -1739,17 +1731,17 @@ private module MkStage { ) or // flow through a callable - exists(DataFlowCall call, ReturnKindExt returnKind0, Ap returnAp0 | - revFlowInToReturn(call, node, state, returnKind0, returnAp0, ap, config) and - revFlowIsReturned(call, returnCtx, returnAp, returnKind0, returnAp0, config) + exists(DataFlowCall call, ParamNodeEx p, ReturnPosition pos, Ap innerReturnAp | + revFlowThrough(call, returnCtx, p, state, pos, returnAp, ap, innerReturnAp, config) and + flowThroughIntoCall(call, node, p, _, ap, innerReturnAp, config) ) or // flow out of a callable - exists(ReturnKindExt kind | - revFlowOut(_, node, kind, state, _, _, ap, config) and - if returnFlowsThrough(node, kind, state, _, _, _, ap, config) + exists(ReturnPosition pos | + revFlowOut(_, node, pos, state, _, _, ap, config) and + if returnFlowsThrough(node, pos, state, _, _, _, ap, config) then ( - returnCtx = TReturnCtxMaybeFlowThrough(kind) and + returnCtx = TReturnCtxMaybeFlowThrough(pos) and returnAp = apSome(ap) ) else ( returnCtx = TReturnCtxNoFlowThrough() and returnAp = apNone() @@ -1782,47 +1774,33 @@ private module MkStage { pragma[nomagic] private predicate revFlowOut( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, FlowState state, ReturnCtx returnCtx, + DataFlowCall call, RetNodeEx ret, ReturnPosition pos, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap, Configuration config ) { exists(NodeEx out, boolean allowsFieldFlow | revFlow(out, state, returnCtx, returnAp, ap, config) and - flowOutOfCallAp(call, ret, kind, out, allowsFieldFlow, ap, config) and + flowOutOfCallAp(call, ret, pos, out, allowsFieldFlow, ap, config) and if allowsFieldFlow = false then ap instanceof ApNil else any() ) } - /** - * Same as `flowThroughIntoCall`, but restricted to calls that are reached - * in the flow covered by `revFlow`, where data might flow through the target - * callable and back out at `call`. - */ - pragma[nomagic] - private predicate revFlowThroughIntoCall( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap argAp, - Configuration config - ) { - flowThroughIntoCall(call, arg, p, allowsFieldFlow, argAp, config) and - revFlowIsReturned(call, _, _, _, _, config) - } - pragma[nomagic] private predicate revFlowParamToReturn( - ParamNodeEx p, FlowState state, ReturnKindExt kind, Ap returnAp, Ap ap, Configuration config + ParamNodeEx p, FlowState state, ReturnPosition pos, Ap returnAp, Ap ap, Configuration config ) { - revFlow(p, state, TReturnCtxMaybeFlowThrough(kind), apSome(returnAp), ap, config) and - parameterFlowThroughAllowed(p, kind) + revFlow(pragma[only_bind_into](p), state, TReturnCtxMaybeFlowThrough(pos), apSome(returnAp), + pragma[only_bind_into](ap), pragma[only_bind_into](config)) and + parameterFlowThroughAllowed(p, pos.getKind()) and + PrevStage::parameterMayFlowThrough(p, getApprox(ap), config) } pragma[nomagic] - private predicate revFlowInToReturn( - DataFlowCall call, ArgNodeEx arg, FlowState state, ReturnKindExt kind, Ap returnAp, Ap ap, - Configuration config + private predicate revFlowThrough( + DataFlowCall call, ReturnCtx returnCtx, ParamNodeEx p, FlowState state, ReturnPosition pos, + ApOption returnAp, Ap ap, Ap innerReturnAp, Configuration config ) { - exists(ParamNodeEx p, boolean allowsFieldFlow | - revFlowParamToReturn(p, state, kind, returnAp, ap, config) and - revFlowThroughIntoCall(call, arg, p, allowsFieldFlow, ap, config) - ) + revFlowParamToReturn(p, state, pos, innerReturnAp, ap, config) and + revFlowIsReturned(call, returnCtx, returnAp, pos, innerReturnAp, config) } /** @@ -1832,12 +1810,12 @@ private module MkStage { */ pragma[nomagic] private predicate revFlowIsReturned( - DataFlowCall call, ReturnCtx returnCtx, ApOption returnAp, ReturnKindExt kind, Ap ap, + DataFlowCall call, ReturnCtx returnCtx, ApOption returnAp, ReturnPosition pos, Ap ap, Configuration config ) { exists(RetNodeEx ret, FlowState state, CcCall ccc | - revFlowOut(call, ret, kind, state, returnCtx, returnAp, ap, config) and - returnFlowsThrough(ret, kind, state, ccc, _, _, ap, config) and + revFlowOut(call, ret, pos, state, returnCtx, returnAp, ap, config) and + returnFlowsThrough(ret, pos, state, ccc, _, _, ap, config) and matchesCall(ccc, call) ) } @@ -1915,17 +1893,17 @@ private module MkStage { pragma[nomagic] private predicate parameterFlowsThroughRev( - ParamNodeEx p, Ap ap, ReturnKindExt kind, Ap returnAp, Configuration config + ParamNodeEx p, Ap ap, ReturnPosition pos, Ap returnAp, Configuration config ) { - revFlow(p, _, TReturnCtxMaybeFlowThrough(kind), apSome(returnAp), ap, config) and - parameterFlowThroughAllowed(p, kind) + revFlow(p, _, TReturnCtxMaybeFlowThrough(pos), apSome(returnAp), ap, config) and + parameterFlowThroughAllowed(p, pos.getKind()) } pragma[nomagic] predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap, Configuration config) { - exists(RetNodeEx ret, ReturnKindExt kind | - returnFlowsThrough(ret, kind, _, _, p, ap, _, config) and - parameterFlowsThroughRev(p, ap, kind, _, config) + exists(RetNodeEx ret, ReturnPosition pos | + returnFlowsThrough(ret, pos, _, _, p, ap, _, config) and + parameterFlowsThroughRev(p, ap, pos, _, config) ) } @@ -1933,20 +1911,21 @@ private module MkStage { predicate returnMayFlowThrough( RetNodeEx ret, Ap argAp, Ap ap, ReturnKindExt kind, Configuration config ) { - exists(ParamNodeEx p | - returnFlowsThrough(ret, kind, _, _, p, argAp, ap, config) and - parameterFlowsThroughRev(p, argAp, kind, ap, config) + exists(ParamNodeEx p, ReturnPosition pos | + returnFlowsThrough(ret, pos, _, _, p, argAp, ap, config) and + parameterFlowsThroughRev(p, argAp, pos, ap, config) and + kind = pos.getKind() ) } pragma[nomagic] - predicate revFlowInToReturnIsReturned( + private predicate revFlowThroughArg( DataFlowCall call, ArgNodeEx arg, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap, Configuration config ) { - exists(ReturnKindExt returnKind0, Ap returnAp0 | - revFlowInToReturn(call, arg, state, returnKind0, returnAp0, ap, config) and - revFlowIsReturned(call, returnCtx, returnAp, returnKind0, returnAp0, config) + exists(ParamNodeEx p, ReturnPosition pos, Ap innerReturnAp | + revFlowThrough(call, returnCtx, p, state, pos, returnAp, ap, innerReturnAp, config) and + flowThroughIntoCall(call, arg, p, _, ap, innerReturnAp, config) ) } @@ -1954,7 +1933,7 @@ private module MkStage { predicate callMayFlowThroughRev(DataFlowCall call, Configuration config) { exists(ArgNodeEx arg, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap | revFlow(arg, state, returnCtx, returnAp, ap, config) and - revFlowInToReturnIsReturned(call, arg, state, returnCtx, returnAp, ap, config) + revFlowThroughArg(call, arg, state, returnCtx, returnAp, ap, config) ) } @@ -1967,8 +1946,9 @@ private module MkStage { conscand = count(TypedContent f0, Ap ap | fwdConsCand(f0, ap, config)) and states = count(FlowState state | fwdFlow(_, state, _, _, _, _, config)) and tuples = - count(NodeEx n, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - Ap ap | fwdFlow(n, state, cc, summaryCtx, argAp, ap, config)) + count(NodeEx n, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap | + fwdFlow(n, state, cc, summaryCtx, argAp, ap, config) + ) or fwd = false and nodes = count(NodeEx node | revFlow(node, _, _, _, _, config)) and @@ -2823,13 +2803,12 @@ private Configuration unbindConf(Configuration conf) { pragma[nomagic] private predicate nodeMayUseSummary0( - NodeEx n, DataFlowCallable c, ParameterPosition pos, FlowState state, AccessPathApprox apa, - Configuration config + NodeEx n, ParamNodeEx p, FlowState state, AccessPathApprox apa, Configuration config ) { exists(AccessPathApprox apa0 | - c = n.getEnclosingCallable() and + Stage5::parameterMayFlowThrough(p, _, _) and Stage5::revFlow(n, state, TReturnCtxMaybeFlowThrough(_), _, apa0, config) and - Stage5::fwdFlow(n, state, any(CallContextCall ccc), TParameterPositionSome(pos), + Stage5::fwdFlow(n, state, any(CallContextCall ccc), TParamNodeSome(p.asNode()), TAccessPathApproxSome(apa), apa0, config) ) } @@ -2838,10 +2817,9 @@ pragma[nomagic] private predicate nodeMayUseSummary( NodeEx n, FlowState state, AccessPathApprox apa, Configuration config ) { - exists(DataFlowCallable c, ParameterPosition pos, ParamNodeEx p | + exists(ParamNodeEx p | Stage5::parameterMayFlowThrough(p, apa, config) and - nodeMayUseSummary0(n, c, pos, state, apa, config) and - p.isParameterOf(c, pos) + nodeMayUseSummary0(n, p, state, apa, config) ) } diff --git a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImplCommon.qll b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImplCommon.qll index c66aefced8d..9aa6a529a5b 100644 --- a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImplCommon.qll +++ b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImplCommon.qll @@ -916,15 +916,15 @@ private module Cached { TDataFlowCallSome(DataFlowCall call) cached - newtype TParameterPositionOption = - TParameterPositionNone() or - TParameterPositionSome(ParameterPosition pos) + newtype TParamNodeOption = + TParamNodeNone() or + TParamNodeSome(ParamNode p) cached newtype TReturnCtx = TReturnCtxNone() or TReturnCtxNoFlowThrough() or - TReturnCtxMaybeFlowThrough(ReturnKindExt kind) + TReturnCtxMaybeFlowThrough(ReturnPosition pos) cached newtype TTypedContentApprox = @@ -1343,15 +1343,15 @@ class DataFlowCallOption extends TDataFlowCallOption { } } -/** An optional `ParameterPosition`. */ -class ParameterPositionOption extends TParameterPositionOption { +/** An optional `ParamNode`. */ +class ParamNodeOption extends TParamNodeOption { string toString() { - this = TParameterPositionNone() and + this = TParamNodeNone() and result = "(none)" or - exists(ParameterPosition pos | - this = TParameterPositionSome(pos) and - result = pos.toString() + exists(ParamNode p | + this = TParamNodeSome(p) and + result = p.toString() ) } } @@ -1363,7 +1363,7 @@ class ParameterPositionOption extends TParameterPositionOption { * * - `TReturnCtxNone()`: no return flow. * - `TReturnCtxNoFlowThrough()`: return flow, but flow through is not possible. - * - `TReturnCtxMaybeFlowThrough(ReturnKindExt kind)`: return flow, of kind `kind`, and + * - `TReturnCtxMaybeFlowThrough(ReturnPosition pos)`: return flow, of kind `pos`, and * flow through may be possible. */ class ReturnCtx extends TReturnCtx { @@ -1374,9 +1374,9 @@ class ReturnCtx extends TReturnCtx { this = TReturnCtxNoFlowThrough() and result = "(no flow through)" or - exists(ReturnKindExt kind | - this = TReturnCtxMaybeFlowThrough(kind) and - result = kind.toString() + exists(ReturnPosition pos | + this = TReturnCtxMaybeFlowThrough(pos) and + result = pos.toString() ) } } diff --git a/python/ql/lib/semmle/python/dataflow/new/internal/FlowSummaryImpl.qll b/python/ql/lib/semmle/python/dataflow/new/internal/FlowSummaryImpl.qll index 61c541d8882..b61142c33a7 100644 --- a/python/ql/lib/semmle/python/dataflow/new/internal/FlowSummaryImpl.qll +++ b/python/ql/lib/semmle/python/dataflow/new/internal/FlowSummaryImpl.qll @@ -241,9 +241,15 @@ module Public { } /** - * Holds if the summary is auto generated. + * Holds if the summary is auto generated and not manually generated. */ predicate isAutoGenerated() { none() } + + /** + * Holds if the summary has the given provenance where `true` is + * `generated` and `false` is `manual`. + */ + predicate hasProvenance(boolean generated) { none() } } /** A callable where there is no flow via the callable. */ @@ -1012,6 +1018,10 @@ module Private { } override predicate isAutoGenerated() { this.relevantSummaryElementGenerated(_, _, _) } + + override predicate hasProvenance(boolean generated) { + summaryElement(this, _, _, _, generated) + } } /** Holds if component `c` of specification `spec` cannot be parsed. */ diff --git a/ruby/ql/lib/change-notes/2022-11-30-rails-globalid.md b/ruby/ql/lib/change-notes/2022-11-30-rails-globalid.md new file mode 100644 index 00000000000..c3db54fcb9e --- /dev/null +++ b/ruby/ql/lib/change-notes/2022-11-30-rails-globalid.md @@ -0,0 +1,4 @@ +--- + category: minorAnalysis +--- + * Calls to `GlobalID::Locator.locate` and its variants are now recognized as instances of `OrmInstantiation`. diff --git a/ruby/ql/lib/change-notes/2022-12-14-constructor-flow.md b/ruby/ql/lib/change-notes/2022-12-14-constructor-flow.md new file mode 100644 index 00000000000..612c323010a --- /dev/null +++ b/ruby/ql/lib/change-notes/2022-12-14-constructor-flow.md @@ -0,0 +1,14 @@ +--- + category: majorAnalysis +--- + * Flow through `initialize` constructors is now taken into account. For example, in + ```rb +class C + def initialize(x) + @field = x + end +end + +C.new(y) +``` +there will be flow from `y` to the field `@field` on the constructed `C` object. \ No newline at end of file diff --git a/ruby/ql/lib/codeql/ruby/ast/Call.qll b/ruby/ql/lib/codeql/ruby/ast/Call.qll index 04ac15ededc..e97497ade52 100644 --- a/ruby/ql/lib/codeql/ruby/ast/Call.qll +++ b/ruby/ql/lib/codeql/ruby/ast/Call.qll @@ -53,9 +53,12 @@ class Call extends Expr instanceof CallImpl { /** Gets a potential target of this call, if any. */ final Callable getATarget() { - exists(DataFlowCall c | this = c.asCall().getExpr() | - TCfgScope(result) = [viableCallable(c), viableCallableLambda(c, _)] + exists(DataFlowCall c | + this = c.asCall().getExpr() and + TCfgScope(result) = viableCallableLambda(c, _) ) + or + result = getTarget(this.getAControlFlowNode()) } override AstNode getAChild(string pred) { diff --git a/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowDispatch.qll b/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowDispatch.qll index 7e9a5ef103e..c3197d42b8c 100644 --- a/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowDispatch.qll +++ b/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowDispatch.qll @@ -11,7 +11,8 @@ private import codeql.ruby.dataflow.SSA newtype TReturnKind = TNormalReturnKind() or - TBreakReturnKind() + TBreakReturnKind() or + TNewReturnKind() /** * Gets a node that can read the value returned from `call` with return kind @@ -43,6 +44,15 @@ class BreakReturnKind extends ReturnKind, TBreakReturnKind { override string toString() { result = "break" } } +/** + * A special return kind that is used to represent the value returned + * from user-defined `new` methods as well as the effect on `self` in + * `initialize` methods. + */ +class NewReturnKind extends ReturnKind, TNewReturnKind { + override string toString() { result = "new" } +} + /** A callable defined in library code, identified by a unique string. */ abstract class LibraryCallable extends string { bindingset[this] @@ -275,14 +285,33 @@ private predicate hasAdjacentTypeCheckedReads( ) } +/** Holds if `new` is a user-defined `self.new` method. */ +predicate isUserDefinedNew(SingletonMethod new) { + exists(Expr object | singletonMethod(new, "new", object) | + selfInModule(object.(SelfVariableReadAccess).getVariable(), _) + or + exists(resolveConstantReadAccess(object)) + ) +} + +private Callable viableSourceCallableNonInit(RelevantCall call) { + result = getTarget(call) and + not call.getExpr() instanceof YieldCall // handled by `lambdaCreation`/`lambdaCall` +} + +private Callable viableSourceCallableInit(RelevantCall call) { + result = getInitializeTarget(call) and + not isUserDefinedNew(getTarget(call)) +} + /** Holds if `call` may resolve to the returned source-code method. */ -private DataFlowCallable viableSourceCallable(DataFlowCall call) { - result = TCfgScope(getTarget(call.asCall())) and - not call.asCall().getExpr() instanceof YieldCall // handled by `lambdaCreation`/`lambdaCall` +private Callable viableSourceCallable(RelevantCall call) { + result = viableSourceCallableNonInit(call) or + result = viableSourceCallableInit(call) } /** Holds if `call` may resolve to the returned summarized library method. */ -private DataFlowCallable viableLibraryCallable(DataFlowCall call) { +DataFlowCallable viableLibraryCallable(DataFlowCall call) { exists(LibraryCallable callable | result = TLibraryCallable(callable) and call.asCall().getExpr() = [callable.getACall(), callable.getACallSimple()] @@ -340,126 +369,22 @@ private module Cached { FlowSummaryImpl::Private::summaryCallbackRange(c, receiver) } - pragma[nomagic] - private Method lookupInstanceMethodCall(RelevantCall call, string method, boolean exact) { - exists(Module tp, DataFlow::Node receiver | - methodCall(call, pragma[only_bind_into](receiver), pragma[only_bind_into](method)) and - receiver = trackInstance(tp, exact) and - result = lookupMethod(tp, pragma[only_bind_into](method), exact) - ) - } - - pragma[nomagic] - private predicate isToplevelMethodInFile(Method m, File f) { - m.getEnclosingModule() instanceof Toplevel and - f = m.getFile() - } - - /** Holds if a `self` access may be the receiver of `call` directly inside module `m`. */ - pragma[nomagic] - private predicate selfInModuleFlowsToMethodCallReceiver(RelevantCall call, Module m, string method) { - exists(SsaSelfDefinitionNode self | - flowsToMethodCallReceiver(call, self, method) and - selfInModule(self.getVariable(), m) - ) - } - /** - * Holds if a `self` access may be the receiver of `call` inside some singleton method, where - * that method belongs to `m` or one of `m`'s transitive super classes. + * Gets the relevant `initialize` method for the `new` call, if any. */ - pragma[nomagic] - private predicate selfInSingletonMethodFlowsToMethodCallReceiver( - RelevantCall call, Module m, string method - ) { - exists(SsaSelfDefinitionNode self, MethodBase caller | - flowsToMethodCallReceiver(call, self, method) and - selfInMethod(self.getVariable(), caller, m) and - singletonMethod(caller, _, _) + cached + Method getInitializeTarget(RelevantCall new) { + exists(Module m | + moduleFlowsToMethodCallReceiver(new, m, "new") and + result = lookupMethod(m, "initialize") ) } cached CfgScope getTarget(RelevantCall call) { - exists(string method | - exists(boolean exact | - result = lookupInstanceMethodCall(call, method, exact) and - ( - if result.(Method).isPrivate() - then - call.getReceiver().getExpr() instanceof SelfVariableAccess and - // For now, we restrict the scope of top-level declarations to their file. - // This may remove some plausible targets, but also removes a lot of - // implausible targets - ( - isToplevelMethodInFile(result, call.getFile()) or - not isToplevelMethodInFile(result, _) - ) - else any() - ) and - if result.(Method).isProtected() - then result = lookupMethod(call.getExpr().getEnclosingModule().getModule(), method, exact) - else any() - ) - or - // singleton method defined on an instance, e.g. - // ```rb - // c = C.new - // def c.singleton; end # <- result - // c.singleton # <- call - // ``` - // or an `extend`ed instance, e.g. - // ```rb - // c = C.new - // module M - // def instance; end # <- result - // end - // c.extend M - // c.instance # <- call - // ``` - exists(DataFlow::Node receiver | - methodCall(call, receiver, method) and - receiver = trackSingletonMethodOnInstance(result, method) - ) - or - // singleton method defined on a module - // or an `extend`ed module, e.g. - // ```rb - // module M - // def instance; end # <- result - // end - // M.extend(M) - // M.instance # <- call - // ``` - exists(Module m, boolean exact | result = lookupSingletonMethod(m, method, exact) | - // ```rb - // def C.singleton; end # <- result - // C.singleton # <- call - // ``` - moduleFlowsToMethodCallReceiver(call, m, method) and - exact = true - or - // ```rb - // class C - // def self.singleton; end # <- result - // self.singleton # <- call - // end - // ``` - selfInModuleFlowsToMethodCallReceiver(call, m, method) and - exact = true - or - // ```rb - // class C - // def self.singleton; end # <- result - // def self.other - // self.singleton # <- call - // end - // end - // ``` - selfInSingletonMethodFlowsToMethodCallReceiver(call, m, method) and - exact = false - ) - ) + result = getTargetInstance(call, _) + or + result = getTargetSingleton(call, _) or exists(Module cls, string method | superCall(call, cls, method) and @@ -472,7 +397,7 @@ private module Cached { /** Gets a viable run-time target for the call `call`. */ cached DataFlowCallable viableCallable(DataFlowCall call) { - result = viableSourceCallable(call) + result.asCallable() = viableSourceCallable(call.asCall()) or result = viableLibraryCallable(call) } @@ -547,6 +472,15 @@ private DataFlow::LocalSourceNode trackModuleAccess(Module m) { result = trackModuleAccess(m, TypeTracker::end()) } +pragma[nomagic] +private predicate hasUserDefinedNew(Module m) { + exists(DataFlow::MethodNode method | + // not `getAnAncestor` because singleton methods cannot be included + singletonMethodOnModule(method.asCallableAstNode(), "new", m.getSuperClass*()) and + not method.getSelfParameter().getAMethodCall("allocate").flowsTo(method.getAReturningNode()) + ) +} + /** Holds if `n` is an instance of type `tp`. */ private predicate isInstance(DataFlow::Node n, Module tp, boolean exact) { n.asExpr().getExpr() instanceof NilLiteral and @@ -603,7 +537,9 @@ private predicate isInstance(DataFlow::Node n, Module tp, boolean exact) { or exists(RelevantCall call, DataFlow::LocalSourceNode sourceNode | flowsToMethodCallReceiver(call, sourceNode, "new") and - n.asExpr() = call + n.asExpr() = call and + // `tp` should not have a user-defined `self.new` method + not hasUserDefinedNew(tp) | // `C.new` sourceNode = trackModuleAccess(tp) and @@ -702,6 +638,44 @@ private DataFlow::Node trackInstance(Module tp, boolean exact) { result = trackInstance(tp, exact, TypeTracker::end()) } +pragma[nomagic] +private Method lookupInstanceMethodCall(RelevantCall call, string method, boolean exact) { + exists(Module tp, DataFlow::Node receiver | + methodCall(call, pragma[only_bind_into](receiver), pragma[only_bind_into](method)) and + receiver = trackInstance(tp, exact) and + result = lookupMethod(tp, pragma[only_bind_into](method), exact) + ) +} + +pragma[nomagic] +private predicate isToplevelMethodInFile(Method m, File f) { + m.getEnclosingModule() instanceof Toplevel and + f = m.getFile() +} + +pragma[nomagic] +private CfgScope getTargetInstance(RelevantCall call, string method) { + exists(boolean exact | + result = lookupInstanceMethodCall(call, method, exact) and + ( + if result.(Method).isPrivate() + then + call.getReceiver().getExpr() instanceof SelfVariableAccess and + // For now, we restrict the scope of top-level declarations to their file. + // This may remove some plausible targets, but also removes a lot of + // implausible targets + ( + isToplevelMethodInFile(result, call.getFile()) or + not isToplevelMethodInFile(result, _) + ) + else any() + ) and + if result.(Method).isProtected() + then result = lookupMethod(call.getExpr().getEnclosingModule().getModule(), method, exact) + else any() + ) +} + pragma[nomagic] private DataFlow::LocalSourceNode trackBlock(Block block, TypeTracker t) { t.start() and result.asExpr().getExpr() = block @@ -813,7 +787,7 @@ private MethodBase lookupSingletonMethod(Module m, string name) { // cannot use `lookupSingletonMethodDirect` because it would introduce // negative recursion not singletonMethodOnModule(_, name, m) and - result = lookupSingletonMethod(m.getSuperClass(), name) + result = lookupSingletonMethod(m.getSuperClass(), name) // not `getAnImmediateAncestor` because singleton methods cannot be included } pragma[nomagic] @@ -824,7 +798,9 @@ private MethodBase lookupSingletonMethodInSubClasses(Module m, string name) { // being resolved to arbitrary singleton methods. // To remedy this, we do not allow following super-classes all the way to Object. not m = TResolved("Object") and - exists(Module sub | sub.getSuperClass() = m | + exists(Module sub | + sub.getSuperClass() = m // not `getAnImmediateAncestor` because singleton methods cannot be included + | result = lookupSingletonMethodDirect(sub, name) or result = lookupSingletonMethodInSubClasses(sub, name) ) @@ -972,6 +948,91 @@ private DataFlow::Node trackSingletonMethodOnInstance(MethodBase method, string result = trackSingletonMethodOnInstance(method, name, TypeTracker::end()) } +/** Holds if a `self` access may be the receiver of `call` directly inside module `m`. */ +pragma[nomagic] +private predicate selfInModuleFlowsToMethodCallReceiver(RelevantCall call, Module m, string method) { + exists(SsaSelfDefinitionNode self | + flowsToMethodCallReceiver(call, self, method) and + selfInModule(self.getVariable(), m) + ) +} + +/** + * Holds if a `self` access may be the receiver of `call` inside some singleton method, where + * that method belongs to `m` or one of `m`'s transitive super classes. + */ +pragma[nomagic] +private predicate selfInSingletonMethodFlowsToMethodCallReceiver( + RelevantCall call, Module m, string method +) { + exists(SsaSelfDefinitionNode self, MethodBase caller | + flowsToMethodCallReceiver(call, self, method) and + selfInMethod(self.getVariable(), caller, m) and + singletonMethod(caller, _, _) + ) +} + +pragma[nomagic] +private CfgScope getTargetSingleton(RelevantCall call, string method) { + // singleton method defined on an instance, e.g. + // ```rb + // c = C.new + // def c.singleton; end # <- result + // c.singleton # <- call + // ``` + // or an `extend`ed instance, e.g. + // ```rb + // c = C.new + // module M + // def instance; end # <- result + // end + // c.extend M + // c.instance # <- call + // ``` + exists(DataFlow::Node receiver | + methodCall(call, receiver, method) and + receiver = trackSingletonMethodOnInstance(result, method) + ) + or + // singleton method defined on a module + // or an `extend`ed module, e.g. + // ```rb + // module M + // def instance; end # <- result + // end + // M.extend(M) + // M.instance # <- call + // ``` + exists(Module m, boolean exact | result = lookupSingletonMethod(m, method, exact) | + // ```rb + // def C.singleton; end # <- result + // C.singleton # <- call + // ``` + moduleFlowsToMethodCallReceiver(call, m, method) and + exact = true + or + // ```rb + // class C + // def self.singleton; end # <- result + // self.singleton # <- call + // end + // ``` + selfInModuleFlowsToMethodCallReceiver(call, m, method) and + exact = true + or + // ```rb + // class C + // def self.singleton; end # <- result + // def self.other + // self.singleton # <- call + // end + // end + // ``` + selfInSingletonMethodFlowsToMethodCallReceiver(call, m, method) and + exact = false + ) +} + /** * Holds if `ctx` targets `encl`, which is the enclosing callable of `call`, the receiver * of `call` is a parameter access, where the corresponding argument of `ctx` is `arg`. @@ -982,25 +1043,54 @@ private DataFlow::Node trackSingletonMethodOnInstance(MethodBase method, string */ pragma[nomagic] private predicate argMustFlowToReceiver( - RelevantCall ctx, DataFlow::LocalSourceNode source, ArgumentNode arg, + RelevantCall ctx, DataFlow::LocalSourceNode source, DataFlow::Node arg, SsaDefinitionExtNode paramDef, RelevantCall call, Callable encl, string name ) { exists(ParameterNodeImpl p, ParameterPosition ppos, ArgumentPosition apos | // the receiver of `call` references `p` exists(DataFlow::Node receiver | LocalFlow::localFlowSsaParamInput(p, paramDef) and - methodCall(pragma[only_bind_into](call), receiver, pragma[only_bind_into](name)) and + methodCall(pragma[only_bind_into](call), pragma[only_bind_into](receiver), + pragma[only_bind_into](name)) and receiver.asExpr() = paramDef.getDefinitionExt().(Ssa::Definition).getARead() ) and // `p` is a parameter of `encl`, encl = call.getScope() and p.isParameterOf(TCfgScope(encl), ppos) and - // `ctx` targets `encl` - getTarget(ctx) = encl and // `arg` is the argument for `p` in the call `ctx` - arg.sourceArgumentOf(ctx, apos) and parameterMatch(ppos, apos) and source.flowsTo(arg) + | + encl = viableSourceCallableNonInit(ctx) and + arg.(ArgumentNode).sourceArgumentOf(ctx, apos) + or + encl = viableSourceCallableInit(ctx) and + if apos.isSelf() + then + // when we are targeting an initializer, the type of `self` inside the + // initializer will be the type of the `new` call itself, not the receiver + // of the `new` call + arg.asExpr() = ctx + else arg.(ArgumentNode).sourceArgumentOf(ctx, apos) + ) +} + +/** + * Holds if `ctx` targets `encl`, which is the enclosing callable of `new`, and + * the receiver of `new` is a parameter access, where the corresponding argument + * `arg` of `ctx` has type `tp`. + * + * `new` calls the object creation `new` method. + */ +pragma[nomagic] +private predicate mayBenefitFromCallContextInitialize( + RelevantCall ctx, RelevantCall new, DataFlow::Node arg, Callable encl, Module tp, string name +) { + exists(DataFlow::LocalSourceNode source | + argMustFlowToReceiver(ctx, pragma[only_bind_into](source), arg, _, new, encl, "new") and + source = trackModuleAccess(tp) and + name = "initialize" and + exists(lookupMethod(tp, name)) ) } @@ -1014,7 +1104,7 @@ private predicate argMustFlowToReceiver( */ pragma[nomagic] private predicate mayBenefitFromCallContextInstance( - RelevantCall ctx, RelevantCall call, ArgumentNode arg, Callable encl, Module tp, boolean exact, + RelevantCall ctx, RelevantCall call, DataFlow::Node arg, Callable encl, Module tp, boolean exact, string name ) { exists(DataFlow::LocalSourceNode source | @@ -1035,7 +1125,7 @@ private predicate mayBenefitFromCallContextInstance( */ pragma[nomagic] private predicate mayBenefitFromCallContextSingleton( - RelevantCall ctx, RelevantCall call, ArgumentNode arg, Callable encl, Module tp, boolean exact, + RelevantCall ctx, RelevantCall call, DataFlow::Node arg, Callable encl, Module tp, boolean exact, string name ) { exists(DataFlow::LocalSourceNode source | @@ -1066,6 +1156,8 @@ private predicate mayBenefitFromCallContextSingleton( * the implicit `self` parameter). */ predicate mayBenefitFromCallContext(DataFlowCall call, DataFlowCallable c) { + mayBenefitFromCallContextInitialize(_, call.asCall(), _, c.asCallable(), _, _) + or mayBenefitFromCallContextInstance(_, call.asCall(), _, c.asCallable(), _, _, _) or mayBenefitFromCallContextSingleton(_, call.asCall(), _, c.asCallable(), _, _, _) @@ -1083,30 +1175,39 @@ DataFlowCallable viableImplInCallContext(DataFlowCall call, DataFlowCall ctx) { exists(RelevantCall call0, Callable res | call0 = call.asCall() and res = result.asCallable() and - result = viableSourceCallable(call) and // make sure to not include e.g. private methods - exists(Module m, boolean exact, string name | - mayBenefitFromCallContextInstance(ctx.asCall(), pragma[only_bind_into](call0), _, _, - pragma[only_bind_into](m), exact, pragma[only_bind_into](name)) and - res = lookupMethod(m, name, exact) + exists(Module m, string name | + mayBenefitFromCallContextInitialize(ctx.asCall(), pragma[only_bind_into](call0), _, _, + pragma[only_bind_into](m), pragma[only_bind_into](name)) and + res = getInitializeTarget(call0) and + res = lookupMethod(m, name) or - mayBenefitFromCallContextSingleton(ctx.asCall(), pragma[only_bind_into](call0), _, _, - pragma[only_bind_into](m), exact, pragma[only_bind_into](name)) and - res = lookupSingletonMethod(m, name, exact) + exists(boolean exact | + mayBenefitFromCallContextInstance(ctx.asCall(), pragma[only_bind_into](call0), _, _, + pragma[only_bind_into](m), pragma[only_bind_into](exact), pragma[only_bind_into](name)) and + res = getTargetInstance(call0, name) and + res = lookupMethod(m, name, exact) + or + mayBenefitFromCallContextSingleton(ctx.asCall(), pragma[only_bind_into](call0), _, _, + pragma[only_bind_into](m), pragma[only_bind_into](exact), pragma[only_bind_into](name)) and + res = getTargetSingleton(call0, name) and + res = lookupSingletonMethod(m, name, exact) + ) ) ) or // `ctx` cannot provide a type bound, and the receiver of the call is `self`; // in this case, still apply an open-world assumption exists( - RelevantCall call0, RelevantCall ctx0, ArgumentNode arg, SsaSelfDefinitionNode self, + RelevantCall call0, RelevantCall ctx0, DataFlow::Node arg, SsaSelfDefinitionNode self, string name | call0 = call.asCall() and ctx0 = ctx.asCall() and argMustFlowToReceiver(ctx0, _, arg, self, call0, _, name) and + not mayBenefitFromCallContextInitialize(ctx0, call0, arg, _, _, _) and not mayBenefitFromCallContextInstance(ctx0, call0, arg, _, _, _, name) and not mayBenefitFromCallContextSingleton(ctx0, call0, arg, _, _, _, name) and - result = viableSourceCallable(call) + result.asCallable() = viableSourceCallable(call0) ) or // library calls should always be able to resolve diff --git a/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImpl.qll b/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImpl.qll index 6741ccc2f06..1228d00b6ba 100644 --- a/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImpl.qll +++ b/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImpl.qll @@ -622,7 +622,11 @@ private predicate parameterFlowThroughAllowed(ParamNodeEx p, ReturnKindExt kind) } private module Stage1 implements StageSig { - class Ap = Unit; + class Ap extends int { + // workaround for bad functionality-induced joins (happens when using `Unit`) + pragma[nomagic] + Ap() { this in [0 .. 1] and this < 1 } + } private class Cc = boolean; @@ -1327,8 +1331,8 @@ private module MkStage { */ pragma[nomagic] additional predicate fwdFlow( - NodeEx node, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - Ap ap, ApApprox apa, Configuration config + NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, + ApApprox apa, Configuration config ) { fwdFlow0(node, state, cc, summaryCtx, argAp, ap, apa, config) and PrevStage::revFlow(node, state, apa, config) and @@ -1337,21 +1341,21 @@ private module MkStage { pragma[inline] additional predicate fwdFlow( - NodeEx node, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - Ap ap, Configuration config + NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, + Configuration config ) { fwdFlow(node, state, cc, summaryCtx, argAp, ap, _, config) } pragma[nomagic] private predicate fwdFlow0( - NodeEx node, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - Ap ap, ApApprox apa, Configuration config + NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, + ApApprox apa, Configuration config ) { sourceNode(node, state, config) and (if hasSourceCallCtx(config) then cc = ccSomeCall() else cc = ccNone()) and argAp = apNone() and - summaryCtx = TParameterPositionNone() and + summaryCtx = TParamNodeNone() and ap = getApNil(node) and apa = getApprox(ap) or @@ -1372,7 +1376,7 @@ private module MkStage { fwdFlow(mid, pragma[only_bind_into](state), _, _, _, ap, apa, pragma[only_bind_into](config)) and jumpStep(mid, node, config) and cc = ccNone() and - summaryCtx = TParameterPositionNone() and + summaryCtx = TParamNodeNone() and argAp = apNone() ) or @@ -1380,7 +1384,7 @@ private module MkStage { fwdFlow(mid, state, _, _, _, nil, pragma[only_bind_into](config)) and additionalJumpStep(mid, node, config) and cc = ccNone() and - summaryCtx = TParameterPositionNone() and + summaryCtx = TParamNodeNone() and argAp = apNone() and ap = getApNil(node) and apa = getApprox(ap) @@ -1390,7 +1394,7 @@ private module MkStage { fwdFlow(mid, state0, _, _, _, nil, pragma[only_bind_into](config)) and additionalJumpStateStep(mid, state0, node, state, config) and cc = ccNone() and - summaryCtx = TParameterPositionNone() and + summaryCtx = TParamNodeNone() and argAp = apNone() and ap = getApNil(node) and apa = getApprox(ap) @@ -1414,10 +1418,10 @@ private module MkStage { fwdFlowIn(_, node, state, _, cc, _, _, ap, apa, config) and if PrevStage::parameterMayFlowThrough(node, apa, config) then ( - summaryCtx = TParameterPositionSome(node.(ParamNodeEx).getPosition()) and + summaryCtx = TParamNodeSome(node.asNode()) and argAp = apSome(ap) ) else ( - summaryCtx = TParameterPositionNone() and argAp = apNone() + summaryCtx = TParamNodeNone() and argAp = apNone() ) or // flow out of a callable @@ -1433,16 +1437,19 @@ private module MkStage { ) or // flow through a callable - exists(DataFlowCall call, ParameterPosition summaryCtx0, Ap argAp0 | - fwdFlowOutFromArg(call, node, state, summaryCtx0, argAp0, ap, apa, config) and - fwdFlowIsEntered(call, cc, summaryCtx, argAp, summaryCtx0, argAp0, config) + exists( + DataFlowCall call, CcCall ccc, RetNodeEx ret, boolean allowsFieldFlow, ApApprox innerArgApa + | + fwdFlowThrough(call, cc, state, ccc, summaryCtx, argAp, ap, apa, ret, innerArgApa, config) and + flowThroughOutOfCall(call, ccc, ret, node, allowsFieldFlow, innerArgApa, apa, config) and + if allowsFieldFlow = false then ap instanceof ApNil else any() ) } pragma[nomagic] private predicate fwdFlowStore( NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, FlowState state, Cc cc, - ParameterPositionOption summaryCtx, ApOption argAp, Configuration config + ParamNodeOption summaryCtx, ApOption argAp, Configuration config ) { exists(DataFlowType contentType, ApApprox apa1 | fwdFlow(node1, state, cc, summaryCtx, argAp, ap1, apa1, config) and @@ -1473,8 +1480,8 @@ private module MkStage { pragma[nomagic] private predicate fwdFlowRead0( - NodeEx node1, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - ApNonNil ap, Configuration config + NodeEx node1, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, ApNonNil ap, + Configuration config ) { fwdFlow(node1, state, cc, summaryCtx, argAp, ap, config) and PrevStage::readStepCand(node1, _, _, config) @@ -1483,7 +1490,7 @@ private module MkStage { pragma[nomagic] private predicate fwdFlowRead( Ap ap, Content c, NodeEx node1, NodeEx node2, FlowState state, Cc cc, - ParameterPositionOption summaryCtx, ApOption argAp, Configuration config + ParamNodeOption summaryCtx, ApOption argAp, Configuration config ) { fwdFlowRead0(node1, state, cc, summaryCtx, argAp, ap, config) and PrevStage::readStepCand(node1, c, node2, config) and @@ -1493,7 +1500,7 @@ private module MkStage { pragma[nomagic] private predicate fwdFlowIn( DataFlowCall call, ParamNodeEx p, FlowState state, Cc outercc, CcCall innercc, - ParameterPositionOption summaryCtx, ApOption argAp, Ap ap, ApApprox apa, Configuration config + ParamNodeOption summaryCtx, ApOption argAp, Ap ap, ApApprox apa, Configuration config ) { exists(ArgNodeEx arg, boolean allowsFieldFlow | fwdFlow(arg, state, outercc, summaryCtx, argAp, ap, apa, config) and @@ -1505,64 +1512,38 @@ private module MkStage { pragma[nomagic] private predicate fwdFlowRetFromArg( - RetNodeEx ret, FlowState state, CcCall ccc, ParameterPosition summaryCtx, ParamNodeEx p, - Ap argAp, ApApprox argApa, Ap ap, ApApprox apa, Configuration config + RetNodeEx ret, FlowState state, CcCall ccc, ParamNodeEx summaryCtx, Ap argAp, ApApprox argApa, + Ap ap, ApApprox apa, Configuration config ) { - exists(DataFlowCallable c, ReturnKindExt kind | + exists(ReturnKindExt kind | fwdFlow(pragma[only_bind_into](ret), state, ccc, - TParameterPositionSome(pragma[only_bind_into](summaryCtx)), apSome(argAp), ap, apa, config) and - getApprox(argAp) = argApa and - c = ret.getEnclosingCallable() and + TParamNodeSome(pragma[only_bind_into](summaryCtx.asNode())), + pragma[only_bind_into](apSome(argAp)), ap, pragma[only_bind_into](apa), + pragma[only_bind_into](config)) and kind = ret.getKind() and - p.isParameterOf(c, pragma[only_bind_into](summaryCtx)) and - parameterFlowThroughAllowed(p, kind) + parameterFlowThroughAllowed(summaryCtx, kind) and + argApa = getApprox(argAp) and + PrevStage::returnMayFlowThrough(ret, argApa, apa, kind, pragma[only_bind_into](config)) ) } pragma[inline] - private predicate fwdFlowInMayFlowThrough( - DataFlowCall call, Cc cc, CcCall innerCc, ParameterPositionOption summaryCtx, ApOption argAp, - ParamNodeEx param, Ap ap, ApApprox apa, Configuration config + private predicate fwdFlowThrough0( + DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, + ApOption argAp, Ap ap, ApApprox apa, RetNodeEx ret, ParamNodeEx innerSummaryCtx, + Ap innerArgAp, ApApprox innerArgApa, Configuration config ) { - fwdFlowIn(call, pragma[only_bind_into](param), _, cc, innerCc, summaryCtx, argAp, ap, - pragma[only_bind_into](apa), pragma[only_bind_into](config)) and - PrevStage::parameterMayFlowThrough(param, apa, config) - } - - // dedup before joining with `flowThroughOutOfCall` - pragma[nomagic] - private predicate fwdFlowInMayFlowThroughProj( - DataFlowCall call, CcCall innerCc, ApApprox apa, Configuration config - ) { - fwdFlowInMayFlowThrough(call, _, innerCc, _, _, _, _, apa, config) - } - - /** - * Same as `flowThroughOutOfCall`, but restricted to calls that are reached - * in the flow covered by `fwdFlow`, where data might flow through the target - * callable and back out at `call`. - */ - pragma[nomagic] - private predicate fwdFlowThroughOutOfCall( - DataFlowCall call, CcCall ccc, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow, - ApApprox argApa, ApApprox apa, Configuration config - ) { - fwdFlowInMayFlowThroughProj(call, ccc, argApa, config) and - flowThroughOutOfCall(call, ccc, ret, out, allowsFieldFlow, argApa, apa, config) + fwdFlowRetFromArg(ret, state, ccc, innerSummaryCtx, innerArgAp, innerArgApa, ap, apa, config) and + fwdFlowIsEntered(call, cc, ccc, summaryCtx, argAp, innerSummaryCtx, innerArgAp, config) } pragma[nomagic] - private predicate fwdFlowOutFromArg( - DataFlowCall call, NodeEx out, FlowState state, ParameterPosition summaryCtx, Ap argAp, Ap ap, - ApApprox apa, Configuration config + private predicate fwdFlowThrough( + DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, + ApOption argAp, Ap ap, ApApprox apa, RetNodeEx ret, ApApprox innerArgApa, Configuration config ) { - exists(RetNodeEx ret, boolean allowsFieldFlow, CcCall ccc, ApApprox argApa | - fwdFlowRetFromArg(pragma[only_bind_into](ret), state, pragma[only_bind_into](ccc), - summaryCtx, _, argAp, pragma[only_bind_into](argApa), ap, pragma[only_bind_into](apa), - config) and - fwdFlowThroughOutOfCall(call, ccc, ret, out, allowsFieldFlow, argApa, apa, config) and - (if allowsFieldFlow = false then ap instanceof ApNil else any()) - ) + fwdFlowThrough0(call, cc, state, ccc, summaryCtx, argAp, ap, apa, ret, _, _, innerArgApa, + config) } /** @@ -1571,12 +1552,14 @@ private module MkStage { */ pragma[nomagic] private predicate fwdFlowIsEntered( - DataFlowCall call, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - ParameterPosition pos, Ap ap, Configuration config + DataFlowCall call, Cc cc, CcCall innerCc, ParamNodeOption summaryCtx, ApOption argAp, + ParamNodeEx p, Ap ap, Configuration config ) { - exists(ParamNodeEx param | - fwdFlowInMayFlowThrough(call, cc, _, summaryCtx, argAp, param, ap, _, config) and - pos = param.getPosition() + exists(ApApprox apa | + fwdFlowIn(call, pragma[only_bind_into](p), _, cc, innerCc, summaryCtx, argAp, ap, + pragma[only_bind_into](apa), pragma[only_bind_into](config)) and + PrevStage::parameterMayFlowThrough(p, apa, config) and + PrevStage::callMayFlowThroughRev(call, pragma[only_bind_into](config)) ) } @@ -1596,23 +1579,31 @@ private module MkStage { fwdFlowConsCand(ap1, c, ap2, config) } + pragma[nomagic] + private predicate returnFlowsThrough0( + DataFlowCall call, FlowState state, CcCall ccc, Ap ap, ApApprox apa, RetNodeEx ret, + ParamNodeEx innerSummaryCtx, Ap innerArgAp, ApApprox innerArgApa, Configuration config + ) { + fwdFlowThrough0(call, _, state, ccc, _, _, ap, apa, ret, innerSummaryCtx, innerArgAp, + innerArgApa, config) + } + pragma[nomagic] private predicate returnFlowsThrough( - RetNodeEx ret, ReturnKindExt kind, FlowState state, CcCall ccc, ParamNodeEx p, Ap argAp, + RetNodeEx ret, ReturnPosition pos, FlowState state, CcCall ccc, ParamNodeEx p, Ap argAp, Ap ap, Configuration config ) { - exists(boolean allowsFieldFlow, ApApprox argApa, ApApprox apa | - fwdFlowRetFromArg(pragma[only_bind_into](ret), state, pragma[only_bind_into](ccc), _, p, - argAp, pragma[only_bind_into](argApa), ap, pragma[only_bind_into](apa), config) and - kind = ret.getKind() and - fwdFlowThroughOutOfCall(_, ccc, ret, _, allowsFieldFlow, argApa, apa, config) and - (if allowsFieldFlow = false then ap instanceof ApNil else any()) + exists(DataFlowCall call, ApApprox apa, boolean allowsFieldFlow, ApApprox innerArgApa | + returnFlowsThrough0(call, state, ccc, ap, apa, ret, p, argAp, innerArgApa, config) and + flowThroughOutOfCall(call, ccc, ret, _, allowsFieldFlow, innerArgApa, apa, config) and + pos = ret.getReturnPosition() and + if allowsFieldFlow = false then ap instanceof ApNil else any() ) } pragma[nomagic] private predicate flowThroughIntoCall( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap argAp, + DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap argAp, Ap ap, Configuration config ) { exists(ApApprox argApa | @@ -1620,7 +1611,7 @@ private module MkStage { allowsFieldFlow, argApa, pragma[only_bind_into](config)) and fwdFlow(arg, _, _, _, _, pragma[only_bind_into](argAp), argApa, pragma[only_bind_into](config)) and - returnFlowsThrough(_, _, _, _, p, pragma[only_bind_into](argAp), _, + returnFlowsThrough(_, _, _, _, p, pragma[only_bind_into](argAp), ap, pragma[only_bind_into](config)) and if allowsFieldFlow = false then argAp instanceof ApNil else any() ) @@ -1639,12 +1630,13 @@ private module MkStage { pragma[nomagic] private predicate flowOutOfCallAp( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, boolean allowsFieldFlow, + DataFlowCall call, RetNodeEx ret, ReturnPosition pos, NodeEx out, boolean allowsFieldFlow, Ap ap, Configuration config ) { exists(ApApprox apa | - flowOutOfCallApa(call, ret, kind, out, allowsFieldFlow, apa, config) and - fwdFlow(ret, _, _, _, _, ap, apa, config) + flowOutOfCallApa(call, ret, _, out, allowsFieldFlow, apa, config) and + fwdFlow(ret, _, _, _, _, ap, apa, config) and + pos = ret.getReturnPosition() ) } @@ -1739,17 +1731,17 @@ private module MkStage { ) or // flow through a callable - exists(DataFlowCall call, ReturnKindExt returnKind0, Ap returnAp0 | - revFlowInToReturn(call, node, state, returnKind0, returnAp0, ap, config) and - revFlowIsReturned(call, returnCtx, returnAp, returnKind0, returnAp0, config) + exists(DataFlowCall call, ParamNodeEx p, ReturnPosition pos, Ap innerReturnAp | + revFlowThrough(call, returnCtx, p, state, pos, returnAp, ap, innerReturnAp, config) and + flowThroughIntoCall(call, node, p, _, ap, innerReturnAp, config) ) or // flow out of a callable - exists(ReturnKindExt kind | - revFlowOut(_, node, kind, state, _, _, ap, config) and - if returnFlowsThrough(node, kind, state, _, _, _, ap, config) + exists(ReturnPosition pos | + revFlowOut(_, node, pos, state, _, _, ap, config) and + if returnFlowsThrough(node, pos, state, _, _, _, ap, config) then ( - returnCtx = TReturnCtxMaybeFlowThrough(kind) and + returnCtx = TReturnCtxMaybeFlowThrough(pos) and returnAp = apSome(ap) ) else ( returnCtx = TReturnCtxNoFlowThrough() and returnAp = apNone() @@ -1782,47 +1774,33 @@ private module MkStage { pragma[nomagic] private predicate revFlowOut( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, FlowState state, ReturnCtx returnCtx, + DataFlowCall call, RetNodeEx ret, ReturnPosition pos, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap, Configuration config ) { exists(NodeEx out, boolean allowsFieldFlow | revFlow(out, state, returnCtx, returnAp, ap, config) and - flowOutOfCallAp(call, ret, kind, out, allowsFieldFlow, ap, config) and + flowOutOfCallAp(call, ret, pos, out, allowsFieldFlow, ap, config) and if allowsFieldFlow = false then ap instanceof ApNil else any() ) } - /** - * Same as `flowThroughIntoCall`, but restricted to calls that are reached - * in the flow covered by `revFlow`, where data might flow through the target - * callable and back out at `call`. - */ - pragma[nomagic] - private predicate revFlowThroughIntoCall( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap argAp, - Configuration config - ) { - flowThroughIntoCall(call, arg, p, allowsFieldFlow, argAp, config) and - revFlowIsReturned(call, _, _, _, _, config) - } - pragma[nomagic] private predicate revFlowParamToReturn( - ParamNodeEx p, FlowState state, ReturnKindExt kind, Ap returnAp, Ap ap, Configuration config + ParamNodeEx p, FlowState state, ReturnPosition pos, Ap returnAp, Ap ap, Configuration config ) { - revFlow(p, state, TReturnCtxMaybeFlowThrough(kind), apSome(returnAp), ap, config) and - parameterFlowThroughAllowed(p, kind) + revFlow(pragma[only_bind_into](p), state, TReturnCtxMaybeFlowThrough(pos), apSome(returnAp), + pragma[only_bind_into](ap), pragma[only_bind_into](config)) and + parameterFlowThroughAllowed(p, pos.getKind()) and + PrevStage::parameterMayFlowThrough(p, getApprox(ap), config) } pragma[nomagic] - private predicate revFlowInToReturn( - DataFlowCall call, ArgNodeEx arg, FlowState state, ReturnKindExt kind, Ap returnAp, Ap ap, - Configuration config + private predicate revFlowThrough( + DataFlowCall call, ReturnCtx returnCtx, ParamNodeEx p, FlowState state, ReturnPosition pos, + ApOption returnAp, Ap ap, Ap innerReturnAp, Configuration config ) { - exists(ParamNodeEx p, boolean allowsFieldFlow | - revFlowParamToReturn(p, state, kind, returnAp, ap, config) and - revFlowThroughIntoCall(call, arg, p, allowsFieldFlow, ap, config) - ) + revFlowParamToReturn(p, state, pos, innerReturnAp, ap, config) and + revFlowIsReturned(call, returnCtx, returnAp, pos, innerReturnAp, config) } /** @@ -1832,12 +1810,12 @@ private module MkStage { */ pragma[nomagic] private predicate revFlowIsReturned( - DataFlowCall call, ReturnCtx returnCtx, ApOption returnAp, ReturnKindExt kind, Ap ap, + DataFlowCall call, ReturnCtx returnCtx, ApOption returnAp, ReturnPosition pos, Ap ap, Configuration config ) { exists(RetNodeEx ret, FlowState state, CcCall ccc | - revFlowOut(call, ret, kind, state, returnCtx, returnAp, ap, config) and - returnFlowsThrough(ret, kind, state, ccc, _, _, ap, config) and + revFlowOut(call, ret, pos, state, returnCtx, returnAp, ap, config) and + returnFlowsThrough(ret, pos, state, ccc, _, _, ap, config) and matchesCall(ccc, call) ) } @@ -1915,17 +1893,17 @@ private module MkStage { pragma[nomagic] private predicate parameterFlowsThroughRev( - ParamNodeEx p, Ap ap, ReturnKindExt kind, Ap returnAp, Configuration config + ParamNodeEx p, Ap ap, ReturnPosition pos, Ap returnAp, Configuration config ) { - revFlow(p, _, TReturnCtxMaybeFlowThrough(kind), apSome(returnAp), ap, config) and - parameterFlowThroughAllowed(p, kind) + revFlow(p, _, TReturnCtxMaybeFlowThrough(pos), apSome(returnAp), ap, config) and + parameterFlowThroughAllowed(p, pos.getKind()) } pragma[nomagic] predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap, Configuration config) { - exists(RetNodeEx ret, ReturnKindExt kind | - returnFlowsThrough(ret, kind, _, _, p, ap, _, config) and - parameterFlowsThroughRev(p, ap, kind, _, config) + exists(RetNodeEx ret, ReturnPosition pos | + returnFlowsThrough(ret, pos, _, _, p, ap, _, config) and + parameterFlowsThroughRev(p, ap, pos, _, config) ) } @@ -1933,20 +1911,21 @@ private module MkStage { predicate returnMayFlowThrough( RetNodeEx ret, Ap argAp, Ap ap, ReturnKindExt kind, Configuration config ) { - exists(ParamNodeEx p | - returnFlowsThrough(ret, kind, _, _, p, argAp, ap, config) and - parameterFlowsThroughRev(p, argAp, kind, ap, config) + exists(ParamNodeEx p, ReturnPosition pos | + returnFlowsThrough(ret, pos, _, _, p, argAp, ap, config) and + parameterFlowsThroughRev(p, argAp, pos, ap, config) and + kind = pos.getKind() ) } pragma[nomagic] - predicate revFlowInToReturnIsReturned( + private predicate revFlowThroughArg( DataFlowCall call, ArgNodeEx arg, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap, Configuration config ) { - exists(ReturnKindExt returnKind0, Ap returnAp0 | - revFlowInToReturn(call, arg, state, returnKind0, returnAp0, ap, config) and - revFlowIsReturned(call, returnCtx, returnAp, returnKind0, returnAp0, config) + exists(ParamNodeEx p, ReturnPosition pos, Ap innerReturnAp | + revFlowThrough(call, returnCtx, p, state, pos, returnAp, ap, innerReturnAp, config) and + flowThroughIntoCall(call, arg, p, _, ap, innerReturnAp, config) ) } @@ -1954,7 +1933,7 @@ private module MkStage { predicate callMayFlowThroughRev(DataFlowCall call, Configuration config) { exists(ArgNodeEx arg, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap | revFlow(arg, state, returnCtx, returnAp, ap, config) and - revFlowInToReturnIsReturned(call, arg, state, returnCtx, returnAp, ap, config) + revFlowThroughArg(call, arg, state, returnCtx, returnAp, ap, config) ) } @@ -1967,8 +1946,9 @@ private module MkStage { conscand = count(TypedContent f0, Ap ap | fwdConsCand(f0, ap, config)) and states = count(FlowState state | fwdFlow(_, state, _, _, _, _, config)) and tuples = - count(NodeEx n, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - Ap ap | fwdFlow(n, state, cc, summaryCtx, argAp, ap, config)) + count(NodeEx n, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap | + fwdFlow(n, state, cc, summaryCtx, argAp, ap, config) + ) or fwd = false and nodes = count(NodeEx node | revFlow(node, _, _, _, _, config)) and @@ -2823,13 +2803,12 @@ private Configuration unbindConf(Configuration conf) { pragma[nomagic] private predicate nodeMayUseSummary0( - NodeEx n, DataFlowCallable c, ParameterPosition pos, FlowState state, AccessPathApprox apa, - Configuration config + NodeEx n, ParamNodeEx p, FlowState state, AccessPathApprox apa, Configuration config ) { exists(AccessPathApprox apa0 | - c = n.getEnclosingCallable() and + Stage5::parameterMayFlowThrough(p, _, _) and Stage5::revFlow(n, state, TReturnCtxMaybeFlowThrough(_), _, apa0, config) and - Stage5::fwdFlow(n, state, any(CallContextCall ccc), TParameterPositionSome(pos), + Stage5::fwdFlow(n, state, any(CallContextCall ccc), TParamNodeSome(p.asNode()), TAccessPathApproxSome(apa), apa0, config) ) } @@ -2838,10 +2817,9 @@ pragma[nomagic] private predicate nodeMayUseSummary( NodeEx n, FlowState state, AccessPathApprox apa, Configuration config ) { - exists(DataFlowCallable c, ParameterPosition pos, ParamNodeEx p | + exists(ParamNodeEx p | Stage5::parameterMayFlowThrough(p, apa, config) and - nodeMayUseSummary0(n, c, pos, state, apa, config) and - p.isParameterOf(c, pos) + nodeMayUseSummary0(n, p, state, apa, config) ) } diff --git a/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImpl2.qll b/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImpl2.qll index 6741ccc2f06..1228d00b6ba 100644 --- a/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImpl2.qll +++ b/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImpl2.qll @@ -622,7 +622,11 @@ private predicate parameterFlowThroughAllowed(ParamNodeEx p, ReturnKindExt kind) } private module Stage1 implements StageSig { - class Ap = Unit; + class Ap extends int { + // workaround for bad functionality-induced joins (happens when using `Unit`) + pragma[nomagic] + Ap() { this in [0 .. 1] and this < 1 } + } private class Cc = boolean; @@ -1327,8 +1331,8 @@ private module MkStage { */ pragma[nomagic] additional predicate fwdFlow( - NodeEx node, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - Ap ap, ApApprox apa, Configuration config + NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, + ApApprox apa, Configuration config ) { fwdFlow0(node, state, cc, summaryCtx, argAp, ap, apa, config) and PrevStage::revFlow(node, state, apa, config) and @@ -1337,21 +1341,21 @@ private module MkStage { pragma[inline] additional predicate fwdFlow( - NodeEx node, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - Ap ap, Configuration config + NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, + Configuration config ) { fwdFlow(node, state, cc, summaryCtx, argAp, ap, _, config) } pragma[nomagic] private predicate fwdFlow0( - NodeEx node, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - Ap ap, ApApprox apa, Configuration config + NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, + ApApprox apa, Configuration config ) { sourceNode(node, state, config) and (if hasSourceCallCtx(config) then cc = ccSomeCall() else cc = ccNone()) and argAp = apNone() and - summaryCtx = TParameterPositionNone() and + summaryCtx = TParamNodeNone() and ap = getApNil(node) and apa = getApprox(ap) or @@ -1372,7 +1376,7 @@ private module MkStage { fwdFlow(mid, pragma[only_bind_into](state), _, _, _, ap, apa, pragma[only_bind_into](config)) and jumpStep(mid, node, config) and cc = ccNone() and - summaryCtx = TParameterPositionNone() and + summaryCtx = TParamNodeNone() and argAp = apNone() ) or @@ -1380,7 +1384,7 @@ private module MkStage { fwdFlow(mid, state, _, _, _, nil, pragma[only_bind_into](config)) and additionalJumpStep(mid, node, config) and cc = ccNone() and - summaryCtx = TParameterPositionNone() and + summaryCtx = TParamNodeNone() and argAp = apNone() and ap = getApNil(node) and apa = getApprox(ap) @@ -1390,7 +1394,7 @@ private module MkStage { fwdFlow(mid, state0, _, _, _, nil, pragma[only_bind_into](config)) and additionalJumpStateStep(mid, state0, node, state, config) and cc = ccNone() and - summaryCtx = TParameterPositionNone() and + summaryCtx = TParamNodeNone() and argAp = apNone() and ap = getApNil(node) and apa = getApprox(ap) @@ -1414,10 +1418,10 @@ private module MkStage { fwdFlowIn(_, node, state, _, cc, _, _, ap, apa, config) and if PrevStage::parameterMayFlowThrough(node, apa, config) then ( - summaryCtx = TParameterPositionSome(node.(ParamNodeEx).getPosition()) and + summaryCtx = TParamNodeSome(node.asNode()) and argAp = apSome(ap) ) else ( - summaryCtx = TParameterPositionNone() and argAp = apNone() + summaryCtx = TParamNodeNone() and argAp = apNone() ) or // flow out of a callable @@ -1433,16 +1437,19 @@ private module MkStage { ) or // flow through a callable - exists(DataFlowCall call, ParameterPosition summaryCtx0, Ap argAp0 | - fwdFlowOutFromArg(call, node, state, summaryCtx0, argAp0, ap, apa, config) and - fwdFlowIsEntered(call, cc, summaryCtx, argAp, summaryCtx0, argAp0, config) + exists( + DataFlowCall call, CcCall ccc, RetNodeEx ret, boolean allowsFieldFlow, ApApprox innerArgApa + | + fwdFlowThrough(call, cc, state, ccc, summaryCtx, argAp, ap, apa, ret, innerArgApa, config) and + flowThroughOutOfCall(call, ccc, ret, node, allowsFieldFlow, innerArgApa, apa, config) and + if allowsFieldFlow = false then ap instanceof ApNil else any() ) } pragma[nomagic] private predicate fwdFlowStore( NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, FlowState state, Cc cc, - ParameterPositionOption summaryCtx, ApOption argAp, Configuration config + ParamNodeOption summaryCtx, ApOption argAp, Configuration config ) { exists(DataFlowType contentType, ApApprox apa1 | fwdFlow(node1, state, cc, summaryCtx, argAp, ap1, apa1, config) and @@ -1473,8 +1480,8 @@ private module MkStage { pragma[nomagic] private predicate fwdFlowRead0( - NodeEx node1, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - ApNonNil ap, Configuration config + NodeEx node1, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, ApNonNil ap, + Configuration config ) { fwdFlow(node1, state, cc, summaryCtx, argAp, ap, config) and PrevStage::readStepCand(node1, _, _, config) @@ -1483,7 +1490,7 @@ private module MkStage { pragma[nomagic] private predicate fwdFlowRead( Ap ap, Content c, NodeEx node1, NodeEx node2, FlowState state, Cc cc, - ParameterPositionOption summaryCtx, ApOption argAp, Configuration config + ParamNodeOption summaryCtx, ApOption argAp, Configuration config ) { fwdFlowRead0(node1, state, cc, summaryCtx, argAp, ap, config) and PrevStage::readStepCand(node1, c, node2, config) and @@ -1493,7 +1500,7 @@ private module MkStage { pragma[nomagic] private predicate fwdFlowIn( DataFlowCall call, ParamNodeEx p, FlowState state, Cc outercc, CcCall innercc, - ParameterPositionOption summaryCtx, ApOption argAp, Ap ap, ApApprox apa, Configuration config + ParamNodeOption summaryCtx, ApOption argAp, Ap ap, ApApprox apa, Configuration config ) { exists(ArgNodeEx arg, boolean allowsFieldFlow | fwdFlow(arg, state, outercc, summaryCtx, argAp, ap, apa, config) and @@ -1505,64 +1512,38 @@ private module MkStage { pragma[nomagic] private predicate fwdFlowRetFromArg( - RetNodeEx ret, FlowState state, CcCall ccc, ParameterPosition summaryCtx, ParamNodeEx p, - Ap argAp, ApApprox argApa, Ap ap, ApApprox apa, Configuration config + RetNodeEx ret, FlowState state, CcCall ccc, ParamNodeEx summaryCtx, Ap argAp, ApApprox argApa, + Ap ap, ApApprox apa, Configuration config ) { - exists(DataFlowCallable c, ReturnKindExt kind | + exists(ReturnKindExt kind | fwdFlow(pragma[only_bind_into](ret), state, ccc, - TParameterPositionSome(pragma[only_bind_into](summaryCtx)), apSome(argAp), ap, apa, config) and - getApprox(argAp) = argApa and - c = ret.getEnclosingCallable() and + TParamNodeSome(pragma[only_bind_into](summaryCtx.asNode())), + pragma[only_bind_into](apSome(argAp)), ap, pragma[only_bind_into](apa), + pragma[only_bind_into](config)) and kind = ret.getKind() and - p.isParameterOf(c, pragma[only_bind_into](summaryCtx)) and - parameterFlowThroughAllowed(p, kind) + parameterFlowThroughAllowed(summaryCtx, kind) and + argApa = getApprox(argAp) and + PrevStage::returnMayFlowThrough(ret, argApa, apa, kind, pragma[only_bind_into](config)) ) } pragma[inline] - private predicate fwdFlowInMayFlowThrough( - DataFlowCall call, Cc cc, CcCall innerCc, ParameterPositionOption summaryCtx, ApOption argAp, - ParamNodeEx param, Ap ap, ApApprox apa, Configuration config + private predicate fwdFlowThrough0( + DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, + ApOption argAp, Ap ap, ApApprox apa, RetNodeEx ret, ParamNodeEx innerSummaryCtx, + Ap innerArgAp, ApApprox innerArgApa, Configuration config ) { - fwdFlowIn(call, pragma[only_bind_into](param), _, cc, innerCc, summaryCtx, argAp, ap, - pragma[only_bind_into](apa), pragma[only_bind_into](config)) and - PrevStage::parameterMayFlowThrough(param, apa, config) - } - - // dedup before joining with `flowThroughOutOfCall` - pragma[nomagic] - private predicate fwdFlowInMayFlowThroughProj( - DataFlowCall call, CcCall innerCc, ApApprox apa, Configuration config - ) { - fwdFlowInMayFlowThrough(call, _, innerCc, _, _, _, _, apa, config) - } - - /** - * Same as `flowThroughOutOfCall`, but restricted to calls that are reached - * in the flow covered by `fwdFlow`, where data might flow through the target - * callable and back out at `call`. - */ - pragma[nomagic] - private predicate fwdFlowThroughOutOfCall( - DataFlowCall call, CcCall ccc, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow, - ApApprox argApa, ApApprox apa, Configuration config - ) { - fwdFlowInMayFlowThroughProj(call, ccc, argApa, config) and - flowThroughOutOfCall(call, ccc, ret, out, allowsFieldFlow, argApa, apa, config) + fwdFlowRetFromArg(ret, state, ccc, innerSummaryCtx, innerArgAp, innerArgApa, ap, apa, config) and + fwdFlowIsEntered(call, cc, ccc, summaryCtx, argAp, innerSummaryCtx, innerArgAp, config) } pragma[nomagic] - private predicate fwdFlowOutFromArg( - DataFlowCall call, NodeEx out, FlowState state, ParameterPosition summaryCtx, Ap argAp, Ap ap, - ApApprox apa, Configuration config + private predicate fwdFlowThrough( + DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, + ApOption argAp, Ap ap, ApApprox apa, RetNodeEx ret, ApApprox innerArgApa, Configuration config ) { - exists(RetNodeEx ret, boolean allowsFieldFlow, CcCall ccc, ApApprox argApa | - fwdFlowRetFromArg(pragma[only_bind_into](ret), state, pragma[only_bind_into](ccc), - summaryCtx, _, argAp, pragma[only_bind_into](argApa), ap, pragma[only_bind_into](apa), - config) and - fwdFlowThroughOutOfCall(call, ccc, ret, out, allowsFieldFlow, argApa, apa, config) and - (if allowsFieldFlow = false then ap instanceof ApNil else any()) - ) + fwdFlowThrough0(call, cc, state, ccc, summaryCtx, argAp, ap, apa, ret, _, _, innerArgApa, + config) } /** @@ -1571,12 +1552,14 @@ private module MkStage { */ pragma[nomagic] private predicate fwdFlowIsEntered( - DataFlowCall call, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - ParameterPosition pos, Ap ap, Configuration config + DataFlowCall call, Cc cc, CcCall innerCc, ParamNodeOption summaryCtx, ApOption argAp, + ParamNodeEx p, Ap ap, Configuration config ) { - exists(ParamNodeEx param | - fwdFlowInMayFlowThrough(call, cc, _, summaryCtx, argAp, param, ap, _, config) and - pos = param.getPosition() + exists(ApApprox apa | + fwdFlowIn(call, pragma[only_bind_into](p), _, cc, innerCc, summaryCtx, argAp, ap, + pragma[only_bind_into](apa), pragma[only_bind_into](config)) and + PrevStage::parameterMayFlowThrough(p, apa, config) and + PrevStage::callMayFlowThroughRev(call, pragma[only_bind_into](config)) ) } @@ -1596,23 +1579,31 @@ private module MkStage { fwdFlowConsCand(ap1, c, ap2, config) } + pragma[nomagic] + private predicate returnFlowsThrough0( + DataFlowCall call, FlowState state, CcCall ccc, Ap ap, ApApprox apa, RetNodeEx ret, + ParamNodeEx innerSummaryCtx, Ap innerArgAp, ApApprox innerArgApa, Configuration config + ) { + fwdFlowThrough0(call, _, state, ccc, _, _, ap, apa, ret, innerSummaryCtx, innerArgAp, + innerArgApa, config) + } + pragma[nomagic] private predicate returnFlowsThrough( - RetNodeEx ret, ReturnKindExt kind, FlowState state, CcCall ccc, ParamNodeEx p, Ap argAp, + RetNodeEx ret, ReturnPosition pos, FlowState state, CcCall ccc, ParamNodeEx p, Ap argAp, Ap ap, Configuration config ) { - exists(boolean allowsFieldFlow, ApApprox argApa, ApApprox apa | - fwdFlowRetFromArg(pragma[only_bind_into](ret), state, pragma[only_bind_into](ccc), _, p, - argAp, pragma[only_bind_into](argApa), ap, pragma[only_bind_into](apa), config) and - kind = ret.getKind() and - fwdFlowThroughOutOfCall(_, ccc, ret, _, allowsFieldFlow, argApa, apa, config) and - (if allowsFieldFlow = false then ap instanceof ApNil else any()) + exists(DataFlowCall call, ApApprox apa, boolean allowsFieldFlow, ApApprox innerArgApa | + returnFlowsThrough0(call, state, ccc, ap, apa, ret, p, argAp, innerArgApa, config) and + flowThroughOutOfCall(call, ccc, ret, _, allowsFieldFlow, innerArgApa, apa, config) and + pos = ret.getReturnPosition() and + if allowsFieldFlow = false then ap instanceof ApNil else any() ) } pragma[nomagic] private predicate flowThroughIntoCall( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap argAp, + DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap argAp, Ap ap, Configuration config ) { exists(ApApprox argApa | @@ -1620,7 +1611,7 @@ private module MkStage { allowsFieldFlow, argApa, pragma[only_bind_into](config)) and fwdFlow(arg, _, _, _, _, pragma[only_bind_into](argAp), argApa, pragma[only_bind_into](config)) and - returnFlowsThrough(_, _, _, _, p, pragma[only_bind_into](argAp), _, + returnFlowsThrough(_, _, _, _, p, pragma[only_bind_into](argAp), ap, pragma[only_bind_into](config)) and if allowsFieldFlow = false then argAp instanceof ApNil else any() ) @@ -1639,12 +1630,13 @@ private module MkStage { pragma[nomagic] private predicate flowOutOfCallAp( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, boolean allowsFieldFlow, + DataFlowCall call, RetNodeEx ret, ReturnPosition pos, NodeEx out, boolean allowsFieldFlow, Ap ap, Configuration config ) { exists(ApApprox apa | - flowOutOfCallApa(call, ret, kind, out, allowsFieldFlow, apa, config) and - fwdFlow(ret, _, _, _, _, ap, apa, config) + flowOutOfCallApa(call, ret, _, out, allowsFieldFlow, apa, config) and + fwdFlow(ret, _, _, _, _, ap, apa, config) and + pos = ret.getReturnPosition() ) } @@ -1739,17 +1731,17 @@ private module MkStage { ) or // flow through a callable - exists(DataFlowCall call, ReturnKindExt returnKind0, Ap returnAp0 | - revFlowInToReturn(call, node, state, returnKind0, returnAp0, ap, config) and - revFlowIsReturned(call, returnCtx, returnAp, returnKind0, returnAp0, config) + exists(DataFlowCall call, ParamNodeEx p, ReturnPosition pos, Ap innerReturnAp | + revFlowThrough(call, returnCtx, p, state, pos, returnAp, ap, innerReturnAp, config) and + flowThroughIntoCall(call, node, p, _, ap, innerReturnAp, config) ) or // flow out of a callable - exists(ReturnKindExt kind | - revFlowOut(_, node, kind, state, _, _, ap, config) and - if returnFlowsThrough(node, kind, state, _, _, _, ap, config) + exists(ReturnPosition pos | + revFlowOut(_, node, pos, state, _, _, ap, config) and + if returnFlowsThrough(node, pos, state, _, _, _, ap, config) then ( - returnCtx = TReturnCtxMaybeFlowThrough(kind) and + returnCtx = TReturnCtxMaybeFlowThrough(pos) and returnAp = apSome(ap) ) else ( returnCtx = TReturnCtxNoFlowThrough() and returnAp = apNone() @@ -1782,47 +1774,33 @@ private module MkStage { pragma[nomagic] private predicate revFlowOut( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, FlowState state, ReturnCtx returnCtx, + DataFlowCall call, RetNodeEx ret, ReturnPosition pos, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap, Configuration config ) { exists(NodeEx out, boolean allowsFieldFlow | revFlow(out, state, returnCtx, returnAp, ap, config) and - flowOutOfCallAp(call, ret, kind, out, allowsFieldFlow, ap, config) and + flowOutOfCallAp(call, ret, pos, out, allowsFieldFlow, ap, config) and if allowsFieldFlow = false then ap instanceof ApNil else any() ) } - /** - * Same as `flowThroughIntoCall`, but restricted to calls that are reached - * in the flow covered by `revFlow`, where data might flow through the target - * callable and back out at `call`. - */ - pragma[nomagic] - private predicate revFlowThroughIntoCall( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap argAp, - Configuration config - ) { - flowThroughIntoCall(call, arg, p, allowsFieldFlow, argAp, config) and - revFlowIsReturned(call, _, _, _, _, config) - } - pragma[nomagic] private predicate revFlowParamToReturn( - ParamNodeEx p, FlowState state, ReturnKindExt kind, Ap returnAp, Ap ap, Configuration config + ParamNodeEx p, FlowState state, ReturnPosition pos, Ap returnAp, Ap ap, Configuration config ) { - revFlow(p, state, TReturnCtxMaybeFlowThrough(kind), apSome(returnAp), ap, config) and - parameterFlowThroughAllowed(p, kind) + revFlow(pragma[only_bind_into](p), state, TReturnCtxMaybeFlowThrough(pos), apSome(returnAp), + pragma[only_bind_into](ap), pragma[only_bind_into](config)) and + parameterFlowThroughAllowed(p, pos.getKind()) and + PrevStage::parameterMayFlowThrough(p, getApprox(ap), config) } pragma[nomagic] - private predicate revFlowInToReturn( - DataFlowCall call, ArgNodeEx arg, FlowState state, ReturnKindExt kind, Ap returnAp, Ap ap, - Configuration config + private predicate revFlowThrough( + DataFlowCall call, ReturnCtx returnCtx, ParamNodeEx p, FlowState state, ReturnPosition pos, + ApOption returnAp, Ap ap, Ap innerReturnAp, Configuration config ) { - exists(ParamNodeEx p, boolean allowsFieldFlow | - revFlowParamToReturn(p, state, kind, returnAp, ap, config) and - revFlowThroughIntoCall(call, arg, p, allowsFieldFlow, ap, config) - ) + revFlowParamToReturn(p, state, pos, innerReturnAp, ap, config) and + revFlowIsReturned(call, returnCtx, returnAp, pos, innerReturnAp, config) } /** @@ -1832,12 +1810,12 @@ private module MkStage { */ pragma[nomagic] private predicate revFlowIsReturned( - DataFlowCall call, ReturnCtx returnCtx, ApOption returnAp, ReturnKindExt kind, Ap ap, + DataFlowCall call, ReturnCtx returnCtx, ApOption returnAp, ReturnPosition pos, Ap ap, Configuration config ) { exists(RetNodeEx ret, FlowState state, CcCall ccc | - revFlowOut(call, ret, kind, state, returnCtx, returnAp, ap, config) and - returnFlowsThrough(ret, kind, state, ccc, _, _, ap, config) and + revFlowOut(call, ret, pos, state, returnCtx, returnAp, ap, config) and + returnFlowsThrough(ret, pos, state, ccc, _, _, ap, config) and matchesCall(ccc, call) ) } @@ -1915,17 +1893,17 @@ private module MkStage { pragma[nomagic] private predicate parameterFlowsThroughRev( - ParamNodeEx p, Ap ap, ReturnKindExt kind, Ap returnAp, Configuration config + ParamNodeEx p, Ap ap, ReturnPosition pos, Ap returnAp, Configuration config ) { - revFlow(p, _, TReturnCtxMaybeFlowThrough(kind), apSome(returnAp), ap, config) and - parameterFlowThroughAllowed(p, kind) + revFlow(p, _, TReturnCtxMaybeFlowThrough(pos), apSome(returnAp), ap, config) and + parameterFlowThroughAllowed(p, pos.getKind()) } pragma[nomagic] predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap, Configuration config) { - exists(RetNodeEx ret, ReturnKindExt kind | - returnFlowsThrough(ret, kind, _, _, p, ap, _, config) and - parameterFlowsThroughRev(p, ap, kind, _, config) + exists(RetNodeEx ret, ReturnPosition pos | + returnFlowsThrough(ret, pos, _, _, p, ap, _, config) and + parameterFlowsThroughRev(p, ap, pos, _, config) ) } @@ -1933,20 +1911,21 @@ private module MkStage { predicate returnMayFlowThrough( RetNodeEx ret, Ap argAp, Ap ap, ReturnKindExt kind, Configuration config ) { - exists(ParamNodeEx p | - returnFlowsThrough(ret, kind, _, _, p, argAp, ap, config) and - parameterFlowsThroughRev(p, argAp, kind, ap, config) + exists(ParamNodeEx p, ReturnPosition pos | + returnFlowsThrough(ret, pos, _, _, p, argAp, ap, config) and + parameterFlowsThroughRev(p, argAp, pos, ap, config) and + kind = pos.getKind() ) } pragma[nomagic] - predicate revFlowInToReturnIsReturned( + private predicate revFlowThroughArg( DataFlowCall call, ArgNodeEx arg, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap, Configuration config ) { - exists(ReturnKindExt returnKind0, Ap returnAp0 | - revFlowInToReturn(call, arg, state, returnKind0, returnAp0, ap, config) and - revFlowIsReturned(call, returnCtx, returnAp, returnKind0, returnAp0, config) + exists(ParamNodeEx p, ReturnPosition pos, Ap innerReturnAp | + revFlowThrough(call, returnCtx, p, state, pos, returnAp, ap, innerReturnAp, config) and + flowThroughIntoCall(call, arg, p, _, ap, innerReturnAp, config) ) } @@ -1954,7 +1933,7 @@ private module MkStage { predicate callMayFlowThroughRev(DataFlowCall call, Configuration config) { exists(ArgNodeEx arg, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap | revFlow(arg, state, returnCtx, returnAp, ap, config) and - revFlowInToReturnIsReturned(call, arg, state, returnCtx, returnAp, ap, config) + revFlowThroughArg(call, arg, state, returnCtx, returnAp, ap, config) ) } @@ -1967,8 +1946,9 @@ private module MkStage { conscand = count(TypedContent f0, Ap ap | fwdConsCand(f0, ap, config)) and states = count(FlowState state | fwdFlow(_, state, _, _, _, _, config)) and tuples = - count(NodeEx n, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - Ap ap | fwdFlow(n, state, cc, summaryCtx, argAp, ap, config)) + count(NodeEx n, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap | + fwdFlow(n, state, cc, summaryCtx, argAp, ap, config) + ) or fwd = false and nodes = count(NodeEx node | revFlow(node, _, _, _, _, config)) and @@ -2823,13 +2803,12 @@ private Configuration unbindConf(Configuration conf) { pragma[nomagic] private predicate nodeMayUseSummary0( - NodeEx n, DataFlowCallable c, ParameterPosition pos, FlowState state, AccessPathApprox apa, - Configuration config + NodeEx n, ParamNodeEx p, FlowState state, AccessPathApprox apa, Configuration config ) { exists(AccessPathApprox apa0 | - c = n.getEnclosingCallable() and + Stage5::parameterMayFlowThrough(p, _, _) and Stage5::revFlow(n, state, TReturnCtxMaybeFlowThrough(_), _, apa0, config) and - Stage5::fwdFlow(n, state, any(CallContextCall ccc), TParameterPositionSome(pos), + Stage5::fwdFlow(n, state, any(CallContextCall ccc), TParamNodeSome(p.asNode()), TAccessPathApproxSome(apa), apa0, config) ) } @@ -2838,10 +2817,9 @@ pragma[nomagic] private predicate nodeMayUseSummary( NodeEx n, FlowState state, AccessPathApprox apa, Configuration config ) { - exists(DataFlowCallable c, ParameterPosition pos, ParamNodeEx p | + exists(ParamNodeEx p | Stage5::parameterMayFlowThrough(p, apa, config) and - nodeMayUseSummary0(n, c, pos, state, apa, config) and - p.isParameterOf(c, pos) + nodeMayUseSummary0(n, p, state, apa, config) ) } diff --git a/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImplCommon.qll b/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImplCommon.qll index c66aefced8d..9aa6a529a5b 100644 --- a/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImplCommon.qll +++ b/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImplCommon.qll @@ -916,15 +916,15 @@ private module Cached { TDataFlowCallSome(DataFlowCall call) cached - newtype TParameterPositionOption = - TParameterPositionNone() or - TParameterPositionSome(ParameterPosition pos) + newtype TParamNodeOption = + TParamNodeNone() or + TParamNodeSome(ParamNode p) cached newtype TReturnCtx = TReturnCtxNone() or TReturnCtxNoFlowThrough() or - TReturnCtxMaybeFlowThrough(ReturnKindExt kind) + TReturnCtxMaybeFlowThrough(ReturnPosition pos) cached newtype TTypedContentApprox = @@ -1343,15 +1343,15 @@ class DataFlowCallOption extends TDataFlowCallOption { } } -/** An optional `ParameterPosition`. */ -class ParameterPositionOption extends TParameterPositionOption { +/** An optional `ParamNode`. */ +class ParamNodeOption extends TParamNodeOption { string toString() { - this = TParameterPositionNone() and + this = TParamNodeNone() and result = "(none)" or - exists(ParameterPosition pos | - this = TParameterPositionSome(pos) and - result = pos.toString() + exists(ParamNode p | + this = TParamNodeSome(p) and + result = p.toString() ) } } @@ -1363,7 +1363,7 @@ class ParameterPositionOption extends TParameterPositionOption { * * - `TReturnCtxNone()`: no return flow. * - `TReturnCtxNoFlowThrough()`: return flow, but flow through is not possible. - * - `TReturnCtxMaybeFlowThrough(ReturnKindExt kind)`: return flow, of kind `kind`, and + * - `TReturnCtxMaybeFlowThrough(ReturnPosition pos)`: return flow, of kind `pos`, and * flow through may be possible. */ class ReturnCtx extends TReturnCtx { @@ -1374,9 +1374,9 @@ class ReturnCtx extends TReturnCtx { this = TReturnCtxNoFlowThrough() and result = "(no flow through)" or - exists(ReturnKindExt kind | - this = TReturnCtxMaybeFlowThrough(kind) and - result = kind.toString() + exists(ReturnPosition pos | + this = TReturnCtxMaybeFlowThrough(pos) and + result = pos.toString() ) } } diff --git a/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImplForHttpClientLibraries.qll b/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImplForHttpClientLibraries.qll index 6741ccc2f06..1228d00b6ba 100644 --- a/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImplForHttpClientLibraries.qll +++ b/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImplForHttpClientLibraries.qll @@ -622,7 +622,11 @@ private predicate parameterFlowThroughAllowed(ParamNodeEx p, ReturnKindExt kind) } private module Stage1 implements StageSig { - class Ap = Unit; + class Ap extends int { + // workaround for bad functionality-induced joins (happens when using `Unit`) + pragma[nomagic] + Ap() { this in [0 .. 1] and this < 1 } + } private class Cc = boolean; @@ -1327,8 +1331,8 @@ private module MkStage { */ pragma[nomagic] additional predicate fwdFlow( - NodeEx node, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - Ap ap, ApApprox apa, Configuration config + NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, + ApApprox apa, Configuration config ) { fwdFlow0(node, state, cc, summaryCtx, argAp, ap, apa, config) and PrevStage::revFlow(node, state, apa, config) and @@ -1337,21 +1341,21 @@ private module MkStage { pragma[inline] additional predicate fwdFlow( - NodeEx node, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - Ap ap, Configuration config + NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, + Configuration config ) { fwdFlow(node, state, cc, summaryCtx, argAp, ap, _, config) } pragma[nomagic] private predicate fwdFlow0( - NodeEx node, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - Ap ap, ApApprox apa, Configuration config + NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, + ApApprox apa, Configuration config ) { sourceNode(node, state, config) and (if hasSourceCallCtx(config) then cc = ccSomeCall() else cc = ccNone()) and argAp = apNone() and - summaryCtx = TParameterPositionNone() and + summaryCtx = TParamNodeNone() and ap = getApNil(node) and apa = getApprox(ap) or @@ -1372,7 +1376,7 @@ private module MkStage { fwdFlow(mid, pragma[only_bind_into](state), _, _, _, ap, apa, pragma[only_bind_into](config)) and jumpStep(mid, node, config) and cc = ccNone() and - summaryCtx = TParameterPositionNone() and + summaryCtx = TParamNodeNone() and argAp = apNone() ) or @@ -1380,7 +1384,7 @@ private module MkStage { fwdFlow(mid, state, _, _, _, nil, pragma[only_bind_into](config)) and additionalJumpStep(mid, node, config) and cc = ccNone() and - summaryCtx = TParameterPositionNone() and + summaryCtx = TParamNodeNone() and argAp = apNone() and ap = getApNil(node) and apa = getApprox(ap) @@ -1390,7 +1394,7 @@ private module MkStage { fwdFlow(mid, state0, _, _, _, nil, pragma[only_bind_into](config)) and additionalJumpStateStep(mid, state0, node, state, config) and cc = ccNone() and - summaryCtx = TParameterPositionNone() and + summaryCtx = TParamNodeNone() and argAp = apNone() and ap = getApNil(node) and apa = getApprox(ap) @@ -1414,10 +1418,10 @@ private module MkStage { fwdFlowIn(_, node, state, _, cc, _, _, ap, apa, config) and if PrevStage::parameterMayFlowThrough(node, apa, config) then ( - summaryCtx = TParameterPositionSome(node.(ParamNodeEx).getPosition()) and + summaryCtx = TParamNodeSome(node.asNode()) and argAp = apSome(ap) ) else ( - summaryCtx = TParameterPositionNone() and argAp = apNone() + summaryCtx = TParamNodeNone() and argAp = apNone() ) or // flow out of a callable @@ -1433,16 +1437,19 @@ private module MkStage { ) or // flow through a callable - exists(DataFlowCall call, ParameterPosition summaryCtx0, Ap argAp0 | - fwdFlowOutFromArg(call, node, state, summaryCtx0, argAp0, ap, apa, config) and - fwdFlowIsEntered(call, cc, summaryCtx, argAp, summaryCtx0, argAp0, config) + exists( + DataFlowCall call, CcCall ccc, RetNodeEx ret, boolean allowsFieldFlow, ApApprox innerArgApa + | + fwdFlowThrough(call, cc, state, ccc, summaryCtx, argAp, ap, apa, ret, innerArgApa, config) and + flowThroughOutOfCall(call, ccc, ret, node, allowsFieldFlow, innerArgApa, apa, config) and + if allowsFieldFlow = false then ap instanceof ApNil else any() ) } pragma[nomagic] private predicate fwdFlowStore( NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, FlowState state, Cc cc, - ParameterPositionOption summaryCtx, ApOption argAp, Configuration config + ParamNodeOption summaryCtx, ApOption argAp, Configuration config ) { exists(DataFlowType contentType, ApApprox apa1 | fwdFlow(node1, state, cc, summaryCtx, argAp, ap1, apa1, config) and @@ -1473,8 +1480,8 @@ private module MkStage { pragma[nomagic] private predicate fwdFlowRead0( - NodeEx node1, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - ApNonNil ap, Configuration config + NodeEx node1, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, ApNonNil ap, + Configuration config ) { fwdFlow(node1, state, cc, summaryCtx, argAp, ap, config) and PrevStage::readStepCand(node1, _, _, config) @@ -1483,7 +1490,7 @@ private module MkStage { pragma[nomagic] private predicate fwdFlowRead( Ap ap, Content c, NodeEx node1, NodeEx node2, FlowState state, Cc cc, - ParameterPositionOption summaryCtx, ApOption argAp, Configuration config + ParamNodeOption summaryCtx, ApOption argAp, Configuration config ) { fwdFlowRead0(node1, state, cc, summaryCtx, argAp, ap, config) and PrevStage::readStepCand(node1, c, node2, config) and @@ -1493,7 +1500,7 @@ private module MkStage { pragma[nomagic] private predicate fwdFlowIn( DataFlowCall call, ParamNodeEx p, FlowState state, Cc outercc, CcCall innercc, - ParameterPositionOption summaryCtx, ApOption argAp, Ap ap, ApApprox apa, Configuration config + ParamNodeOption summaryCtx, ApOption argAp, Ap ap, ApApprox apa, Configuration config ) { exists(ArgNodeEx arg, boolean allowsFieldFlow | fwdFlow(arg, state, outercc, summaryCtx, argAp, ap, apa, config) and @@ -1505,64 +1512,38 @@ private module MkStage { pragma[nomagic] private predicate fwdFlowRetFromArg( - RetNodeEx ret, FlowState state, CcCall ccc, ParameterPosition summaryCtx, ParamNodeEx p, - Ap argAp, ApApprox argApa, Ap ap, ApApprox apa, Configuration config + RetNodeEx ret, FlowState state, CcCall ccc, ParamNodeEx summaryCtx, Ap argAp, ApApprox argApa, + Ap ap, ApApprox apa, Configuration config ) { - exists(DataFlowCallable c, ReturnKindExt kind | + exists(ReturnKindExt kind | fwdFlow(pragma[only_bind_into](ret), state, ccc, - TParameterPositionSome(pragma[only_bind_into](summaryCtx)), apSome(argAp), ap, apa, config) and - getApprox(argAp) = argApa and - c = ret.getEnclosingCallable() and + TParamNodeSome(pragma[only_bind_into](summaryCtx.asNode())), + pragma[only_bind_into](apSome(argAp)), ap, pragma[only_bind_into](apa), + pragma[only_bind_into](config)) and kind = ret.getKind() and - p.isParameterOf(c, pragma[only_bind_into](summaryCtx)) and - parameterFlowThroughAllowed(p, kind) + parameterFlowThroughAllowed(summaryCtx, kind) and + argApa = getApprox(argAp) and + PrevStage::returnMayFlowThrough(ret, argApa, apa, kind, pragma[only_bind_into](config)) ) } pragma[inline] - private predicate fwdFlowInMayFlowThrough( - DataFlowCall call, Cc cc, CcCall innerCc, ParameterPositionOption summaryCtx, ApOption argAp, - ParamNodeEx param, Ap ap, ApApprox apa, Configuration config + private predicate fwdFlowThrough0( + DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, + ApOption argAp, Ap ap, ApApprox apa, RetNodeEx ret, ParamNodeEx innerSummaryCtx, + Ap innerArgAp, ApApprox innerArgApa, Configuration config ) { - fwdFlowIn(call, pragma[only_bind_into](param), _, cc, innerCc, summaryCtx, argAp, ap, - pragma[only_bind_into](apa), pragma[only_bind_into](config)) and - PrevStage::parameterMayFlowThrough(param, apa, config) - } - - // dedup before joining with `flowThroughOutOfCall` - pragma[nomagic] - private predicate fwdFlowInMayFlowThroughProj( - DataFlowCall call, CcCall innerCc, ApApprox apa, Configuration config - ) { - fwdFlowInMayFlowThrough(call, _, innerCc, _, _, _, _, apa, config) - } - - /** - * Same as `flowThroughOutOfCall`, but restricted to calls that are reached - * in the flow covered by `fwdFlow`, where data might flow through the target - * callable and back out at `call`. - */ - pragma[nomagic] - private predicate fwdFlowThroughOutOfCall( - DataFlowCall call, CcCall ccc, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow, - ApApprox argApa, ApApprox apa, Configuration config - ) { - fwdFlowInMayFlowThroughProj(call, ccc, argApa, config) and - flowThroughOutOfCall(call, ccc, ret, out, allowsFieldFlow, argApa, apa, config) + fwdFlowRetFromArg(ret, state, ccc, innerSummaryCtx, innerArgAp, innerArgApa, ap, apa, config) and + fwdFlowIsEntered(call, cc, ccc, summaryCtx, argAp, innerSummaryCtx, innerArgAp, config) } pragma[nomagic] - private predicate fwdFlowOutFromArg( - DataFlowCall call, NodeEx out, FlowState state, ParameterPosition summaryCtx, Ap argAp, Ap ap, - ApApprox apa, Configuration config + private predicate fwdFlowThrough( + DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, + ApOption argAp, Ap ap, ApApprox apa, RetNodeEx ret, ApApprox innerArgApa, Configuration config ) { - exists(RetNodeEx ret, boolean allowsFieldFlow, CcCall ccc, ApApprox argApa | - fwdFlowRetFromArg(pragma[only_bind_into](ret), state, pragma[only_bind_into](ccc), - summaryCtx, _, argAp, pragma[only_bind_into](argApa), ap, pragma[only_bind_into](apa), - config) and - fwdFlowThroughOutOfCall(call, ccc, ret, out, allowsFieldFlow, argApa, apa, config) and - (if allowsFieldFlow = false then ap instanceof ApNil else any()) - ) + fwdFlowThrough0(call, cc, state, ccc, summaryCtx, argAp, ap, apa, ret, _, _, innerArgApa, + config) } /** @@ -1571,12 +1552,14 @@ private module MkStage { */ pragma[nomagic] private predicate fwdFlowIsEntered( - DataFlowCall call, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - ParameterPosition pos, Ap ap, Configuration config + DataFlowCall call, Cc cc, CcCall innerCc, ParamNodeOption summaryCtx, ApOption argAp, + ParamNodeEx p, Ap ap, Configuration config ) { - exists(ParamNodeEx param | - fwdFlowInMayFlowThrough(call, cc, _, summaryCtx, argAp, param, ap, _, config) and - pos = param.getPosition() + exists(ApApprox apa | + fwdFlowIn(call, pragma[only_bind_into](p), _, cc, innerCc, summaryCtx, argAp, ap, + pragma[only_bind_into](apa), pragma[only_bind_into](config)) and + PrevStage::parameterMayFlowThrough(p, apa, config) and + PrevStage::callMayFlowThroughRev(call, pragma[only_bind_into](config)) ) } @@ -1596,23 +1579,31 @@ private module MkStage { fwdFlowConsCand(ap1, c, ap2, config) } + pragma[nomagic] + private predicate returnFlowsThrough0( + DataFlowCall call, FlowState state, CcCall ccc, Ap ap, ApApprox apa, RetNodeEx ret, + ParamNodeEx innerSummaryCtx, Ap innerArgAp, ApApprox innerArgApa, Configuration config + ) { + fwdFlowThrough0(call, _, state, ccc, _, _, ap, apa, ret, innerSummaryCtx, innerArgAp, + innerArgApa, config) + } + pragma[nomagic] private predicate returnFlowsThrough( - RetNodeEx ret, ReturnKindExt kind, FlowState state, CcCall ccc, ParamNodeEx p, Ap argAp, + RetNodeEx ret, ReturnPosition pos, FlowState state, CcCall ccc, ParamNodeEx p, Ap argAp, Ap ap, Configuration config ) { - exists(boolean allowsFieldFlow, ApApprox argApa, ApApprox apa | - fwdFlowRetFromArg(pragma[only_bind_into](ret), state, pragma[only_bind_into](ccc), _, p, - argAp, pragma[only_bind_into](argApa), ap, pragma[only_bind_into](apa), config) and - kind = ret.getKind() and - fwdFlowThroughOutOfCall(_, ccc, ret, _, allowsFieldFlow, argApa, apa, config) and - (if allowsFieldFlow = false then ap instanceof ApNil else any()) + exists(DataFlowCall call, ApApprox apa, boolean allowsFieldFlow, ApApprox innerArgApa | + returnFlowsThrough0(call, state, ccc, ap, apa, ret, p, argAp, innerArgApa, config) and + flowThroughOutOfCall(call, ccc, ret, _, allowsFieldFlow, innerArgApa, apa, config) and + pos = ret.getReturnPosition() and + if allowsFieldFlow = false then ap instanceof ApNil else any() ) } pragma[nomagic] private predicate flowThroughIntoCall( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap argAp, + DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap argAp, Ap ap, Configuration config ) { exists(ApApprox argApa | @@ -1620,7 +1611,7 @@ private module MkStage { allowsFieldFlow, argApa, pragma[only_bind_into](config)) and fwdFlow(arg, _, _, _, _, pragma[only_bind_into](argAp), argApa, pragma[only_bind_into](config)) and - returnFlowsThrough(_, _, _, _, p, pragma[only_bind_into](argAp), _, + returnFlowsThrough(_, _, _, _, p, pragma[only_bind_into](argAp), ap, pragma[only_bind_into](config)) and if allowsFieldFlow = false then argAp instanceof ApNil else any() ) @@ -1639,12 +1630,13 @@ private module MkStage { pragma[nomagic] private predicate flowOutOfCallAp( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, boolean allowsFieldFlow, + DataFlowCall call, RetNodeEx ret, ReturnPosition pos, NodeEx out, boolean allowsFieldFlow, Ap ap, Configuration config ) { exists(ApApprox apa | - flowOutOfCallApa(call, ret, kind, out, allowsFieldFlow, apa, config) and - fwdFlow(ret, _, _, _, _, ap, apa, config) + flowOutOfCallApa(call, ret, _, out, allowsFieldFlow, apa, config) and + fwdFlow(ret, _, _, _, _, ap, apa, config) and + pos = ret.getReturnPosition() ) } @@ -1739,17 +1731,17 @@ private module MkStage { ) or // flow through a callable - exists(DataFlowCall call, ReturnKindExt returnKind0, Ap returnAp0 | - revFlowInToReturn(call, node, state, returnKind0, returnAp0, ap, config) and - revFlowIsReturned(call, returnCtx, returnAp, returnKind0, returnAp0, config) + exists(DataFlowCall call, ParamNodeEx p, ReturnPosition pos, Ap innerReturnAp | + revFlowThrough(call, returnCtx, p, state, pos, returnAp, ap, innerReturnAp, config) and + flowThroughIntoCall(call, node, p, _, ap, innerReturnAp, config) ) or // flow out of a callable - exists(ReturnKindExt kind | - revFlowOut(_, node, kind, state, _, _, ap, config) and - if returnFlowsThrough(node, kind, state, _, _, _, ap, config) + exists(ReturnPosition pos | + revFlowOut(_, node, pos, state, _, _, ap, config) and + if returnFlowsThrough(node, pos, state, _, _, _, ap, config) then ( - returnCtx = TReturnCtxMaybeFlowThrough(kind) and + returnCtx = TReturnCtxMaybeFlowThrough(pos) and returnAp = apSome(ap) ) else ( returnCtx = TReturnCtxNoFlowThrough() and returnAp = apNone() @@ -1782,47 +1774,33 @@ private module MkStage { pragma[nomagic] private predicate revFlowOut( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, FlowState state, ReturnCtx returnCtx, + DataFlowCall call, RetNodeEx ret, ReturnPosition pos, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap, Configuration config ) { exists(NodeEx out, boolean allowsFieldFlow | revFlow(out, state, returnCtx, returnAp, ap, config) and - flowOutOfCallAp(call, ret, kind, out, allowsFieldFlow, ap, config) and + flowOutOfCallAp(call, ret, pos, out, allowsFieldFlow, ap, config) and if allowsFieldFlow = false then ap instanceof ApNil else any() ) } - /** - * Same as `flowThroughIntoCall`, but restricted to calls that are reached - * in the flow covered by `revFlow`, where data might flow through the target - * callable and back out at `call`. - */ - pragma[nomagic] - private predicate revFlowThroughIntoCall( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap argAp, - Configuration config - ) { - flowThroughIntoCall(call, arg, p, allowsFieldFlow, argAp, config) and - revFlowIsReturned(call, _, _, _, _, config) - } - pragma[nomagic] private predicate revFlowParamToReturn( - ParamNodeEx p, FlowState state, ReturnKindExt kind, Ap returnAp, Ap ap, Configuration config + ParamNodeEx p, FlowState state, ReturnPosition pos, Ap returnAp, Ap ap, Configuration config ) { - revFlow(p, state, TReturnCtxMaybeFlowThrough(kind), apSome(returnAp), ap, config) and - parameterFlowThroughAllowed(p, kind) + revFlow(pragma[only_bind_into](p), state, TReturnCtxMaybeFlowThrough(pos), apSome(returnAp), + pragma[only_bind_into](ap), pragma[only_bind_into](config)) and + parameterFlowThroughAllowed(p, pos.getKind()) and + PrevStage::parameterMayFlowThrough(p, getApprox(ap), config) } pragma[nomagic] - private predicate revFlowInToReturn( - DataFlowCall call, ArgNodeEx arg, FlowState state, ReturnKindExt kind, Ap returnAp, Ap ap, - Configuration config + private predicate revFlowThrough( + DataFlowCall call, ReturnCtx returnCtx, ParamNodeEx p, FlowState state, ReturnPosition pos, + ApOption returnAp, Ap ap, Ap innerReturnAp, Configuration config ) { - exists(ParamNodeEx p, boolean allowsFieldFlow | - revFlowParamToReturn(p, state, kind, returnAp, ap, config) and - revFlowThroughIntoCall(call, arg, p, allowsFieldFlow, ap, config) - ) + revFlowParamToReturn(p, state, pos, innerReturnAp, ap, config) and + revFlowIsReturned(call, returnCtx, returnAp, pos, innerReturnAp, config) } /** @@ -1832,12 +1810,12 @@ private module MkStage { */ pragma[nomagic] private predicate revFlowIsReturned( - DataFlowCall call, ReturnCtx returnCtx, ApOption returnAp, ReturnKindExt kind, Ap ap, + DataFlowCall call, ReturnCtx returnCtx, ApOption returnAp, ReturnPosition pos, Ap ap, Configuration config ) { exists(RetNodeEx ret, FlowState state, CcCall ccc | - revFlowOut(call, ret, kind, state, returnCtx, returnAp, ap, config) and - returnFlowsThrough(ret, kind, state, ccc, _, _, ap, config) and + revFlowOut(call, ret, pos, state, returnCtx, returnAp, ap, config) and + returnFlowsThrough(ret, pos, state, ccc, _, _, ap, config) and matchesCall(ccc, call) ) } @@ -1915,17 +1893,17 @@ private module MkStage { pragma[nomagic] private predicate parameterFlowsThroughRev( - ParamNodeEx p, Ap ap, ReturnKindExt kind, Ap returnAp, Configuration config + ParamNodeEx p, Ap ap, ReturnPosition pos, Ap returnAp, Configuration config ) { - revFlow(p, _, TReturnCtxMaybeFlowThrough(kind), apSome(returnAp), ap, config) and - parameterFlowThroughAllowed(p, kind) + revFlow(p, _, TReturnCtxMaybeFlowThrough(pos), apSome(returnAp), ap, config) and + parameterFlowThroughAllowed(p, pos.getKind()) } pragma[nomagic] predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap, Configuration config) { - exists(RetNodeEx ret, ReturnKindExt kind | - returnFlowsThrough(ret, kind, _, _, p, ap, _, config) and - parameterFlowsThroughRev(p, ap, kind, _, config) + exists(RetNodeEx ret, ReturnPosition pos | + returnFlowsThrough(ret, pos, _, _, p, ap, _, config) and + parameterFlowsThroughRev(p, ap, pos, _, config) ) } @@ -1933,20 +1911,21 @@ private module MkStage { predicate returnMayFlowThrough( RetNodeEx ret, Ap argAp, Ap ap, ReturnKindExt kind, Configuration config ) { - exists(ParamNodeEx p | - returnFlowsThrough(ret, kind, _, _, p, argAp, ap, config) and - parameterFlowsThroughRev(p, argAp, kind, ap, config) + exists(ParamNodeEx p, ReturnPosition pos | + returnFlowsThrough(ret, pos, _, _, p, argAp, ap, config) and + parameterFlowsThroughRev(p, argAp, pos, ap, config) and + kind = pos.getKind() ) } pragma[nomagic] - predicate revFlowInToReturnIsReturned( + private predicate revFlowThroughArg( DataFlowCall call, ArgNodeEx arg, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap, Configuration config ) { - exists(ReturnKindExt returnKind0, Ap returnAp0 | - revFlowInToReturn(call, arg, state, returnKind0, returnAp0, ap, config) and - revFlowIsReturned(call, returnCtx, returnAp, returnKind0, returnAp0, config) + exists(ParamNodeEx p, ReturnPosition pos, Ap innerReturnAp | + revFlowThrough(call, returnCtx, p, state, pos, returnAp, ap, innerReturnAp, config) and + flowThroughIntoCall(call, arg, p, _, ap, innerReturnAp, config) ) } @@ -1954,7 +1933,7 @@ private module MkStage { predicate callMayFlowThroughRev(DataFlowCall call, Configuration config) { exists(ArgNodeEx arg, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap | revFlow(arg, state, returnCtx, returnAp, ap, config) and - revFlowInToReturnIsReturned(call, arg, state, returnCtx, returnAp, ap, config) + revFlowThroughArg(call, arg, state, returnCtx, returnAp, ap, config) ) } @@ -1967,8 +1946,9 @@ private module MkStage { conscand = count(TypedContent f0, Ap ap | fwdConsCand(f0, ap, config)) and states = count(FlowState state | fwdFlow(_, state, _, _, _, _, config)) and tuples = - count(NodeEx n, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - Ap ap | fwdFlow(n, state, cc, summaryCtx, argAp, ap, config)) + count(NodeEx n, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap | + fwdFlow(n, state, cc, summaryCtx, argAp, ap, config) + ) or fwd = false and nodes = count(NodeEx node | revFlow(node, _, _, _, _, config)) and @@ -2823,13 +2803,12 @@ private Configuration unbindConf(Configuration conf) { pragma[nomagic] private predicate nodeMayUseSummary0( - NodeEx n, DataFlowCallable c, ParameterPosition pos, FlowState state, AccessPathApprox apa, - Configuration config + NodeEx n, ParamNodeEx p, FlowState state, AccessPathApprox apa, Configuration config ) { exists(AccessPathApprox apa0 | - c = n.getEnclosingCallable() and + Stage5::parameterMayFlowThrough(p, _, _) and Stage5::revFlow(n, state, TReturnCtxMaybeFlowThrough(_), _, apa0, config) and - Stage5::fwdFlow(n, state, any(CallContextCall ccc), TParameterPositionSome(pos), + Stage5::fwdFlow(n, state, any(CallContextCall ccc), TParamNodeSome(p.asNode()), TAccessPathApproxSome(apa), apa0, config) ) } @@ -2838,10 +2817,9 @@ pragma[nomagic] private predicate nodeMayUseSummary( NodeEx n, FlowState state, AccessPathApprox apa, Configuration config ) { - exists(DataFlowCallable c, ParameterPosition pos, ParamNodeEx p | + exists(ParamNodeEx p | Stage5::parameterMayFlowThrough(p, apa, config) and - nodeMayUseSummary0(n, c, pos, state, apa, config) and - p.isParameterOf(c, pos) + nodeMayUseSummary0(n, p, state, apa, config) ) } diff --git a/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImplForPathname.qll b/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImplForPathname.qll index 6741ccc2f06..1228d00b6ba 100644 --- a/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImplForPathname.qll +++ b/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImplForPathname.qll @@ -622,7 +622,11 @@ private predicate parameterFlowThroughAllowed(ParamNodeEx p, ReturnKindExt kind) } private module Stage1 implements StageSig { - class Ap = Unit; + class Ap extends int { + // workaround for bad functionality-induced joins (happens when using `Unit`) + pragma[nomagic] + Ap() { this in [0 .. 1] and this < 1 } + } private class Cc = boolean; @@ -1327,8 +1331,8 @@ private module MkStage { */ pragma[nomagic] additional predicate fwdFlow( - NodeEx node, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - Ap ap, ApApprox apa, Configuration config + NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, + ApApprox apa, Configuration config ) { fwdFlow0(node, state, cc, summaryCtx, argAp, ap, apa, config) and PrevStage::revFlow(node, state, apa, config) and @@ -1337,21 +1341,21 @@ private module MkStage { pragma[inline] additional predicate fwdFlow( - NodeEx node, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - Ap ap, Configuration config + NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, + Configuration config ) { fwdFlow(node, state, cc, summaryCtx, argAp, ap, _, config) } pragma[nomagic] private predicate fwdFlow0( - NodeEx node, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - Ap ap, ApApprox apa, Configuration config + NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, + ApApprox apa, Configuration config ) { sourceNode(node, state, config) and (if hasSourceCallCtx(config) then cc = ccSomeCall() else cc = ccNone()) and argAp = apNone() and - summaryCtx = TParameterPositionNone() and + summaryCtx = TParamNodeNone() and ap = getApNil(node) and apa = getApprox(ap) or @@ -1372,7 +1376,7 @@ private module MkStage { fwdFlow(mid, pragma[only_bind_into](state), _, _, _, ap, apa, pragma[only_bind_into](config)) and jumpStep(mid, node, config) and cc = ccNone() and - summaryCtx = TParameterPositionNone() and + summaryCtx = TParamNodeNone() and argAp = apNone() ) or @@ -1380,7 +1384,7 @@ private module MkStage { fwdFlow(mid, state, _, _, _, nil, pragma[only_bind_into](config)) and additionalJumpStep(mid, node, config) and cc = ccNone() and - summaryCtx = TParameterPositionNone() and + summaryCtx = TParamNodeNone() and argAp = apNone() and ap = getApNil(node) and apa = getApprox(ap) @@ -1390,7 +1394,7 @@ private module MkStage { fwdFlow(mid, state0, _, _, _, nil, pragma[only_bind_into](config)) and additionalJumpStateStep(mid, state0, node, state, config) and cc = ccNone() and - summaryCtx = TParameterPositionNone() and + summaryCtx = TParamNodeNone() and argAp = apNone() and ap = getApNil(node) and apa = getApprox(ap) @@ -1414,10 +1418,10 @@ private module MkStage { fwdFlowIn(_, node, state, _, cc, _, _, ap, apa, config) and if PrevStage::parameterMayFlowThrough(node, apa, config) then ( - summaryCtx = TParameterPositionSome(node.(ParamNodeEx).getPosition()) and + summaryCtx = TParamNodeSome(node.asNode()) and argAp = apSome(ap) ) else ( - summaryCtx = TParameterPositionNone() and argAp = apNone() + summaryCtx = TParamNodeNone() and argAp = apNone() ) or // flow out of a callable @@ -1433,16 +1437,19 @@ private module MkStage { ) or // flow through a callable - exists(DataFlowCall call, ParameterPosition summaryCtx0, Ap argAp0 | - fwdFlowOutFromArg(call, node, state, summaryCtx0, argAp0, ap, apa, config) and - fwdFlowIsEntered(call, cc, summaryCtx, argAp, summaryCtx0, argAp0, config) + exists( + DataFlowCall call, CcCall ccc, RetNodeEx ret, boolean allowsFieldFlow, ApApprox innerArgApa + | + fwdFlowThrough(call, cc, state, ccc, summaryCtx, argAp, ap, apa, ret, innerArgApa, config) and + flowThroughOutOfCall(call, ccc, ret, node, allowsFieldFlow, innerArgApa, apa, config) and + if allowsFieldFlow = false then ap instanceof ApNil else any() ) } pragma[nomagic] private predicate fwdFlowStore( NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, FlowState state, Cc cc, - ParameterPositionOption summaryCtx, ApOption argAp, Configuration config + ParamNodeOption summaryCtx, ApOption argAp, Configuration config ) { exists(DataFlowType contentType, ApApprox apa1 | fwdFlow(node1, state, cc, summaryCtx, argAp, ap1, apa1, config) and @@ -1473,8 +1480,8 @@ private module MkStage { pragma[nomagic] private predicate fwdFlowRead0( - NodeEx node1, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - ApNonNil ap, Configuration config + NodeEx node1, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, ApNonNil ap, + Configuration config ) { fwdFlow(node1, state, cc, summaryCtx, argAp, ap, config) and PrevStage::readStepCand(node1, _, _, config) @@ -1483,7 +1490,7 @@ private module MkStage { pragma[nomagic] private predicate fwdFlowRead( Ap ap, Content c, NodeEx node1, NodeEx node2, FlowState state, Cc cc, - ParameterPositionOption summaryCtx, ApOption argAp, Configuration config + ParamNodeOption summaryCtx, ApOption argAp, Configuration config ) { fwdFlowRead0(node1, state, cc, summaryCtx, argAp, ap, config) and PrevStage::readStepCand(node1, c, node2, config) and @@ -1493,7 +1500,7 @@ private module MkStage { pragma[nomagic] private predicate fwdFlowIn( DataFlowCall call, ParamNodeEx p, FlowState state, Cc outercc, CcCall innercc, - ParameterPositionOption summaryCtx, ApOption argAp, Ap ap, ApApprox apa, Configuration config + ParamNodeOption summaryCtx, ApOption argAp, Ap ap, ApApprox apa, Configuration config ) { exists(ArgNodeEx arg, boolean allowsFieldFlow | fwdFlow(arg, state, outercc, summaryCtx, argAp, ap, apa, config) and @@ -1505,64 +1512,38 @@ private module MkStage { pragma[nomagic] private predicate fwdFlowRetFromArg( - RetNodeEx ret, FlowState state, CcCall ccc, ParameterPosition summaryCtx, ParamNodeEx p, - Ap argAp, ApApprox argApa, Ap ap, ApApprox apa, Configuration config + RetNodeEx ret, FlowState state, CcCall ccc, ParamNodeEx summaryCtx, Ap argAp, ApApprox argApa, + Ap ap, ApApprox apa, Configuration config ) { - exists(DataFlowCallable c, ReturnKindExt kind | + exists(ReturnKindExt kind | fwdFlow(pragma[only_bind_into](ret), state, ccc, - TParameterPositionSome(pragma[only_bind_into](summaryCtx)), apSome(argAp), ap, apa, config) and - getApprox(argAp) = argApa and - c = ret.getEnclosingCallable() and + TParamNodeSome(pragma[only_bind_into](summaryCtx.asNode())), + pragma[only_bind_into](apSome(argAp)), ap, pragma[only_bind_into](apa), + pragma[only_bind_into](config)) and kind = ret.getKind() and - p.isParameterOf(c, pragma[only_bind_into](summaryCtx)) and - parameterFlowThroughAllowed(p, kind) + parameterFlowThroughAllowed(summaryCtx, kind) and + argApa = getApprox(argAp) and + PrevStage::returnMayFlowThrough(ret, argApa, apa, kind, pragma[only_bind_into](config)) ) } pragma[inline] - private predicate fwdFlowInMayFlowThrough( - DataFlowCall call, Cc cc, CcCall innerCc, ParameterPositionOption summaryCtx, ApOption argAp, - ParamNodeEx param, Ap ap, ApApprox apa, Configuration config + private predicate fwdFlowThrough0( + DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, + ApOption argAp, Ap ap, ApApprox apa, RetNodeEx ret, ParamNodeEx innerSummaryCtx, + Ap innerArgAp, ApApprox innerArgApa, Configuration config ) { - fwdFlowIn(call, pragma[only_bind_into](param), _, cc, innerCc, summaryCtx, argAp, ap, - pragma[only_bind_into](apa), pragma[only_bind_into](config)) and - PrevStage::parameterMayFlowThrough(param, apa, config) - } - - // dedup before joining with `flowThroughOutOfCall` - pragma[nomagic] - private predicate fwdFlowInMayFlowThroughProj( - DataFlowCall call, CcCall innerCc, ApApprox apa, Configuration config - ) { - fwdFlowInMayFlowThrough(call, _, innerCc, _, _, _, _, apa, config) - } - - /** - * Same as `flowThroughOutOfCall`, but restricted to calls that are reached - * in the flow covered by `fwdFlow`, where data might flow through the target - * callable and back out at `call`. - */ - pragma[nomagic] - private predicate fwdFlowThroughOutOfCall( - DataFlowCall call, CcCall ccc, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow, - ApApprox argApa, ApApprox apa, Configuration config - ) { - fwdFlowInMayFlowThroughProj(call, ccc, argApa, config) and - flowThroughOutOfCall(call, ccc, ret, out, allowsFieldFlow, argApa, apa, config) + fwdFlowRetFromArg(ret, state, ccc, innerSummaryCtx, innerArgAp, innerArgApa, ap, apa, config) and + fwdFlowIsEntered(call, cc, ccc, summaryCtx, argAp, innerSummaryCtx, innerArgAp, config) } pragma[nomagic] - private predicate fwdFlowOutFromArg( - DataFlowCall call, NodeEx out, FlowState state, ParameterPosition summaryCtx, Ap argAp, Ap ap, - ApApprox apa, Configuration config + private predicate fwdFlowThrough( + DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, + ApOption argAp, Ap ap, ApApprox apa, RetNodeEx ret, ApApprox innerArgApa, Configuration config ) { - exists(RetNodeEx ret, boolean allowsFieldFlow, CcCall ccc, ApApprox argApa | - fwdFlowRetFromArg(pragma[only_bind_into](ret), state, pragma[only_bind_into](ccc), - summaryCtx, _, argAp, pragma[only_bind_into](argApa), ap, pragma[only_bind_into](apa), - config) and - fwdFlowThroughOutOfCall(call, ccc, ret, out, allowsFieldFlow, argApa, apa, config) and - (if allowsFieldFlow = false then ap instanceof ApNil else any()) - ) + fwdFlowThrough0(call, cc, state, ccc, summaryCtx, argAp, ap, apa, ret, _, _, innerArgApa, + config) } /** @@ -1571,12 +1552,14 @@ private module MkStage { */ pragma[nomagic] private predicate fwdFlowIsEntered( - DataFlowCall call, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - ParameterPosition pos, Ap ap, Configuration config + DataFlowCall call, Cc cc, CcCall innerCc, ParamNodeOption summaryCtx, ApOption argAp, + ParamNodeEx p, Ap ap, Configuration config ) { - exists(ParamNodeEx param | - fwdFlowInMayFlowThrough(call, cc, _, summaryCtx, argAp, param, ap, _, config) and - pos = param.getPosition() + exists(ApApprox apa | + fwdFlowIn(call, pragma[only_bind_into](p), _, cc, innerCc, summaryCtx, argAp, ap, + pragma[only_bind_into](apa), pragma[only_bind_into](config)) and + PrevStage::parameterMayFlowThrough(p, apa, config) and + PrevStage::callMayFlowThroughRev(call, pragma[only_bind_into](config)) ) } @@ -1596,23 +1579,31 @@ private module MkStage { fwdFlowConsCand(ap1, c, ap2, config) } + pragma[nomagic] + private predicate returnFlowsThrough0( + DataFlowCall call, FlowState state, CcCall ccc, Ap ap, ApApprox apa, RetNodeEx ret, + ParamNodeEx innerSummaryCtx, Ap innerArgAp, ApApprox innerArgApa, Configuration config + ) { + fwdFlowThrough0(call, _, state, ccc, _, _, ap, apa, ret, innerSummaryCtx, innerArgAp, + innerArgApa, config) + } + pragma[nomagic] private predicate returnFlowsThrough( - RetNodeEx ret, ReturnKindExt kind, FlowState state, CcCall ccc, ParamNodeEx p, Ap argAp, + RetNodeEx ret, ReturnPosition pos, FlowState state, CcCall ccc, ParamNodeEx p, Ap argAp, Ap ap, Configuration config ) { - exists(boolean allowsFieldFlow, ApApprox argApa, ApApprox apa | - fwdFlowRetFromArg(pragma[only_bind_into](ret), state, pragma[only_bind_into](ccc), _, p, - argAp, pragma[only_bind_into](argApa), ap, pragma[only_bind_into](apa), config) and - kind = ret.getKind() and - fwdFlowThroughOutOfCall(_, ccc, ret, _, allowsFieldFlow, argApa, apa, config) and - (if allowsFieldFlow = false then ap instanceof ApNil else any()) + exists(DataFlowCall call, ApApprox apa, boolean allowsFieldFlow, ApApprox innerArgApa | + returnFlowsThrough0(call, state, ccc, ap, apa, ret, p, argAp, innerArgApa, config) and + flowThroughOutOfCall(call, ccc, ret, _, allowsFieldFlow, innerArgApa, apa, config) and + pos = ret.getReturnPosition() and + if allowsFieldFlow = false then ap instanceof ApNil else any() ) } pragma[nomagic] private predicate flowThroughIntoCall( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap argAp, + DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap argAp, Ap ap, Configuration config ) { exists(ApApprox argApa | @@ -1620,7 +1611,7 @@ private module MkStage { allowsFieldFlow, argApa, pragma[only_bind_into](config)) and fwdFlow(arg, _, _, _, _, pragma[only_bind_into](argAp), argApa, pragma[only_bind_into](config)) and - returnFlowsThrough(_, _, _, _, p, pragma[only_bind_into](argAp), _, + returnFlowsThrough(_, _, _, _, p, pragma[only_bind_into](argAp), ap, pragma[only_bind_into](config)) and if allowsFieldFlow = false then argAp instanceof ApNil else any() ) @@ -1639,12 +1630,13 @@ private module MkStage { pragma[nomagic] private predicate flowOutOfCallAp( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, boolean allowsFieldFlow, + DataFlowCall call, RetNodeEx ret, ReturnPosition pos, NodeEx out, boolean allowsFieldFlow, Ap ap, Configuration config ) { exists(ApApprox apa | - flowOutOfCallApa(call, ret, kind, out, allowsFieldFlow, apa, config) and - fwdFlow(ret, _, _, _, _, ap, apa, config) + flowOutOfCallApa(call, ret, _, out, allowsFieldFlow, apa, config) and + fwdFlow(ret, _, _, _, _, ap, apa, config) and + pos = ret.getReturnPosition() ) } @@ -1739,17 +1731,17 @@ private module MkStage { ) or // flow through a callable - exists(DataFlowCall call, ReturnKindExt returnKind0, Ap returnAp0 | - revFlowInToReturn(call, node, state, returnKind0, returnAp0, ap, config) and - revFlowIsReturned(call, returnCtx, returnAp, returnKind0, returnAp0, config) + exists(DataFlowCall call, ParamNodeEx p, ReturnPosition pos, Ap innerReturnAp | + revFlowThrough(call, returnCtx, p, state, pos, returnAp, ap, innerReturnAp, config) and + flowThroughIntoCall(call, node, p, _, ap, innerReturnAp, config) ) or // flow out of a callable - exists(ReturnKindExt kind | - revFlowOut(_, node, kind, state, _, _, ap, config) and - if returnFlowsThrough(node, kind, state, _, _, _, ap, config) + exists(ReturnPosition pos | + revFlowOut(_, node, pos, state, _, _, ap, config) and + if returnFlowsThrough(node, pos, state, _, _, _, ap, config) then ( - returnCtx = TReturnCtxMaybeFlowThrough(kind) and + returnCtx = TReturnCtxMaybeFlowThrough(pos) and returnAp = apSome(ap) ) else ( returnCtx = TReturnCtxNoFlowThrough() and returnAp = apNone() @@ -1782,47 +1774,33 @@ private module MkStage { pragma[nomagic] private predicate revFlowOut( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, FlowState state, ReturnCtx returnCtx, + DataFlowCall call, RetNodeEx ret, ReturnPosition pos, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap, Configuration config ) { exists(NodeEx out, boolean allowsFieldFlow | revFlow(out, state, returnCtx, returnAp, ap, config) and - flowOutOfCallAp(call, ret, kind, out, allowsFieldFlow, ap, config) and + flowOutOfCallAp(call, ret, pos, out, allowsFieldFlow, ap, config) and if allowsFieldFlow = false then ap instanceof ApNil else any() ) } - /** - * Same as `flowThroughIntoCall`, but restricted to calls that are reached - * in the flow covered by `revFlow`, where data might flow through the target - * callable and back out at `call`. - */ - pragma[nomagic] - private predicate revFlowThroughIntoCall( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap argAp, - Configuration config - ) { - flowThroughIntoCall(call, arg, p, allowsFieldFlow, argAp, config) and - revFlowIsReturned(call, _, _, _, _, config) - } - pragma[nomagic] private predicate revFlowParamToReturn( - ParamNodeEx p, FlowState state, ReturnKindExt kind, Ap returnAp, Ap ap, Configuration config + ParamNodeEx p, FlowState state, ReturnPosition pos, Ap returnAp, Ap ap, Configuration config ) { - revFlow(p, state, TReturnCtxMaybeFlowThrough(kind), apSome(returnAp), ap, config) and - parameterFlowThroughAllowed(p, kind) + revFlow(pragma[only_bind_into](p), state, TReturnCtxMaybeFlowThrough(pos), apSome(returnAp), + pragma[only_bind_into](ap), pragma[only_bind_into](config)) and + parameterFlowThroughAllowed(p, pos.getKind()) and + PrevStage::parameterMayFlowThrough(p, getApprox(ap), config) } pragma[nomagic] - private predicate revFlowInToReturn( - DataFlowCall call, ArgNodeEx arg, FlowState state, ReturnKindExt kind, Ap returnAp, Ap ap, - Configuration config + private predicate revFlowThrough( + DataFlowCall call, ReturnCtx returnCtx, ParamNodeEx p, FlowState state, ReturnPosition pos, + ApOption returnAp, Ap ap, Ap innerReturnAp, Configuration config ) { - exists(ParamNodeEx p, boolean allowsFieldFlow | - revFlowParamToReturn(p, state, kind, returnAp, ap, config) and - revFlowThroughIntoCall(call, arg, p, allowsFieldFlow, ap, config) - ) + revFlowParamToReturn(p, state, pos, innerReturnAp, ap, config) and + revFlowIsReturned(call, returnCtx, returnAp, pos, innerReturnAp, config) } /** @@ -1832,12 +1810,12 @@ private module MkStage { */ pragma[nomagic] private predicate revFlowIsReturned( - DataFlowCall call, ReturnCtx returnCtx, ApOption returnAp, ReturnKindExt kind, Ap ap, + DataFlowCall call, ReturnCtx returnCtx, ApOption returnAp, ReturnPosition pos, Ap ap, Configuration config ) { exists(RetNodeEx ret, FlowState state, CcCall ccc | - revFlowOut(call, ret, kind, state, returnCtx, returnAp, ap, config) and - returnFlowsThrough(ret, kind, state, ccc, _, _, ap, config) and + revFlowOut(call, ret, pos, state, returnCtx, returnAp, ap, config) and + returnFlowsThrough(ret, pos, state, ccc, _, _, ap, config) and matchesCall(ccc, call) ) } @@ -1915,17 +1893,17 @@ private module MkStage { pragma[nomagic] private predicate parameterFlowsThroughRev( - ParamNodeEx p, Ap ap, ReturnKindExt kind, Ap returnAp, Configuration config + ParamNodeEx p, Ap ap, ReturnPosition pos, Ap returnAp, Configuration config ) { - revFlow(p, _, TReturnCtxMaybeFlowThrough(kind), apSome(returnAp), ap, config) and - parameterFlowThroughAllowed(p, kind) + revFlow(p, _, TReturnCtxMaybeFlowThrough(pos), apSome(returnAp), ap, config) and + parameterFlowThroughAllowed(p, pos.getKind()) } pragma[nomagic] predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap, Configuration config) { - exists(RetNodeEx ret, ReturnKindExt kind | - returnFlowsThrough(ret, kind, _, _, p, ap, _, config) and - parameterFlowsThroughRev(p, ap, kind, _, config) + exists(RetNodeEx ret, ReturnPosition pos | + returnFlowsThrough(ret, pos, _, _, p, ap, _, config) and + parameterFlowsThroughRev(p, ap, pos, _, config) ) } @@ -1933,20 +1911,21 @@ private module MkStage { predicate returnMayFlowThrough( RetNodeEx ret, Ap argAp, Ap ap, ReturnKindExt kind, Configuration config ) { - exists(ParamNodeEx p | - returnFlowsThrough(ret, kind, _, _, p, argAp, ap, config) and - parameterFlowsThroughRev(p, argAp, kind, ap, config) + exists(ParamNodeEx p, ReturnPosition pos | + returnFlowsThrough(ret, pos, _, _, p, argAp, ap, config) and + parameterFlowsThroughRev(p, argAp, pos, ap, config) and + kind = pos.getKind() ) } pragma[nomagic] - predicate revFlowInToReturnIsReturned( + private predicate revFlowThroughArg( DataFlowCall call, ArgNodeEx arg, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap, Configuration config ) { - exists(ReturnKindExt returnKind0, Ap returnAp0 | - revFlowInToReturn(call, arg, state, returnKind0, returnAp0, ap, config) and - revFlowIsReturned(call, returnCtx, returnAp, returnKind0, returnAp0, config) + exists(ParamNodeEx p, ReturnPosition pos, Ap innerReturnAp | + revFlowThrough(call, returnCtx, p, state, pos, returnAp, ap, innerReturnAp, config) and + flowThroughIntoCall(call, arg, p, _, ap, innerReturnAp, config) ) } @@ -1954,7 +1933,7 @@ private module MkStage { predicate callMayFlowThroughRev(DataFlowCall call, Configuration config) { exists(ArgNodeEx arg, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap | revFlow(arg, state, returnCtx, returnAp, ap, config) and - revFlowInToReturnIsReturned(call, arg, state, returnCtx, returnAp, ap, config) + revFlowThroughArg(call, arg, state, returnCtx, returnAp, ap, config) ) } @@ -1967,8 +1946,9 @@ private module MkStage { conscand = count(TypedContent f0, Ap ap | fwdConsCand(f0, ap, config)) and states = count(FlowState state | fwdFlow(_, state, _, _, _, _, config)) and tuples = - count(NodeEx n, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - Ap ap | fwdFlow(n, state, cc, summaryCtx, argAp, ap, config)) + count(NodeEx n, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap | + fwdFlow(n, state, cc, summaryCtx, argAp, ap, config) + ) or fwd = false and nodes = count(NodeEx node | revFlow(node, _, _, _, _, config)) and @@ -2823,13 +2803,12 @@ private Configuration unbindConf(Configuration conf) { pragma[nomagic] private predicate nodeMayUseSummary0( - NodeEx n, DataFlowCallable c, ParameterPosition pos, FlowState state, AccessPathApprox apa, - Configuration config + NodeEx n, ParamNodeEx p, FlowState state, AccessPathApprox apa, Configuration config ) { exists(AccessPathApprox apa0 | - c = n.getEnclosingCallable() and + Stage5::parameterMayFlowThrough(p, _, _) and Stage5::revFlow(n, state, TReturnCtxMaybeFlowThrough(_), _, apa0, config) and - Stage5::fwdFlow(n, state, any(CallContextCall ccc), TParameterPositionSome(pos), + Stage5::fwdFlow(n, state, any(CallContextCall ccc), TParamNodeSome(p.asNode()), TAccessPathApproxSome(apa), apa0, config) ) } @@ -2838,10 +2817,9 @@ pragma[nomagic] private predicate nodeMayUseSummary( NodeEx n, FlowState state, AccessPathApprox apa, Configuration config ) { - exists(DataFlowCallable c, ParameterPosition pos, ParamNodeEx p | + exists(ParamNodeEx p | Stage5::parameterMayFlowThrough(p, apa, config) and - nodeMayUseSummary0(n, c, pos, state, apa, config) and - p.isParameterOf(c, pos) + nodeMayUseSummary0(n, p, state, apa, config) ) } diff --git a/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImplForRegExp.qll b/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImplForRegExp.qll index 6741ccc2f06..1228d00b6ba 100644 --- a/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImplForRegExp.qll +++ b/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImplForRegExp.qll @@ -622,7 +622,11 @@ private predicate parameterFlowThroughAllowed(ParamNodeEx p, ReturnKindExt kind) } private module Stage1 implements StageSig { - class Ap = Unit; + class Ap extends int { + // workaround for bad functionality-induced joins (happens when using `Unit`) + pragma[nomagic] + Ap() { this in [0 .. 1] and this < 1 } + } private class Cc = boolean; @@ -1327,8 +1331,8 @@ private module MkStage { */ pragma[nomagic] additional predicate fwdFlow( - NodeEx node, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - Ap ap, ApApprox apa, Configuration config + NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, + ApApprox apa, Configuration config ) { fwdFlow0(node, state, cc, summaryCtx, argAp, ap, apa, config) and PrevStage::revFlow(node, state, apa, config) and @@ -1337,21 +1341,21 @@ private module MkStage { pragma[inline] additional predicate fwdFlow( - NodeEx node, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - Ap ap, Configuration config + NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, + Configuration config ) { fwdFlow(node, state, cc, summaryCtx, argAp, ap, _, config) } pragma[nomagic] private predicate fwdFlow0( - NodeEx node, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - Ap ap, ApApprox apa, Configuration config + NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, + ApApprox apa, Configuration config ) { sourceNode(node, state, config) and (if hasSourceCallCtx(config) then cc = ccSomeCall() else cc = ccNone()) and argAp = apNone() and - summaryCtx = TParameterPositionNone() and + summaryCtx = TParamNodeNone() and ap = getApNil(node) and apa = getApprox(ap) or @@ -1372,7 +1376,7 @@ private module MkStage { fwdFlow(mid, pragma[only_bind_into](state), _, _, _, ap, apa, pragma[only_bind_into](config)) and jumpStep(mid, node, config) and cc = ccNone() and - summaryCtx = TParameterPositionNone() and + summaryCtx = TParamNodeNone() and argAp = apNone() ) or @@ -1380,7 +1384,7 @@ private module MkStage { fwdFlow(mid, state, _, _, _, nil, pragma[only_bind_into](config)) and additionalJumpStep(mid, node, config) and cc = ccNone() and - summaryCtx = TParameterPositionNone() and + summaryCtx = TParamNodeNone() and argAp = apNone() and ap = getApNil(node) and apa = getApprox(ap) @@ -1390,7 +1394,7 @@ private module MkStage { fwdFlow(mid, state0, _, _, _, nil, pragma[only_bind_into](config)) and additionalJumpStateStep(mid, state0, node, state, config) and cc = ccNone() and - summaryCtx = TParameterPositionNone() and + summaryCtx = TParamNodeNone() and argAp = apNone() and ap = getApNil(node) and apa = getApprox(ap) @@ -1414,10 +1418,10 @@ private module MkStage { fwdFlowIn(_, node, state, _, cc, _, _, ap, apa, config) and if PrevStage::parameterMayFlowThrough(node, apa, config) then ( - summaryCtx = TParameterPositionSome(node.(ParamNodeEx).getPosition()) and + summaryCtx = TParamNodeSome(node.asNode()) and argAp = apSome(ap) ) else ( - summaryCtx = TParameterPositionNone() and argAp = apNone() + summaryCtx = TParamNodeNone() and argAp = apNone() ) or // flow out of a callable @@ -1433,16 +1437,19 @@ private module MkStage { ) or // flow through a callable - exists(DataFlowCall call, ParameterPosition summaryCtx0, Ap argAp0 | - fwdFlowOutFromArg(call, node, state, summaryCtx0, argAp0, ap, apa, config) and - fwdFlowIsEntered(call, cc, summaryCtx, argAp, summaryCtx0, argAp0, config) + exists( + DataFlowCall call, CcCall ccc, RetNodeEx ret, boolean allowsFieldFlow, ApApprox innerArgApa + | + fwdFlowThrough(call, cc, state, ccc, summaryCtx, argAp, ap, apa, ret, innerArgApa, config) and + flowThroughOutOfCall(call, ccc, ret, node, allowsFieldFlow, innerArgApa, apa, config) and + if allowsFieldFlow = false then ap instanceof ApNil else any() ) } pragma[nomagic] private predicate fwdFlowStore( NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, FlowState state, Cc cc, - ParameterPositionOption summaryCtx, ApOption argAp, Configuration config + ParamNodeOption summaryCtx, ApOption argAp, Configuration config ) { exists(DataFlowType contentType, ApApprox apa1 | fwdFlow(node1, state, cc, summaryCtx, argAp, ap1, apa1, config) and @@ -1473,8 +1480,8 @@ private module MkStage { pragma[nomagic] private predicate fwdFlowRead0( - NodeEx node1, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - ApNonNil ap, Configuration config + NodeEx node1, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, ApNonNil ap, + Configuration config ) { fwdFlow(node1, state, cc, summaryCtx, argAp, ap, config) and PrevStage::readStepCand(node1, _, _, config) @@ -1483,7 +1490,7 @@ private module MkStage { pragma[nomagic] private predicate fwdFlowRead( Ap ap, Content c, NodeEx node1, NodeEx node2, FlowState state, Cc cc, - ParameterPositionOption summaryCtx, ApOption argAp, Configuration config + ParamNodeOption summaryCtx, ApOption argAp, Configuration config ) { fwdFlowRead0(node1, state, cc, summaryCtx, argAp, ap, config) and PrevStage::readStepCand(node1, c, node2, config) and @@ -1493,7 +1500,7 @@ private module MkStage { pragma[nomagic] private predicate fwdFlowIn( DataFlowCall call, ParamNodeEx p, FlowState state, Cc outercc, CcCall innercc, - ParameterPositionOption summaryCtx, ApOption argAp, Ap ap, ApApprox apa, Configuration config + ParamNodeOption summaryCtx, ApOption argAp, Ap ap, ApApprox apa, Configuration config ) { exists(ArgNodeEx arg, boolean allowsFieldFlow | fwdFlow(arg, state, outercc, summaryCtx, argAp, ap, apa, config) and @@ -1505,64 +1512,38 @@ private module MkStage { pragma[nomagic] private predicate fwdFlowRetFromArg( - RetNodeEx ret, FlowState state, CcCall ccc, ParameterPosition summaryCtx, ParamNodeEx p, - Ap argAp, ApApprox argApa, Ap ap, ApApprox apa, Configuration config + RetNodeEx ret, FlowState state, CcCall ccc, ParamNodeEx summaryCtx, Ap argAp, ApApprox argApa, + Ap ap, ApApprox apa, Configuration config ) { - exists(DataFlowCallable c, ReturnKindExt kind | + exists(ReturnKindExt kind | fwdFlow(pragma[only_bind_into](ret), state, ccc, - TParameterPositionSome(pragma[only_bind_into](summaryCtx)), apSome(argAp), ap, apa, config) and - getApprox(argAp) = argApa and - c = ret.getEnclosingCallable() and + TParamNodeSome(pragma[only_bind_into](summaryCtx.asNode())), + pragma[only_bind_into](apSome(argAp)), ap, pragma[only_bind_into](apa), + pragma[only_bind_into](config)) and kind = ret.getKind() and - p.isParameterOf(c, pragma[only_bind_into](summaryCtx)) and - parameterFlowThroughAllowed(p, kind) + parameterFlowThroughAllowed(summaryCtx, kind) and + argApa = getApprox(argAp) and + PrevStage::returnMayFlowThrough(ret, argApa, apa, kind, pragma[only_bind_into](config)) ) } pragma[inline] - private predicate fwdFlowInMayFlowThrough( - DataFlowCall call, Cc cc, CcCall innerCc, ParameterPositionOption summaryCtx, ApOption argAp, - ParamNodeEx param, Ap ap, ApApprox apa, Configuration config + private predicate fwdFlowThrough0( + DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, + ApOption argAp, Ap ap, ApApprox apa, RetNodeEx ret, ParamNodeEx innerSummaryCtx, + Ap innerArgAp, ApApprox innerArgApa, Configuration config ) { - fwdFlowIn(call, pragma[only_bind_into](param), _, cc, innerCc, summaryCtx, argAp, ap, - pragma[only_bind_into](apa), pragma[only_bind_into](config)) and - PrevStage::parameterMayFlowThrough(param, apa, config) - } - - // dedup before joining with `flowThroughOutOfCall` - pragma[nomagic] - private predicate fwdFlowInMayFlowThroughProj( - DataFlowCall call, CcCall innerCc, ApApprox apa, Configuration config - ) { - fwdFlowInMayFlowThrough(call, _, innerCc, _, _, _, _, apa, config) - } - - /** - * Same as `flowThroughOutOfCall`, but restricted to calls that are reached - * in the flow covered by `fwdFlow`, where data might flow through the target - * callable and back out at `call`. - */ - pragma[nomagic] - private predicate fwdFlowThroughOutOfCall( - DataFlowCall call, CcCall ccc, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow, - ApApprox argApa, ApApprox apa, Configuration config - ) { - fwdFlowInMayFlowThroughProj(call, ccc, argApa, config) and - flowThroughOutOfCall(call, ccc, ret, out, allowsFieldFlow, argApa, apa, config) + fwdFlowRetFromArg(ret, state, ccc, innerSummaryCtx, innerArgAp, innerArgApa, ap, apa, config) and + fwdFlowIsEntered(call, cc, ccc, summaryCtx, argAp, innerSummaryCtx, innerArgAp, config) } pragma[nomagic] - private predicate fwdFlowOutFromArg( - DataFlowCall call, NodeEx out, FlowState state, ParameterPosition summaryCtx, Ap argAp, Ap ap, - ApApprox apa, Configuration config + private predicate fwdFlowThrough( + DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, + ApOption argAp, Ap ap, ApApprox apa, RetNodeEx ret, ApApprox innerArgApa, Configuration config ) { - exists(RetNodeEx ret, boolean allowsFieldFlow, CcCall ccc, ApApprox argApa | - fwdFlowRetFromArg(pragma[only_bind_into](ret), state, pragma[only_bind_into](ccc), - summaryCtx, _, argAp, pragma[only_bind_into](argApa), ap, pragma[only_bind_into](apa), - config) and - fwdFlowThroughOutOfCall(call, ccc, ret, out, allowsFieldFlow, argApa, apa, config) and - (if allowsFieldFlow = false then ap instanceof ApNil else any()) - ) + fwdFlowThrough0(call, cc, state, ccc, summaryCtx, argAp, ap, apa, ret, _, _, innerArgApa, + config) } /** @@ -1571,12 +1552,14 @@ private module MkStage { */ pragma[nomagic] private predicate fwdFlowIsEntered( - DataFlowCall call, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - ParameterPosition pos, Ap ap, Configuration config + DataFlowCall call, Cc cc, CcCall innerCc, ParamNodeOption summaryCtx, ApOption argAp, + ParamNodeEx p, Ap ap, Configuration config ) { - exists(ParamNodeEx param | - fwdFlowInMayFlowThrough(call, cc, _, summaryCtx, argAp, param, ap, _, config) and - pos = param.getPosition() + exists(ApApprox apa | + fwdFlowIn(call, pragma[only_bind_into](p), _, cc, innerCc, summaryCtx, argAp, ap, + pragma[only_bind_into](apa), pragma[only_bind_into](config)) and + PrevStage::parameterMayFlowThrough(p, apa, config) and + PrevStage::callMayFlowThroughRev(call, pragma[only_bind_into](config)) ) } @@ -1596,23 +1579,31 @@ private module MkStage { fwdFlowConsCand(ap1, c, ap2, config) } + pragma[nomagic] + private predicate returnFlowsThrough0( + DataFlowCall call, FlowState state, CcCall ccc, Ap ap, ApApprox apa, RetNodeEx ret, + ParamNodeEx innerSummaryCtx, Ap innerArgAp, ApApprox innerArgApa, Configuration config + ) { + fwdFlowThrough0(call, _, state, ccc, _, _, ap, apa, ret, innerSummaryCtx, innerArgAp, + innerArgApa, config) + } + pragma[nomagic] private predicate returnFlowsThrough( - RetNodeEx ret, ReturnKindExt kind, FlowState state, CcCall ccc, ParamNodeEx p, Ap argAp, + RetNodeEx ret, ReturnPosition pos, FlowState state, CcCall ccc, ParamNodeEx p, Ap argAp, Ap ap, Configuration config ) { - exists(boolean allowsFieldFlow, ApApprox argApa, ApApprox apa | - fwdFlowRetFromArg(pragma[only_bind_into](ret), state, pragma[only_bind_into](ccc), _, p, - argAp, pragma[only_bind_into](argApa), ap, pragma[only_bind_into](apa), config) and - kind = ret.getKind() and - fwdFlowThroughOutOfCall(_, ccc, ret, _, allowsFieldFlow, argApa, apa, config) and - (if allowsFieldFlow = false then ap instanceof ApNil else any()) + exists(DataFlowCall call, ApApprox apa, boolean allowsFieldFlow, ApApprox innerArgApa | + returnFlowsThrough0(call, state, ccc, ap, apa, ret, p, argAp, innerArgApa, config) and + flowThroughOutOfCall(call, ccc, ret, _, allowsFieldFlow, innerArgApa, apa, config) and + pos = ret.getReturnPosition() and + if allowsFieldFlow = false then ap instanceof ApNil else any() ) } pragma[nomagic] private predicate flowThroughIntoCall( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap argAp, + DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap argAp, Ap ap, Configuration config ) { exists(ApApprox argApa | @@ -1620,7 +1611,7 @@ private module MkStage { allowsFieldFlow, argApa, pragma[only_bind_into](config)) and fwdFlow(arg, _, _, _, _, pragma[only_bind_into](argAp), argApa, pragma[only_bind_into](config)) and - returnFlowsThrough(_, _, _, _, p, pragma[only_bind_into](argAp), _, + returnFlowsThrough(_, _, _, _, p, pragma[only_bind_into](argAp), ap, pragma[only_bind_into](config)) and if allowsFieldFlow = false then argAp instanceof ApNil else any() ) @@ -1639,12 +1630,13 @@ private module MkStage { pragma[nomagic] private predicate flowOutOfCallAp( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, boolean allowsFieldFlow, + DataFlowCall call, RetNodeEx ret, ReturnPosition pos, NodeEx out, boolean allowsFieldFlow, Ap ap, Configuration config ) { exists(ApApprox apa | - flowOutOfCallApa(call, ret, kind, out, allowsFieldFlow, apa, config) and - fwdFlow(ret, _, _, _, _, ap, apa, config) + flowOutOfCallApa(call, ret, _, out, allowsFieldFlow, apa, config) and + fwdFlow(ret, _, _, _, _, ap, apa, config) and + pos = ret.getReturnPosition() ) } @@ -1739,17 +1731,17 @@ private module MkStage { ) or // flow through a callable - exists(DataFlowCall call, ReturnKindExt returnKind0, Ap returnAp0 | - revFlowInToReturn(call, node, state, returnKind0, returnAp0, ap, config) and - revFlowIsReturned(call, returnCtx, returnAp, returnKind0, returnAp0, config) + exists(DataFlowCall call, ParamNodeEx p, ReturnPosition pos, Ap innerReturnAp | + revFlowThrough(call, returnCtx, p, state, pos, returnAp, ap, innerReturnAp, config) and + flowThroughIntoCall(call, node, p, _, ap, innerReturnAp, config) ) or // flow out of a callable - exists(ReturnKindExt kind | - revFlowOut(_, node, kind, state, _, _, ap, config) and - if returnFlowsThrough(node, kind, state, _, _, _, ap, config) + exists(ReturnPosition pos | + revFlowOut(_, node, pos, state, _, _, ap, config) and + if returnFlowsThrough(node, pos, state, _, _, _, ap, config) then ( - returnCtx = TReturnCtxMaybeFlowThrough(kind) and + returnCtx = TReturnCtxMaybeFlowThrough(pos) and returnAp = apSome(ap) ) else ( returnCtx = TReturnCtxNoFlowThrough() and returnAp = apNone() @@ -1782,47 +1774,33 @@ private module MkStage { pragma[nomagic] private predicate revFlowOut( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, FlowState state, ReturnCtx returnCtx, + DataFlowCall call, RetNodeEx ret, ReturnPosition pos, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap, Configuration config ) { exists(NodeEx out, boolean allowsFieldFlow | revFlow(out, state, returnCtx, returnAp, ap, config) and - flowOutOfCallAp(call, ret, kind, out, allowsFieldFlow, ap, config) and + flowOutOfCallAp(call, ret, pos, out, allowsFieldFlow, ap, config) and if allowsFieldFlow = false then ap instanceof ApNil else any() ) } - /** - * Same as `flowThroughIntoCall`, but restricted to calls that are reached - * in the flow covered by `revFlow`, where data might flow through the target - * callable and back out at `call`. - */ - pragma[nomagic] - private predicate revFlowThroughIntoCall( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap argAp, - Configuration config - ) { - flowThroughIntoCall(call, arg, p, allowsFieldFlow, argAp, config) and - revFlowIsReturned(call, _, _, _, _, config) - } - pragma[nomagic] private predicate revFlowParamToReturn( - ParamNodeEx p, FlowState state, ReturnKindExt kind, Ap returnAp, Ap ap, Configuration config + ParamNodeEx p, FlowState state, ReturnPosition pos, Ap returnAp, Ap ap, Configuration config ) { - revFlow(p, state, TReturnCtxMaybeFlowThrough(kind), apSome(returnAp), ap, config) and - parameterFlowThroughAllowed(p, kind) + revFlow(pragma[only_bind_into](p), state, TReturnCtxMaybeFlowThrough(pos), apSome(returnAp), + pragma[only_bind_into](ap), pragma[only_bind_into](config)) and + parameterFlowThroughAllowed(p, pos.getKind()) and + PrevStage::parameterMayFlowThrough(p, getApprox(ap), config) } pragma[nomagic] - private predicate revFlowInToReturn( - DataFlowCall call, ArgNodeEx arg, FlowState state, ReturnKindExt kind, Ap returnAp, Ap ap, - Configuration config + private predicate revFlowThrough( + DataFlowCall call, ReturnCtx returnCtx, ParamNodeEx p, FlowState state, ReturnPosition pos, + ApOption returnAp, Ap ap, Ap innerReturnAp, Configuration config ) { - exists(ParamNodeEx p, boolean allowsFieldFlow | - revFlowParamToReturn(p, state, kind, returnAp, ap, config) and - revFlowThroughIntoCall(call, arg, p, allowsFieldFlow, ap, config) - ) + revFlowParamToReturn(p, state, pos, innerReturnAp, ap, config) and + revFlowIsReturned(call, returnCtx, returnAp, pos, innerReturnAp, config) } /** @@ -1832,12 +1810,12 @@ private module MkStage { */ pragma[nomagic] private predicate revFlowIsReturned( - DataFlowCall call, ReturnCtx returnCtx, ApOption returnAp, ReturnKindExt kind, Ap ap, + DataFlowCall call, ReturnCtx returnCtx, ApOption returnAp, ReturnPosition pos, Ap ap, Configuration config ) { exists(RetNodeEx ret, FlowState state, CcCall ccc | - revFlowOut(call, ret, kind, state, returnCtx, returnAp, ap, config) and - returnFlowsThrough(ret, kind, state, ccc, _, _, ap, config) and + revFlowOut(call, ret, pos, state, returnCtx, returnAp, ap, config) and + returnFlowsThrough(ret, pos, state, ccc, _, _, ap, config) and matchesCall(ccc, call) ) } @@ -1915,17 +1893,17 @@ private module MkStage { pragma[nomagic] private predicate parameterFlowsThroughRev( - ParamNodeEx p, Ap ap, ReturnKindExt kind, Ap returnAp, Configuration config + ParamNodeEx p, Ap ap, ReturnPosition pos, Ap returnAp, Configuration config ) { - revFlow(p, _, TReturnCtxMaybeFlowThrough(kind), apSome(returnAp), ap, config) and - parameterFlowThroughAllowed(p, kind) + revFlow(p, _, TReturnCtxMaybeFlowThrough(pos), apSome(returnAp), ap, config) and + parameterFlowThroughAllowed(p, pos.getKind()) } pragma[nomagic] predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap, Configuration config) { - exists(RetNodeEx ret, ReturnKindExt kind | - returnFlowsThrough(ret, kind, _, _, p, ap, _, config) and - parameterFlowsThroughRev(p, ap, kind, _, config) + exists(RetNodeEx ret, ReturnPosition pos | + returnFlowsThrough(ret, pos, _, _, p, ap, _, config) and + parameterFlowsThroughRev(p, ap, pos, _, config) ) } @@ -1933,20 +1911,21 @@ private module MkStage { predicate returnMayFlowThrough( RetNodeEx ret, Ap argAp, Ap ap, ReturnKindExt kind, Configuration config ) { - exists(ParamNodeEx p | - returnFlowsThrough(ret, kind, _, _, p, argAp, ap, config) and - parameterFlowsThroughRev(p, argAp, kind, ap, config) + exists(ParamNodeEx p, ReturnPosition pos | + returnFlowsThrough(ret, pos, _, _, p, argAp, ap, config) and + parameterFlowsThroughRev(p, argAp, pos, ap, config) and + kind = pos.getKind() ) } pragma[nomagic] - predicate revFlowInToReturnIsReturned( + private predicate revFlowThroughArg( DataFlowCall call, ArgNodeEx arg, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap, Configuration config ) { - exists(ReturnKindExt returnKind0, Ap returnAp0 | - revFlowInToReturn(call, arg, state, returnKind0, returnAp0, ap, config) and - revFlowIsReturned(call, returnCtx, returnAp, returnKind0, returnAp0, config) + exists(ParamNodeEx p, ReturnPosition pos, Ap innerReturnAp | + revFlowThrough(call, returnCtx, p, state, pos, returnAp, ap, innerReturnAp, config) and + flowThroughIntoCall(call, arg, p, _, ap, innerReturnAp, config) ) } @@ -1954,7 +1933,7 @@ private module MkStage { predicate callMayFlowThroughRev(DataFlowCall call, Configuration config) { exists(ArgNodeEx arg, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap | revFlow(arg, state, returnCtx, returnAp, ap, config) and - revFlowInToReturnIsReturned(call, arg, state, returnCtx, returnAp, ap, config) + revFlowThroughArg(call, arg, state, returnCtx, returnAp, ap, config) ) } @@ -1967,8 +1946,9 @@ private module MkStage { conscand = count(TypedContent f0, Ap ap | fwdConsCand(f0, ap, config)) and states = count(FlowState state | fwdFlow(_, state, _, _, _, _, config)) and tuples = - count(NodeEx n, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - Ap ap | fwdFlow(n, state, cc, summaryCtx, argAp, ap, config)) + count(NodeEx n, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap | + fwdFlow(n, state, cc, summaryCtx, argAp, ap, config) + ) or fwd = false and nodes = count(NodeEx node | revFlow(node, _, _, _, _, config)) and @@ -2823,13 +2803,12 @@ private Configuration unbindConf(Configuration conf) { pragma[nomagic] private predicate nodeMayUseSummary0( - NodeEx n, DataFlowCallable c, ParameterPosition pos, FlowState state, AccessPathApprox apa, - Configuration config + NodeEx n, ParamNodeEx p, FlowState state, AccessPathApprox apa, Configuration config ) { exists(AccessPathApprox apa0 | - c = n.getEnclosingCallable() and + Stage5::parameterMayFlowThrough(p, _, _) and Stage5::revFlow(n, state, TReturnCtxMaybeFlowThrough(_), _, apa0, config) and - Stage5::fwdFlow(n, state, any(CallContextCall ccc), TParameterPositionSome(pos), + Stage5::fwdFlow(n, state, any(CallContextCall ccc), TParamNodeSome(p.asNode()), TAccessPathApproxSome(apa), apa0, config) ) } @@ -2838,10 +2817,9 @@ pragma[nomagic] private predicate nodeMayUseSummary( NodeEx n, FlowState state, AccessPathApprox apa, Configuration config ) { - exists(DataFlowCallable c, ParameterPosition pos, ParamNodeEx p | + exists(ParamNodeEx p | Stage5::parameterMayFlowThrough(p, apa, config) and - nodeMayUseSummary0(n, c, pos, state, apa, config) and - p.isParameterOf(c, pos) + nodeMayUseSummary0(n, p, state, apa, config) ) } diff --git a/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowPrivate.qll b/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowPrivate.qll index 1f3a6a3f575..76380de9415 100644 --- a/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowPrivate.qll +++ b/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowPrivate.qll @@ -828,8 +828,8 @@ import ParameterNodes /** A data-flow node used to model flow summaries. */ class SummaryNode extends NodeImpl, TSummaryNode { - private FlowSummaryImpl::Public::SummarizedCallable c; - private FlowSummaryImpl::Private::SummaryNodeState state; + FlowSummaryImpl::Public::SummarizedCallable c; + FlowSummaryImpl::Private::SummaryNodeState state; SummaryNode() { this = TSummaryNode(c, state) } @@ -951,6 +951,11 @@ private module ArgumentNodes { import ArgumentNodes +/** A call to `new`. */ +private class NewCall extends DataFlowCall { + NewCall() { this.asCall().getExpr().(MethodCall).getMethodName() = "new" } +} + /** A data-flow node that represents a value syntactically returned by a callable. */ abstract class ReturningNode extends Node { /** Gets the kind of this return node. */ @@ -994,7 +999,12 @@ private module ReturnNodes { override ReturnKind getKind() { if n.getNode() instanceof BreakStmt then result instanceof BreakReturnKind - else result instanceof NormalReturnKind + else + exists(CfgScope scope | scope = this.getCfgScope() | + if isUserDefinedNew(scope) + then result instanceof NewReturnKind + else result instanceof NormalReturnKind + ) } } @@ -1018,7 +1028,42 @@ private module ReturnNodes { class ExprReturnNode extends ReturningNode, ExprNode { ExprReturnNode() { exists(Callable c | implicitReturn(c, this) = c.getAStmt()) } - override ReturnKind getKind() { result instanceof NormalReturnKind } + override ReturnKind getKind() { + exists(CfgScope scope | scope = this.(NodeImpl).getCfgScope() | + if isUserDefinedNew(scope) + then result instanceof NewReturnKind + else result instanceof NormalReturnKind + ) + } + } + + /** + * A `self` node inside an `initialize` method through which data may return. + * + * For example, in + * + * ```rb + * class C + * def initialize(x) + * @x = x + * end + * end + * ``` + * + * the implicit `self` reference in `@x` will return data stored in the field + * `x` out to the call `C.new`. + */ + class InitializeReturnNode extends ExprPostUpdateNode, ReturningNode { + InitializeReturnNode() { + exists(Method initialize | + this.getCfgScope() = initialize and + initialize.getName() = "initialize" and + initialize = any(ClassDeclaration c).getAMethod() and + this.getPreUpdateNode().asExpr().getExpr() instanceof SelfVariableReadAccess + ) + } + + override ReturnKind getKind() { result instanceof NewReturnKind } } /** @@ -1054,7 +1099,14 @@ private module ReturnNodes { SummaryReturnNode() { FlowSummaryImpl::Private::summaryReturnNode(this, rk) } - override ReturnKind getKind() { result = rk } + override ReturnKind getKind() { + result = rk + or + exists(NewCall new | + TLibraryCallable(c) = viableLibraryCallable(new) and + result instanceof NewReturnKind + ) + } } } @@ -1078,7 +1130,9 @@ private module OutNodes { override DataFlowCall getCall(ReturnKind kind) { result = call and - kind instanceof NormalReturnKind + if call instanceof NewCall + then kind instanceof NewReturnKind + else kind instanceof NormalReturnKind } } diff --git a/ruby/ql/lib/codeql/ruby/dataflow/internal/FlowSummaryImpl.qll b/ruby/ql/lib/codeql/ruby/dataflow/internal/FlowSummaryImpl.qll index 61c541d8882..b61142c33a7 100644 --- a/ruby/ql/lib/codeql/ruby/dataflow/internal/FlowSummaryImpl.qll +++ b/ruby/ql/lib/codeql/ruby/dataflow/internal/FlowSummaryImpl.qll @@ -241,9 +241,15 @@ module Public { } /** - * Holds if the summary is auto generated. + * Holds if the summary is auto generated and not manually generated. */ predicate isAutoGenerated() { none() } + + /** + * Holds if the summary has the given provenance where `true` is + * `generated` and `false` is `manual`. + */ + predicate hasProvenance(boolean generated) { none() } } /** A callable where there is no flow via the callable. */ @@ -1012,6 +1018,10 @@ module Private { } override predicate isAutoGenerated() { this.relevantSummaryElementGenerated(_, _, _) } + + override predicate hasProvenance(boolean generated) { + summaryElement(this, _, _, _, generated) + } } /** Holds if component `c` of specification `spec` cannot be parsed. */ diff --git a/ruby/ql/lib/codeql/ruby/frameworks/GlobalId.qll b/ruby/ql/lib/codeql/ruby/frameworks/GlobalId.qll new file mode 100644 index 00000000000..cb3a8abfd20 --- /dev/null +++ b/ruby/ql/lib/codeql/ruby/frameworks/GlobalId.qll @@ -0,0 +1,125 @@ +/** + * Provides modeling for `GlobalID`, a library for identifying model instances by URI. + * Version: 1.0.0 + * https://github.com/rails/globalid + */ + +private import codeql.ruby.ApiGraphs +private import codeql.ruby.Concepts +private import codeql.ruby.DataFlow +private import codeql.ruby.frameworks.ActiveRecord + +/** + * Provides modeling for `GlobalID`, a library for identifying model instances by URI. + * Version: 1.0.0 + * https://github.com/rails/globalid + */ +module GlobalId { + /** A call to `GlobalID::parse` */ + class ParseCall extends DataFlow::CallNode { + ParseCall() { this = API::getTopLevelMember("GlobalID").getAMethodCall("parse") } + } + + /** A call to `GlobalID::find` */ + class FindCall extends DataFlow::CallNode, OrmInstantiation::Range { + FindCall() { this = API::getTopLevelMember("GlobalID").getAMethodCall("find") } + + override predicate methodCallMayAccessField(string methodName) { none() } + } + + /** `GlobalID::Locator` */ + module Locator { + /** A call to `GlobalID::Locator.locate` */ + class LocateCall extends DataFlow::CallNode, OrmInstantiation::Range { + LocateCall() { + this = API::getTopLevelMember("GlobalID").getMember("Locator").getAMethodCall("locate") + } + + override predicate methodCallMayAccessField(string methodName) { none() } + } + + /** A call to `GlobalID::Locator.locate_signed` */ + class LocateSignedCall extends DataFlow::CallNode, OrmInstantiation::Range { + LocateSignedCall() { + this = + API::getTopLevelMember("GlobalID").getMember("Locator").getAMethodCall("locate_signed") + } + + override predicate methodCallMayAccessField(string methodName) { none() } + } + + /** A call to `GlobalID::Locator.locate_many` */ + class LocateManyCall extends DataFlow::CallNode, OrmInstantiation::Range { + LocateManyCall() { + this = API::getTopLevelMember("GlobalID").getMember("Locator").getAMethodCall("locate_many") + } + + override predicate methodCallMayAccessField(string methodName) { none() } + } + + /** A call to `GlobalID::Locator.locate_many_signed` */ + class LocateManySignedCall extends DataFlow::CallNode, OrmInstantiation::Range { + LocateManySignedCall() { + this = + API::getTopLevelMember("GlobalID") + .getMember("Locator") + .getAMethodCall("locate_many_signed") + } + + override predicate methodCallMayAccessField(string methodName) { none() } + } + } + + /** `GlobalID::Identification` */ + module Identification { + /** A `DataFlow::CallNode` against an instance of a class that includes the `GlobalID::Identification` module */ + private class IdentificationInstanceCall extends DataFlow::CallNode { + IdentificationInstanceCall() { + this = + DataFlow::getConstant("GlobalID") + .getConstant("Identification") + .getADescendentModule() + .getAnImmediateReference() + .getAMethodCall(["new", "find"]) + .getAMethodCall() + or + this instanceof ActiveRecordInstanceMethodCall + } + } + + /** A call to `GlobalID::Identification.to_global_id` */ + class ToGlobalIdCall extends IdentificationInstanceCall { + ToGlobalIdCall() { this.getMethodName() = ["to_global_id", "to_gid"] } + } + + /** A call to `GlobalID::Identification.to_gid_param` */ + class ToGidParamCall extends DataFlow::CallNode { + ToGidParamCall() { this.getMethodName() = "to_gid_param" } + } + + /** A call to `GlobalID::Identification.to_signed_global_id` */ + class ToSignedGlobalIdCall extends DataFlow::CallNode { + ToSignedGlobalIdCall() { this.getMethodName() = ["to_signed_global_id", "to_sgid"] } + } + + /** A call to `GlobalID::Identification.to_sgid_param` */ + class ToSgidParamCall extends DataFlow::CallNode { + ToSgidParamCall() { this.getMethodName() = "to_sgid_param" } + } + } +} + +/** Provides modeling for `SignedGlobalID`, a module of the `rails/globalid` library. */ +module SignedGlobalId { + /** A call to `SignedGlobalID::parse` */ + class ParseCall extends DataFlow::CallNode { + ParseCall() { this = API::getTopLevelMember("SignedGlobalID").getAMethodCall("parse") } + } + + /** A call to `SignedGlobalID::find` */ + class FindCall extends DataFlow::CallNode, OrmInstantiation::Range { + FindCall() { this = API::getTopLevelMember("SignedGlobalID").getAMethodCall("find") } + + override predicate methodCallMayAccessField(string methodName) { none() } + } +} diff --git a/ruby/ql/lib/codeql/ruby/typetracking/TypeTrackerSpecific.qll b/ruby/ql/lib/codeql/ruby/typetracking/TypeTrackerSpecific.qll index 1c636c6987f..cc11b6b2a87 100644 --- a/ruby/ql/lib/codeql/ruby/typetracking/TypeTrackerSpecific.qll +++ b/ruby/ql/lib/codeql/ruby/typetracking/TypeTrackerSpecific.qll @@ -79,10 +79,15 @@ predicate jumpStep = DataFlowPrivate::jumpStep/2; /** Holds if there is direct flow from `param` to a return. */ pragma[nomagic] private predicate flowThrough(DataFlowPublic::ParameterNode param) { - exists(DataFlowPrivate::ReturningNode returnNode | + exists(DataFlowPrivate::ReturningNode returnNode, DataFlowDispatch::ReturnKind rk | DataFlowPrivate::LocalFlow::getParameterDefNode(param.getParameter()) .(TypeTrackingNode) - .flowsTo(returnNode) + .flowsTo(returnNode) and + rk = returnNode.getKind() + | + rk instanceof DataFlowDispatch::NormalReturnKind + or + rk instanceof DataFlowDispatch::BreakReturnKind ) } @@ -184,7 +189,9 @@ private predicate viableParam( DataFlowDispatch::ParameterPosition ppos ) { exists(Cfg::CfgScope callable | - DataFlowDispatch::getTarget(call) = callable and + DataFlowDispatch::getTarget(call) = callable or + DataFlowDispatch::getInitializeTarget(call) = callable + | p.isSourceParameterOf(callable, ppos) ) } @@ -226,6 +233,9 @@ predicate returnStep(Node nodeFrom, Node nodeTo) { exists(ExprNodes::CallCfgNode call | nodeFrom instanceof DataFlowPrivate::ReturnNode and nodeFrom.(DataFlowPrivate::NodeImpl).getCfgScope() = DataFlowDispatch::getTarget(call) and + // deliberately do not include `getInitializeTarget`, since calls to `new` should not + // get the return value from `initialize`. Any fields being set in the initializer + // will reach all reads via `callStep` and `localFieldStep`. nodeTo.asExpr().getNode() = call.getNode() ) or @@ -233,7 +243,8 @@ predicate returnStep(Node nodeFrom, Node nodeTo) { // we model it as a returning flow step, in order to avoid computing a potential // self-cross product of all calls to a function that returns one of its parameters // (only to later filter that flow out using `TypeTracker::append`). - nodeTo.(DataFlowPrivate::SynthReturnNode).getAnInput() = nodeFrom + nodeTo.(DataFlowPrivate::SynthReturnNode).getAnInput() = nodeFrom and + not nodeFrom instanceof DataFlowPrivate::InitializeReturnNode } /** diff --git a/ruby/ql/src/queries/analysis/Definitions.ql b/ruby/ql/src/queries/analysis/Definitions.ql index 24e968b124d..3f97223d9e8 100644 --- a/ruby/ql/src/queries/analysis/Definitions.ql +++ b/ruby/ql/src/queries/analysis/Definitions.ql @@ -12,6 +12,7 @@ import codeql.ruby.AST import codeql.ruby.dataflow.SSA +import codeql.ruby.dataflow.internal.DataFlowDispatch from DefLoc loc, Expr src, Expr target, string kind where @@ -38,7 +39,12 @@ newtype DefLoc = write = definitionOf(read.getAQualifiedName()) } or /** A method call. */ - MethodLoc(MethodCall call, Method meth) { meth = call.getATarget() } or + MethodLoc(MethodCall call, Method meth) { + meth = call.getATarget() + or + // include implicit `initialize` calls + meth = getInitializeTarget(call.getAControlFlowNode()) + } or /** A local variable. */ LocalVariableLoc(VariableReadAccess read, VariableWriteAccess write) { exists(Ssa::WriteDefinition w | diff --git a/ruby/ql/test/library-tests/dataflow/call-sensitivity/call-sensitivity.expected b/ruby/ql/test/library-tests/dataflow/call-sensitivity/call-sensitivity.expected index c3fd0fb8654..46491d9b980 100644 --- a/ruby/ql/test/library-tests/dataflow/call-sensitivity/call-sensitivity.expected +++ b/ruby/ql/test/library-tests/dataflow/call-sensitivity/call-sensitivity.expected @@ -92,26 +92,54 @@ edges | call_sensitivity.rb:92:35:92:35 | x : | call_sensitivity.rb:93:34:93:34 | x : | | call_sensitivity.rb:93:34:93:34 | x : | call_sensitivity.rb:88:33:88:33 | y : | | call_sensitivity.rb:93:34:93:34 | x : | call_sensitivity.rb:88:33:88:33 | y : | -| call_sensitivity.rb:98:11:98:18 | call to taint : | call_sensitivity.rb:54:15:54:15 | x : | -| call_sensitivity.rb:98:11:98:18 | call to taint : | call_sensitivity.rb:54:15:54:15 | x : | -| call_sensitivity.rb:99:16:99:23 | call to taint : | call_sensitivity.rb:58:20:58:20 | x : | -| call_sensitivity.rb:99:16:99:23 | call to taint : | call_sensitivity.rb:58:20:58:20 | x : | -| call_sensitivity.rb:100:14:100:22 | call to taint : | call_sensitivity.rb:62:18:62:18 | y : | -| call_sensitivity.rb:100:14:100:22 | call to taint : | call_sensitivity.rb:62:18:62:18 | y : | -| call_sensitivity.rb:101:16:101:24 | call to taint : | call_sensitivity.rb:66:20:66:20 | x : | -| call_sensitivity.rb:101:16:101:24 | call to taint : | call_sensitivity.rb:66:20:66:20 | x : | -| call_sensitivity.rb:102:14:102:22 | call to taint : | call_sensitivity.rb:74:18:74:18 | y : | -| call_sensitivity.rb:102:14:102:22 | call to taint : | call_sensitivity.rb:74:18:74:18 | y : | -| call_sensitivity.rb:104:21:104:28 | call to taint : | call_sensitivity.rb:80:30:80:30 | x : | -| call_sensitivity.rb:104:21:104:28 | call to taint : | call_sensitivity.rb:80:30:80:30 | x : | -| call_sensitivity.rb:105:26:105:33 | call to taint : | call_sensitivity.rb:84:35:84:35 | x : | -| call_sensitivity.rb:105:26:105:33 | call to taint : | call_sensitivity.rb:84:35:84:35 | x : | -| call_sensitivity.rb:106:24:106:32 | call to taint : | call_sensitivity.rb:88:33:88:33 | y : | -| call_sensitivity.rb:106:24:106:32 | call to taint : | call_sensitivity.rb:88:33:88:33 | y : | -| call_sensitivity.rb:107:26:107:33 | call to taint : | call_sensitivity.rb:92:35:92:35 | x : | -| call_sensitivity.rb:107:26:107:33 | call to taint : | call_sensitivity.rb:92:35:92:35 | x : | -| call_sensitivity.rb:140:14:140:22 | call to taint : | call_sensitivity.rb:74:18:74:18 | y : | -| call_sensitivity.rb:140:14:140:22 | call to taint : | call_sensitivity.rb:74:18:74:18 | y : | +| call_sensitivity.rb:96:18:96:18 | x : | call_sensitivity.rb:97:10:97:10 | x | +| call_sensitivity.rb:96:18:96:18 | x : | call_sensitivity.rb:97:10:97:10 | x | +| call_sensitivity.rb:96:18:96:18 | x : | call_sensitivity.rb:97:10:97:10 | x | +| call_sensitivity.rb:96:18:96:18 | x : | call_sensitivity.rb:97:10:97:10 | x | +| call_sensitivity.rb:96:18:96:18 | x : | call_sensitivity.rb:97:10:97:10 | x | +| call_sensitivity.rb:96:18:96:18 | x : | call_sensitivity.rb:97:10:97:10 | x | +| call_sensitivity.rb:96:18:96:18 | x : | call_sensitivity.rb:98:13:98:13 | x : | +| call_sensitivity.rb:96:18:96:18 | x : | call_sensitivity.rb:98:13:98:13 | x : | +| call_sensitivity.rb:96:18:96:18 | x : | call_sensitivity.rb:98:13:98:13 | x : | +| call_sensitivity.rb:96:18:96:18 | x : | call_sensitivity.rb:98:13:98:13 | x : | +| call_sensitivity.rb:98:13:98:13 | x : | call_sensitivity.rb:50:15:50:15 | x : | +| call_sensitivity.rb:98:13:98:13 | x : | call_sensitivity.rb:50:15:50:15 | x : | +| call_sensitivity.rb:98:13:98:13 | x : | call_sensitivity.rb:50:15:50:15 | x : | +| call_sensitivity.rb:98:13:98:13 | x : | call_sensitivity.rb:50:15:50:15 | x : | +| call_sensitivity.rb:102:11:102:20 | ( ... ) : | call_sensitivity.rb:96:18:96:18 | x : | +| call_sensitivity.rb:102:11:102:20 | ( ... ) : | call_sensitivity.rb:96:18:96:18 | x : | +| call_sensitivity.rb:102:12:102:19 | call to taint : | call_sensitivity.rb:102:11:102:20 | ( ... ) : | +| call_sensitivity.rb:102:12:102:19 | call to taint : | call_sensitivity.rb:102:11:102:20 | ( ... ) : | +| call_sensitivity.rb:103:11:103:18 | call to taint : | call_sensitivity.rb:54:15:54:15 | x : | +| call_sensitivity.rb:103:11:103:18 | call to taint : | call_sensitivity.rb:54:15:54:15 | x : | +| call_sensitivity.rb:104:16:104:23 | call to taint : | call_sensitivity.rb:58:20:58:20 | x : | +| call_sensitivity.rb:104:16:104:23 | call to taint : | call_sensitivity.rb:58:20:58:20 | x : | +| call_sensitivity.rb:105:14:105:22 | call to taint : | call_sensitivity.rb:62:18:62:18 | y : | +| call_sensitivity.rb:105:14:105:22 | call to taint : | call_sensitivity.rb:62:18:62:18 | y : | +| call_sensitivity.rb:106:16:106:24 | call to taint : | call_sensitivity.rb:66:20:66:20 | x : | +| call_sensitivity.rb:106:16:106:24 | call to taint : | call_sensitivity.rb:66:20:66:20 | x : | +| call_sensitivity.rb:107:14:107:22 | call to taint : | call_sensitivity.rb:74:18:74:18 | y : | +| call_sensitivity.rb:107:14:107:22 | call to taint : | call_sensitivity.rb:74:18:74:18 | y : | +| call_sensitivity.rb:109:21:109:28 | call to taint : | call_sensitivity.rb:80:30:80:30 | x : | +| call_sensitivity.rb:109:21:109:28 | call to taint : | call_sensitivity.rb:80:30:80:30 | x : | +| call_sensitivity.rb:110:26:110:33 | call to taint : | call_sensitivity.rb:84:35:84:35 | x : | +| call_sensitivity.rb:110:26:110:33 | call to taint : | call_sensitivity.rb:84:35:84:35 | x : | +| call_sensitivity.rb:111:24:111:32 | call to taint : | call_sensitivity.rb:88:33:88:33 | y : | +| call_sensitivity.rb:111:24:111:32 | call to taint : | call_sensitivity.rb:88:33:88:33 | y : | +| call_sensitivity.rb:112:26:112:33 | call to taint : | call_sensitivity.rb:92:35:92:35 | x : | +| call_sensitivity.rb:112:26:112:33 | call to taint : | call_sensitivity.rb:92:35:92:35 | x : | +| call_sensitivity.rb:149:14:149:22 | call to taint : | call_sensitivity.rb:74:18:74:18 | y : | +| call_sensitivity.rb:149:14:149:22 | call to taint : | call_sensitivity.rb:74:18:74:18 | y : | +| call_sensitivity.rb:156:19:156:19 | x : | call_sensitivity.rb:157:12:157:12 | x : | +| call_sensitivity.rb:156:19:156:19 | x : | call_sensitivity.rb:157:12:157:12 | x : | +| call_sensitivity.rb:157:12:157:12 | x : | call_sensitivity.rb:96:18:96:18 | x : | +| call_sensitivity.rb:157:12:157:12 | x : | call_sensitivity.rb:96:18:96:18 | x : | +| call_sensitivity.rb:160:11:160:19 | call to taint : | call_sensitivity.rb:156:19:156:19 | x : | +| call_sensitivity.rb:160:11:160:19 | call to taint : | call_sensitivity.rb:156:19:156:19 | x : | +| call_sensitivity.rb:169:11:169:20 | ( ... ) : | call_sensitivity.rb:96:18:96:18 | x : | +| call_sensitivity.rb:169:11:169:20 | ( ... ) : | call_sensitivity.rb:96:18:96:18 | x : | +| call_sensitivity.rb:169:12:169:19 | call to taint : | call_sensitivity.rb:169:11:169:20 | ( ... ) : | +| call_sensitivity.rb:169:12:169:19 | call to taint : | call_sensitivity.rb:169:11:169:20 | ( ... ) : | nodes | call_sensitivity.rb:9:6:9:14 | ( ... ) | semmle.label | ( ... ) | | call_sensitivity.rb:9:6:9:14 | ( ... ) | semmle.label | ( ... ) | @@ -219,26 +247,52 @@ nodes | call_sensitivity.rb:92:35:92:35 | x : | semmle.label | x : | | call_sensitivity.rb:93:34:93:34 | x : | semmle.label | x : | | call_sensitivity.rb:93:34:93:34 | x : | semmle.label | x : | -| call_sensitivity.rb:98:11:98:18 | call to taint : | semmle.label | call to taint : | -| call_sensitivity.rb:98:11:98:18 | call to taint : | semmle.label | call to taint : | -| call_sensitivity.rb:99:16:99:23 | call to taint : | semmle.label | call to taint : | -| call_sensitivity.rb:99:16:99:23 | call to taint : | semmle.label | call to taint : | -| call_sensitivity.rb:100:14:100:22 | call to taint : | semmle.label | call to taint : | -| call_sensitivity.rb:100:14:100:22 | call to taint : | semmle.label | call to taint : | -| call_sensitivity.rb:101:16:101:24 | call to taint : | semmle.label | call to taint : | -| call_sensitivity.rb:101:16:101:24 | call to taint : | semmle.label | call to taint : | -| call_sensitivity.rb:102:14:102:22 | call to taint : | semmle.label | call to taint : | -| call_sensitivity.rb:102:14:102:22 | call to taint : | semmle.label | call to taint : | -| call_sensitivity.rb:104:21:104:28 | call to taint : | semmle.label | call to taint : | -| call_sensitivity.rb:104:21:104:28 | call to taint : | semmle.label | call to taint : | -| call_sensitivity.rb:105:26:105:33 | call to taint : | semmle.label | call to taint : | -| call_sensitivity.rb:105:26:105:33 | call to taint : | semmle.label | call to taint : | -| call_sensitivity.rb:106:24:106:32 | call to taint : | semmle.label | call to taint : | -| call_sensitivity.rb:106:24:106:32 | call to taint : | semmle.label | call to taint : | -| call_sensitivity.rb:107:26:107:33 | call to taint : | semmle.label | call to taint : | -| call_sensitivity.rb:107:26:107:33 | call to taint : | semmle.label | call to taint : | -| call_sensitivity.rb:140:14:140:22 | call to taint : | semmle.label | call to taint : | -| call_sensitivity.rb:140:14:140:22 | call to taint : | semmle.label | call to taint : | +| call_sensitivity.rb:96:18:96:18 | x : | semmle.label | x : | +| call_sensitivity.rb:96:18:96:18 | x : | semmle.label | x : | +| call_sensitivity.rb:96:18:96:18 | x : | semmle.label | x : | +| call_sensitivity.rb:96:18:96:18 | x : | semmle.label | x : | +| call_sensitivity.rb:96:18:96:18 | x : | semmle.label | x : | +| call_sensitivity.rb:96:18:96:18 | x : | semmle.label | x : | +| call_sensitivity.rb:97:10:97:10 | x | semmle.label | x | +| call_sensitivity.rb:97:10:97:10 | x | semmle.label | x | +| call_sensitivity.rb:98:13:98:13 | x : | semmle.label | x : | +| call_sensitivity.rb:98:13:98:13 | x : | semmle.label | x : | +| call_sensitivity.rb:98:13:98:13 | x : | semmle.label | x : | +| call_sensitivity.rb:98:13:98:13 | x : | semmle.label | x : | +| call_sensitivity.rb:102:11:102:20 | ( ... ) : | semmle.label | ( ... ) : | +| call_sensitivity.rb:102:11:102:20 | ( ... ) : | semmle.label | ( ... ) : | +| call_sensitivity.rb:102:12:102:19 | call to taint : | semmle.label | call to taint : | +| call_sensitivity.rb:102:12:102:19 | call to taint : | semmle.label | call to taint : | +| call_sensitivity.rb:103:11:103:18 | call to taint : | semmle.label | call to taint : | +| call_sensitivity.rb:103:11:103:18 | call to taint : | semmle.label | call to taint : | +| call_sensitivity.rb:104:16:104:23 | call to taint : | semmle.label | call to taint : | +| call_sensitivity.rb:104:16:104:23 | call to taint : | semmle.label | call to taint : | +| call_sensitivity.rb:105:14:105:22 | call to taint : | semmle.label | call to taint : | +| call_sensitivity.rb:105:14:105:22 | call to taint : | semmle.label | call to taint : | +| call_sensitivity.rb:106:16:106:24 | call to taint : | semmle.label | call to taint : | +| call_sensitivity.rb:106:16:106:24 | call to taint : | semmle.label | call to taint : | +| call_sensitivity.rb:107:14:107:22 | call to taint : | semmle.label | call to taint : | +| call_sensitivity.rb:107:14:107:22 | call to taint : | semmle.label | call to taint : | +| call_sensitivity.rb:109:21:109:28 | call to taint : | semmle.label | call to taint : | +| call_sensitivity.rb:109:21:109:28 | call to taint : | semmle.label | call to taint : | +| call_sensitivity.rb:110:26:110:33 | call to taint : | semmle.label | call to taint : | +| call_sensitivity.rb:110:26:110:33 | call to taint : | semmle.label | call to taint : | +| call_sensitivity.rb:111:24:111:32 | call to taint : | semmle.label | call to taint : | +| call_sensitivity.rb:111:24:111:32 | call to taint : | semmle.label | call to taint : | +| call_sensitivity.rb:112:26:112:33 | call to taint : | semmle.label | call to taint : | +| call_sensitivity.rb:112:26:112:33 | call to taint : | semmle.label | call to taint : | +| call_sensitivity.rb:149:14:149:22 | call to taint : | semmle.label | call to taint : | +| call_sensitivity.rb:149:14:149:22 | call to taint : | semmle.label | call to taint : | +| call_sensitivity.rb:156:19:156:19 | x : | semmle.label | x : | +| call_sensitivity.rb:156:19:156:19 | x : | semmle.label | x : | +| call_sensitivity.rb:157:12:157:12 | x : | semmle.label | x : | +| call_sensitivity.rb:157:12:157:12 | x : | semmle.label | x : | +| call_sensitivity.rb:160:11:160:19 | call to taint : | semmle.label | call to taint : | +| call_sensitivity.rb:160:11:160:19 | call to taint : | semmle.label | call to taint : | +| call_sensitivity.rb:169:11:169:20 | ( ... ) : | semmle.label | ( ... ) : | +| call_sensitivity.rb:169:11:169:20 | ( ... ) : | semmle.label | ( ... ) : | +| call_sensitivity.rb:169:12:169:19 | call to taint : | semmle.label | call to taint : | +| call_sensitivity.rb:169:12:169:19 | call to taint : | semmle.label | call to taint : | subpaths #select | call_sensitivity.rb:9:6:9:14 | ( ... ) | call_sensitivity.rb:9:7:9:13 | call to taint : | call_sensitivity.rb:9:6:9:14 | ( ... ) | $@ | call_sensitivity.rb:9:7:9:13 | call to taint : | call to taint : | @@ -246,16 +300,21 @@ subpaths | call_sensitivity.rb:31:27:31:27 | x | call_sensitivity.rb:32:25:32:32 | call to taint : | call_sensitivity.rb:31:27:31:27 | x | $@ | call_sensitivity.rb:32:25:32:32 | call to taint : | call to taint : | | call_sensitivity.rb:40:31:40:31 | x | call_sensitivity.rb:41:25:41:32 | call to taint : | call_sensitivity.rb:40:31:40:31 | x | $@ | call_sensitivity.rb:41:25:41:32 | call to taint : | call to taint : | | call_sensitivity.rb:43:32:43:32 | x | call_sensitivity.rb:44:26:44:33 | call to taint : | call_sensitivity.rb:43:32:43:32 | x | $@ | call_sensitivity.rb:44:26:44:33 | call to taint : | call to taint : | -| call_sensitivity.rb:51:10:51:10 | x | call_sensitivity.rb:98:11:98:18 | call to taint : | call_sensitivity.rb:51:10:51:10 | x | $@ | call_sensitivity.rb:98:11:98:18 | call to taint : | call to taint : | -| call_sensitivity.rb:51:10:51:10 | x | call_sensitivity.rb:99:16:99:23 | call to taint : | call_sensitivity.rb:51:10:51:10 | x | $@ | call_sensitivity.rb:99:16:99:23 | call to taint : | call to taint : | -| call_sensitivity.rb:51:10:51:10 | x | call_sensitivity.rb:100:14:100:22 | call to taint : | call_sensitivity.rb:51:10:51:10 | x | $@ | call_sensitivity.rb:100:14:100:22 | call to taint : | call to taint : | -| call_sensitivity.rb:51:10:51:10 | x | call_sensitivity.rb:101:16:101:24 | call to taint : | call_sensitivity.rb:51:10:51:10 | x | $@ | call_sensitivity.rb:101:16:101:24 | call to taint : | call to taint : | -| call_sensitivity.rb:51:10:51:10 | x | call_sensitivity.rb:102:14:102:22 | call to taint : | call_sensitivity.rb:51:10:51:10 | x | $@ | call_sensitivity.rb:102:14:102:22 | call to taint : | call to taint : | -| call_sensitivity.rb:51:10:51:10 | x | call_sensitivity.rb:140:14:140:22 | call to taint : | call_sensitivity.rb:51:10:51:10 | x | $@ | call_sensitivity.rb:140:14:140:22 | call to taint : | call to taint : | -| call_sensitivity.rb:71:10:71:10 | x | call_sensitivity.rb:104:21:104:28 | call to taint : | call_sensitivity.rb:71:10:71:10 | x | $@ | call_sensitivity.rb:104:21:104:28 | call to taint : | call to taint : | -| call_sensitivity.rb:71:10:71:10 | x | call_sensitivity.rb:105:26:105:33 | call to taint : | call_sensitivity.rb:71:10:71:10 | x | $@ | call_sensitivity.rb:105:26:105:33 | call to taint : | call to taint : | -| call_sensitivity.rb:71:10:71:10 | x | call_sensitivity.rb:106:24:106:32 | call to taint : | call_sensitivity.rb:71:10:71:10 | x | $@ | call_sensitivity.rb:106:24:106:32 | call to taint : | call to taint : | -| call_sensitivity.rb:71:10:71:10 | x | call_sensitivity.rb:107:26:107:33 | call to taint : | call_sensitivity.rb:71:10:71:10 | x | $@ | call_sensitivity.rb:107:26:107:33 | call to taint : | call to taint : | +| call_sensitivity.rb:51:10:51:10 | x | call_sensitivity.rb:102:12:102:19 | call to taint : | call_sensitivity.rb:51:10:51:10 | x | $@ | call_sensitivity.rb:102:12:102:19 | call to taint : | call to taint : | +| call_sensitivity.rb:51:10:51:10 | x | call_sensitivity.rb:103:11:103:18 | call to taint : | call_sensitivity.rb:51:10:51:10 | x | $@ | call_sensitivity.rb:103:11:103:18 | call to taint : | call to taint : | +| call_sensitivity.rb:51:10:51:10 | x | call_sensitivity.rb:104:16:104:23 | call to taint : | call_sensitivity.rb:51:10:51:10 | x | $@ | call_sensitivity.rb:104:16:104:23 | call to taint : | call to taint : | +| call_sensitivity.rb:51:10:51:10 | x | call_sensitivity.rb:105:14:105:22 | call to taint : | call_sensitivity.rb:51:10:51:10 | x | $@ | call_sensitivity.rb:105:14:105:22 | call to taint : | call to taint : | +| call_sensitivity.rb:51:10:51:10 | x | call_sensitivity.rb:106:16:106:24 | call to taint : | call_sensitivity.rb:51:10:51:10 | x | $@ | call_sensitivity.rb:106:16:106:24 | call to taint : | call to taint : | +| call_sensitivity.rb:51:10:51:10 | x | call_sensitivity.rb:107:14:107:22 | call to taint : | call_sensitivity.rb:51:10:51:10 | x | $@ | call_sensitivity.rb:107:14:107:22 | call to taint : | call to taint : | +| call_sensitivity.rb:51:10:51:10 | x | call_sensitivity.rb:149:14:149:22 | call to taint : | call_sensitivity.rb:51:10:51:10 | x | $@ | call_sensitivity.rb:149:14:149:22 | call to taint : | call to taint : | +| call_sensitivity.rb:51:10:51:10 | x | call_sensitivity.rb:160:11:160:19 | call to taint : | call_sensitivity.rb:51:10:51:10 | x | $@ | call_sensitivity.rb:160:11:160:19 | call to taint : | call to taint : | +| call_sensitivity.rb:71:10:71:10 | x | call_sensitivity.rb:109:21:109:28 | call to taint : | call_sensitivity.rb:71:10:71:10 | x | $@ | call_sensitivity.rb:109:21:109:28 | call to taint : | call to taint : | +| call_sensitivity.rb:71:10:71:10 | x | call_sensitivity.rb:110:26:110:33 | call to taint : | call_sensitivity.rb:71:10:71:10 | x | $@ | call_sensitivity.rb:110:26:110:33 | call to taint : | call to taint : | +| call_sensitivity.rb:71:10:71:10 | x | call_sensitivity.rb:111:24:111:32 | call to taint : | call_sensitivity.rb:71:10:71:10 | x | $@ | call_sensitivity.rb:111:24:111:32 | call to taint : | call to taint : | +| call_sensitivity.rb:71:10:71:10 | x | call_sensitivity.rb:112:26:112:33 | call to taint : | call_sensitivity.rb:71:10:71:10 | x | $@ | call_sensitivity.rb:112:26:112:33 | call to taint : | call to taint : | +| call_sensitivity.rb:97:10:97:10 | x | call_sensitivity.rb:102:12:102:19 | call to taint : | call_sensitivity.rb:97:10:97:10 | x | $@ | call_sensitivity.rb:102:12:102:19 | call to taint : | call to taint : | +| call_sensitivity.rb:97:10:97:10 | x | call_sensitivity.rb:160:11:160:19 | call to taint : | call_sensitivity.rb:97:10:97:10 | x | $@ | call_sensitivity.rb:160:11:160:19 | call to taint : | call to taint : | +| call_sensitivity.rb:97:10:97:10 | x | call_sensitivity.rb:169:12:169:19 | call to taint : | call_sensitivity.rb:97:10:97:10 | x | $@ | call_sensitivity.rb:169:12:169:19 | call to taint : | call to taint : | mayBenefitFromCallContext | call_sensitivity.rb:51:5:51:10 | call to sink | call_sensitivity.rb:50:3:52:5 | method1 | | call_sensitivity.rb:55:5:55:13 | call to method1 | call_sensitivity.rb:54:3:56:5 | method2 | @@ -266,39 +325,54 @@ mayBenefitFromCallContext | call_sensitivity.rb:85:5:85:28 | call to singleton_method2 | call_sensitivity.rb:84:3:86:5 | call_singleton_method2 | | call_sensitivity.rb:89:5:89:26 | call to singleton_method1 | call_sensitivity.rb:88:3:90:5 | singleton_method3 | | call_sensitivity.rb:93:5:93:35 | call to singleton_method3 | call_sensitivity.rb:92:3:94:5 | call_singleton_method3 | -| call_sensitivity.rb:119:5:119:18 | call to method2 | call_sensitivity.rb:118:3:120:5 | call_method2 | -| call_sensitivity.rb:123:5:123:25 | call to method3 | call_sensitivity.rb:122:3:124:5 | call_method3 | -| call_sensitivity.rb:127:5:127:28 | call to singleton_method2 | call_sensitivity.rb:126:3:128:5 | call_singleton_method2 | -| call_sensitivity.rb:131:5:131:35 | call to singleton_method3 | call_sensitivity.rb:130:3:132:5 | call_singleton_method3 | +| call_sensitivity.rb:97:5:97:10 | call to sink | call_sensitivity.rb:96:3:99:5 | initialize | +| call_sensitivity.rb:98:5:98:13 | call to method1 | call_sensitivity.rb:96:3:99:5 | initialize | +| call_sensitivity.rb:124:5:124:18 | call to method2 | call_sensitivity.rb:123:3:125:5 | call_method2 | +| call_sensitivity.rb:128:5:128:25 | call to method3 | call_sensitivity.rb:127:3:129:5 | call_method3 | +| call_sensitivity.rb:132:5:132:28 | call to singleton_method2 | call_sensitivity.rb:131:3:133:5 | call_singleton_method2 | +| call_sensitivity.rb:136:5:136:35 | call to singleton_method3 | call_sensitivity.rb:135:3:137:5 | call_singleton_method3 | +| call_sensitivity.rb:157:3:157:12 | call to new | call_sensitivity.rb:156:1:158:3 | create | viableImplInCallContext | call_sensitivity.rb:51:5:51:10 | call to sink | call_sensitivity.rb:55:5:55:13 | call to method1 | call_sensitivity.rb:5:1:7:3 | sink | | call_sensitivity.rb:51:5:51:10 | call to sink | call_sensitivity.rb:63:5:63:16 | call to method1 | call_sensitivity.rb:5:1:7:3 | sink | | call_sensitivity.rb:51:5:51:10 | call to sink | call_sensitivity.rb:76:7:76:18 | call to method1 | call_sensitivity.rb:5:1:7:3 | sink | +| call_sensitivity.rb:51:5:51:10 | call to sink | call_sensitivity.rb:98:5:98:13 | call to method1 | call_sensitivity.rb:5:1:7:3 | sink | | call_sensitivity.rb:55:5:55:13 | call to method1 | call_sensitivity.rb:59:5:59:18 | call to method2 | call_sensitivity.rb:50:3:52:5 | method1 | -| call_sensitivity.rb:55:5:55:13 | call to method1 | call_sensitivity.rb:59:5:59:18 | call to method2 | call_sensitivity.rb:110:3:112:5 | method1 | -| call_sensitivity.rb:55:5:55:13 | call to method1 | call_sensitivity.rb:98:1:98:19 | call to method2 | call_sensitivity.rb:50:3:52:5 | method1 | -| call_sensitivity.rb:55:5:55:13 | call to method1 | call_sensitivity.rb:119:5:119:18 | call to method2 | call_sensitivity.rb:110:3:112:5 | method1 | -| call_sensitivity.rb:55:5:55:13 | call to method1 | call_sensitivity.rb:136:1:136:19 | call to method2 | call_sensitivity.rb:110:3:112:5 | method1 | -| call_sensitivity.rb:59:5:59:18 | call to method2 | call_sensitivity.rb:99:1:99:24 | call to call_method2 | call_sensitivity.rb:54:3:56:5 | method2 | +| call_sensitivity.rb:55:5:55:13 | call to method1 | call_sensitivity.rb:59:5:59:18 | call to method2 | call_sensitivity.rb:115:3:117:5 | method1 | +| call_sensitivity.rb:55:5:55:13 | call to method1 | call_sensitivity.rb:59:5:59:18 | call to method2 | call_sensitivity.rb:164:3:166:5 | method1 | +| call_sensitivity.rb:55:5:55:13 | call to method1 | call_sensitivity.rb:103:1:103:19 | call to method2 | call_sensitivity.rb:50:3:52:5 | method1 | +| call_sensitivity.rb:55:5:55:13 | call to method1 | call_sensitivity.rb:124:5:124:18 | call to method2 | call_sensitivity.rb:115:3:117:5 | method1 | +| call_sensitivity.rb:55:5:55:13 | call to method1 | call_sensitivity.rb:145:1:145:19 | call to method2 | call_sensitivity.rb:115:3:117:5 | method1 | +| call_sensitivity.rb:59:5:59:18 | call to method2 | call_sensitivity.rb:104:1:104:24 | call to call_method2 | call_sensitivity.rb:54:3:56:5 | method2 | | call_sensitivity.rb:63:5:63:16 | call to method1 | call_sensitivity.rb:67:5:67:25 | call to method3 | call_sensitivity.rb:50:3:52:5 | method1 | -| call_sensitivity.rb:63:5:63:16 | call to method1 | call_sensitivity.rb:67:5:67:25 | call to method3 | call_sensitivity.rb:110:3:112:5 | method1 | -| call_sensitivity.rb:63:5:63:16 | call to method1 | call_sensitivity.rb:100:1:100:23 | call to method3 | call_sensitivity.rb:50:3:52:5 | method1 | -| call_sensitivity.rb:63:5:63:16 | call to method1 | call_sensitivity.rb:123:5:123:25 | call to method3 | call_sensitivity.rb:110:3:112:5 | method1 | -| call_sensitivity.rb:63:5:63:16 | call to method1 | call_sensitivity.rb:138:1:138:23 | call to method3 | call_sensitivity.rb:110:3:112:5 | method1 | -| call_sensitivity.rb:67:5:67:25 | call to method3 | call_sensitivity.rb:101:1:101:25 | call to call_method3 | call_sensitivity.rb:62:3:64:5 | method3 | +| call_sensitivity.rb:63:5:63:16 | call to method1 | call_sensitivity.rb:67:5:67:25 | call to method3 | call_sensitivity.rb:115:3:117:5 | method1 | +| call_sensitivity.rb:63:5:63:16 | call to method1 | call_sensitivity.rb:67:5:67:25 | call to method3 | call_sensitivity.rb:164:3:166:5 | method1 | +| call_sensitivity.rb:63:5:63:16 | call to method1 | call_sensitivity.rb:105:1:105:23 | call to method3 | call_sensitivity.rb:50:3:52:5 | method1 | +| call_sensitivity.rb:63:5:63:16 | call to method1 | call_sensitivity.rb:128:5:128:25 | call to method3 | call_sensitivity.rb:115:3:117:5 | method1 | +| call_sensitivity.rb:63:5:63:16 | call to method1 | call_sensitivity.rb:147:1:147:23 | call to method3 | call_sensitivity.rb:115:3:117:5 | method1 | +| call_sensitivity.rb:67:5:67:25 | call to method3 | call_sensitivity.rb:106:1:106:25 | call to call_method3 | call_sensitivity.rb:62:3:64:5 | method3 | | call_sensitivity.rb:81:5:81:23 | call to singleton_method1 | call_sensitivity.rb:85:5:85:28 | call to singleton_method2 | call_sensitivity.rb:70:3:72:5 | singleton_method1 | -| call_sensitivity.rb:81:5:81:23 | call to singleton_method1 | call_sensitivity.rb:85:5:85:28 | call to singleton_method2 | call_sensitivity.rb:114:3:116:5 | singleton_method1 | -| call_sensitivity.rb:81:5:81:23 | call to singleton_method1 | call_sensitivity.rb:104:1:104:29 | call to singleton_method2 | call_sensitivity.rb:70:3:72:5 | singleton_method1 | -| call_sensitivity.rb:81:5:81:23 | call to singleton_method1 | call_sensitivity.rb:127:5:127:28 | call to singleton_method2 | call_sensitivity.rb:114:3:116:5 | singleton_method1 | -| call_sensitivity.rb:81:5:81:23 | call to singleton_method1 | call_sensitivity.rb:142:1:142:29 | call to singleton_method2 | call_sensitivity.rb:114:3:116:5 | singleton_method1 | -| call_sensitivity.rb:85:5:85:28 | call to singleton_method2 | call_sensitivity.rb:105:1:105:34 | call to call_singleton_method2 | call_sensitivity.rb:80:3:82:5 | singleton_method2 | +| call_sensitivity.rb:81:5:81:23 | call to singleton_method1 | call_sensitivity.rb:85:5:85:28 | call to singleton_method2 | call_sensitivity.rb:119:3:121:5 | singleton_method1 | +| call_sensitivity.rb:81:5:81:23 | call to singleton_method1 | call_sensitivity.rb:109:1:109:29 | call to singleton_method2 | call_sensitivity.rb:70:3:72:5 | singleton_method1 | +| call_sensitivity.rb:81:5:81:23 | call to singleton_method1 | call_sensitivity.rb:132:5:132:28 | call to singleton_method2 | call_sensitivity.rb:119:3:121:5 | singleton_method1 | +| call_sensitivity.rb:81:5:81:23 | call to singleton_method1 | call_sensitivity.rb:151:1:151:29 | call to singleton_method2 | call_sensitivity.rb:119:3:121:5 | singleton_method1 | +| call_sensitivity.rb:85:5:85:28 | call to singleton_method2 | call_sensitivity.rb:110:1:110:34 | call to call_singleton_method2 | call_sensitivity.rb:80:3:82:5 | singleton_method2 | | call_sensitivity.rb:89:5:89:26 | call to singleton_method1 | call_sensitivity.rb:93:5:93:35 | call to singleton_method3 | call_sensitivity.rb:70:3:72:5 | singleton_method1 | -| call_sensitivity.rb:89:5:89:26 | call to singleton_method1 | call_sensitivity.rb:93:5:93:35 | call to singleton_method3 | call_sensitivity.rb:114:3:116:5 | singleton_method1 | -| call_sensitivity.rb:89:5:89:26 | call to singleton_method1 | call_sensitivity.rb:106:1:106:33 | call to singleton_method3 | call_sensitivity.rb:70:3:72:5 | singleton_method1 | -| call_sensitivity.rb:89:5:89:26 | call to singleton_method1 | call_sensitivity.rb:131:5:131:35 | call to singleton_method3 | call_sensitivity.rb:114:3:116:5 | singleton_method1 | -| call_sensitivity.rb:89:5:89:26 | call to singleton_method1 | call_sensitivity.rb:144:1:144:33 | call to singleton_method3 | call_sensitivity.rb:114:3:116:5 | singleton_method1 | -| call_sensitivity.rb:93:5:93:35 | call to singleton_method3 | call_sensitivity.rb:107:1:107:34 | call to call_singleton_method3 | call_sensitivity.rb:88:3:90:5 | singleton_method3 | -| call_sensitivity.rb:119:5:119:18 | call to method2 | call_sensitivity.rb:137:1:137:24 | call to call_method2 | call_sensitivity.rb:54:3:56:5 | method2 | -| call_sensitivity.rb:123:5:123:25 | call to method3 | call_sensitivity.rb:139:1:139:25 | call to call_method3 | call_sensitivity.rb:62:3:64:5 | method3 | -| call_sensitivity.rb:127:5:127:28 | call to singleton_method2 | call_sensitivity.rb:143:1:143:34 | call to call_singleton_method2 | call_sensitivity.rb:80:3:82:5 | singleton_method2 | -| call_sensitivity.rb:131:5:131:35 | call to singleton_method3 | call_sensitivity.rb:145:1:145:34 | call to call_singleton_method3 | call_sensitivity.rb:88:3:90:5 | singleton_method3 | +| call_sensitivity.rb:89:5:89:26 | call to singleton_method1 | call_sensitivity.rb:93:5:93:35 | call to singleton_method3 | call_sensitivity.rb:119:3:121:5 | singleton_method1 | +| call_sensitivity.rb:89:5:89:26 | call to singleton_method1 | call_sensitivity.rb:111:1:111:33 | call to singleton_method3 | call_sensitivity.rb:70:3:72:5 | singleton_method1 | +| call_sensitivity.rb:89:5:89:26 | call to singleton_method1 | call_sensitivity.rb:136:5:136:35 | call to singleton_method3 | call_sensitivity.rb:119:3:121:5 | singleton_method1 | +| call_sensitivity.rb:89:5:89:26 | call to singleton_method1 | call_sensitivity.rb:153:1:153:33 | call to singleton_method3 | call_sensitivity.rb:119:3:121:5 | singleton_method1 | +| call_sensitivity.rb:93:5:93:35 | call to singleton_method3 | call_sensitivity.rb:112:1:112:34 | call to call_singleton_method3 | call_sensitivity.rb:88:3:90:5 | singleton_method3 | +| call_sensitivity.rb:97:5:97:10 | call to sink | call_sensitivity.rb:102:5:102:20 | call to new | call_sensitivity.rb:5:1:7:3 | sink | +| call_sensitivity.rb:97:5:97:10 | call to sink | call_sensitivity.rb:157:3:157:12 | call to new | call_sensitivity.rb:5:1:7:3 | sink | +| call_sensitivity.rb:97:5:97:10 | call to sink | call_sensitivity.rb:169:5:169:20 | call to new | call_sensitivity.rb:5:1:7:3 | sink | +| call_sensitivity.rb:98:5:98:13 | call to method1 | call_sensitivity.rb:102:5:102:20 | call to new | call_sensitivity.rb:50:3:52:5 | method1 | +| call_sensitivity.rb:98:5:98:13 | call to method1 | call_sensitivity.rb:157:3:157:12 | call to new | call_sensitivity.rb:50:3:52:5 | method1 | +| call_sensitivity.rb:98:5:98:13 | call to method1 | call_sensitivity.rb:157:3:157:12 | call to new | call_sensitivity.rb:115:3:117:5 | method1 | +| call_sensitivity.rb:98:5:98:13 | call to method1 | call_sensitivity.rb:169:5:169:20 | call to new | call_sensitivity.rb:164:3:166:5 | method1 | +| call_sensitivity.rb:124:5:124:18 | call to method2 | call_sensitivity.rb:146:1:146:24 | call to call_method2 | call_sensitivity.rb:54:3:56:5 | method2 | +| call_sensitivity.rb:128:5:128:25 | call to method3 | call_sensitivity.rb:148:1:148:25 | call to call_method3 | call_sensitivity.rb:62:3:64:5 | method3 | +| call_sensitivity.rb:132:5:132:28 | call to singleton_method2 | call_sensitivity.rb:152:1:152:34 | call to call_singleton_method2 | call_sensitivity.rb:80:3:82:5 | singleton_method2 | +| call_sensitivity.rb:136:5:136:35 | call to singleton_method3 | call_sensitivity.rb:154:1:154:34 | call to call_singleton_method3 | call_sensitivity.rb:88:3:90:5 | singleton_method3 | +| call_sensitivity.rb:157:3:157:12 | call to new | call_sensitivity.rb:160:1:160:20 | call to create | call_sensitivity.rb:96:3:99:5 | initialize | +| call_sensitivity.rb:157:3:157:12 | call to new | call_sensitivity.rb:161:1:161:20 | call to create | call_sensitivity.rb:139:3:141:5 | initialize | diff --git a/ruby/ql/test/library-tests/dataflow/call-sensitivity/call_sensitivity.rb b/ruby/ql/test/library-tests/dataflow/call-sensitivity/call_sensitivity.rb index 20107e09dc3..f96b61050e6 100644 --- a/ruby/ql/test/library-tests/dataflow/call-sensitivity/call_sensitivity.rb +++ b/ruby/ql/test/library-tests/dataflow/call-sensitivity/call_sensitivity.rb @@ -48,7 +48,7 @@ apply_lambda(MY_LAMBDA2, taint(9)) class A def method1 x - sink x # $ hasValueFlow=10 $ hasValueFlow=11 $ hasValueFlow=12 $ hasValueFlow=13 $ hasValueFlow=26 $ SPURIOUS: hasValueFlow=27 + sink x # $ hasValueFlow=10 $ hasValueFlow=11 $ hasValueFlow=12 $ hasValueFlow=13 $ hasValueFlow=26 $ hasValueFlow=28 $ hasValueFlow=30 $ SPURIOUS: hasValueFlow=27 end def method2 x @@ -92,9 +92,14 @@ class A def self.call_singleton_method3 x self.singleton_method3(self, x) end + + def initialize(x) + sink x # $ hasValueFlow=28 $ hasValueFlow=30 $ hasValueFlow=32 + method1 x + end end -a = A.new +a = A.new (taint 30) a.method2(taint 10) a.call_method2(taint 11) a.method3(a, taint(12)) @@ -130,9 +135,13 @@ class B < A def self.call_singleton_method3 x self.singleton_method3(self, x) end + + def initialize(x) + puts "NON SINK: #{x}" + end end -b = B.new +b = B.new (taint 31) b.method2(taint 18) b.call_method2(taint 19) b.method3(b, taint(20)) @@ -143,3 +152,18 @@ B.singleton_method2(taint 22) B.call_singleton_method2(taint 23) B.singleton_method3(B, taint(24)) B.call_singleton_method3(taint 25) + +def create (type, x) + type.new x +end + +create(A, taint(28)) +create(B, taint(29)) + +class C < A + def method1 x + puts "NON SINK: #{x}" + end +end + +c = C.new (taint 32) diff --git a/ruby/ql/test/library-tests/dataflow/global/Flow.expected b/ruby/ql/test/library-tests/dataflow/global/Flow.expected index ffba59b0f7e..cae1f06abb7 100644 --- a/ruby/ql/test/library-tests/dataflow/global/Flow.expected +++ b/ruby/ql/test/library-tests/dataflow/global/Flow.expected @@ -30,139 +30,177 @@ edges | instance_variables.rb:19:12:19:21 | call to taint : | instance_variables.rb:19:5:19:8 | [post] self [@foo] : | | instance_variables.rb:20:10:20:13 | self [@foo] : | instance_variables.rb:20:10:20:13 | @foo | | instance_variables.rb:20:10:20:13 | self [@foo] : | instance_variables.rb:20:10:20:13 | @foo | -| instance_variables.rb:24:1:24:3 | [post] foo [@field] : | instance_variables.rb:25:6:25:8 | foo [@field] : | -| instance_variables.rb:24:1:24:3 | [post] foo [@field] : | instance_variables.rb:25:6:25:8 | foo [@field] : | -| instance_variables.rb:24:15:24:23 | call to taint : | instance_variables.rb:10:19:10:19 | x : | -| instance_variables.rb:24:15:24:23 | call to taint : | instance_variables.rb:10:19:10:19 | x : | -| instance_variables.rb:24:15:24:23 | call to taint : | instance_variables.rb:24:1:24:3 | [post] foo [@field] : | -| instance_variables.rb:24:15:24:23 | call to taint : | instance_variables.rb:24:1:24:3 | [post] foo [@field] : | -| instance_variables.rb:25:6:25:8 | foo [@field] : | instance_variables.rb:13:5:15:7 | self in get_field [@field] : | -| instance_variables.rb:25:6:25:8 | foo [@field] : | instance_variables.rb:13:5:15:7 | self in get_field [@field] : | -| instance_variables.rb:25:6:25:8 | foo [@field] : | instance_variables.rb:25:6:25:18 | call to get_field | -| instance_variables.rb:25:6:25:8 | foo [@field] : | instance_variables.rb:25:6:25:18 | call to get_field | -| instance_variables.rb:28:1:28:3 | [post] bar [@field] : | instance_variables.rb:29:6:29:8 | bar [@field] : | -| instance_variables.rb:28:15:28:22 | call to taint : | instance_variables.rb:10:19:10:19 | x : | -| instance_variables.rb:28:15:28:22 | call to taint : | instance_variables.rb:28:1:28:3 | [post] bar [@field] : | -| instance_variables.rb:29:6:29:8 | bar [@field] : | instance_variables.rb:16:5:18:7 | self in inc_field [@field] : | -| instance_variables.rb:29:6:29:8 | bar [@field] : | instance_variables.rb:29:6:29:18 | call to inc_field | -| instance_variables.rb:32:1:32:4 | [post] foo1 [@field] : | instance_variables.rb:33:6:33:9 | foo1 [@field] : | -| instance_variables.rb:32:1:32:4 | [post] foo1 [@field] : | instance_variables.rb:33:6:33:9 | foo1 [@field] : | -| instance_variables.rb:32:14:32:22 | call to taint : | instance_variables.rb:32:1:32:4 | [post] foo1 [@field] : | -| instance_variables.rb:32:14:32:22 | call to taint : | instance_variables.rb:32:1:32:4 | [post] foo1 [@field] : | -| instance_variables.rb:33:6:33:9 | foo1 [@field] : | instance_variables.rb:33:6:33:15 | call to field | -| instance_variables.rb:33:6:33:9 | foo1 [@field] : | instance_variables.rb:33:6:33:15 | call to field | -| instance_variables.rb:36:1:36:4 | [post] foo2 [@field] : | instance_variables.rb:37:6:37:9 | foo2 [@field] : | -| instance_variables.rb:36:1:36:4 | [post] foo2 [@field] : | instance_variables.rb:37:6:37:9 | foo2 [@field] : | -| instance_variables.rb:36:14:36:22 | call to taint : | instance_variables.rb:36:1:36:4 | [post] foo2 [@field] : | -| instance_variables.rb:36:14:36:22 | call to taint : | instance_variables.rb:36:1:36:4 | [post] foo2 [@field] : | -| instance_variables.rb:37:6:37:9 | foo2 [@field] : | instance_variables.rb:13:5:15:7 | self in get_field [@field] : | -| instance_variables.rb:37:6:37:9 | foo2 [@field] : | instance_variables.rb:13:5:15:7 | self in get_field [@field] : | -| instance_variables.rb:37:6:37:9 | foo2 [@field] : | instance_variables.rb:37:6:37:19 | call to get_field | -| instance_variables.rb:37:6:37:9 | foo2 [@field] : | instance_variables.rb:37:6:37:19 | call to get_field | -| instance_variables.rb:40:1:40:4 | [post] foo3 [@field] : | instance_variables.rb:41:6:41:9 | foo3 [@field] : | -| instance_variables.rb:40:1:40:4 | [post] foo3 [@field] : | instance_variables.rb:41:6:41:9 | foo3 [@field] : | -| instance_variables.rb:40:1:40:4 | [post] foo3 [@field] : | instance_variables.rb:53:6:53:9 | foo3 [@field] : | -| instance_variables.rb:40:1:40:4 | [post] foo3 [@field] : | instance_variables.rb:53:6:53:9 | foo3 [@field] : | -| instance_variables.rb:40:16:40:24 | call to taint : | instance_variables.rb:10:19:10:19 | x : | -| instance_variables.rb:40:16:40:24 | call to taint : | instance_variables.rb:10:19:10:19 | x : | -| instance_variables.rb:40:16:40:24 | call to taint : | instance_variables.rb:40:1:40:4 | [post] foo3 [@field] : | -| instance_variables.rb:40:16:40:24 | call to taint : | instance_variables.rb:40:1:40:4 | [post] foo3 [@field] : | -| instance_variables.rb:41:6:41:9 | foo3 [@field] : | instance_variables.rb:41:6:41:15 | call to field | -| instance_variables.rb:41:6:41:9 | foo3 [@field] : | instance_variables.rb:41:6:41:15 | call to field | -| instance_variables.rb:48:2:48:5 | [post] foo5 [@field] : | instance_variables.rb:49:6:49:9 | foo5 [@field] : | -| instance_variables.rb:48:2:48:5 | [post] foo5 [@field] : | instance_variables.rb:49:6:49:9 | foo5 [@field] : | -| instance_variables.rb:48:2:48:5 | [post] foo5 [@field] : | instance_variables.rb:54:6:54:9 | foo5 [@field] : | -| instance_variables.rb:48:2:48:5 | [post] foo5 [@field] : | instance_variables.rb:54:6:54:9 | foo5 [@field] : | -| instance_variables.rb:48:18:48:26 | call to taint : | instance_variables.rb:10:19:10:19 | x : | -| instance_variables.rb:48:18:48:26 | call to taint : | instance_variables.rb:10:19:10:19 | x : | -| instance_variables.rb:48:18:48:26 | call to taint : | instance_variables.rb:48:2:48:5 | [post] foo5 [@field] : | -| instance_variables.rb:48:18:48:26 | call to taint : | instance_variables.rb:48:2:48:5 | [post] foo5 [@field] : | -| instance_variables.rb:49:6:49:9 | foo5 [@field] : | instance_variables.rb:13:5:15:7 | self in get_field [@field] : | -| instance_variables.rb:49:6:49:9 | foo5 [@field] : | instance_variables.rb:13:5:15:7 | self in get_field [@field] : | -| instance_variables.rb:49:6:49:9 | foo5 [@field] : | instance_variables.rb:49:6:49:19 | call to get_field | -| instance_variables.rb:49:6:49:9 | foo5 [@field] : | instance_variables.rb:49:6:49:19 | call to get_field | -| instance_variables.rb:52:15:52:18 | [post] foo6 [@field] : | instance_variables.rb:55:6:55:9 | foo6 [@field] : | -| instance_variables.rb:52:15:52:18 | [post] foo6 [@field] : | instance_variables.rb:55:6:55:9 | foo6 [@field] : | -| instance_variables.rb:52:32:52:40 | call to taint : | instance_variables.rb:10:19:10:19 | x : | -| instance_variables.rb:52:32:52:40 | call to taint : | instance_variables.rb:10:19:10:19 | x : | -| instance_variables.rb:52:32:52:40 | call to taint : | instance_variables.rb:52:15:52:18 | [post] foo6 [@field] : | -| instance_variables.rb:52:32:52:40 | call to taint : | instance_variables.rb:52:15:52:18 | [post] foo6 [@field] : | -| instance_variables.rb:53:6:53:9 | foo3 [@field] : | instance_variables.rb:13:5:15:7 | self in get_field [@field] : | -| instance_variables.rb:53:6:53:9 | foo3 [@field] : | instance_variables.rb:13:5:15:7 | self in get_field [@field] : | -| instance_variables.rb:53:6:53:9 | foo3 [@field] : | instance_variables.rb:53:6:53:19 | call to get_field | -| instance_variables.rb:53:6:53:9 | foo3 [@field] : | instance_variables.rb:53:6:53:19 | call to get_field | -| instance_variables.rb:54:6:54:9 | foo5 [@field] : | instance_variables.rb:13:5:15:7 | self in get_field [@field] : | -| instance_variables.rb:54:6:54:9 | foo5 [@field] : | instance_variables.rb:13:5:15:7 | self in get_field [@field] : | -| instance_variables.rb:54:6:54:9 | foo5 [@field] : | instance_variables.rb:54:6:54:19 | call to get_field | -| instance_variables.rb:54:6:54:9 | foo5 [@field] : | instance_variables.rb:54:6:54:19 | call to get_field | -| instance_variables.rb:55:6:55:9 | foo6 [@field] : | instance_variables.rb:13:5:15:7 | self in get_field [@field] : | -| instance_variables.rb:55:6:55:9 | foo6 [@field] : | instance_variables.rb:13:5:15:7 | self in get_field [@field] : | -| instance_variables.rb:55:6:55:9 | foo6 [@field] : | instance_variables.rb:55:6:55:19 | call to get_field | -| instance_variables.rb:55:6:55:9 | foo6 [@field] : | instance_variables.rb:55:6:55:19 | call to get_field | -| instance_variables.rb:59:15:59:18 | [post] foo7 [@field] : | instance_variables.rb:60:6:60:9 | foo7 [@field] : | -| instance_variables.rb:59:15:59:18 | [post] foo7 [@field] : | instance_variables.rb:60:6:60:9 | foo7 [@field] : | -| instance_variables.rb:59:25:59:28 | [post] foo8 [@field] : | instance_variables.rb:61:6:61:9 | foo8 [@field] : | -| instance_variables.rb:59:25:59:28 | [post] foo8 [@field] : | instance_variables.rb:61:6:61:9 | foo8 [@field] : | -| instance_variables.rb:59:45:59:53 | call to taint : | instance_variables.rb:10:19:10:19 | x : | -| instance_variables.rb:59:45:59:53 | call to taint : | instance_variables.rb:10:19:10:19 | x : | -| instance_variables.rb:59:45:59:53 | call to taint : | instance_variables.rb:59:15:59:18 | [post] foo7 [@field] : | -| instance_variables.rb:59:45:59:53 | call to taint : | instance_variables.rb:59:15:59:18 | [post] foo7 [@field] : | -| instance_variables.rb:59:45:59:53 | call to taint : | instance_variables.rb:59:25:59:28 | [post] foo8 [@field] : | -| instance_variables.rb:59:45:59:53 | call to taint : | instance_variables.rb:59:25:59:28 | [post] foo8 [@field] : | -| instance_variables.rb:60:6:60:9 | foo7 [@field] : | instance_variables.rb:13:5:15:7 | self in get_field [@field] : | -| instance_variables.rb:60:6:60:9 | foo7 [@field] : | instance_variables.rb:13:5:15:7 | self in get_field [@field] : | -| instance_variables.rb:60:6:60:9 | foo7 [@field] : | instance_variables.rb:60:6:60:19 | call to get_field | -| instance_variables.rb:60:6:60:9 | foo7 [@field] : | instance_variables.rb:60:6:60:19 | call to get_field | -| instance_variables.rb:61:6:61:9 | foo8 [@field] : | instance_variables.rb:13:5:15:7 | self in get_field [@field] : | -| instance_variables.rb:61:6:61:9 | foo8 [@field] : | instance_variables.rb:13:5:15:7 | self in get_field [@field] : | -| instance_variables.rb:61:6:61:9 | foo8 [@field] : | instance_variables.rb:61:6:61:19 | call to get_field | -| instance_variables.rb:61:6:61:9 | foo8 [@field] : | instance_variables.rb:61:6:61:19 | call to get_field | -| instance_variables.rb:65:22:65:25 | [post] foo9 [@field] : | instance_variables.rb:66:6:66:9 | foo9 [@field] : | -| instance_variables.rb:65:22:65:25 | [post] foo9 [@field] : | instance_variables.rb:66:6:66:9 | foo9 [@field] : | -| instance_variables.rb:65:32:65:36 | [post] foo10 [@field] : | instance_variables.rb:67:6:67:10 | foo10 [@field] : | -| instance_variables.rb:65:32:65:36 | [post] foo10 [@field] : | instance_variables.rb:67:6:67:10 | foo10 [@field] : | -| instance_variables.rb:65:53:65:61 | call to taint : | instance_variables.rb:10:19:10:19 | x : | -| instance_variables.rb:65:53:65:61 | call to taint : | instance_variables.rb:10:19:10:19 | x : | -| instance_variables.rb:65:53:65:61 | call to taint : | instance_variables.rb:65:22:65:25 | [post] foo9 [@field] : | -| instance_variables.rb:65:53:65:61 | call to taint : | instance_variables.rb:65:22:65:25 | [post] foo9 [@field] : | -| instance_variables.rb:65:53:65:61 | call to taint : | instance_variables.rb:65:32:65:36 | [post] foo10 [@field] : | -| instance_variables.rb:65:53:65:61 | call to taint : | instance_variables.rb:65:32:65:36 | [post] foo10 [@field] : | -| instance_variables.rb:66:6:66:9 | foo9 [@field] : | instance_variables.rb:13:5:15:7 | self in get_field [@field] : | -| instance_variables.rb:66:6:66:9 | foo9 [@field] : | instance_variables.rb:13:5:15:7 | self in get_field [@field] : | -| instance_variables.rb:66:6:66:9 | foo9 [@field] : | instance_variables.rb:66:6:66:19 | call to get_field | -| instance_variables.rb:66:6:66:9 | foo9 [@field] : | instance_variables.rb:66:6:66:19 | call to get_field | -| instance_variables.rb:67:6:67:10 | foo10 [@field] : | instance_variables.rb:13:5:15:7 | self in get_field [@field] : | -| instance_variables.rb:67:6:67:10 | foo10 [@field] : | instance_variables.rb:13:5:15:7 | self in get_field [@field] : | -| instance_variables.rb:67:6:67:10 | foo10 [@field] : | instance_variables.rb:67:6:67:20 | call to get_field | -| instance_variables.rb:67:6:67:10 | foo10 [@field] : | instance_variables.rb:67:6:67:20 | call to get_field | -| instance_variables.rb:70:5:70:5 | [post] x [@field] : | instance_variables.rb:74:14:74:18 | [post] foo11 [@field] : | -| instance_variables.rb:70:5:70:5 | [post] x [@field] : | instance_variables.rb:74:14:74:18 | [post] foo11 [@field] : | -| instance_variables.rb:70:5:70:5 | [post] x [@field] : | instance_variables.rb:78:15:78:19 | [post] foo12 [@field] : | -| instance_variables.rb:70:5:70:5 | [post] x [@field] : | instance_variables.rb:78:15:78:19 | [post] foo12 [@field] : | -| instance_variables.rb:70:5:70:5 | [post] x [@field] : | instance_variables.rb:83:22:83:26 | [post] foo13 [@field] : | -| instance_variables.rb:70:5:70:5 | [post] x [@field] : | instance_variables.rb:83:22:83:26 | [post] foo13 [@field] : | -| instance_variables.rb:70:17:70:25 | call to taint : | instance_variables.rb:10:19:10:19 | x : | -| instance_variables.rb:70:17:70:25 | call to taint : | instance_variables.rb:10:19:10:19 | x : | -| instance_variables.rb:70:17:70:25 | call to taint : | instance_variables.rb:70:5:70:5 | [post] x [@field] : | -| instance_variables.rb:70:17:70:25 | call to taint : | instance_variables.rb:70:5:70:5 | [post] x [@field] : | -| instance_variables.rb:74:14:74:18 | [post] foo11 [@field] : | instance_variables.rb:75:6:75:10 | foo11 [@field] : | -| instance_variables.rb:74:14:74:18 | [post] foo11 [@field] : | instance_variables.rb:75:6:75:10 | foo11 [@field] : | -| instance_variables.rb:75:6:75:10 | foo11 [@field] : | instance_variables.rb:13:5:15:7 | self in get_field [@field] : | -| instance_variables.rb:75:6:75:10 | foo11 [@field] : | instance_variables.rb:13:5:15:7 | self in get_field [@field] : | -| instance_variables.rb:75:6:75:10 | foo11 [@field] : | instance_variables.rb:75:6:75:20 | call to get_field | -| instance_variables.rb:75:6:75:10 | foo11 [@field] : | instance_variables.rb:75:6:75:20 | call to get_field | -| instance_variables.rb:78:15:78:19 | [post] foo12 [@field] : | instance_variables.rb:79:6:79:10 | foo12 [@field] : | -| instance_variables.rb:78:15:78:19 | [post] foo12 [@field] : | instance_variables.rb:79:6:79:10 | foo12 [@field] : | -| instance_variables.rb:79:6:79:10 | foo12 [@field] : | instance_variables.rb:13:5:15:7 | self in get_field [@field] : | -| instance_variables.rb:79:6:79:10 | foo12 [@field] : | instance_variables.rb:13:5:15:7 | self in get_field [@field] : | -| instance_variables.rb:79:6:79:10 | foo12 [@field] : | instance_variables.rb:79:6:79:20 | call to get_field | -| instance_variables.rb:79:6:79:10 | foo12 [@field] : | instance_variables.rb:79:6:79:20 | call to get_field | -| instance_variables.rb:83:22:83:26 | [post] foo13 [@field] : | instance_variables.rb:84:6:84:10 | foo13 [@field] : | -| instance_variables.rb:83:22:83:26 | [post] foo13 [@field] : | instance_variables.rb:84:6:84:10 | foo13 [@field] : | -| instance_variables.rb:84:6:84:10 | foo13 [@field] : | instance_variables.rb:13:5:15:7 | self in get_field [@field] : | -| instance_variables.rb:84:6:84:10 | foo13 [@field] : | instance_variables.rb:13:5:15:7 | self in get_field [@field] : | -| instance_variables.rb:84:6:84:10 | foo13 [@field] : | instance_variables.rb:84:6:84:20 | call to get_field | -| instance_variables.rb:84:6:84:10 | foo13 [@field] : | instance_variables.rb:84:6:84:20 | call to get_field | +| instance_variables.rb:22:20:22:24 | field : | instance_variables.rb:23:18:23:22 | field : | +| instance_variables.rb:22:20:22:24 | field : | instance_variables.rb:23:18:23:22 | field : | +| instance_variables.rb:23:18:23:22 | field : | instance_variables.rb:23:9:23:14 | [post] self [@field] : | +| instance_variables.rb:23:18:23:22 | field : | instance_variables.rb:23:9:23:14 | [post] self [@field] : | +| instance_variables.rb:24:9:24:17 | call to taint : | instance_variables.rb:28:9:28:25 | call to initialize : | +| instance_variables.rb:24:9:24:17 | call to taint : | instance_variables.rb:28:9:28:25 | call to initialize : | +| instance_variables.rb:27:25:27:29 | field : | instance_variables.rb:28:20:28:24 | field : | +| instance_variables.rb:27:25:27:29 | field : | instance_variables.rb:28:20:28:24 | field : | +| instance_variables.rb:28:9:28:25 | call to initialize : | instance_variables.rb:104:6:104:37 | call to call_initialize | +| instance_variables.rb:28:9:28:25 | call to initialize : | instance_variables.rb:104:6:104:37 | call to call_initialize | +| instance_variables.rb:28:20:28:24 | field : | instance_variables.rb:22:20:22:24 | field : | +| instance_variables.rb:28:20:28:24 | field : | instance_variables.rb:22:20:22:24 | field : | +| instance_variables.rb:28:20:28:24 | field : | instance_variables.rb:28:9:28:25 | [post] self [@field] : | +| instance_variables.rb:28:20:28:24 | field : | instance_variables.rb:28:9:28:25 | [post] self [@field] : | +| instance_variables.rb:34:9:34:17 | call to taint : | instance_variables.rb:106:7:106:24 | call to new : | +| instance_variables.rb:34:9:34:17 | call to taint : | instance_variables.rb:106:7:106:24 | call to new : | +| instance_variables.rb:39:1:39:3 | [post] foo [@field] : | instance_variables.rb:40:6:40:8 | foo [@field] : | +| instance_variables.rb:39:1:39:3 | [post] foo [@field] : | instance_variables.rb:40:6:40:8 | foo [@field] : | +| instance_variables.rb:39:15:39:23 | call to taint : | instance_variables.rb:10:19:10:19 | x : | +| instance_variables.rb:39:15:39:23 | call to taint : | instance_variables.rb:10:19:10:19 | x : | +| instance_variables.rb:39:15:39:23 | call to taint : | instance_variables.rb:39:1:39:3 | [post] foo [@field] : | +| instance_variables.rb:39:15:39:23 | call to taint : | instance_variables.rb:39:1:39:3 | [post] foo [@field] : | +| instance_variables.rb:40:6:40:8 | foo [@field] : | instance_variables.rb:13:5:15:7 | self in get_field [@field] : | +| instance_variables.rb:40:6:40:8 | foo [@field] : | instance_variables.rb:13:5:15:7 | self in get_field [@field] : | +| instance_variables.rb:40:6:40:8 | foo [@field] : | instance_variables.rb:40:6:40:18 | call to get_field | +| instance_variables.rb:40:6:40:8 | foo [@field] : | instance_variables.rb:40:6:40:18 | call to get_field | +| instance_variables.rb:43:1:43:3 | [post] bar [@field] : | instance_variables.rb:44:6:44:8 | bar [@field] : | +| instance_variables.rb:43:15:43:22 | call to taint : | instance_variables.rb:10:19:10:19 | x : | +| instance_variables.rb:43:15:43:22 | call to taint : | instance_variables.rb:43:1:43:3 | [post] bar [@field] : | +| instance_variables.rb:44:6:44:8 | bar [@field] : | instance_variables.rb:16:5:18:7 | self in inc_field [@field] : | +| instance_variables.rb:44:6:44:8 | bar [@field] : | instance_variables.rb:44:6:44:18 | call to inc_field | +| instance_variables.rb:47:1:47:4 | [post] foo1 [@field] : | instance_variables.rb:48:6:48:9 | foo1 [@field] : | +| instance_variables.rb:47:1:47:4 | [post] foo1 [@field] : | instance_variables.rb:48:6:48:9 | foo1 [@field] : | +| instance_variables.rb:47:14:47:22 | call to taint : | instance_variables.rb:47:1:47:4 | [post] foo1 [@field] : | +| instance_variables.rb:47:14:47:22 | call to taint : | instance_variables.rb:47:1:47:4 | [post] foo1 [@field] : | +| instance_variables.rb:48:6:48:9 | foo1 [@field] : | instance_variables.rb:48:6:48:15 | call to field | +| instance_variables.rb:48:6:48:9 | foo1 [@field] : | instance_variables.rb:48:6:48:15 | call to field | +| instance_variables.rb:51:1:51:4 | [post] foo2 [@field] : | instance_variables.rb:52:6:52:9 | foo2 [@field] : | +| instance_variables.rb:51:1:51:4 | [post] foo2 [@field] : | instance_variables.rb:52:6:52:9 | foo2 [@field] : | +| instance_variables.rb:51:14:51:22 | call to taint : | instance_variables.rb:51:1:51:4 | [post] foo2 [@field] : | +| instance_variables.rb:51:14:51:22 | call to taint : | instance_variables.rb:51:1:51:4 | [post] foo2 [@field] : | +| instance_variables.rb:52:6:52:9 | foo2 [@field] : | instance_variables.rb:13:5:15:7 | self in get_field [@field] : | +| instance_variables.rb:52:6:52:9 | foo2 [@field] : | instance_variables.rb:13:5:15:7 | self in get_field [@field] : | +| instance_variables.rb:52:6:52:9 | foo2 [@field] : | instance_variables.rb:52:6:52:19 | call to get_field | +| instance_variables.rb:52:6:52:9 | foo2 [@field] : | instance_variables.rb:52:6:52:19 | call to get_field | +| instance_variables.rb:55:1:55:4 | [post] foo3 [@field] : | instance_variables.rb:56:6:56:9 | foo3 [@field] : | +| instance_variables.rb:55:1:55:4 | [post] foo3 [@field] : | instance_variables.rb:56:6:56:9 | foo3 [@field] : | +| instance_variables.rb:55:1:55:4 | [post] foo3 [@field] : | instance_variables.rb:68:6:68:9 | foo3 [@field] : | +| instance_variables.rb:55:1:55:4 | [post] foo3 [@field] : | instance_variables.rb:68:6:68:9 | foo3 [@field] : | +| instance_variables.rb:55:16:55:24 | call to taint : | instance_variables.rb:10:19:10:19 | x : | +| instance_variables.rb:55:16:55:24 | call to taint : | instance_variables.rb:10:19:10:19 | x : | +| instance_variables.rb:55:16:55:24 | call to taint : | instance_variables.rb:55:1:55:4 | [post] foo3 [@field] : | +| instance_variables.rb:55:16:55:24 | call to taint : | instance_variables.rb:55:1:55:4 | [post] foo3 [@field] : | +| instance_variables.rb:56:6:56:9 | foo3 [@field] : | instance_variables.rb:56:6:56:15 | call to field | +| instance_variables.rb:56:6:56:9 | foo3 [@field] : | instance_variables.rb:56:6:56:15 | call to field | +| instance_variables.rb:63:2:63:5 | [post] foo5 [@field] : | instance_variables.rb:64:6:64:9 | foo5 [@field] : | +| instance_variables.rb:63:2:63:5 | [post] foo5 [@field] : | instance_variables.rb:64:6:64:9 | foo5 [@field] : | +| instance_variables.rb:63:2:63:5 | [post] foo5 [@field] : | instance_variables.rb:69:6:69:9 | foo5 [@field] : | +| instance_variables.rb:63:2:63:5 | [post] foo5 [@field] : | instance_variables.rb:69:6:69:9 | foo5 [@field] : | +| instance_variables.rb:63:18:63:26 | call to taint : | instance_variables.rb:10:19:10:19 | x : | +| instance_variables.rb:63:18:63:26 | call to taint : | instance_variables.rb:10:19:10:19 | x : | +| instance_variables.rb:63:18:63:26 | call to taint : | instance_variables.rb:63:2:63:5 | [post] foo5 [@field] : | +| instance_variables.rb:63:18:63:26 | call to taint : | instance_variables.rb:63:2:63:5 | [post] foo5 [@field] : | +| instance_variables.rb:64:6:64:9 | foo5 [@field] : | instance_variables.rb:13:5:15:7 | self in get_field [@field] : | +| instance_variables.rb:64:6:64:9 | foo5 [@field] : | instance_variables.rb:13:5:15:7 | self in get_field [@field] : | +| instance_variables.rb:64:6:64:9 | foo5 [@field] : | instance_variables.rb:64:6:64:19 | call to get_field | +| instance_variables.rb:64:6:64:9 | foo5 [@field] : | instance_variables.rb:64:6:64:19 | call to get_field | +| instance_variables.rb:67:15:67:18 | [post] foo6 [@field] : | instance_variables.rb:70:6:70:9 | foo6 [@field] : | +| instance_variables.rb:67:15:67:18 | [post] foo6 [@field] : | instance_variables.rb:70:6:70:9 | foo6 [@field] : | +| instance_variables.rb:67:32:67:40 | call to taint : | instance_variables.rb:10:19:10:19 | x : | +| instance_variables.rb:67:32:67:40 | call to taint : | instance_variables.rb:10:19:10:19 | x : | +| instance_variables.rb:67:32:67:40 | call to taint : | instance_variables.rb:67:15:67:18 | [post] foo6 [@field] : | +| instance_variables.rb:67:32:67:40 | call to taint : | instance_variables.rb:67:15:67:18 | [post] foo6 [@field] : | +| instance_variables.rb:68:6:68:9 | foo3 [@field] : | instance_variables.rb:13:5:15:7 | self in get_field [@field] : | +| instance_variables.rb:68:6:68:9 | foo3 [@field] : | instance_variables.rb:13:5:15:7 | self in get_field [@field] : | +| instance_variables.rb:68:6:68:9 | foo3 [@field] : | instance_variables.rb:68:6:68:19 | call to get_field | +| instance_variables.rb:68:6:68:9 | foo3 [@field] : | instance_variables.rb:68:6:68:19 | call to get_field | +| instance_variables.rb:69:6:69:9 | foo5 [@field] : | instance_variables.rb:13:5:15:7 | self in get_field [@field] : | +| instance_variables.rb:69:6:69:9 | foo5 [@field] : | instance_variables.rb:13:5:15:7 | self in get_field [@field] : | +| instance_variables.rb:69:6:69:9 | foo5 [@field] : | instance_variables.rb:69:6:69:19 | call to get_field | +| instance_variables.rb:69:6:69:9 | foo5 [@field] : | instance_variables.rb:69:6:69:19 | call to get_field | +| instance_variables.rb:70:6:70:9 | foo6 [@field] : | instance_variables.rb:13:5:15:7 | self in get_field [@field] : | +| instance_variables.rb:70:6:70:9 | foo6 [@field] : | instance_variables.rb:13:5:15:7 | self in get_field [@field] : | +| instance_variables.rb:70:6:70:9 | foo6 [@field] : | instance_variables.rb:70:6:70:19 | call to get_field | +| instance_variables.rb:70:6:70:9 | foo6 [@field] : | instance_variables.rb:70:6:70:19 | call to get_field | +| instance_variables.rb:74:15:74:18 | [post] foo7 [@field] : | instance_variables.rb:75:6:75:9 | foo7 [@field] : | +| instance_variables.rb:74:15:74:18 | [post] foo7 [@field] : | instance_variables.rb:75:6:75:9 | foo7 [@field] : | +| instance_variables.rb:74:25:74:28 | [post] foo8 [@field] : | instance_variables.rb:76:6:76:9 | foo8 [@field] : | +| instance_variables.rb:74:25:74:28 | [post] foo8 [@field] : | instance_variables.rb:76:6:76:9 | foo8 [@field] : | +| instance_variables.rb:74:45:74:53 | call to taint : | instance_variables.rb:10:19:10:19 | x : | +| instance_variables.rb:74:45:74:53 | call to taint : | instance_variables.rb:10:19:10:19 | x : | +| instance_variables.rb:74:45:74:53 | call to taint : | instance_variables.rb:74:15:74:18 | [post] foo7 [@field] : | +| instance_variables.rb:74:45:74:53 | call to taint : | instance_variables.rb:74:15:74:18 | [post] foo7 [@field] : | +| instance_variables.rb:74:45:74:53 | call to taint : | instance_variables.rb:74:25:74:28 | [post] foo8 [@field] : | +| instance_variables.rb:74:45:74:53 | call to taint : | instance_variables.rb:74:25:74:28 | [post] foo8 [@field] : | +| instance_variables.rb:75:6:75:9 | foo7 [@field] : | instance_variables.rb:13:5:15:7 | self in get_field [@field] : | +| instance_variables.rb:75:6:75:9 | foo7 [@field] : | instance_variables.rb:13:5:15:7 | self in get_field [@field] : | +| instance_variables.rb:75:6:75:9 | foo7 [@field] : | instance_variables.rb:75:6:75:19 | call to get_field | +| instance_variables.rb:75:6:75:9 | foo7 [@field] : | instance_variables.rb:75:6:75:19 | call to get_field | +| instance_variables.rb:76:6:76:9 | foo8 [@field] : | instance_variables.rb:13:5:15:7 | self in get_field [@field] : | +| instance_variables.rb:76:6:76:9 | foo8 [@field] : | instance_variables.rb:13:5:15:7 | self in get_field [@field] : | +| instance_variables.rb:76:6:76:9 | foo8 [@field] : | instance_variables.rb:76:6:76:19 | call to get_field | +| instance_variables.rb:76:6:76:9 | foo8 [@field] : | instance_variables.rb:76:6:76:19 | call to get_field | +| instance_variables.rb:80:22:80:25 | [post] foo9 [@field] : | instance_variables.rb:81:6:81:9 | foo9 [@field] : | +| instance_variables.rb:80:22:80:25 | [post] foo9 [@field] : | instance_variables.rb:81:6:81:9 | foo9 [@field] : | +| instance_variables.rb:80:32:80:36 | [post] foo10 [@field] : | instance_variables.rb:82:6:82:10 | foo10 [@field] : | +| instance_variables.rb:80:32:80:36 | [post] foo10 [@field] : | instance_variables.rb:82:6:82:10 | foo10 [@field] : | +| instance_variables.rb:80:53:80:61 | call to taint : | instance_variables.rb:10:19:10:19 | x : | +| instance_variables.rb:80:53:80:61 | call to taint : | instance_variables.rb:10:19:10:19 | x : | +| instance_variables.rb:80:53:80:61 | call to taint : | instance_variables.rb:80:22:80:25 | [post] foo9 [@field] : | +| instance_variables.rb:80:53:80:61 | call to taint : | instance_variables.rb:80:22:80:25 | [post] foo9 [@field] : | +| instance_variables.rb:80:53:80:61 | call to taint : | instance_variables.rb:80:32:80:36 | [post] foo10 [@field] : | +| instance_variables.rb:80:53:80:61 | call to taint : | instance_variables.rb:80:32:80:36 | [post] foo10 [@field] : | +| instance_variables.rb:81:6:81:9 | foo9 [@field] : | instance_variables.rb:13:5:15:7 | self in get_field [@field] : | +| instance_variables.rb:81:6:81:9 | foo9 [@field] : | instance_variables.rb:13:5:15:7 | self in get_field [@field] : | +| instance_variables.rb:81:6:81:9 | foo9 [@field] : | instance_variables.rb:81:6:81:19 | call to get_field | +| instance_variables.rb:81:6:81:9 | foo9 [@field] : | instance_variables.rb:81:6:81:19 | call to get_field | +| instance_variables.rb:82:6:82:10 | foo10 [@field] : | instance_variables.rb:13:5:15:7 | self in get_field [@field] : | +| instance_variables.rb:82:6:82:10 | foo10 [@field] : | instance_variables.rb:13:5:15:7 | self in get_field [@field] : | +| instance_variables.rb:82:6:82:10 | foo10 [@field] : | instance_variables.rb:82:6:82:20 | call to get_field | +| instance_variables.rb:82:6:82:10 | foo10 [@field] : | instance_variables.rb:82:6:82:20 | call to get_field | +| instance_variables.rb:85:5:85:5 | [post] x [@field] : | instance_variables.rb:89:14:89:18 | [post] foo11 [@field] : | +| instance_variables.rb:85:5:85:5 | [post] x [@field] : | instance_variables.rb:89:14:89:18 | [post] foo11 [@field] : | +| instance_variables.rb:85:5:85:5 | [post] x [@field] : | instance_variables.rb:93:15:93:19 | [post] foo12 [@field] : | +| instance_variables.rb:85:5:85:5 | [post] x [@field] : | instance_variables.rb:93:15:93:19 | [post] foo12 [@field] : | +| instance_variables.rb:85:5:85:5 | [post] x [@field] : | instance_variables.rb:98:22:98:26 | [post] foo13 [@field] : | +| instance_variables.rb:85:5:85:5 | [post] x [@field] : | instance_variables.rb:98:22:98:26 | [post] foo13 [@field] : | +| instance_variables.rb:85:17:85:25 | call to taint : | instance_variables.rb:10:19:10:19 | x : | +| instance_variables.rb:85:17:85:25 | call to taint : | instance_variables.rb:10:19:10:19 | x : | +| instance_variables.rb:85:17:85:25 | call to taint : | instance_variables.rb:85:5:85:5 | [post] x [@field] : | +| instance_variables.rb:85:17:85:25 | call to taint : | instance_variables.rb:85:5:85:5 | [post] x [@field] : | +| instance_variables.rb:89:14:89:18 | [post] foo11 [@field] : | instance_variables.rb:90:6:90:10 | foo11 [@field] : | +| instance_variables.rb:89:14:89:18 | [post] foo11 [@field] : | instance_variables.rb:90:6:90:10 | foo11 [@field] : | +| instance_variables.rb:90:6:90:10 | foo11 [@field] : | instance_variables.rb:13:5:15:7 | self in get_field [@field] : | +| instance_variables.rb:90:6:90:10 | foo11 [@field] : | instance_variables.rb:13:5:15:7 | self in get_field [@field] : | +| instance_variables.rb:90:6:90:10 | foo11 [@field] : | instance_variables.rb:90:6:90:20 | call to get_field | +| instance_variables.rb:90:6:90:10 | foo11 [@field] : | instance_variables.rb:90:6:90:20 | call to get_field | +| instance_variables.rb:93:15:93:19 | [post] foo12 [@field] : | instance_variables.rb:94:6:94:10 | foo12 [@field] : | +| instance_variables.rb:93:15:93:19 | [post] foo12 [@field] : | instance_variables.rb:94:6:94:10 | foo12 [@field] : | +| instance_variables.rb:94:6:94:10 | foo12 [@field] : | instance_variables.rb:13:5:15:7 | self in get_field [@field] : | +| instance_variables.rb:94:6:94:10 | foo12 [@field] : | instance_variables.rb:13:5:15:7 | self in get_field [@field] : | +| instance_variables.rb:94:6:94:10 | foo12 [@field] : | instance_variables.rb:94:6:94:20 | call to get_field | +| instance_variables.rb:94:6:94:10 | foo12 [@field] : | instance_variables.rb:94:6:94:20 | call to get_field | +| instance_variables.rb:98:22:98:26 | [post] foo13 [@field] : | instance_variables.rb:99:6:99:10 | foo13 [@field] : | +| instance_variables.rb:98:22:98:26 | [post] foo13 [@field] : | instance_variables.rb:99:6:99:10 | foo13 [@field] : | +| instance_variables.rb:99:6:99:10 | foo13 [@field] : | instance_variables.rb:13:5:15:7 | self in get_field [@field] : | +| instance_variables.rb:99:6:99:10 | foo13 [@field] : | instance_variables.rb:13:5:15:7 | self in get_field [@field] : | +| instance_variables.rb:99:6:99:10 | foo13 [@field] : | instance_variables.rb:99:6:99:20 | call to get_field | +| instance_variables.rb:99:6:99:10 | foo13 [@field] : | instance_variables.rb:99:6:99:20 | call to get_field | +| instance_variables.rb:101:9:101:26 | call to new [@field] : | instance_variables.rb:102:6:102:10 | foo15 [@field] : | +| instance_variables.rb:101:9:101:26 | call to new [@field] : | instance_variables.rb:102:6:102:10 | foo15 [@field] : | +| instance_variables.rb:101:17:101:25 | call to taint : | instance_variables.rb:22:20:22:24 | field : | +| instance_variables.rb:101:17:101:25 | call to taint : | instance_variables.rb:22:20:22:24 | field : | +| instance_variables.rb:101:17:101:25 | call to taint : | instance_variables.rb:101:9:101:26 | call to new [@field] : | +| instance_variables.rb:101:17:101:25 | call to taint : | instance_variables.rb:101:9:101:26 | call to new [@field] : | +| instance_variables.rb:102:6:102:10 | foo15 [@field] : | instance_variables.rb:13:5:15:7 | self in get_field [@field] : | +| instance_variables.rb:102:6:102:10 | foo15 [@field] : | instance_variables.rb:13:5:15:7 | self in get_field [@field] : | +| instance_variables.rb:102:6:102:10 | foo15 [@field] : | instance_variables.rb:102:6:102:20 | call to get_field | +| instance_variables.rb:102:6:102:10 | foo15 [@field] : | instance_variables.rb:102:6:102:20 | call to get_field | +| instance_variables.rb:104:6:104:10 | [post] foo16 [@field] : | instance_variables.rb:105:6:105:10 | foo16 [@field] : | +| instance_variables.rb:104:6:104:10 | [post] foo16 [@field] : | instance_variables.rb:105:6:105:10 | foo16 [@field] : | +| instance_variables.rb:104:28:104:36 | call to taint : | instance_variables.rb:27:25:27:29 | field : | +| instance_variables.rb:104:28:104:36 | call to taint : | instance_variables.rb:27:25:27:29 | field : | +| instance_variables.rb:104:28:104:36 | call to taint : | instance_variables.rb:104:6:104:10 | [post] foo16 [@field] : | +| instance_variables.rb:104:28:104:36 | call to taint : | instance_variables.rb:104:6:104:10 | [post] foo16 [@field] : | +| instance_variables.rb:105:6:105:10 | foo16 [@field] : | instance_variables.rb:13:5:15:7 | self in get_field [@field] : | +| instance_variables.rb:105:6:105:10 | foo16 [@field] : | instance_variables.rb:13:5:15:7 | self in get_field [@field] : | +| instance_variables.rb:105:6:105:10 | foo16 [@field] : | instance_variables.rb:105:6:105:20 | call to get_field | +| instance_variables.rb:105:6:105:10 | foo16 [@field] : | instance_variables.rb:105:6:105:20 | call to get_field | +| instance_variables.rb:106:7:106:24 | call to new : | instance_variables.rb:107:6:107:8 | bar | +| instance_variables.rb:106:7:106:24 | call to new : | instance_variables.rb:107:6:107:8 | bar | nodes | captured_variables.rb:1:24:1:24 | x : | semmle.label | x : | | captured_variables.rb:1:24:1:24 | x : | semmle.label | x : | @@ -206,182 +244,236 @@ nodes | instance_variables.rb:20:10:20:13 | @foo | semmle.label | @foo | | instance_variables.rb:20:10:20:13 | self [@foo] : | semmle.label | self [@foo] : | | instance_variables.rb:20:10:20:13 | self [@foo] : | semmle.label | self [@foo] : | -| instance_variables.rb:24:1:24:3 | [post] foo [@field] : | semmle.label | [post] foo [@field] : | -| instance_variables.rb:24:1:24:3 | [post] foo [@field] : | semmle.label | [post] foo [@field] : | -| instance_variables.rb:24:15:24:23 | call to taint : | semmle.label | call to taint : | -| instance_variables.rb:24:15:24:23 | call to taint : | semmle.label | call to taint : | -| instance_variables.rb:25:6:25:8 | foo [@field] : | semmle.label | foo [@field] : | -| instance_variables.rb:25:6:25:8 | foo [@field] : | semmle.label | foo [@field] : | -| instance_variables.rb:25:6:25:18 | call to get_field | semmle.label | call to get_field | -| instance_variables.rb:25:6:25:18 | call to get_field | semmle.label | call to get_field | -| instance_variables.rb:28:1:28:3 | [post] bar [@field] : | semmle.label | [post] bar [@field] : | -| instance_variables.rb:28:15:28:22 | call to taint : | semmle.label | call to taint : | -| instance_variables.rb:29:6:29:8 | bar [@field] : | semmle.label | bar [@field] : | -| instance_variables.rb:29:6:29:18 | call to inc_field | semmle.label | call to inc_field | -| instance_variables.rb:32:1:32:4 | [post] foo1 [@field] : | semmle.label | [post] foo1 [@field] : | -| instance_variables.rb:32:1:32:4 | [post] foo1 [@field] : | semmle.label | [post] foo1 [@field] : | -| instance_variables.rb:32:14:32:22 | call to taint : | semmle.label | call to taint : | -| instance_variables.rb:32:14:32:22 | call to taint : | semmle.label | call to taint : | -| instance_variables.rb:33:6:33:9 | foo1 [@field] : | semmle.label | foo1 [@field] : | -| instance_variables.rb:33:6:33:9 | foo1 [@field] : | semmle.label | foo1 [@field] : | -| instance_variables.rb:33:6:33:15 | call to field | semmle.label | call to field | -| instance_variables.rb:33:6:33:15 | call to field | semmle.label | call to field | -| instance_variables.rb:36:1:36:4 | [post] foo2 [@field] : | semmle.label | [post] foo2 [@field] : | -| instance_variables.rb:36:1:36:4 | [post] foo2 [@field] : | semmle.label | [post] foo2 [@field] : | -| instance_variables.rb:36:14:36:22 | call to taint : | semmle.label | call to taint : | -| instance_variables.rb:36:14:36:22 | call to taint : | semmle.label | call to taint : | -| instance_variables.rb:37:6:37:9 | foo2 [@field] : | semmle.label | foo2 [@field] : | -| instance_variables.rb:37:6:37:9 | foo2 [@field] : | semmle.label | foo2 [@field] : | -| instance_variables.rb:37:6:37:19 | call to get_field | semmle.label | call to get_field | -| instance_variables.rb:37:6:37:19 | call to get_field | semmle.label | call to get_field | -| instance_variables.rb:40:1:40:4 | [post] foo3 [@field] : | semmle.label | [post] foo3 [@field] : | -| instance_variables.rb:40:1:40:4 | [post] foo3 [@field] : | semmle.label | [post] foo3 [@field] : | -| instance_variables.rb:40:16:40:24 | call to taint : | semmle.label | call to taint : | -| instance_variables.rb:40:16:40:24 | call to taint : | semmle.label | call to taint : | -| instance_variables.rb:41:6:41:9 | foo3 [@field] : | semmle.label | foo3 [@field] : | -| instance_variables.rb:41:6:41:9 | foo3 [@field] : | semmle.label | foo3 [@field] : | -| instance_variables.rb:41:6:41:15 | call to field | semmle.label | call to field | -| instance_variables.rb:41:6:41:15 | call to field | semmle.label | call to field | -| instance_variables.rb:48:2:48:5 | [post] foo5 [@field] : | semmle.label | [post] foo5 [@field] : | -| instance_variables.rb:48:2:48:5 | [post] foo5 [@field] : | semmle.label | [post] foo5 [@field] : | -| instance_variables.rb:48:18:48:26 | call to taint : | semmle.label | call to taint : | -| instance_variables.rb:48:18:48:26 | call to taint : | semmle.label | call to taint : | -| instance_variables.rb:49:6:49:9 | foo5 [@field] : | semmle.label | foo5 [@field] : | -| instance_variables.rb:49:6:49:9 | foo5 [@field] : | semmle.label | foo5 [@field] : | -| instance_variables.rb:49:6:49:19 | call to get_field | semmle.label | call to get_field | -| instance_variables.rb:49:6:49:19 | call to get_field | semmle.label | call to get_field | -| instance_variables.rb:52:15:52:18 | [post] foo6 [@field] : | semmle.label | [post] foo6 [@field] : | -| instance_variables.rb:52:15:52:18 | [post] foo6 [@field] : | semmle.label | [post] foo6 [@field] : | -| instance_variables.rb:52:32:52:40 | call to taint : | semmle.label | call to taint : | -| instance_variables.rb:52:32:52:40 | call to taint : | semmle.label | call to taint : | -| instance_variables.rb:53:6:53:9 | foo3 [@field] : | semmle.label | foo3 [@field] : | -| instance_variables.rb:53:6:53:9 | foo3 [@field] : | semmle.label | foo3 [@field] : | -| instance_variables.rb:53:6:53:19 | call to get_field | semmle.label | call to get_field | -| instance_variables.rb:53:6:53:19 | call to get_field | semmle.label | call to get_field | -| instance_variables.rb:54:6:54:9 | foo5 [@field] : | semmle.label | foo5 [@field] : | -| instance_variables.rb:54:6:54:9 | foo5 [@field] : | semmle.label | foo5 [@field] : | -| instance_variables.rb:54:6:54:19 | call to get_field | semmle.label | call to get_field | -| instance_variables.rb:54:6:54:19 | call to get_field | semmle.label | call to get_field | -| instance_variables.rb:55:6:55:9 | foo6 [@field] : | semmle.label | foo6 [@field] : | -| instance_variables.rb:55:6:55:9 | foo6 [@field] : | semmle.label | foo6 [@field] : | -| instance_variables.rb:55:6:55:19 | call to get_field | semmle.label | call to get_field | -| instance_variables.rb:55:6:55:19 | call to get_field | semmle.label | call to get_field | -| instance_variables.rb:59:15:59:18 | [post] foo7 [@field] : | semmle.label | [post] foo7 [@field] : | -| instance_variables.rb:59:15:59:18 | [post] foo7 [@field] : | semmle.label | [post] foo7 [@field] : | -| instance_variables.rb:59:25:59:28 | [post] foo8 [@field] : | semmle.label | [post] foo8 [@field] : | -| instance_variables.rb:59:25:59:28 | [post] foo8 [@field] : | semmle.label | [post] foo8 [@field] : | -| instance_variables.rb:59:45:59:53 | call to taint : | semmle.label | call to taint : | -| instance_variables.rb:59:45:59:53 | call to taint : | semmle.label | call to taint : | -| instance_variables.rb:60:6:60:9 | foo7 [@field] : | semmle.label | foo7 [@field] : | -| instance_variables.rb:60:6:60:9 | foo7 [@field] : | semmle.label | foo7 [@field] : | -| instance_variables.rb:60:6:60:19 | call to get_field | semmle.label | call to get_field | -| instance_variables.rb:60:6:60:19 | call to get_field | semmle.label | call to get_field | -| instance_variables.rb:61:6:61:9 | foo8 [@field] : | semmle.label | foo8 [@field] : | -| instance_variables.rb:61:6:61:9 | foo8 [@field] : | semmle.label | foo8 [@field] : | -| instance_variables.rb:61:6:61:19 | call to get_field | semmle.label | call to get_field | -| instance_variables.rb:61:6:61:19 | call to get_field | semmle.label | call to get_field | -| instance_variables.rb:65:22:65:25 | [post] foo9 [@field] : | semmle.label | [post] foo9 [@field] : | -| instance_variables.rb:65:22:65:25 | [post] foo9 [@field] : | semmle.label | [post] foo9 [@field] : | -| instance_variables.rb:65:32:65:36 | [post] foo10 [@field] : | semmle.label | [post] foo10 [@field] : | -| instance_variables.rb:65:32:65:36 | [post] foo10 [@field] : | semmle.label | [post] foo10 [@field] : | -| instance_variables.rb:65:53:65:61 | call to taint : | semmle.label | call to taint : | -| instance_variables.rb:65:53:65:61 | call to taint : | semmle.label | call to taint : | -| instance_variables.rb:66:6:66:9 | foo9 [@field] : | semmle.label | foo9 [@field] : | -| instance_variables.rb:66:6:66:9 | foo9 [@field] : | semmle.label | foo9 [@field] : | -| instance_variables.rb:66:6:66:19 | call to get_field | semmle.label | call to get_field | -| instance_variables.rb:66:6:66:19 | call to get_field | semmle.label | call to get_field | -| instance_variables.rb:67:6:67:10 | foo10 [@field] : | semmle.label | foo10 [@field] : | -| instance_variables.rb:67:6:67:10 | foo10 [@field] : | semmle.label | foo10 [@field] : | -| instance_variables.rb:67:6:67:20 | call to get_field | semmle.label | call to get_field | -| instance_variables.rb:67:6:67:20 | call to get_field | semmle.label | call to get_field | -| instance_variables.rb:70:5:70:5 | [post] x [@field] : | semmle.label | [post] x [@field] : | -| instance_variables.rb:70:5:70:5 | [post] x [@field] : | semmle.label | [post] x [@field] : | -| instance_variables.rb:70:17:70:25 | call to taint : | semmle.label | call to taint : | -| instance_variables.rb:70:17:70:25 | call to taint : | semmle.label | call to taint : | -| instance_variables.rb:74:14:74:18 | [post] foo11 [@field] : | semmle.label | [post] foo11 [@field] : | -| instance_variables.rb:74:14:74:18 | [post] foo11 [@field] : | semmle.label | [post] foo11 [@field] : | -| instance_variables.rb:75:6:75:10 | foo11 [@field] : | semmle.label | foo11 [@field] : | -| instance_variables.rb:75:6:75:10 | foo11 [@field] : | semmle.label | foo11 [@field] : | -| instance_variables.rb:75:6:75:20 | call to get_field | semmle.label | call to get_field | -| instance_variables.rb:75:6:75:20 | call to get_field | semmle.label | call to get_field | -| instance_variables.rb:78:15:78:19 | [post] foo12 [@field] : | semmle.label | [post] foo12 [@field] : | -| instance_variables.rb:78:15:78:19 | [post] foo12 [@field] : | semmle.label | [post] foo12 [@field] : | -| instance_variables.rb:79:6:79:10 | foo12 [@field] : | semmle.label | foo12 [@field] : | -| instance_variables.rb:79:6:79:10 | foo12 [@field] : | semmle.label | foo12 [@field] : | -| instance_variables.rb:79:6:79:20 | call to get_field | semmle.label | call to get_field | -| instance_variables.rb:79:6:79:20 | call to get_field | semmle.label | call to get_field | -| instance_variables.rb:83:22:83:26 | [post] foo13 [@field] : | semmle.label | [post] foo13 [@field] : | -| instance_variables.rb:83:22:83:26 | [post] foo13 [@field] : | semmle.label | [post] foo13 [@field] : | -| instance_variables.rb:84:6:84:10 | foo13 [@field] : | semmle.label | foo13 [@field] : | -| instance_variables.rb:84:6:84:10 | foo13 [@field] : | semmle.label | foo13 [@field] : | -| instance_variables.rb:84:6:84:20 | call to get_field | semmle.label | call to get_field | -| instance_variables.rb:84:6:84:20 | call to get_field | semmle.label | call to get_field | +| instance_variables.rb:22:20:22:24 | field : | semmle.label | field : | +| instance_variables.rb:22:20:22:24 | field : | semmle.label | field : | +| instance_variables.rb:23:9:23:14 | [post] self [@field] : | semmle.label | [post] self [@field] : | +| instance_variables.rb:23:9:23:14 | [post] self [@field] : | semmle.label | [post] self [@field] : | +| instance_variables.rb:23:18:23:22 | field : | semmle.label | field : | +| instance_variables.rb:23:18:23:22 | field : | semmle.label | field : | +| instance_variables.rb:24:9:24:17 | call to taint : | semmle.label | call to taint : | +| instance_variables.rb:24:9:24:17 | call to taint : | semmle.label | call to taint : | +| instance_variables.rb:27:25:27:29 | field : | semmle.label | field : | +| instance_variables.rb:27:25:27:29 | field : | semmle.label | field : | +| instance_variables.rb:28:9:28:25 | [post] self [@field] : | semmle.label | [post] self [@field] : | +| instance_variables.rb:28:9:28:25 | [post] self [@field] : | semmle.label | [post] self [@field] : | +| instance_variables.rb:28:9:28:25 | call to initialize : | semmle.label | call to initialize : | +| instance_variables.rb:28:9:28:25 | call to initialize : | semmle.label | call to initialize : | +| instance_variables.rb:28:20:28:24 | field : | semmle.label | field : | +| instance_variables.rb:28:20:28:24 | field : | semmle.label | field : | +| instance_variables.rb:34:9:34:17 | call to taint : | semmle.label | call to taint : | +| instance_variables.rb:34:9:34:17 | call to taint : | semmle.label | call to taint : | +| instance_variables.rb:39:1:39:3 | [post] foo [@field] : | semmle.label | [post] foo [@field] : | +| instance_variables.rb:39:1:39:3 | [post] foo [@field] : | semmle.label | [post] foo [@field] : | +| instance_variables.rb:39:15:39:23 | call to taint : | semmle.label | call to taint : | +| instance_variables.rb:39:15:39:23 | call to taint : | semmle.label | call to taint : | +| instance_variables.rb:40:6:40:8 | foo [@field] : | semmle.label | foo [@field] : | +| instance_variables.rb:40:6:40:8 | foo [@field] : | semmle.label | foo [@field] : | +| instance_variables.rb:40:6:40:18 | call to get_field | semmle.label | call to get_field | +| instance_variables.rb:40:6:40:18 | call to get_field | semmle.label | call to get_field | +| instance_variables.rb:43:1:43:3 | [post] bar [@field] : | semmle.label | [post] bar [@field] : | +| instance_variables.rb:43:15:43:22 | call to taint : | semmle.label | call to taint : | +| instance_variables.rb:44:6:44:8 | bar [@field] : | semmle.label | bar [@field] : | +| instance_variables.rb:44:6:44:18 | call to inc_field | semmle.label | call to inc_field | +| instance_variables.rb:47:1:47:4 | [post] foo1 [@field] : | semmle.label | [post] foo1 [@field] : | +| instance_variables.rb:47:1:47:4 | [post] foo1 [@field] : | semmle.label | [post] foo1 [@field] : | +| instance_variables.rb:47:14:47:22 | call to taint : | semmle.label | call to taint : | +| instance_variables.rb:47:14:47:22 | call to taint : | semmle.label | call to taint : | +| instance_variables.rb:48:6:48:9 | foo1 [@field] : | semmle.label | foo1 [@field] : | +| instance_variables.rb:48:6:48:9 | foo1 [@field] : | semmle.label | foo1 [@field] : | +| instance_variables.rb:48:6:48:15 | call to field | semmle.label | call to field | +| instance_variables.rb:48:6:48:15 | call to field | semmle.label | call to field | +| instance_variables.rb:51:1:51:4 | [post] foo2 [@field] : | semmle.label | [post] foo2 [@field] : | +| instance_variables.rb:51:1:51:4 | [post] foo2 [@field] : | semmle.label | [post] foo2 [@field] : | +| instance_variables.rb:51:14:51:22 | call to taint : | semmle.label | call to taint : | +| instance_variables.rb:51:14:51:22 | call to taint : | semmle.label | call to taint : | +| instance_variables.rb:52:6:52:9 | foo2 [@field] : | semmle.label | foo2 [@field] : | +| instance_variables.rb:52:6:52:9 | foo2 [@field] : | semmle.label | foo2 [@field] : | +| instance_variables.rb:52:6:52:19 | call to get_field | semmle.label | call to get_field | +| instance_variables.rb:52:6:52:19 | call to get_field | semmle.label | call to get_field | +| instance_variables.rb:55:1:55:4 | [post] foo3 [@field] : | semmle.label | [post] foo3 [@field] : | +| instance_variables.rb:55:1:55:4 | [post] foo3 [@field] : | semmle.label | [post] foo3 [@field] : | +| instance_variables.rb:55:16:55:24 | call to taint : | semmle.label | call to taint : | +| instance_variables.rb:55:16:55:24 | call to taint : | semmle.label | call to taint : | +| instance_variables.rb:56:6:56:9 | foo3 [@field] : | semmle.label | foo3 [@field] : | +| instance_variables.rb:56:6:56:9 | foo3 [@field] : | semmle.label | foo3 [@field] : | +| instance_variables.rb:56:6:56:15 | call to field | semmle.label | call to field | +| instance_variables.rb:56:6:56:15 | call to field | semmle.label | call to field | +| instance_variables.rb:63:2:63:5 | [post] foo5 [@field] : | semmle.label | [post] foo5 [@field] : | +| instance_variables.rb:63:2:63:5 | [post] foo5 [@field] : | semmle.label | [post] foo5 [@field] : | +| instance_variables.rb:63:18:63:26 | call to taint : | semmle.label | call to taint : | +| instance_variables.rb:63:18:63:26 | call to taint : | semmle.label | call to taint : | +| instance_variables.rb:64:6:64:9 | foo5 [@field] : | semmle.label | foo5 [@field] : | +| instance_variables.rb:64:6:64:9 | foo5 [@field] : | semmle.label | foo5 [@field] : | +| instance_variables.rb:64:6:64:19 | call to get_field | semmle.label | call to get_field | +| instance_variables.rb:64:6:64:19 | call to get_field | semmle.label | call to get_field | +| instance_variables.rb:67:15:67:18 | [post] foo6 [@field] : | semmle.label | [post] foo6 [@field] : | +| instance_variables.rb:67:15:67:18 | [post] foo6 [@field] : | semmle.label | [post] foo6 [@field] : | +| instance_variables.rb:67:32:67:40 | call to taint : | semmle.label | call to taint : | +| instance_variables.rb:67:32:67:40 | call to taint : | semmle.label | call to taint : | +| instance_variables.rb:68:6:68:9 | foo3 [@field] : | semmle.label | foo3 [@field] : | +| instance_variables.rb:68:6:68:9 | foo3 [@field] : | semmle.label | foo3 [@field] : | +| instance_variables.rb:68:6:68:19 | call to get_field | semmle.label | call to get_field | +| instance_variables.rb:68:6:68:19 | call to get_field | semmle.label | call to get_field | +| instance_variables.rb:69:6:69:9 | foo5 [@field] : | semmle.label | foo5 [@field] : | +| instance_variables.rb:69:6:69:9 | foo5 [@field] : | semmle.label | foo5 [@field] : | +| instance_variables.rb:69:6:69:19 | call to get_field | semmle.label | call to get_field | +| instance_variables.rb:69:6:69:19 | call to get_field | semmle.label | call to get_field | +| instance_variables.rb:70:6:70:9 | foo6 [@field] : | semmle.label | foo6 [@field] : | +| instance_variables.rb:70:6:70:9 | foo6 [@field] : | semmle.label | foo6 [@field] : | +| instance_variables.rb:70:6:70:19 | call to get_field | semmle.label | call to get_field | +| instance_variables.rb:70:6:70:19 | call to get_field | semmle.label | call to get_field | +| instance_variables.rb:74:15:74:18 | [post] foo7 [@field] : | semmle.label | [post] foo7 [@field] : | +| instance_variables.rb:74:15:74:18 | [post] foo7 [@field] : | semmle.label | [post] foo7 [@field] : | +| instance_variables.rb:74:25:74:28 | [post] foo8 [@field] : | semmle.label | [post] foo8 [@field] : | +| instance_variables.rb:74:25:74:28 | [post] foo8 [@field] : | semmle.label | [post] foo8 [@field] : | +| instance_variables.rb:74:45:74:53 | call to taint : | semmle.label | call to taint : | +| instance_variables.rb:74:45:74:53 | call to taint : | semmle.label | call to taint : | +| instance_variables.rb:75:6:75:9 | foo7 [@field] : | semmle.label | foo7 [@field] : | +| instance_variables.rb:75:6:75:9 | foo7 [@field] : | semmle.label | foo7 [@field] : | +| instance_variables.rb:75:6:75:19 | call to get_field | semmle.label | call to get_field | +| instance_variables.rb:75:6:75:19 | call to get_field | semmle.label | call to get_field | +| instance_variables.rb:76:6:76:9 | foo8 [@field] : | semmle.label | foo8 [@field] : | +| instance_variables.rb:76:6:76:9 | foo8 [@field] : | semmle.label | foo8 [@field] : | +| instance_variables.rb:76:6:76:19 | call to get_field | semmle.label | call to get_field | +| instance_variables.rb:76:6:76:19 | call to get_field | semmle.label | call to get_field | +| instance_variables.rb:80:22:80:25 | [post] foo9 [@field] : | semmle.label | [post] foo9 [@field] : | +| instance_variables.rb:80:22:80:25 | [post] foo9 [@field] : | semmle.label | [post] foo9 [@field] : | +| instance_variables.rb:80:32:80:36 | [post] foo10 [@field] : | semmle.label | [post] foo10 [@field] : | +| instance_variables.rb:80:32:80:36 | [post] foo10 [@field] : | semmle.label | [post] foo10 [@field] : | +| instance_variables.rb:80:53:80:61 | call to taint : | semmle.label | call to taint : | +| instance_variables.rb:80:53:80:61 | call to taint : | semmle.label | call to taint : | +| instance_variables.rb:81:6:81:9 | foo9 [@field] : | semmle.label | foo9 [@field] : | +| instance_variables.rb:81:6:81:9 | foo9 [@field] : | semmle.label | foo9 [@field] : | +| instance_variables.rb:81:6:81:19 | call to get_field | semmle.label | call to get_field | +| instance_variables.rb:81:6:81:19 | call to get_field | semmle.label | call to get_field | +| instance_variables.rb:82:6:82:10 | foo10 [@field] : | semmle.label | foo10 [@field] : | +| instance_variables.rb:82:6:82:10 | foo10 [@field] : | semmle.label | foo10 [@field] : | +| instance_variables.rb:82:6:82:20 | call to get_field | semmle.label | call to get_field | +| instance_variables.rb:82:6:82:20 | call to get_field | semmle.label | call to get_field | +| instance_variables.rb:85:5:85:5 | [post] x [@field] : | semmle.label | [post] x [@field] : | +| instance_variables.rb:85:5:85:5 | [post] x [@field] : | semmle.label | [post] x [@field] : | +| instance_variables.rb:85:17:85:25 | call to taint : | semmle.label | call to taint : | +| instance_variables.rb:85:17:85:25 | call to taint : | semmle.label | call to taint : | +| instance_variables.rb:89:14:89:18 | [post] foo11 [@field] : | semmle.label | [post] foo11 [@field] : | +| instance_variables.rb:89:14:89:18 | [post] foo11 [@field] : | semmle.label | [post] foo11 [@field] : | +| instance_variables.rb:90:6:90:10 | foo11 [@field] : | semmle.label | foo11 [@field] : | +| instance_variables.rb:90:6:90:10 | foo11 [@field] : | semmle.label | foo11 [@field] : | +| instance_variables.rb:90:6:90:20 | call to get_field | semmle.label | call to get_field | +| instance_variables.rb:90:6:90:20 | call to get_field | semmle.label | call to get_field | +| instance_variables.rb:93:15:93:19 | [post] foo12 [@field] : | semmle.label | [post] foo12 [@field] : | +| instance_variables.rb:93:15:93:19 | [post] foo12 [@field] : | semmle.label | [post] foo12 [@field] : | +| instance_variables.rb:94:6:94:10 | foo12 [@field] : | semmle.label | foo12 [@field] : | +| instance_variables.rb:94:6:94:10 | foo12 [@field] : | semmle.label | foo12 [@field] : | +| instance_variables.rb:94:6:94:20 | call to get_field | semmle.label | call to get_field | +| instance_variables.rb:94:6:94:20 | call to get_field | semmle.label | call to get_field | +| instance_variables.rb:98:22:98:26 | [post] foo13 [@field] : | semmle.label | [post] foo13 [@field] : | +| instance_variables.rb:98:22:98:26 | [post] foo13 [@field] : | semmle.label | [post] foo13 [@field] : | +| instance_variables.rb:99:6:99:10 | foo13 [@field] : | semmle.label | foo13 [@field] : | +| instance_variables.rb:99:6:99:10 | foo13 [@field] : | semmle.label | foo13 [@field] : | +| instance_variables.rb:99:6:99:20 | call to get_field | semmle.label | call to get_field | +| instance_variables.rb:99:6:99:20 | call to get_field | semmle.label | call to get_field | +| instance_variables.rb:101:9:101:26 | call to new [@field] : | semmle.label | call to new [@field] : | +| instance_variables.rb:101:9:101:26 | call to new [@field] : | semmle.label | call to new [@field] : | +| instance_variables.rb:101:17:101:25 | call to taint : | semmle.label | call to taint : | +| instance_variables.rb:101:17:101:25 | call to taint : | semmle.label | call to taint : | +| instance_variables.rb:102:6:102:10 | foo15 [@field] : | semmle.label | foo15 [@field] : | +| instance_variables.rb:102:6:102:10 | foo15 [@field] : | semmle.label | foo15 [@field] : | +| instance_variables.rb:102:6:102:20 | call to get_field | semmle.label | call to get_field | +| instance_variables.rb:102:6:102:20 | call to get_field | semmle.label | call to get_field | +| instance_variables.rb:104:6:104:10 | [post] foo16 [@field] : | semmle.label | [post] foo16 [@field] : | +| instance_variables.rb:104:6:104:10 | [post] foo16 [@field] : | semmle.label | [post] foo16 [@field] : | +| instance_variables.rb:104:6:104:37 | call to call_initialize | semmle.label | call to call_initialize | +| instance_variables.rb:104:6:104:37 | call to call_initialize | semmle.label | call to call_initialize | +| instance_variables.rb:104:28:104:36 | call to taint : | semmle.label | call to taint : | +| instance_variables.rb:104:28:104:36 | call to taint : | semmle.label | call to taint : | +| instance_variables.rb:105:6:105:10 | foo16 [@field] : | semmle.label | foo16 [@field] : | +| instance_variables.rb:105:6:105:10 | foo16 [@field] : | semmle.label | foo16 [@field] : | +| instance_variables.rb:105:6:105:20 | call to get_field | semmle.label | call to get_field | +| instance_variables.rb:105:6:105:20 | call to get_field | semmle.label | call to get_field | +| instance_variables.rb:106:7:106:24 | call to new : | semmle.label | call to new : | +| instance_variables.rb:106:7:106:24 | call to new : | semmle.label | call to new : | +| instance_variables.rb:107:6:107:8 | bar | semmle.label | bar | +| instance_variables.rb:107:6:107:8 | bar | semmle.label | bar | subpaths -| instance_variables.rb:24:15:24:23 | call to taint : | instance_variables.rb:10:19:10:19 | x : | instance_variables.rb:11:9:11:14 | [post] self [@field] : | instance_variables.rb:24:1:24:3 | [post] foo [@field] : | -| instance_variables.rb:24:15:24:23 | call to taint : | instance_variables.rb:10:19:10:19 | x : | instance_variables.rb:11:9:11:14 | [post] self [@field] : | instance_variables.rb:24:1:24:3 | [post] foo [@field] : | -| instance_variables.rb:25:6:25:8 | foo [@field] : | instance_variables.rb:13:5:15:7 | self in get_field [@field] : | instance_variables.rb:14:9:14:21 | return : | instance_variables.rb:25:6:25:18 | call to get_field | -| instance_variables.rb:25:6:25:8 | foo [@field] : | instance_variables.rb:13:5:15:7 | self in get_field [@field] : | instance_variables.rb:14:9:14:21 | return : | instance_variables.rb:25:6:25:18 | call to get_field | -| instance_variables.rb:28:15:28:22 | call to taint : | instance_variables.rb:10:19:10:19 | x : | instance_variables.rb:11:9:11:14 | [post] self [@field] : | instance_variables.rb:28:1:28:3 | [post] bar [@field] : | -| instance_variables.rb:29:6:29:8 | bar [@field] : | instance_variables.rb:16:5:18:7 | self in inc_field [@field] : | instance_variables.rb:16:5:18:7 | self in inc_field [@field] : | instance_variables.rb:29:6:29:18 | call to inc_field | -| instance_variables.rb:29:6:29:8 | bar [@field] : | instance_variables.rb:16:5:18:7 | self in inc_field [@field] : | instance_variables.rb:17:9:17:14 | [post] self [@field] : | instance_variables.rb:29:6:29:18 | call to inc_field | -| instance_variables.rb:37:6:37:9 | foo2 [@field] : | instance_variables.rb:13:5:15:7 | self in get_field [@field] : | instance_variables.rb:14:9:14:21 | return : | instance_variables.rb:37:6:37:19 | call to get_field | -| instance_variables.rb:37:6:37:9 | foo2 [@field] : | instance_variables.rb:13:5:15:7 | self in get_field [@field] : | instance_variables.rb:14:9:14:21 | return : | instance_variables.rb:37:6:37:19 | call to get_field | -| instance_variables.rb:40:16:40:24 | call to taint : | instance_variables.rb:10:19:10:19 | x : | instance_variables.rb:11:9:11:14 | [post] self [@field] : | instance_variables.rb:40:1:40:4 | [post] foo3 [@field] : | -| instance_variables.rb:40:16:40:24 | call to taint : | instance_variables.rb:10:19:10:19 | x : | instance_variables.rb:11:9:11:14 | [post] self [@field] : | instance_variables.rb:40:1:40:4 | [post] foo3 [@field] : | -| instance_variables.rb:48:18:48:26 | call to taint : | instance_variables.rb:10:19:10:19 | x : | instance_variables.rb:11:9:11:14 | [post] self [@field] : | instance_variables.rb:48:2:48:5 | [post] foo5 [@field] : | -| instance_variables.rb:48:18:48:26 | call to taint : | instance_variables.rb:10:19:10:19 | x : | instance_variables.rb:11:9:11:14 | [post] self [@field] : | instance_variables.rb:48:2:48:5 | [post] foo5 [@field] : | -| instance_variables.rb:49:6:49:9 | foo5 [@field] : | instance_variables.rb:13:5:15:7 | self in get_field [@field] : | instance_variables.rb:14:9:14:21 | return : | instance_variables.rb:49:6:49:19 | call to get_field | -| instance_variables.rb:49:6:49:9 | foo5 [@field] : | instance_variables.rb:13:5:15:7 | self in get_field [@field] : | instance_variables.rb:14:9:14:21 | return : | instance_variables.rb:49:6:49:19 | call to get_field | -| instance_variables.rb:52:32:52:40 | call to taint : | instance_variables.rb:10:19:10:19 | x : | instance_variables.rb:11:9:11:14 | [post] self [@field] : | instance_variables.rb:52:15:52:18 | [post] foo6 [@field] : | -| instance_variables.rb:52:32:52:40 | call to taint : | instance_variables.rb:10:19:10:19 | x : | instance_variables.rb:11:9:11:14 | [post] self [@field] : | instance_variables.rb:52:15:52:18 | [post] foo6 [@field] : | -| instance_variables.rb:53:6:53:9 | foo3 [@field] : | instance_variables.rb:13:5:15:7 | self in get_field [@field] : | instance_variables.rb:14:9:14:21 | return : | instance_variables.rb:53:6:53:19 | call to get_field | -| instance_variables.rb:53:6:53:9 | foo3 [@field] : | instance_variables.rb:13:5:15:7 | self in get_field [@field] : | instance_variables.rb:14:9:14:21 | return : | instance_variables.rb:53:6:53:19 | call to get_field | -| instance_variables.rb:54:6:54:9 | foo5 [@field] : | instance_variables.rb:13:5:15:7 | self in get_field [@field] : | instance_variables.rb:14:9:14:21 | return : | instance_variables.rb:54:6:54:19 | call to get_field | -| instance_variables.rb:54:6:54:9 | foo5 [@field] : | instance_variables.rb:13:5:15:7 | self in get_field [@field] : | instance_variables.rb:14:9:14:21 | return : | instance_variables.rb:54:6:54:19 | call to get_field | -| instance_variables.rb:55:6:55:9 | foo6 [@field] : | instance_variables.rb:13:5:15:7 | self in get_field [@field] : | instance_variables.rb:14:9:14:21 | return : | instance_variables.rb:55:6:55:19 | call to get_field | -| instance_variables.rb:55:6:55:9 | foo6 [@field] : | instance_variables.rb:13:5:15:7 | self in get_field [@field] : | instance_variables.rb:14:9:14:21 | return : | instance_variables.rb:55:6:55:19 | call to get_field | -| instance_variables.rb:59:45:59:53 | call to taint : | instance_variables.rb:10:19:10:19 | x : | instance_variables.rb:11:9:11:14 | [post] self [@field] : | instance_variables.rb:59:15:59:18 | [post] foo7 [@field] : | -| instance_variables.rb:59:45:59:53 | call to taint : | instance_variables.rb:10:19:10:19 | x : | instance_variables.rb:11:9:11:14 | [post] self [@field] : | instance_variables.rb:59:15:59:18 | [post] foo7 [@field] : | -| instance_variables.rb:59:45:59:53 | call to taint : | instance_variables.rb:10:19:10:19 | x : | instance_variables.rb:11:9:11:14 | [post] self [@field] : | instance_variables.rb:59:25:59:28 | [post] foo8 [@field] : | -| instance_variables.rb:59:45:59:53 | call to taint : | instance_variables.rb:10:19:10:19 | x : | instance_variables.rb:11:9:11:14 | [post] self [@field] : | instance_variables.rb:59:25:59:28 | [post] foo8 [@field] : | -| instance_variables.rb:60:6:60:9 | foo7 [@field] : | instance_variables.rb:13:5:15:7 | self in get_field [@field] : | instance_variables.rb:14:9:14:21 | return : | instance_variables.rb:60:6:60:19 | call to get_field | -| instance_variables.rb:60:6:60:9 | foo7 [@field] : | instance_variables.rb:13:5:15:7 | self in get_field [@field] : | instance_variables.rb:14:9:14:21 | return : | instance_variables.rb:60:6:60:19 | call to get_field | -| instance_variables.rb:61:6:61:9 | foo8 [@field] : | instance_variables.rb:13:5:15:7 | self in get_field [@field] : | instance_variables.rb:14:9:14:21 | return : | instance_variables.rb:61:6:61:19 | call to get_field | -| instance_variables.rb:61:6:61:9 | foo8 [@field] : | instance_variables.rb:13:5:15:7 | self in get_field [@field] : | instance_variables.rb:14:9:14:21 | return : | instance_variables.rb:61:6:61:19 | call to get_field | -| instance_variables.rb:65:53:65:61 | call to taint : | instance_variables.rb:10:19:10:19 | x : | instance_variables.rb:11:9:11:14 | [post] self [@field] : | instance_variables.rb:65:22:65:25 | [post] foo9 [@field] : | -| instance_variables.rb:65:53:65:61 | call to taint : | instance_variables.rb:10:19:10:19 | x : | instance_variables.rb:11:9:11:14 | [post] self [@field] : | instance_variables.rb:65:22:65:25 | [post] foo9 [@field] : | -| instance_variables.rb:65:53:65:61 | call to taint : | instance_variables.rb:10:19:10:19 | x : | instance_variables.rb:11:9:11:14 | [post] self [@field] : | instance_variables.rb:65:32:65:36 | [post] foo10 [@field] : | -| instance_variables.rb:65:53:65:61 | call to taint : | instance_variables.rb:10:19:10:19 | x : | instance_variables.rb:11:9:11:14 | [post] self [@field] : | instance_variables.rb:65:32:65:36 | [post] foo10 [@field] : | -| instance_variables.rb:66:6:66:9 | foo9 [@field] : | instance_variables.rb:13:5:15:7 | self in get_field [@field] : | instance_variables.rb:14:9:14:21 | return : | instance_variables.rb:66:6:66:19 | call to get_field | -| instance_variables.rb:66:6:66:9 | foo9 [@field] : | instance_variables.rb:13:5:15:7 | self in get_field [@field] : | instance_variables.rb:14:9:14:21 | return : | instance_variables.rb:66:6:66:19 | call to get_field | -| instance_variables.rb:67:6:67:10 | foo10 [@field] : | instance_variables.rb:13:5:15:7 | self in get_field [@field] : | instance_variables.rb:14:9:14:21 | return : | instance_variables.rb:67:6:67:20 | call to get_field | -| instance_variables.rb:67:6:67:10 | foo10 [@field] : | instance_variables.rb:13:5:15:7 | self in get_field [@field] : | instance_variables.rb:14:9:14:21 | return : | instance_variables.rb:67:6:67:20 | call to get_field | -| instance_variables.rb:70:17:70:25 | call to taint : | instance_variables.rb:10:19:10:19 | x : | instance_variables.rb:11:9:11:14 | [post] self [@field] : | instance_variables.rb:70:5:70:5 | [post] x [@field] : | -| instance_variables.rb:70:17:70:25 | call to taint : | instance_variables.rb:10:19:10:19 | x : | instance_variables.rb:11:9:11:14 | [post] self [@field] : | instance_variables.rb:70:5:70:5 | [post] x [@field] : | -| instance_variables.rb:75:6:75:10 | foo11 [@field] : | instance_variables.rb:13:5:15:7 | self in get_field [@field] : | instance_variables.rb:14:9:14:21 | return : | instance_variables.rb:75:6:75:20 | call to get_field | -| instance_variables.rb:75:6:75:10 | foo11 [@field] : | instance_variables.rb:13:5:15:7 | self in get_field [@field] : | instance_variables.rb:14:9:14:21 | return : | instance_variables.rb:75:6:75:20 | call to get_field | -| instance_variables.rb:79:6:79:10 | foo12 [@field] : | instance_variables.rb:13:5:15:7 | self in get_field [@field] : | instance_variables.rb:14:9:14:21 | return : | instance_variables.rb:79:6:79:20 | call to get_field | -| instance_variables.rb:79:6:79:10 | foo12 [@field] : | instance_variables.rb:13:5:15:7 | self in get_field [@field] : | instance_variables.rb:14:9:14:21 | return : | instance_variables.rb:79:6:79:20 | call to get_field | -| instance_variables.rb:84:6:84:10 | foo13 [@field] : | instance_variables.rb:13:5:15:7 | self in get_field [@field] : | instance_variables.rb:14:9:14:21 | return : | instance_variables.rb:84:6:84:20 | call to get_field | -| instance_variables.rb:84:6:84:10 | foo13 [@field] : | instance_variables.rb:13:5:15:7 | self in get_field [@field] : | instance_variables.rb:14:9:14:21 | return : | instance_variables.rb:84:6:84:20 | call to get_field | +| instance_variables.rb:28:20:28:24 | field : | instance_variables.rb:22:20:22:24 | field : | instance_variables.rb:23:9:23:14 | [post] self [@field] : | instance_variables.rb:28:9:28:25 | [post] self [@field] : | +| instance_variables.rb:28:20:28:24 | field : | instance_variables.rb:22:20:22:24 | field : | instance_variables.rb:23:9:23:14 | [post] self [@field] : | instance_variables.rb:28:9:28:25 | [post] self [@field] : | +| instance_variables.rb:39:15:39:23 | call to taint : | instance_variables.rb:10:19:10:19 | x : | instance_variables.rb:11:9:11:14 | [post] self [@field] : | instance_variables.rb:39:1:39:3 | [post] foo [@field] : | +| instance_variables.rb:39:15:39:23 | call to taint : | instance_variables.rb:10:19:10:19 | x : | instance_variables.rb:11:9:11:14 | [post] self [@field] : | instance_variables.rb:39:1:39:3 | [post] foo [@field] : | +| instance_variables.rb:40:6:40:8 | foo [@field] : | instance_variables.rb:13:5:15:7 | self in get_field [@field] : | instance_variables.rb:14:9:14:21 | return : | instance_variables.rb:40:6:40:18 | call to get_field | +| instance_variables.rb:40:6:40:8 | foo [@field] : | instance_variables.rb:13:5:15:7 | self in get_field [@field] : | instance_variables.rb:14:9:14:21 | return : | instance_variables.rb:40:6:40:18 | call to get_field | +| instance_variables.rb:43:15:43:22 | call to taint : | instance_variables.rb:10:19:10:19 | x : | instance_variables.rb:11:9:11:14 | [post] self [@field] : | instance_variables.rb:43:1:43:3 | [post] bar [@field] : | +| instance_variables.rb:44:6:44:8 | bar [@field] : | instance_variables.rb:16:5:18:7 | self in inc_field [@field] : | instance_variables.rb:16:5:18:7 | self in inc_field [@field] : | instance_variables.rb:44:6:44:18 | call to inc_field | +| instance_variables.rb:44:6:44:8 | bar [@field] : | instance_variables.rb:16:5:18:7 | self in inc_field [@field] : | instance_variables.rb:17:9:17:14 | [post] self [@field] : | instance_variables.rb:44:6:44:18 | call to inc_field | +| instance_variables.rb:52:6:52:9 | foo2 [@field] : | instance_variables.rb:13:5:15:7 | self in get_field [@field] : | instance_variables.rb:14:9:14:21 | return : | instance_variables.rb:52:6:52:19 | call to get_field | +| instance_variables.rb:52:6:52:9 | foo2 [@field] : | instance_variables.rb:13:5:15:7 | self in get_field [@field] : | instance_variables.rb:14:9:14:21 | return : | instance_variables.rb:52:6:52:19 | call to get_field | +| instance_variables.rb:55:16:55:24 | call to taint : | instance_variables.rb:10:19:10:19 | x : | instance_variables.rb:11:9:11:14 | [post] self [@field] : | instance_variables.rb:55:1:55:4 | [post] foo3 [@field] : | +| instance_variables.rb:55:16:55:24 | call to taint : | instance_variables.rb:10:19:10:19 | x : | instance_variables.rb:11:9:11:14 | [post] self [@field] : | instance_variables.rb:55:1:55:4 | [post] foo3 [@field] : | +| instance_variables.rb:63:18:63:26 | call to taint : | instance_variables.rb:10:19:10:19 | x : | instance_variables.rb:11:9:11:14 | [post] self [@field] : | instance_variables.rb:63:2:63:5 | [post] foo5 [@field] : | +| instance_variables.rb:63:18:63:26 | call to taint : | instance_variables.rb:10:19:10:19 | x : | instance_variables.rb:11:9:11:14 | [post] self [@field] : | instance_variables.rb:63:2:63:5 | [post] foo5 [@field] : | +| instance_variables.rb:64:6:64:9 | foo5 [@field] : | instance_variables.rb:13:5:15:7 | self in get_field [@field] : | instance_variables.rb:14:9:14:21 | return : | instance_variables.rb:64:6:64:19 | call to get_field | +| instance_variables.rb:64:6:64:9 | foo5 [@field] : | instance_variables.rb:13:5:15:7 | self in get_field [@field] : | instance_variables.rb:14:9:14:21 | return : | instance_variables.rb:64:6:64:19 | call to get_field | +| instance_variables.rb:67:32:67:40 | call to taint : | instance_variables.rb:10:19:10:19 | x : | instance_variables.rb:11:9:11:14 | [post] self [@field] : | instance_variables.rb:67:15:67:18 | [post] foo6 [@field] : | +| instance_variables.rb:67:32:67:40 | call to taint : | instance_variables.rb:10:19:10:19 | x : | instance_variables.rb:11:9:11:14 | [post] self [@field] : | instance_variables.rb:67:15:67:18 | [post] foo6 [@field] : | +| instance_variables.rb:68:6:68:9 | foo3 [@field] : | instance_variables.rb:13:5:15:7 | self in get_field [@field] : | instance_variables.rb:14:9:14:21 | return : | instance_variables.rb:68:6:68:19 | call to get_field | +| instance_variables.rb:68:6:68:9 | foo3 [@field] : | instance_variables.rb:13:5:15:7 | self in get_field [@field] : | instance_variables.rb:14:9:14:21 | return : | instance_variables.rb:68:6:68:19 | call to get_field | +| instance_variables.rb:69:6:69:9 | foo5 [@field] : | instance_variables.rb:13:5:15:7 | self in get_field [@field] : | instance_variables.rb:14:9:14:21 | return : | instance_variables.rb:69:6:69:19 | call to get_field | +| instance_variables.rb:69:6:69:9 | foo5 [@field] : | instance_variables.rb:13:5:15:7 | self in get_field [@field] : | instance_variables.rb:14:9:14:21 | return : | instance_variables.rb:69:6:69:19 | call to get_field | +| instance_variables.rb:70:6:70:9 | foo6 [@field] : | instance_variables.rb:13:5:15:7 | self in get_field [@field] : | instance_variables.rb:14:9:14:21 | return : | instance_variables.rb:70:6:70:19 | call to get_field | +| instance_variables.rb:70:6:70:9 | foo6 [@field] : | instance_variables.rb:13:5:15:7 | self in get_field [@field] : | instance_variables.rb:14:9:14:21 | return : | instance_variables.rb:70:6:70:19 | call to get_field | +| instance_variables.rb:74:45:74:53 | call to taint : | instance_variables.rb:10:19:10:19 | x : | instance_variables.rb:11:9:11:14 | [post] self [@field] : | instance_variables.rb:74:15:74:18 | [post] foo7 [@field] : | +| instance_variables.rb:74:45:74:53 | call to taint : | instance_variables.rb:10:19:10:19 | x : | instance_variables.rb:11:9:11:14 | [post] self [@field] : | instance_variables.rb:74:15:74:18 | [post] foo7 [@field] : | +| instance_variables.rb:74:45:74:53 | call to taint : | instance_variables.rb:10:19:10:19 | x : | instance_variables.rb:11:9:11:14 | [post] self [@field] : | instance_variables.rb:74:25:74:28 | [post] foo8 [@field] : | +| instance_variables.rb:74:45:74:53 | call to taint : | instance_variables.rb:10:19:10:19 | x : | instance_variables.rb:11:9:11:14 | [post] self [@field] : | instance_variables.rb:74:25:74:28 | [post] foo8 [@field] : | +| instance_variables.rb:75:6:75:9 | foo7 [@field] : | instance_variables.rb:13:5:15:7 | self in get_field [@field] : | instance_variables.rb:14:9:14:21 | return : | instance_variables.rb:75:6:75:19 | call to get_field | +| instance_variables.rb:75:6:75:9 | foo7 [@field] : | instance_variables.rb:13:5:15:7 | self in get_field [@field] : | instance_variables.rb:14:9:14:21 | return : | instance_variables.rb:75:6:75:19 | call to get_field | +| instance_variables.rb:76:6:76:9 | foo8 [@field] : | instance_variables.rb:13:5:15:7 | self in get_field [@field] : | instance_variables.rb:14:9:14:21 | return : | instance_variables.rb:76:6:76:19 | call to get_field | +| instance_variables.rb:76:6:76:9 | foo8 [@field] : | instance_variables.rb:13:5:15:7 | self in get_field [@field] : | instance_variables.rb:14:9:14:21 | return : | instance_variables.rb:76:6:76:19 | call to get_field | +| instance_variables.rb:80:53:80:61 | call to taint : | instance_variables.rb:10:19:10:19 | x : | instance_variables.rb:11:9:11:14 | [post] self [@field] : | instance_variables.rb:80:22:80:25 | [post] foo9 [@field] : | +| instance_variables.rb:80:53:80:61 | call to taint : | instance_variables.rb:10:19:10:19 | x : | instance_variables.rb:11:9:11:14 | [post] self [@field] : | instance_variables.rb:80:22:80:25 | [post] foo9 [@field] : | +| instance_variables.rb:80:53:80:61 | call to taint : | instance_variables.rb:10:19:10:19 | x : | instance_variables.rb:11:9:11:14 | [post] self [@field] : | instance_variables.rb:80:32:80:36 | [post] foo10 [@field] : | +| instance_variables.rb:80:53:80:61 | call to taint : | instance_variables.rb:10:19:10:19 | x : | instance_variables.rb:11:9:11:14 | [post] self [@field] : | instance_variables.rb:80:32:80:36 | [post] foo10 [@field] : | +| instance_variables.rb:81:6:81:9 | foo9 [@field] : | instance_variables.rb:13:5:15:7 | self in get_field [@field] : | instance_variables.rb:14:9:14:21 | return : | instance_variables.rb:81:6:81:19 | call to get_field | +| instance_variables.rb:81:6:81:9 | foo9 [@field] : | instance_variables.rb:13:5:15:7 | self in get_field [@field] : | instance_variables.rb:14:9:14:21 | return : | instance_variables.rb:81:6:81:19 | call to get_field | +| instance_variables.rb:82:6:82:10 | foo10 [@field] : | instance_variables.rb:13:5:15:7 | self in get_field [@field] : | instance_variables.rb:14:9:14:21 | return : | instance_variables.rb:82:6:82:20 | call to get_field | +| instance_variables.rb:82:6:82:10 | foo10 [@field] : | instance_variables.rb:13:5:15:7 | self in get_field [@field] : | instance_variables.rb:14:9:14:21 | return : | instance_variables.rb:82:6:82:20 | call to get_field | +| instance_variables.rb:85:17:85:25 | call to taint : | instance_variables.rb:10:19:10:19 | x : | instance_variables.rb:11:9:11:14 | [post] self [@field] : | instance_variables.rb:85:5:85:5 | [post] x [@field] : | +| instance_variables.rb:85:17:85:25 | call to taint : | instance_variables.rb:10:19:10:19 | x : | instance_variables.rb:11:9:11:14 | [post] self [@field] : | instance_variables.rb:85:5:85:5 | [post] x [@field] : | +| instance_variables.rb:90:6:90:10 | foo11 [@field] : | instance_variables.rb:13:5:15:7 | self in get_field [@field] : | instance_variables.rb:14:9:14:21 | return : | instance_variables.rb:90:6:90:20 | call to get_field | +| instance_variables.rb:90:6:90:10 | foo11 [@field] : | instance_variables.rb:13:5:15:7 | self in get_field [@field] : | instance_variables.rb:14:9:14:21 | return : | instance_variables.rb:90:6:90:20 | call to get_field | +| instance_variables.rb:94:6:94:10 | foo12 [@field] : | instance_variables.rb:13:5:15:7 | self in get_field [@field] : | instance_variables.rb:14:9:14:21 | return : | instance_variables.rb:94:6:94:20 | call to get_field | +| instance_variables.rb:94:6:94:10 | foo12 [@field] : | instance_variables.rb:13:5:15:7 | self in get_field [@field] : | instance_variables.rb:14:9:14:21 | return : | instance_variables.rb:94:6:94:20 | call to get_field | +| instance_variables.rb:99:6:99:10 | foo13 [@field] : | instance_variables.rb:13:5:15:7 | self in get_field [@field] : | instance_variables.rb:14:9:14:21 | return : | instance_variables.rb:99:6:99:20 | call to get_field | +| instance_variables.rb:99:6:99:10 | foo13 [@field] : | instance_variables.rb:13:5:15:7 | self in get_field [@field] : | instance_variables.rb:14:9:14:21 | return : | instance_variables.rb:99:6:99:20 | call to get_field | +| instance_variables.rb:101:17:101:25 | call to taint : | instance_variables.rb:22:20:22:24 | field : | instance_variables.rb:23:9:23:14 | [post] self [@field] : | instance_variables.rb:101:9:101:26 | call to new [@field] : | +| instance_variables.rb:101:17:101:25 | call to taint : | instance_variables.rb:22:20:22:24 | field : | instance_variables.rb:23:9:23:14 | [post] self [@field] : | instance_variables.rb:101:9:101:26 | call to new [@field] : | +| instance_variables.rb:102:6:102:10 | foo15 [@field] : | instance_variables.rb:13:5:15:7 | self in get_field [@field] : | instance_variables.rb:14:9:14:21 | return : | instance_variables.rb:102:6:102:20 | call to get_field | +| instance_variables.rb:102:6:102:10 | foo15 [@field] : | instance_variables.rb:13:5:15:7 | self in get_field [@field] : | instance_variables.rb:14:9:14:21 | return : | instance_variables.rb:102:6:102:20 | call to get_field | +| instance_variables.rb:104:28:104:36 | call to taint : | instance_variables.rb:27:25:27:29 | field : | instance_variables.rb:28:9:28:25 | [post] self [@field] : | instance_variables.rb:104:6:104:10 | [post] foo16 [@field] : | +| instance_variables.rb:104:28:104:36 | call to taint : | instance_variables.rb:27:25:27:29 | field : | instance_variables.rb:28:9:28:25 | [post] self [@field] : | instance_variables.rb:104:6:104:10 | [post] foo16 [@field] : | +| instance_variables.rb:105:6:105:10 | foo16 [@field] : | instance_variables.rb:13:5:15:7 | self in get_field [@field] : | instance_variables.rb:14:9:14:21 | return : | instance_variables.rb:105:6:105:20 | call to get_field | +| instance_variables.rb:105:6:105:10 | foo16 [@field] : | instance_variables.rb:13:5:15:7 | self in get_field [@field] : | instance_variables.rb:14:9:14:21 | return : | instance_variables.rb:105:6:105:20 | call to get_field | #select | captured_variables.rb:2:20:2:20 | x | captured_variables.rb:5:20:5:30 | call to source : | captured_variables.rb:2:20:2:20 | x | $@ | captured_variables.rb:5:20:5:30 | call to source : | call to source : | | captured_variables.rb:23:14:23:14 | x | captured_variables.rb:27:29:27:39 | call to source : | captured_variables.rb:23:14:23:14 | x | $@ | captured_variables.rb:27:29:27:39 | call to source : | call to source : | | captured_variables.rb:34:14:34:14 | x | captured_variables.rb:38:27:38:37 | call to source : | captured_variables.rb:34:14:34:14 | x | $@ | captured_variables.rb:38:27:38:37 | call to source : | call to source : | | instance_variables.rb:20:10:20:13 | @foo | instance_variables.rb:19:12:19:21 | call to taint : | instance_variables.rb:20:10:20:13 | @foo | $@ | instance_variables.rb:19:12:19:21 | call to taint : | call to taint : | -| instance_variables.rb:25:6:25:18 | call to get_field | instance_variables.rb:24:15:24:23 | call to taint : | instance_variables.rb:25:6:25:18 | call to get_field | $@ | instance_variables.rb:24:15:24:23 | call to taint : | call to taint : | -| instance_variables.rb:29:6:29:18 | call to inc_field | instance_variables.rb:28:15:28:22 | call to taint : | instance_variables.rb:29:6:29:18 | call to inc_field | $@ | instance_variables.rb:28:15:28:22 | call to taint : | call to taint : | -| instance_variables.rb:33:6:33:15 | call to field | instance_variables.rb:32:14:32:22 | call to taint : | instance_variables.rb:33:6:33:15 | call to field | $@ | instance_variables.rb:32:14:32:22 | call to taint : | call to taint : | -| instance_variables.rb:37:6:37:19 | call to get_field | instance_variables.rb:36:14:36:22 | call to taint : | instance_variables.rb:37:6:37:19 | call to get_field | $@ | instance_variables.rb:36:14:36:22 | call to taint : | call to taint : | -| instance_variables.rb:41:6:41:15 | call to field | instance_variables.rb:40:16:40:24 | call to taint : | instance_variables.rb:41:6:41:15 | call to field | $@ | instance_variables.rb:40:16:40:24 | call to taint : | call to taint : | -| instance_variables.rb:49:6:49:19 | call to get_field | instance_variables.rb:48:18:48:26 | call to taint : | instance_variables.rb:49:6:49:19 | call to get_field | $@ | instance_variables.rb:48:18:48:26 | call to taint : | call to taint : | -| instance_variables.rb:53:6:53:19 | call to get_field | instance_variables.rb:40:16:40:24 | call to taint : | instance_variables.rb:53:6:53:19 | call to get_field | $@ | instance_variables.rb:40:16:40:24 | call to taint : | call to taint : | -| instance_variables.rb:54:6:54:19 | call to get_field | instance_variables.rb:48:18:48:26 | call to taint : | instance_variables.rb:54:6:54:19 | call to get_field | $@ | instance_variables.rb:48:18:48:26 | call to taint : | call to taint : | -| instance_variables.rb:55:6:55:19 | call to get_field | instance_variables.rb:52:32:52:40 | call to taint : | instance_variables.rb:55:6:55:19 | call to get_field | $@ | instance_variables.rb:52:32:52:40 | call to taint : | call to taint : | -| instance_variables.rb:60:6:60:19 | call to get_field | instance_variables.rb:59:45:59:53 | call to taint : | instance_variables.rb:60:6:60:19 | call to get_field | $@ | instance_variables.rb:59:45:59:53 | call to taint : | call to taint : | -| instance_variables.rb:61:6:61:19 | call to get_field | instance_variables.rb:59:45:59:53 | call to taint : | instance_variables.rb:61:6:61:19 | call to get_field | $@ | instance_variables.rb:59:45:59:53 | call to taint : | call to taint : | -| instance_variables.rb:66:6:66:19 | call to get_field | instance_variables.rb:65:53:65:61 | call to taint : | instance_variables.rb:66:6:66:19 | call to get_field | $@ | instance_variables.rb:65:53:65:61 | call to taint : | call to taint : | -| instance_variables.rb:67:6:67:20 | call to get_field | instance_variables.rb:65:53:65:61 | call to taint : | instance_variables.rb:67:6:67:20 | call to get_field | $@ | instance_variables.rb:65:53:65:61 | call to taint : | call to taint : | -| instance_variables.rb:75:6:75:20 | call to get_field | instance_variables.rb:70:17:70:25 | call to taint : | instance_variables.rb:75:6:75:20 | call to get_field | $@ | instance_variables.rb:70:17:70:25 | call to taint : | call to taint : | -| instance_variables.rb:79:6:79:20 | call to get_field | instance_variables.rb:70:17:70:25 | call to taint : | instance_variables.rb:79:6:79:20 | call to get_field | $@ | instance_variables.rb:70:17:70:25 | call to taint : | call to taint : | -| instance_variables.rb:84:6:84:20 | call to get_field | instance_variables.rb:70:17:70:25 | call to taint : | instance_variables.rb:84:6:84:20 | call to get_field | $@ | instance_variables.rb:70:17:70:25 | call to taint : | call to taint : | +| instance_variables.rb:40:6:40:18 | call to get_field | instance_variables.rb:39:15:39:23 | call to taint : | instance_variables.rb:40:6:40:18 | call to get_field | $@ | instance_variables.rb:39:15:39:23 | call to taint : | call to taint : | +| instance_variables.rb:44:6:44:18 | call to inc_field | instance_variables.rb:43:15:43:22 | call to taint : | instance_variables.rb:44:6:44:18 | call to inc_field | $@ | instance_variables.rb:43:15:43:22 | call to taint : | call to taint : | +| instance_variables.rb:48:6:48:15 | call to field | instance_variables.rb:47:14:47:22 | call to taint : | instance_variables.rb:48:6:48:15 | call to field | $@ | instance_variables.rb:47:14:47:22 | call to taint : | call to taint : | +| instance_variables.rb:52:6:52:19 | call to get_field | instance_variables.rb:51:14:51:22 | call to taint : | instance_variables.rb:52:6:52:19 | call to get_field | $@ | instance_variables.rb:51:14:51:22 | call to taint : | call to taint : | +| instance_variables.rb:56:6:56:15 | call to field | instance_variables.rb:55:16:55:24 | call to taint : | instance_variables.rb:56:6:56:15 | call to field | $@ | instance_variables.rb:55:16:55:24 | call to taint : | call to taint : | +| instance_variables.rb:64:6:64:19 | call to get_field | instance_variables.rb:63:18:63:26 | call to taint : | instance_variables.rb:64:6:64:19 | call to get_field | $@ | instance_variables.rb:63:18:63:26 | call to taint : | call to taint : | +| instance_variables.rb:68:6:68:19 | call to get_field | instance_variables.rb:55:16:55:24 | call to taint : | instance_variables.rb:68:6:68:19 | call to get_field | $@ | instance_variables.rb:55:16:55:24 | call to taint : | call to taint : | +| instance_variables.rb:69:6:69:19 | call to get_field | instance_variables.rb:63:18:63:26 | call to taint : | instance_variables.rb:69:6:69:19 | call to get_field | $@ | instance_variables.rb:63:18:63:26 | call to taint : | call to taint : | +| instance_variables.rb:70:6:70:19 | call to get_field | instance_variables.rb:67:32:67:40 | call to taint : | instance_variables.rb:70:6:70:19 | call to get_field | $@ | instance_variables.rb:67:32:67:40 | call to taint : | call to taint : | +| instance_variables.rb:75:6:75:19 | call to get_field | instance_variables.rb:74:45:74:53 | call to taint : | instance_variables.rb:75:6:75:19 | call to get_field | $@ | instance_variables.rb:74:45:74:53 | call to taint : | call to taint : | +| instance_variables.rb:76:6:76:19 | call to get_field | instance_variables.rb:74:45:74:53 | call to taint : | instance_variables.rb:76:6:76:19 | call to get_field | $@ | instance_variables.rb:74:45:74:53 | call to taint : | call to taint : | +| instance_variables.rb:81:6:81:19 | call to get_field | instance_variables.rb:80:53:80:61 | call to taint : | instance_variables.rb:81:6:81:19 | call to get_field | $@ | instance_variables.rb:80:53:80:61 | call to taint : | call to taint : | +| instance_variables.rb:82:6:82:20 | call to get_field | instance_variables.rb:80:53:80:61 | call to taint : | instance_variables.rb:82:6:82:20 | call to get_field | $@ | instance_variables.rb:80:53:80:61 | call to taint : | call to taint : | +| instance_variables.rb:90:6:90:20 | call to get_field | instance_variables.rb:85:17:85:25 | call to taint : | instance_variables.rb:90:6:90:20 | call to get_field | $@ | instance_variables.rb:85:17:85:25 | call to taint : | call to taint : | +| instance_variables.rb:94:6:94:20 | call to get_field | instance_variables.rb:85:17:85:25 | call to taint : | instance_variables.rb:94:6:94:20 | call to get_field | $@ | instance_variables.rb:85:17:85:25 | call to taint : | call to taint : | +| instance_variables.rb:99:6:99:20 | call to get_field | instance_variables.rb:85:17:85:25 | call to taint : | instance_variables.rb:99:6:99:20 | call to get_field | $@ | instance_variables.rb:85:17:85:25 | call to taint : | call to taint : | +| instance_variables.rb:102:6:102:20 | call to get_field | instance_variables.rb:101:17:101:25 | call to taint : | instance_variables.rb:102:6:102:20 | call to get_field | $@ | instance_variables.rb:101:17:101:25 | call to taint : | call to taint : | +| instance_variables.rb:104:6:104:37 | call to call_initialize | instance_variables.rb:24:9:24:17 | call to taint : | instance_variables.rb:104:6:104:37 | call to call_initialize | $@ | instance_variables.rb:24:9:24:17 | call to taint : | call to taint : | +| instance_variables.rb:105:6:105:20 | call to get_field | instance_variables.rb:104:28:104:36 | call to taint : | instance_variables.rb:105:6:105:20 | call to get_field | $@ | instance_variables.rb:104:28:104:36 | call to taint : | call to taint : | +| instance_variables.rb:107:6:107:8 | bar | instance_variables.rb:34:9:34:17 | call to taint : | instance_variables.rb:107:6:107:8 | bar | $@ | instance_variables.rb:34:9:34:17 | call to taint : | call to taint : | diff --git a/ruby/ql/test/library-tests/dataflow/global/TypeTrackingInlineTest.expected b/ruby/ql/test/library-tests/dataflow/global/TypeTrackingInlineTest.expected index 8a8a3b7c977..a5b27a120d9 100644 --- a/ruby/ql/test/library-tests/dataflow/global/TypeTrackingInlineTest.expected +++ b/ruby/ql/test/library-tests/dataflow/global/TypeTrackingInlineTest.expected @@ -1,17 +1,19 @@ | captured_variables.rb:9:14:9:14 | x | Fixed missing result:hasValueFlow=1.2 | | captured_variables.rb:16:14:16:14 | x | Fixed missing result:hasValueFlow=1.3 | | instance_variables.rb:20:16:20:33 | # $ hasValueFlow=7 | Missing result:hasValueFlow=7 | -| instance_variables.rb:25:21:25:39 | # $ hasValueFlow=42 | Missing result:hasValueFlow=42 | -| instance_variables.rb:37:22:37:40 | # $ hasValueFlow=21 | Missing result:hasValueFlow=21 | -| instance_variables.rb:41:18:41:36 | # $ hasValueFlow=22 | Missing result:hasValueFlow=22 | -| instance_variables.rb:49:22:49:40 | # $ hasValueFlow=24 | Missing result:hasValueFlow=24 | -| instance_variables.rb:53:22:53:40 | # $ hasValueFlow=22 | Missing result:hasValueFlow=22 | -| instance_variables.rb:54:22:54:40 | # $ hasValueFlow=24 | Missing result:hasValueFlow=24 | -| instance_variables.rb:55:22:55:40 | # $ hasValueFlow=25 | Missing result:hasValueFlow=25 | -| instance_variables.rb:60:22:60:40 | # $ hasValueFlow=26 | Missing result:hasValueFlow=26 | -| instance_variables.rb:61:22:61:40 | # $ hasValueFlow=26 | Missing result:hasValueFlow=26 | -| instance_variables.rb:66:22:66:40 | # $ hasValueFlow=27 | Missing result:hasValueFlow=27 | -| instance_variables.rb:67:23:67:41 | # $ hasValueFlow=27 | Missing result:hasValueFlow=27 | -| instance_variables.rb:75:23:75:41 | # $ hasValueFlow=28 | Missing result:hasValueFlow=28 | -| instance_variables.rb:79:23:79:41 | # $ hasValueFlow=28 | Missing result:hasValueFlow=28 | -| instance_variables.rb:84:23:84:41 | # $ hasValueFlow=28 | Missing result:hasValueFlow=28 | +| instance_variables.rb:40:21:40:39 | # $ hasValueFlow=42 | Missing result:hasValueFlow=42 | +| instance_variables.rb:52:22:52:40 | # $ hasValueFlow=21 | Missing result:hasValueFlow=21 | +| instance_variables.rb:56:18:56:36 | # $ hasValueFlow=22 | Missing result:hasValueFlow=22 | +| instance_variables.rb:64:22:64:40 | # $ hasValueFlow=24 | Missing result:hasValueFlow=24 | +| instance_variables.rb:68:22:68:40 | # $ hasValueFlow=22 | Missing result:hasValueFlow=22 | +| instance_variables.rb:69:22:69:40 | # $ hasValueFlow=24 | Missing result:hasValueFlow=24 | +| instance_variables.rb:70:22:70:40 | # $ hasValueFlow=25 | Missing result:hasValueFlow=25 | +| instance_variables.rb:75:22:75:40 | # $ hasValueFlow=26 | Missing result:hasValueFlow=26 | +| instance_variables.rb:76:22:76:40 | # $ hasValueFlow=26 | Missing result:hasValueFlow=26 | +| instance_variables.rb:81:22:81:40 | # $ hasValueFlow=27 | Missing result:hasValueFlow=27 | +| instance_variables.rb:82:23:82:41 | # $ hasValueFlow=27 | Missing result:hasValueFlow=27 | +| instance_variables.rb:90:23:90:41 | # $ hasValueFlow=28 | Missing result:hasValueFlow=28 | +| instance_variables.rb:94:23:94:41 | # $ hasValueFlow=28 | Missing result:hasValueFlow=28 | +| instance_variables.rb:99:23:99:41 | # $ hasValueFlow=28 | Missing result:hasValueFlow=28 | +| instance_variables.rb:102:23:102:41 | # $ hasValueFlow=29 | Missing result:hasValueFlow=29 | +| instance_variables.rb:105:23:105:41 | # $ hasValueFlow=30 | Missing result:hasValueFlow=30 | diff --git a/ruby/ql/test/library-tests/dataflow/global/instance_variables.rb b/ruby/ql/test/library-tests/dataflow/global/instance_variables.rb index dd8910e2dca..73a13a7d55e 100644 --- a/ruby/ql/test/library-tests/dataflow/global/instance_variables.rb +++ b/ruby/ql/test/library-tests/dataflow/global/instance_variables.rb @@ -19,7 +19,22 @@ class Foo @foo = taint("7") sink(@foo) # $ hasValueFlow=7 + def initialize(field = nil) + @field = field + taint(31) + end + + def call_initialize(field) + initialize(field) + end end + +class Bar < Foo + def self.new arg + taint(32) + end +end + foo = Foo.new foo.set_field(taint(42)) sink(foo.get_field) # $ hasValueFlow=42 @@ -81,4 +96,13 @@ sink(foo12.get_field) # $ hasValueFlow=28 foo13 = Foo.new foo14 = Foo.new set_field_on(foo14 = foo13) -sink(foo13.get_field) # $ hasValueFlow=28 \ No newline at end of file +sink(foo13.get_field) # $ hasValueFlow=28 + +foo15 = Foo.new(taint(29)) +sink(foo15.get_field) # $ hasValueFlow=29 +foo16 = Foo.new +sink(foo16.call_initialize(taint(30))) # $ hasValueFlow=31 +sink(foo16.get_field) # $ hasValueFlow=30 +bar = Bar.new(taint(33)) +sink(bar) # $ hasValueFlow=32 +sink(bar.get_field) \ No newline at end of file diff --git a/ruby/ql/test/library-tests/frameworks/globalid/GlobalId.expected b/ruby/ql/test/library-tests/frameworks/globalid/GlobalId.expected new file mode 100644 index 00000000000..1a149338027 --- /dev/null +++ b/ruby/ql/test/library-tests/frameworks/globalid/GlobalId.expected @@ -0,0 +1,38 @@ +locateCalls +| globalid.rb:6:3:6:30 | call to locate | +| globalid.rb:11:3:11:30 | call to locate | +| globalid.rb:70:3:70:30 | call to locate | +locateSignedCalls +| globalid.rb:16:3:16:38 | call to locate_signed | +| globalid.rb:21:3:21:38 | call to locate_signed | +| globalid.rb:89:3:89:38 | call to locate_signed | +toGlobalIdCalls +| globalid.rb:5:9:5:33 | call to to_global_id | +| globalid.rb:10:9:10:27 | call to to_gid | +| globalid.rb:56:9:56:16 | call to to_gid | +| globalid.rb:62:9:62:22 | call to to_global_id | +toGidParamCalls +| globalid.rb:35:10:35:34 | call to to_gid_param | +| globalid.rb:68:10:68:23 | call to to_gid_param | +toSignedGlobalIdCalls +| globalid.rb:15:10:15:41 | call to to_signed_global_id | +| globalid.rb:20:10:20:29 | call to to_sgid | +| globalid.rb:75:10:75:18 | call to to_sgid | +| globalid.rb:81:10:81:30 | call to to_signed_global_id | +toSgidParamCalls +| globalid.rb:41:11:41:36 | call to to_sgid_param | +| globalid.rb:87:11:87:25 | call to to_sgid_param | +globalIdParseCalls +| globalid.rb:36:9:36:27 | call to parse | +| globalid.rb:69:9:69:27 | call to parse | +globalIdFindCalls +| globalid.rb:37:3:37:19 | call to find | +| globalid.rb:57:3:57:19 | call to find | +| globalid.rb:63:3:63:19 | call to find | +signedGlobalIdParseCalls +| globalid.rb:42:10:42:35 | call to parse | +| globalid.rb:88:10:88:35 | call to parse | +signedGlobalIdFindCalls +| globalid.rb:43:3:43:26 | call to find | +| globalid.rb:76:3:76:26 | call to find | +| globalid.rb:82:3:82:26 | call to find | diff --git a/ruby/ql/test/library-tests/frameworks/globalid/GlobalId.ql b/ruby/ql/test/library-tests/frameworks/globalid/GlobalId.ql new file mode 100644 index 00000000000..d48465b0e52 --- /dev/null +++ b/ruby/ql/test/library-tests/frameworks/globalid/GlobalId.ql @@ -0,0 +1,21 @@ +import codeql.ruby.frameworks.GlobalId + +query predicate locateCalls(GlobalId::Locator::LocateCall c) { any() } + +query predicate locateSignedCalls(GlobalId::Locator::LocateSignedCall c) { any() } + +query predicate toGlobalIdCalls(GlobalId::Identification::ToGlobalIdCall c) { any() } + +query predicate toGidParamCalls(GlobalId::Identification::ToGidParamCall c) { any() } + +query predicate toSignedGlobalIdCalls(GlobalId::Identification::ToSignedGlobalIdCall c) { any() } + +query predicate toSgidParamCalls(GlobalId::Identification::ToSgidParamCall c) { any() } + +query predicate globalIdParseCalls(GlobalId::ParseCall c) { any() } + +query predicate globalIdFindCalls(GlobalId::FindCall c) { any() } + +query predicate signedGlobalIdParseCalls(SignedGlobalId::ParseCall c) { any() } + +query predicate signedGlobalIdFindCalls(SignedGlobalId::FindCall c) { any() } diff --git a/ruby/ql/test/library-tests/frameworks/globalid/globalid.rb b/ruby/ql/test/library-tests/frameworks/globalid/globalid.rb new file mode 100644 index 00000000000..f06cbd761f2 --- /dev/null +++ b/ruby/ql/test/library-tests/frameworks/globalid/globalid.rb @@ -0,0 +1,90 @@ +class User < ActiveRecord::Base +end + +def m1 + gid = User.find(1).to_global_id + GlobalID::Locator.locate gid +end + +def m2 + gid = User.find(1).to_gid + GlobalID::Locator.locate gid +end + +def m3 + sgid = User.find(1).to_signed_global_id + GlobalID::Locator.locate_signed sgid +end + +def m4 + sgid = User.find(1).to_sgid + GlobalID::Locator.locate_signed sgid +end + +def m5 + gids = User.all.map(&:to_gid) + GlobalID::Locator.locate_many gids +end + +def m6 + sgids = User.all.map(&:to_sgid) + GlobalID::Locator.locate_many_signed sgids +end + +def m7 + gidp = User.find(1).to_gid_param + gid = GlobalID.parse gidp + GlobalID.find gid +end + +def m8 + sgidp = User.find(1).to_sgid_param + sgid = SignedGlobalID.parse sgidp + SignedGlobalID.find sgid +end + +class Person + include GlobalID::Identification + + def self.find(id) + # implementation goes here + end +end + +def m9 + p = Person.find(1) + gid = p.to_gid + GlobalID.find gid +end + +def m10 + p = Person.find(1) + gid = p.to_global_id + GlobalID.find gid +end + +def m11 + p = Person.find(1) + gidp = p.to_gid_param + gid = GlobalID.parse gidp + GlobalID::Locator.locate gid +end + +def m12 + p = Person.find(1) + sgid = p.to_sgid + SignedGlobalID.find sgid +end + +def m10 + p = Person.find(1) + sgid = p.to_signed_global_id + SignedGlobalID.find sgid +end + +def m11 + p = Person.find(1) + sgidp = p.to_sgid_param + sgid = SignedGlobalID.parse sgidp + GlobalID::Locator.locate_signed sgid +end diff --git a/ruby/ql/test/library-tests/modules/ancestors.expected b/ruby/ql/test/library-tests/modules/ancestors.expected index 50a5f7dc72e..9e2c70f6f1c 100644 --- a/ruby/ql/test/library-tests/modules/ancestors.expected +++ b/ruby/ql/test/library-tests/modules/ancestors.expected @@ -142,6 +142,12 @@ calls.rb: #-----| super -> Object #-----| include -> Included +# 633| CustomNew1 +#-----| super -> Object + +# 641| CustomNew2 +#-----| super -> Object + hello.rb: # 1| EnglishWords diff --git a/ruby/ql/test/library-tests/modules/callgraph.expected b/ruby/ql/test/library-tests/modules/callgraph.expected index 93f262b3105..19eea285289 100644 --- a/ruby/ql/test/library-tests/modules/callgraph.expected +++ b/ruby/ql/test/library-tests/modules/callgraph.expected @@ -237,6 +237,14 @@ getTarget | calls.rb:620:9:620:16 | call to bar | calls.rb:628:5:630:7 | bar | | calls.rb:627:5:627:20 | call to include | calls.rb:108:5:110:7 | include | | calls.rb:629:9:629:13 | call to super | calls.rb:622:5:623:7 | bar | +| calls.rb:635:9:635:14 | call to new | calls.rb:117:5:117:16 | new | +| calls.rb:639:1:639:14 | call to new | calls.rb:117:5:117:16 | new | +| calls.rb:639:1:639:14 | call to new | calls.rb:634:5:636:7 | new | +| calls.rb:639:1:639:23 | call to instance | calls.rb:326:5:328:7 | instance | +| calls.rb:647:9:647:34 | call to puts | calls.rb:102:5:102:30 | puts | +| calls.rb:651:1:651:14 | call to new | calls.rb:117:5:117:16 | new | +| calls.rb:651:1:651:14 | call to new | calls.rb:642:5:644:7 | new | +| calls.rb:651:1:651:23 | call to instance | calls.rb:646:5:648:7 | instance | | hello.rb:12:5:12:24 | call to include | calls.rb:108:5:110:7 | include | | hello.rb:14:16:14:20 | call to hello | hello.rb:2:5:4:7 | hello | | hello.rb:20:16:20:20 | call to super | hello.rb:13:5:15:7 | message | @@ -361,6 +369,7 @@ unresolvedCall | calls.rb:562:1:562:13 | call to [] | | calls.rb:562:1:562:39 | call to each | | calls.rb:570:5:570:14 | call to singleton2 | +| calls.rb:643:9:643:21 | call to allocate | | hello.rb:20:16:20:26 | ... + ... | | hello.rb:20:16:20:34 | ... + ... | | hello.rb:20:16:20:40 | ... + ... | @@ -483,6 +492,9 @@ publicMethod | calls.rb:619:5:621:7 | foo | | calls.rb:622:5:623:7 | bar | | calls.rb:628:5:630:7 | bar | +| calls.rb:634:5:636:7 | new | +| calls.rb:642:5:644:7 | new | +| calls.rb:646:5:648:7 | instance | | hello.rb:2:5:4:7 | hello | | hello.rb:5:5:7:7 | world | | hello.rb:13:5:15:7 | message | diff --git a/ruby/ql/test/library-tests/modules/calls.rb b/ruby/ql/test/library-tests/modules/calls.rb index c6cd849571c..27d90f84e93 100644 --- a/ruby/ql/test/library-tests/modules/calls.rb +++ b/ruby/ql/test/library-tests/modules/calls.rb @@ -630,3 +630,22 @@ class IncludesIncluded end end +class CustomNew1 + def self.new + C1.new + end +end + +CustomNew1.new.instance + +class CustomNew2 + def self.new + self.allocate + end + + def instance + puts "CustomNew2#instance" + end +end + +CustomNew2.new.instance diff --git a/ruby/ql/test/library-tests/modules/methods.expected b/ruby/ql/test/library-tests/modules/methods.expected index 8bd0d32fde6..eb3d1de05a7 100644 --- a/ruby/ql/test/library-tests/modules/methods.expected +++ b/ruby/ql/test/library-tests/modules/methods.expected @@ -48,6 +48,7 @@ getMethod | calls.rb:618:1:624:3 | Included | bar | calls.rb:622:5:623:7 | bar | | calls.rb:618:1:624:3 | Included | foo | calls.rb:619:5:621:7 | foo | | calls.rb:626:1:631:3 | IncludesIncluded | bar | calls.rb:628:5:630:7 | bar | +| calls.rb:641:1:649:3 | CustomNew2 | instance | calls.rb:646:5:648:7 | instance | | hello.rb:1:1:8:3 | EnglishWords | hello | hello.rb:2:5:4:7 | hello | | hello.rb:1:1:8:3 | EnglishWords | world | hello.rb:5:5:7:7 | world | | hello.rb:11:1:16:3 | Greeting | message | hello.rb:13:5:15:7 | message | @@ -497,6 +498,35 @@ lookupMethod | calls.rb:626:1:631:3 | IncludesIncluded | private_on_main | calls.rb:185:1:186:3 | private_on_main | | calls.rb:626:1:631:3 | IncludesIncluded | puts | calls.rb:102:5:102:30 | puts | | calls.rb:626:1:631:3 | IncludesIncluded | to_s | calls.rb:172:5:173:7 | to_s | +| calls.rb:633:1:637:3 | CustomNew1 | add_singleton | calls.rb:367:1:371:3 | add_singleton | +| calls.rb:633:1:637:3 | CustomNew1 | call_block | calls.rb:81:1:83:3 | call_block | +| calls.rb:633:1:637:3 | CustomNew1 | call_instance_m | calls.rb:39:1:41:3 | call_instance_m | +| calls.rb:633:1:637:3 | CustomNew1 | create | calls.rb:278:1:286:3 | create | +| calls.rb:633:1:637:3 | CustomNew1 | foo | calls.rb:1:1:3:3 | foo | +| calls.rb:633:1:637:3 | CustomNew1 | foo | calls.rb:85:1:89:3 | foo | +| calls.rb:633:1:637:3 | CustomNew1 | funny | calls.rb:140:1:142:3 | funny | +| calls.rb:633:1:637:3 | CustomNew1 | indirect | calls.rb:158:1:160:3 | indirect | +| calls.rb:633:1:637:3 | CustomNew1 | new | calls.rb:117:5:117:16 | new | +| calls.rb:633:1:637:3 | CustomNew1 | optional_arg | calls.rb:76:1:79:3 | optional_arg | +| calls.rb:633:1:637:3 | CustomNew1 | pattern_dispatch | calls.rb:343:1:359:3 | pattern_dispatch | +| calls.rb:633:1:637:3 | CustomNew1 | private_on_main | calls.rb:185:1:186:3 | private_on_main | +| calls.rb:633:1:637:3 | CustomNew1 | puts | calls.rb:102:5:102:30 | puts | +| calls.rb:633:1:637:3 | CustomNew1 | to_s | calls.rb:172:5:173:7 | to_s | +| calls.rb:641:1:649:3 | CustomNew2 | add_singleton | calls.rb:367:1:371:3 | add_singleton | +| calls.rb:641:1:649:3 | CustomNew2 | call_block | calls.rb:81:1:83:3 | call_block | +| calls.rb:641:1:649:3 | CustomNew2 | call_instance_m | calls.rb:39:1:41:3 | call_instance_m | +| calls.rb:641:1:649:3 | CustomNew2 | create | calls.rb:278:1:286:3 | create | +| calls.rb:641:1:649:3 | CustomNew2 | foo | calls.rb:1:1:3:3 | foo | +| calls.rb:641:1:649:3 | CustomNew2 | foo | calls.rb:85:1:89:3 | foo | +| calls.rb:641:1:649:3 | CustomNew2 | funny | calls.rb:140:1:142:3 | funny | +| calls.rb:641:1:649:3 | CustomNew2 | indirect | calls.rb:158:1:160:3 | indirect | +| calls.rb:641:1:649:3 | CustomNew2 | instance | calls.rb:646:5:648:7 | instance | +| calls.rb:641:1:649:3 | CustomNew2 | new | calls.rb:117:5:117:16 | new | +| calls.rb:641:1:649:3 | CustomNew2 | optional_arg | calls.rb:76:1:79:3 | optional_arg | +| calls.rb:641:1:649:3 | CustomNew2 | pattern_dispatch | calls.rb:343:1:359:3 | pattern_dispatch | +| calls.rb:641:1:649:3 | CustomNew2 | private_on_main | calls.rb:185:1:186:3 | private_on_main | +| calls.rb:641:1:649:3 | CustomNew2 | puts | calls.rb:102:5:102:30 | puts | +| calls.rb:641:1:649:3 | CustomNew2 | to_s | calls.rb:172:5:173:7 | to_s | | file://:0:0:0:0 | Class | include | calls.rb:108:5:110:7 | include | | file://:0:0:0:0 | Class | module_eval | calls.rb:107:5:107:24 | module_eval | | file://:0:0:0:0 | Class | new | calls.rb:117:5:117:16 | new | @@ -987,6 +1017,14 @@ enclosingMethod | calls.rb:620:9:620:12 | self | calls.rb:619:5:621:7 | foo | | calls.rb:620:9:620:16 | call to bar | calls.rb:619:5:621:7 | foo | | calls.rb:629:9:629:13 | call to super | calls.rb:628:5:630:7 | bar | +| calls.rb:635:9:635:10 | C1 | calls.rb:634:5:636:7 | new | +| calls.rb:635:9:635:14 | call to new | calls.rb:634:5:636:7 | new | +| calls.rb:643:9:643:12 | self | calls.rb:642:5:644:7 | new | +| calls.rb:643:9:643:21 | call to allocate | calls.rb:642:5:644:7 | new | +| calls.rb:647:9:647:34 | call to puts | calls.rb:646:5:648:7 | instance | +| calls.rb:647:9:647:34 | self | calls.rb:646:5:648:7 | instance | +| calls.rb:647:14:647:34 | "CustomNew2#instance" | calls.rb:646:5:648:7 | instance | +| calls.rb:647:15:647:33 | CustomNew2#instance | calls.rb:646:5:648:7 | instance | | hello.rb:3:9:3:22 | return | hello.rb:2:5:4:7 | hello | | hello.rb:3:16:3:22 | "hello" | hello.rb:2:5:4:7 | hello | | hello.rb:3:17:3:21 | hello | hello.rb:2:5:4:7 | hello | diff --git a/ruby/ql/test/library-tests/modules/modules.expected b/ruby/ql/test/library-tests/modules/modules.expected index 57cebf1907c..6c25a173009 100644 --- a/ruby/ql/test/library-tests/modules/modules.expected +++ b/ruby/ql/test/library-tests/modules/modules.expected @@ -34,6 +34,8 @@ getModule | calls.rb:605:1:612:3 | SingletonC | | calls.rb:618:1:624:3 | Included | | calls.rb:626:1:631:3 | IncludesIncluded | +| calls.rb:633:1:637:3 | CustomNew1 | +| calls.rb:641:1:649:3 | CustomNew2 | | file://:0:0:0:0 | BasicObject | | file://:0:0:0:0 | Class | | file://:0:0:0:0 | Complex | @@ -103,7 +105,7 @@ getADeclaration | calls.rb:96:1:98:3 | String | calls.rb:96:1:98:3 | String | | calls.rb:100:1:103:3 | Kernel | calls.rb:100:1:103:3 | Kernel | | calls.rb:105:1:113:3 | Module | calls.rb:105:1:113:3 | Module | -| calls.rb:115:1:118:3 | Object | calls.rb:1:1:632:1 | calls.rb | +| calls.rb:115:1:118:3 | Object | calls.rb:1:1:651:24 | calls.rb | | calls.rb:115:1:118:3 | Object | calls.rb:115:1:118:3 | Object | | calls.rb:115:1:118:3 | Object | hello.rb:1:1:22:3 | hello.rb | | calls.rb:115:1:118:3 | Object | instance_fields.rb:1:1:29:4 | instance_fields.rb | @@ -143,6 +145,8 @@ getADeclaration | calls.rb:605:1:612:3 | SingletonC | calls.rb:605:1:612:3 | SingletonC | | calls.rb:618:1:624:3 | Included | calls.rb:618:1:624:3 | Included | | calls.rb:626:1:631:3 | IncludesIncluded | calls.rb:626:1:631:3 | IncludesIncluded | +| calls.rb:633:1:637:3 | CustomNew1 | calls.rb:633:1:637:3 | CustomNew1 | +| calls.rb:641:1:649:3 | CustomNew2 | calls.rb:641:1:649:3 | CustomNew2 | | hello.rb:1:1:8:3 | EnglishWords | hello.rb:1:1:8:3 | EnglishWords | | hello.rb:11:1:16:3 | Greeting | hello.rb:11:1:16:3 | Greeting | | hello.rb:18:1:22:3 | HelloWorld | hello.rb:18:1:22:3 | HelloWorld | @@ -223,6 +227,8 @@ getSuperClass | calls.rb:596:1:603:3 | SingletonB | calls.rb:583:1:594:3 | SingletonA | | calls.rb:605:1:612:3 | SingletonC | calls.rb:583:1:594:3 | SingletonA | | calls.rb:626:1:631:3 | IncludesIncluded | calls.rb:115:1:118:3 | Object | +| calls.rb:633:1:637:3 | CustomNew1 | calls.rb:115:1:118:3 | Object | +| calls.rb:641:1:649:3 | CustomNew2 | calls.rb:115:1:118:3 | Object | | file://:0:0:0:0 | Class | calls.rb:105:1:113:3 | Module | | file://:0:0:0:0 | Complex | file://:0:0:0:0 | Numeric | | file://:0:0:0:0 | FalseClass | calls.rb:115:1:118:3 | Object | @@ -365,6 +371,9 @@ resolveConstantReadAccess | calls.rb:615:1:615:10 | SingletonB | SingletonB | | calls.rb:616:1:616:10 | SingletonC | SingletonC | | calls.rb:627:13:627:20 | Included | Included | +| calls.rb:635:9:635:10 | C1 | C1 | +| calls.rb:639:1:639:10 | CustomNew1 | CustomNew1 | +| calls.rb:651:1:651:10 | CustomNew2 | CustomNew2 | | hello.rb:12:13:12:24 | EnglishWords | EnglishWords | | hello.rb:18:20:18:27 | Greeting | Greeting | | instance_fields.rb:4:22:4:31 | A_target | A_target | @@ -447,6 +456,8 @@ resolveConstantWriteAccess | calls.rb:605:1:612:3 | SingletonC | SingletonC | | calls.rb:618:1:624:3 | Included | Included | | calls.rb:626:1:631:3 | IncludesIncluded | IncludesIncluded | +| calls.rb:633:1:637:3 | CustomNew1 | CustomNew1 | +| calls.rb:641:1:649:3 | CustomNew2 | CustomNew2 | | hello.rb:1:1:8:3 | EnglishWords | EnglishWords | | hello.rb:11:1:16:3 | Greeting | Greeting | | hello.rb:18:1:22:3 | HelloWorld | HelloWorld | @@ -513,32 +524,32 @@ resolveConstantWriteAccess | unresolved_subclass.rb:7:1:8:3 | Subclass2 | UnresolvedNamespace::Subclass2 | | unresolved_subclass.rb:11:1:12:3 | A | UnresolvedNamespace::A | enclosingModule -| calls.rb:1:1:3:3 | foo | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:2:5:2:14 | call to puts | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:2:5:2:14 | self | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:2:10:2:14 | "foo" | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:2:11:2:13 | foo | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:5:1:5:3 | call to foo | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:5:1:5:3 | self | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:7:1:9:3 | bar | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:7:5:7:8 | self | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:8:5:8:15 | call to puts | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:8:5:8:15 | self | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:8:10:8:15 | "bar1" | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:8:11:8:14 | bar1 | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:11:1:11:4 | self | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:11:1:11:8 | call to bar | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:13:1:15:3 | bar | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:13:5:13:8 | self | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:14:5:14:15 | call to puts | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:14:5:14:15 | self | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:14:10:14:15 | "bar2" | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:14:11:14:14 | bar2 | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:17:1:17:4 | self | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:17:1:17:8 | call to bar | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:19:1:19:4 | self | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:19:1:19:8 | call to foo | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:21:1:34:3 | M | calls.rb:1:1:632:1 | calls.rb | +| calls.rb:1:1:3:3 | foo | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:2:5:2:14 | call to puts | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:2:5:2:14 | self | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:2:10:2:14 | "foo" | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:2:11:2:13 | foo | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:5:1:5:3 | call to foo | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:5:1:5:3 | self | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:7:1:9:3 | bar | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:7:5:7:8 | self | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:8:5:8:15 | call to puts | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:8:5:8:15 | self | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:8:10:8:15 | "bar1" | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:8:11:8:14 | bar1 | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:11:1:11:4 | self | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:11:1:11:8 | call to bar | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:13:1:15:3 | bar | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:13:5:13:8 | self | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:14:5:14:15 | call to puts | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:14:5:14:15 | self | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:14:10:14:15 | "bar2" | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:14:11:14:14 | bar2 | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:17:1:17:4 | self | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:17:1:17:8 | call to bar | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:19:1:19:4 | self | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:19:1:19:8 | call to foo | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:21:1:34:3 | M | calls.rb:1:1:651:24 | calls.rb | | calls.rb:22:5:24:7 | instance_m | calls.rb:21:1:34:3 | M | | calls.rb:23:9:23:19 | call to singleton_m | calls.rb:21:1:34:3 | M | | calls.rb:23:9:23:19 | self | calls.rb:21:1:34:3 | M | @@ -554,14 +565,14 @@ enclosingModule | calls.rb:32:5:32:15 | self | calls.rb:21:1:34:3 | M | | calls.rb:33:5:33:8 | self | calls.rb:21:1:34:3 | M | | calls.rb:33:5:33:20 | call to singleton_m | calls.rb:21:1:34:3 | M | -| calls.rb:36:1:36:1 | M | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:36:1:36:12 | call to instance_m | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:37:1:37:1 | M | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:37:1:37:13 | call to singleton_m | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:39:1:41:3 | call_instance_m | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:40:5:40:14 | call to instance_m | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:40:5:40:14 | self | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:43:1:58:3 | C | calls.rb:1:1:632:1 | calls.rb | +| calls.rb:36:1:36:1 | M | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:36:1:36:12 | call to instance_m | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:37:1:37:1 | M | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:37:1:37:13 | call to singleton_m | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:39:1:41:3 | call_instance_m | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:40:5:40:14 | call to instance_m | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:40:5:40:14 | self | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:43:1:58:3 | C | calls.rb:1:1:651:24 | calls.rb | | calls.rb:44:5:44:13 | call to include | calls.rb:43:1:58:3 | C | | calls.rb:44:5:44:13 | self | calls.rb:43:1:58:3 | C | | calls.rb:44:13:44:13 | M | calls.rb:43:1:58:3 | C | @@ -582,66 +593,66 @@ enclosingModule | calls.rb:55:9:55:19 | self | calls.rb:43:1:58:3 | C | | calls.rb:56:9:56:12 | self | calls.rb:43:1:58:3 | C | | calls.rb:56:9:56:24 | call to singleton_m | calls.rb:43:1:58:3 | C | -| calls.rb:60:1:60:1 | c | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:60:1:60:9 | ... = ... | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:60:5:60:5 | C | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:60:5:60:9 | call to new | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:61:1:61:1 | c | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:61:1:61:5 | call to baz | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:62:1:62:1 | c | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:62:1:62:13 | call to singleton_m | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:63:1:63:1 | c | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:63:1:63:12 | call to instance_m | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:65:1:69:3 | D | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:65:11:65:11 | C | calls.rb:1:1:632:1 | calls.rb | +| calls.rb:60:1:60:1 | c | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:60:1:60:9 | ... = ... | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:60:5:60:5 | C | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:60:5:60:9 | call to new | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:61:1:61:1 | c | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:61:1:61:5 | call to baz | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:62:1:62:1 | c | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:62:1:62:13 | call to singleton_m | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:63:1:63:1 | c | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:63:1:63:12 | call to instance_m | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:65:1:69:3 | D | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:65:11:65:11 | C | calls.rb:1:1:651:24 | calls.rb | | calls.rb:66:5:68:7 | baz | calls.rb:65:1:69:3 | D | | calls.rb:67:9:67:13 | call to super | calls.rb:65:1:69:3 | D | -| calls.rb:71:1:71:1 | d | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:71:1:71:9 | ... = ... | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:71:5:71:5 | D | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:71:5:71:9 | call to new | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:72:1:72:1 | d | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:72:1:72:5 | call to baz | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:73:1:73:1 | d | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:73:1:73:13 | call to singleton_m | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:74:1:74:1 | d | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:74:1:74:12 | call to instance_m | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:76:1:79:3 | optional_arg | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:76:18:76:18 | a | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:76:18:76:18 | a | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:76:22:76:22 | 4 | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:76:25:76:25 | b | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:76:25:76:25 | b | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:76:28:76:28 | 5 | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:77:5:77:5 | a | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:77:5:77:16 | call to bit_length | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:78:5:78:5 | b | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:78:5:78:16 | call to bit_length | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:81:1:83:3 | call_block | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:82:5:82:11 | yield ... | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:82:11:82:11 | 1 | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:85:1:89:3 | foo | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:86:5:86:7 | var | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:86:5:86:18 | ... = ... | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:86:11:86:14 | Hash | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:86:11:86:18 | call to new | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:87:5:87:7 | var | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:87:5:87:10 | ...[...] | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:87:9:87:9 | 1 | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:88:5:88:29 | call to call_block | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:88:5:88:29 | self | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:88:16:88:29 | { ... } | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:88:19:88:19 | x | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:88:19:88:19 | x | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:88:22:88:24 | var | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:88:22:88:27 | ...[...] | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:88:26:88:26 | x | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:91:1:94:3 | Integer | calls.rb:1:1:632:1 | calls.rb | +| calls.rb:71:1:71:1 | d | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:71:1:71:9 | ... = ... | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:71:5:71:5 | D | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:71:5:71:9 | call to new | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:72:1:72:1 | d | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:72:1:72:5 | call to baz | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:73:1:73:1 | d | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:73:1:73:13 | call to singleton_m | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:74:1:74:1 | d | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:74:1:74:12 | call to instance_m | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:76:1:79:3 | optional_arg | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:76:18:76:18 | a | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:76:18:76:18 | a | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:76:22:76:22 | 4 | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:76:25:76:25 | b | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:76:25:76:25 | b | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:76:28:76:28 | 5 | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:77:5:77:5 | a | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:77:5:77:16 | call to bit_length | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:78:5:78:5 | b | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:78:5:78:16 | call to bit_length | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:81:1:83:3 | call_block | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:82:5:82:11 | yield ... | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:82:11:82:11 | 1 | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:85:1:89:3 | foo | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:86:5:86:7 | var | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:86:5:86:18 | ... = ... | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:86:11:86:14 | Hash | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:86:11:86:18 | call to new | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:87:5:87:7 | var | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:87:5:87:10 | ...[...] | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:87:9:87:9 | 1 | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:88:5:88:29 | call to call_block | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:88:5:88:29 | self | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:88:16:88:29 | { ... } | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:88:19:88:19 | x | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:88:19:88:19 | x | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:88:22:88:24 | var | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:88:22:88:27 | ...[...] | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:88:26:88:26 | x | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:91:1:94:3 | Integer | calls.rb:1:1:651:24 | calls.rb | | calls.rb:92:5:92:23 | bit_length | calls.rb:91:1:94:3 | Integer | | calls.rb:93:5:93:16 | abs | calls.rb:91:1:94:3 | Integer | -| calls.rb:96:1:98:3 | String | calls.rb:1:1:632:1 | calls.rb | +| calls.rb:96:1:98:3 | String | calls.rb:1:1:651:24 | calls.rb | | calls.rb:97:5:97:23 | capitalize | calls.rb:96:1:98:3 | String | -| calls.rb:100:1:103:3 | Kernel | calls.rb:1:1:632:1 | calls.rb | +| calls.rb:100:1:103:3 | Kernel | calls.rb:1:1:651:24 | calls.rb | | calls.rb:101:5:101:25 | alias ... | calls.rb:100:1:103:3 | Kernel | | calls.rb:101:11:101:19 | :old_puts | calls.rb:100:1:103:3 | Kernel | | calls.rb:101:11:101:19 | old_puts | calls.rb:100:1:103:3 | Kernel | @@ -653,7 +664,7 @@ enclosingModule | calls.rb:102:17:102:26 | call to old_puts | calls.rb:100:1:103:3 | Kernel | | calls.rb:102:17:102:26 | self | calls.rb:100:1:103:3 | Kernel | | calls.rb:102:26:102:26 | x | calls.rb:100:1:103:3 | Kernel | -| calls.rb:105:1:113:3 | Module | calls.rb:1:1:632:1 | calls.rb | +| calls.rb:105:1:113:3 | Module | calls.rb:1:1:651:24 | calls.rb | | calls.rb:106:5:106:31 | alias ... | calls.rb:105:1:113:3 | Module | | calls.rb:106:11:106:22 | :old_include | calls.rb:105:1:113:3 | Module | | calls.rb:106:11:106:22 | old_include | calls.rb:105:1:113:3 | Module | @@ -668,13 +679,13 @@ enclosingModule | calls.rb:109:21:109:21 | x | calls.rb:105:1:113:3 | Module | | calls.rb:111:5:111:20 | prepend | calls.rb:105:1:113:3 | Module | | calls.rb:112:5:112:20 | private | calls.rb:105:1:113:3 | Module | -| calls.rb:115:1:118:3 | Object | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:115:16:115:21 | Module | calls.rb:1:1:632:1 | calls.rb | +| calls.rb:115:1:118:3 | Object | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:115:16:115:21 | Module | calls.rb:1:1:651:24 | calls.rb | | calls.rb:116:5:116:18 | call to include | calls.rb:115:1:118:3 | Object | | calls.rb:116:5:116:18 | self | calls.rb:115:1:118:3 | Object | | calls.rb:116:13:116:18 | Kernel | calls.rb:115:1:118:3 | Object | | calls.rb:117:5:117:16 | new | calls.rb:115:1:118:3 | Object | -| calls.rb:120:1:123:3 | Hash | calls.rb:1:1:632:1 | calls.rb | +| calls.rb:120:1:123:3 | Hash | calls.rb:1:1:651:24 | calls.rb | | calls.rb:121:5:121:25 | alias ... | calls.rb:120:1:123:3 | Hash | | calls.rb:121:11:121:21 | :old_lookup | calls.rb:120:1:123:3 | Hash | | calls.rb:121:11:121:21 | old_lookup | calls.rb:120:1:123:3 | Hash | @@ -686,7 +697,7 @@ enclosingModule | calls.rb:122:15:122:27 | call to old_lookup | calls.rb:120:1:123:3 | Hash | | calls.rb:122:15:122:27 | self | calls.rb:120:1:123:3 | Hash | | calls.rb:122:26:122:26 | x | calls.rb:120:1:123:3 | Hash | -| calls.rb:125:1:138:3 | Array | calls.rb:1:1:632:1 | calls.rb | +| calls.rb:125:1:138:3 | Array | calls.rb:1:1:651:24 | calls.rb | | calls.rb:126:3:126:23 | alias ... | calls.rb:125:1:138:3 | Array | | calls.rb:126:9:126:19 | :old_lookup | calls.rb:125:1:138:3 | Array | | calls.rb:126:9:126:19 | old_lookup | calls.rb:125:1:138:3 | Array | @@ -722,130 +733,130 @@ enclosingModule | calls.rb:135:9:135:14 | ... = ... | calls.rb:125:1:138:3 | Array | | calls.rb:135:11:135:12 | ... + ... | calls.rb:125:1:138:3 | Array | | calls.rb:135:14:135:14 | 1 | calls.rb:125:1:138:3 | Array | -| calls.rb:140:1:142:3 | funny | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:141:5:141:20 | yield ... | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:141:11:141:20 | "prefix: " | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:141:12:141:19 | prefix: | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:144:1:144:30 | call to funny | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:144:1:144:30 | self | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:144:7:144:30 | { ... } | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:144:10:144:10 | i | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:144:10:144:10 | i | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:144:13:144:29 | call to puts | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:144:13:144:29 | self | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:144:18:144:18 | i | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:144:18:144:29 | call to capitalize | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:146:1:146:3 | "a" | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:146:1:146:14 | call to capitalize | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:146:2:146:2 | a | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:147:1:147:1 | 1 | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:147:1:147:12 | call to bit_length | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:148:1:148:1 | 1 | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:148:1:148:5 | call to abs | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:150:1:150:13 | Array | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:150:1:150:13 | [...] | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:150:1:150:13 | call to [] | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:150:1:150:62 | call to foreach | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:150:2:150:4 | "a" | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:150:3:150:3 | a | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:150:6:150:8 | "b" | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:150:7:150:7 | b | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:150:10:150:12 | "c" | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:150:11:150:11 | c | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:150:23:150:62 | { ... } | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:150:26:150:26 | i | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:150:26:150:26 | i | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:150:29:150:29 | v | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:150:29:150:29 | v | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:150:32:150:61 | call to puts | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:150:32:150:61 | self | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:150:37:150:61 | "#{...} -> #{...}" | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:150:38:150:41 | #{...} | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:150:40:150:40 | i | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:150:42:150:45 | -> | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:150:46:150:60 | #{...} | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:150:48:150:48 | v | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:150:48:150:59 | call to capitalize | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:152:1:152:7 | Array | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:152:1:152:7 | [...] | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:152:1:152:7 | call to [] | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:152:1:152:35 | call to foreach | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:152:2:152:2 | 1 | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:152:4:152:4 | 2 | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:152:6:152:6 | 3 | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:152:17:152:35 | { ... } | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:152:20:152:20 | i | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:152:20:152:20 | i | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:152:23:152:23 | i | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:152:23:152:34 | call to bit_length | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:154:1:154:7 | Array | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:154:1:154:7 | [...] | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:154:1:154:7 | call to [] | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:154:1:154:40 | call to foreach | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:154:2:154:2 | 1 | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:154:4:154:4 | 2 | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:154:6:154:6 | 3 | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:154:17:154:40 | { ... } | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:154:20:154:20 | i | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:154:20:154:20 | i | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:154:23:154:39 | call to puts | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:154:23:154:39 | self | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:154:28:154:28 | i | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:154:28:154:39 | call to capitalize | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:156:1:156:8 | Array | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:156:1:156:8 | [...] | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:156:1:156:8 | call to [] | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:156:1:156:37 | call to foreach | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:156:2:156:2 | 1 | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:156:4:156:5 | - ... | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:156:5:156:5 | 2 | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:156:7:156:7 | 3 | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:156:18:156:37 | { ... } | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:156:21:156:21 | _ | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:156:21:156:21 | _ | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:156:24:156:24 | v | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:156:24:156:24 | v | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:156:27:156:36 | call to puts | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:156:27:156:36 | self | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:156:32:156:32 | v | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:156:32:156:36 | call to abs | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:158:1:160:3 | indirect | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:158:14:158:15 | &b | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:158:15:158:15 | b | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:159:5:159:17 | call to call_block | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:159:5:159:17 | self | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:159:16:159:17 | &... | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:159:17:159:17 | b | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:162:1:162:28 | call to indirect | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:162:1:162:28 | self | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:162:10:162:28 | { ... } | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:162:13:162:13 | i | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:162:13:162:13 | i | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:162:16:162:16 | i | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:162:16:162:27 | call to bit_length | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:165:1:169:3 | S | calls.rb:1:1:632:1 | calls.rb | +| calls.rb:140:1:142:3 | funny | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:141:5:141:20 | yield ... | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:141:11:141:20 | "prefix: " | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:141:12:141:19 | prefix: | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:144:1:144:30 | call to funny | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:144:1:144:30 | self | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:144:7:144:30 | { ... } | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:144:10:144:10 | i | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:144:10:144:10 | i | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:144:13:144:29 | call to puts | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:144:13:144:29 | self | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:144:18:144:18 | i | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:144:18:144:29 | call to capitalize | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:146:1:146:3 | "a" | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:146:1:146:14 | call to capitalize | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:146:2:146:2 | a | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:147:1:147:1 | 1 | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:147:1:147:12 | call to bit_length | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:148:1:148:1 | 1 | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:148:1:148:5 | call to abs | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:150:1:150:13 | Array | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:150:1:150:13 | [...] | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:150:1:150:13 | call to [] | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:150:1:150:62 | call to foreach | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:150:2:150:4 | "a" | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:150:3:150:3 | a | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:150:6:150:8 | "b" | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:150:7:150:7 | b | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:150:10:150:12 | "c" | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:150:11:150:11 | c | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:150:23:150:62 | { ... } | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:150:26:150:26 | i | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:150:26:150:26 | i | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:150:29:150:29 | v | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:150:29:150:29 | v | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:150:32:150:61 | call to puts | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:150:32:150:61 | self | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:150:37:150:61 | "#{...} -> #{...}" | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:150:38:150:41 | #{...} | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:150:40:150:40 | i | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:150:42:150:45 | -> | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:150:46:150:60 | #{...} | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:150:48:150:48 | v | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:150:48:150:59 | call to capitalize | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:152:1:152:7 | Array | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:152:1:152:7 | [...] | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:152:1:152:7 | call to [] | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:152:1:152:35 | call to foreach | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:152:2:152:2 | 1 | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:152:4:152:4 | 2 | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:152:6:152:6 | 3 | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:152:17:152:35 | { ... } | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:152:20:152:20 | i | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:152:20:152:20 | i | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:152:23:152:23 | i | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:152:23:152:34 | call to bit_length | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:154:1:154:7 | Array | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:154:1:154:7 | [...] | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:154:1:154:7 | call to [] | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:154:1:154:40 | call to foreach | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:154:2:154:2 | 1 | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:154:4:154:4 | 2 | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:154:6:154:6 | 3 | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:154:17:154:40 | { ... } | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:154:20:154:20 | i | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:154:20:154:20 | i | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:154:23:154:39 | call to puts | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:154:23:154:39 | self | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:154:28:154:28 | i | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:154:28:154:39 | call to capitalize | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:156:1:156:8 | Array | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:156:1:156:8 | [...] | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:156:1:156:8 | call to [] | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:156:1:156:37 | call to foreach | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:156:2:156:2 | 1 | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:156:4:156:5 | - ... | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:156:5:156:5 | 2 | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:156:7:156:7 | 3 | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:156:18:156:37 | { ... } | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:156:21:156:21 | _ | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:156:21:156:21 | _ | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:156:24:156:24 | v | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:156:24:156:24 | v | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:156:27:156:36 | call to puts | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:156:27:156:36 | self | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:156:32:156:32 | v | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:156:32:156:36 | call to abs | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:158:1:160:3 | indirect | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:158:14:158:15 | &b | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:158:15:158:15 | b | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:159:5:159:17 | call to call_block | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:159:5:159:17 | self | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:159:16:159:17 | &... | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:159:17:159:17 | b | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:162:1:162:28 | call to indirect | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:162:1:162:28 | self | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:162:10:162:28 | { ... } | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:162:13:162:13 | i | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:162:13:162:13 | i | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:162:16:162:16 | i | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:162:16:162:27 | call to bit_length | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:165:1:169:3 | S | calls.rb:1:1:651:24 | calls.rb | | calls.rb:166:5:168:7 | s_method | calls.rb:165:1:169:3 | S | | calls.rb:167:9:167:12 | self | calls.rb:165:1:169:3 | S | | calls.rb:167:9:167:17 | call to to_s | calls.rb:165:1:169:3 | S | -| calls.rb:171:1:174:3 | A | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:171:11:171:11 | S | calls.rb:1:1:632:1 | calls.rb | +| calls.rb:171:1:174:3 | A | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:171:11:171:11 | S | calls.rb:1:1:651:24 | calls.rb | | calls.rb:172:5:173:7 | to_s | calls.rb:171:1:174:3 | A | -| calls.rb:176:1:179:3 | B | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:176:11:176:11 | S | calls.rb:1:1:632:1 | calls.rb | +| calls.rb:176:1:179:3 | B | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:176:11:176:11 | S | calls.rb:1:1:651:24 | calls.rb | | calls.rb:177:5:178:7 | to_s | calls.rb:176:1:179:3 | B | -| calls.rb:181:1:181:1 | S | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:181:1:181:5 | call to new | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:181:1:181:14 | call to s_method | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:182:1:182:1 | A | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:182:1:182:5 | call to new | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:182:1:182:14 | call to s_method | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:183:1:183:1 | B | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:183:1:183:5 | call to new | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:183:1:183:14 | call to s_method | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:185:1:186:3 | private_on_main | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:188:1:188:15 | call to private_on_main | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:188:1:188:15 | self | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:190:1:226:3 | Singletons | calls.rb:1:1:632:1 | calls.rb | +| calls.rb:181:1:181:1 | S | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:181:1:181:5 | call to new | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:181:1:181:14 | call to s_method | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:182:1:182:1 | A | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:182:1:182:5 | call to new | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:182:1:182:14 | call to s_method | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:183:1:183:1 | B | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:183:1:183:5 | call to new | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:183:1:183:14 | call to s_method | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:185:1:186:3 | private_on_main | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:188:1:188:15 | call to private_on_main | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:188:1:188:15 | self | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:190:1:226:3 | Singletons | calls.rb:1:1:651:24 | calls.rb | | calls.rb:191:5:194:7 | singleton_a | calls.rb:190:1:226:3 | Singletons | | calls.rb:191:9:191:12 | self | calls.rb:190:1:226:3 | Singletons | | calls.rb:192:9:192:26 | call to puts | calls.rb:190:1:226:3 | Singletons | @@ -895,126 +906,126 @@ enclosingModule | calls.rb:223:5:225:7 | call_singleton_g | calls.rb:190:1:226:3 | Singletons | | calls.rb:224:9:224:12 | self | calls.rb:190:1:226:3 | Singletons | | calls.rb:224:9:224:24 | call to singleton_g | calls.rb:190:1:226:3 | Singletons | -| calls.rb:228:1:228:10 | Singletons | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:228:1:228:22 | call to singleton_a | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:229:1:229:10 | Singletons | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:229:1:229:22 | call to singleton_f | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:231:1:231:2 | c1 | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:231:1:231:19 | ... = ... | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:231:6:231:15 | Singletons | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:231:6:231:19 | call to new | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:233:1:233:2 | c1 | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:233:1:233:11 | call to instance | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:234:1:234:2 | c1 | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:234:1:234:14 | call to singleton_e | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:236:1:238:3 | singleton_g | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:236:5:236:6 | c1 | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:237:5:237:24 | call to puts | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:237:5:237:24 | self | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:237:10:237:24 | "singleton_g_1" | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:237:11:237:23 | singleton_g_1 | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:240:1:240:2 | c1 | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:240:1:240:14 | call to singleton_g | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:241:1:241:2 | c1 | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:241:1:241:19 | call to call_singleton_g | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:243:1:245:3 | singleton_g | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:243:5:243:6 | c1 | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:244:5:244:24 | call to puts | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:244:5:244:24 | self | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:244:10:244:24 | "singleton_g_2" | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:244:11:244:23 | singleton_g_2 | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:247:1:247:2 | c1 | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:247:1:247:14 | call to singleton_g | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:248:1:248:2 | c1 | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:248:1:248:19 | call to call_singleton_g | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:250:1:254:3 | class << ... | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:250:10:250:11 | c1 | calls.rb:1:1:632:1 | calls.rb | +| calls.rb:228:1:228:10 | Singletons | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:228:1:228:22 | call to singleton_a | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:229:1:229:10 | Singletons | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:229:1:229:22 | call to singleton_f | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:231:1:231:2 | c1 | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:231:1:231:19 | ... = ... | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:231:6:231:15 | Singletons | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:231:6:231:19 | call to new | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:233:1:233:2 | c1 | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:233:1:233:11 | call to instance | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:234:1:234:2 | c1 | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:234:1:234:14 | call to singleton_e | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:236:1:238:3 | singleton_g | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:236:5:236:6 | c1 | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:237:5:237:24 | call to puts | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:237:5:237:24 | self | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:237:10:237:24 | "singleton_g_1" | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:237:11:237:23 | singleton_g_1 | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:240:1:240:2 | c1 | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:240:1:240:14 | call to singleton_g | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:241:1:241:2 | c1 | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:241:1:241:19 | call to call_singleton_g | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:243:1:245:3 | singleton_g | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:243:5:243:6 | c1 | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:244:5:244:24 | call to puts | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:244:5:244:24 | self | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:244:10:244:24 | "singleton_g_2" | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:244:11:244:23 | singleton_g_2 | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:247:1:247:2 | c1 | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:247:1:247:14 | call to singleton_g | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:248:1:248:2 | c1 | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:248:1:248:19 | call to call_singleton_g | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:250:1:254:3 | class << ... | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:250:10:250:11 | c1 | calls.rb:1:1:651:24 | calls.rb | | calls.rb:251:5:253:7 | singleton_g | calls.rb:250:1:254:3 | class << ... | | calls.rb:252:9:252:28 | call to puts | calls.rb:250:1:254:3 | class << ... | | calls.rb:252:9:252:28 | self | calls.rb:250:1:254:3 | class << ... | | calls.rb:252:14:252:28 | "singleton_g_3" | calls.rb:250:1:254:3 | class << ... | | calls.rb:252:15:252:27 | singleton_g_3 | calls.rb:250:1:254:3 | class << ... | -| calls.rb:256:1:256:2 | c1 | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:256:1:256:14 | call to singleton_g | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:257:1:257:2 | c1 | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:257:1:257:19 | call to call_singleton_g | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:259:1:259:2 | c2 | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:259:1:259:19 | ... = ... | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:259:6:259:15 | Singletons | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:259:6:259:19 | call to new | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:260:1:260:2 | c2 | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:260:1:260:14 | call to singleton_e | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:261:1:261:2 | c2 | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:261:1:261:14 | call to singleton_g | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:263:1:263:4 | self | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:263:1:263:8 | call to new | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:265:1:265:16 | call to puts | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:265:1:265:16 | self | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:265:6:265:16 | "top-level" | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:265:7:265:15 | top-level | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:267:1:269:3 | singleton_g | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:267:5:267:14 | Singletons | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:268:5:268:22 | call to puts | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:268:5:268:22 | self | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:268:10:268:22 | "singleton_g" | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:268:11:268:21 | singleton_g | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:271:1:271:10 | Singletons | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:271:1:271:22 | call to singleton_g | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:272:1:272:2 | c1 | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:272:1:272:14 | call to singleton_g | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:273:1:273:2 | c1 | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:273:1:273:19 | call to call_singleton_g | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:274:1:274:2 | c2 | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:274:1:274:14 | call to singleton_g | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:275:1:275:2 | c3 | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:275:1:275:19 | ... = ... | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:275:6:275:15 | Singletons | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:275:6:275:19 | call to new | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:276:1:276:2 | c3 | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:276:1:276:14 | call to singleton_g | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:278:1:286:3 | create | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:278:12:278:15 | type | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:278:12:278:15 | type | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:279:5:279:8 | type | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:279:5:279:12 | call to new | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:279:5:279:21 | call to instance | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:281:5:283:7 | singleton_h | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:281:9:281:12 | type | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:282:9:282:26 | call to puts | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:282:9:282:26 | self | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:282:14:282:26 | "singleton_h" | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:282:15:282:25 | singleton_h | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:285:5:285:8 | type | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:285:5:285:20 | call to singleton_h | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:288:1:288:17 | call to create | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:288:1:288:17 | self | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:288:8:288:17 | Singletons | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:289:1:289:10 | Singletons | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:289:1:289:22 | call to singleton_h | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:291:1:291:1 | x | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:291:1:291:14 | ... = ... | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:291:5:291:14 | Singletons | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:293:1:297:3 | class << ... | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:293:10:293:10 | x | calls.rb:1:1:632:1 | calls.rb | +| calls.rb:256:1:256:2 | c1 | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:256:1:256:14 | call to singleton_g | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:257:1:257:2 | c1 | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:257:1:257:19 | call to call_singleton_g | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:259:1:259:2 | c2 | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:259:1:259:19 | ... = ... | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:259:6:259:15 | Singletons | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:259:6:259:19 | call to new | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:260:1:260:2 | c2 | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:260:1:260:14 | call to singleton_e | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:261:1:261:2 | c2 | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:261:1:261:14 | call to singleton_g | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:263:1:263:4 | self | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:263:1:263:8 | call to new | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:265:1:265:16 | call to puts | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:265:1:265:16 | self | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:265:6:265:16 | "top-level" | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:265:7:265:15 | top-level | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:267:1:269:3 | singleton_g | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:267:5:267:14 | Singletons | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:268:5:268:22 | call to puts | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:268:5:268:22 | self | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:268:10:268:22 | "singleton_g" | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:268:11:268:21 | singleton_g | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:271:1:271:10 | Singletons | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:271:1:271:22 | call to singleton_g | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:272:1:272:2 | c1 | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:272:1:272:14 | call to singleton_g | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:273:1:273:2 | c1 | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:273:1:273:19 | call to call_singleton_g | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:274:1:274:2 | c2 | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:274:1:274:14 | call to singleton_g | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:275:1:275:2 | c3 | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:275:1:275:19 | ... = ... | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:275:6:275:15 | Singletons | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:275:6:275:19 | call to new | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:276:1:276:2 | c3 | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:276:1:276:14 | call to singleton_g | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:278:1:286:3 | create | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:278:12:278:15 | type | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:278:12:278:15 | type | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:279:5:279:8 | type | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:279:5:279:12 | call to new | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:279:5:279:21 | call to instance | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:281:5:283:7 | singleton_h | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:281:9:281:12 | type | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:282:9:282:26 | call to puts | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:282:9:282:26 | self | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:282:14:282:26 | "singleton_h" | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:282:15:282:25 | singleton_h | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:285:5:285:8 | type | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:285:5:285:20 | call to singleton_h | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:288:1:288:17 | call to create | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:288:1:288:17 | self | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:288:8:288:17 | Singletons | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:289:1:289:10 | Singletons | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:289:1:289:22 | call to singleton_h | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:291:1:291:1 | x | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:291:1:291:14 | ... = ... | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:291:5:291:14 | Singletons | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:293:1:297:3 | class << ... | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:293:10:293:10 | x | calls.rb:1:1:651:24 | calls.rb | | calls.rb:294:5:296:7 | singleton_i | calls.rb:293:1:297:3 | class << ... | | calls.rb:295:9:295:26 | call to puts | calls.rb:293:1:297:3 | class << ... | | calls.rb:295:9:295:26 | self | calls.rb:293:1:297:3 | class << ... | | calls.rb:295:14:295:26 | "singleton_i" | calls.rb:293:1:297:3 | class << ... | | calls.rb:295:15:295:25 | singleton_i | calls.rb:293:1:297:3 | class << ... | -| calls.rb:299:1:299:1 | x | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:299:1:299:13 | call to singleton_i | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:300:1:300:10 | Singletons | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:300:1:300:22 | call to singleton_i | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:302:1:306:3 | class << ... | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:302:10:302:19 | Singletons | calls.rb:1:1:632:1 | calls.rb | +| calls.rb:299:1:299:1 | x | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:299:1:299:13 | call to singleton_i | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:300:1:300:10 | Singletons | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:300:1:300:22 | call to singleton_i | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:302:1:306:3 | class << ... | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:302:10:302:19 | Singletons | calls.rb:1:1:651:24 | calls.rb | | calls.rb:303:5:305:7 | singleton_j | calls.rb:302:1:306:3 | class << ... | | calls.rb:304:9:304:26 | call to puts | calls.rb:302:1:306:3 | class << ... | | calls.rb:304:9:304:26 | self | calls.rb:302:1:306:3 | class << ... | | calls.rb:304:14:304:26 | "singleton_j" | calls.rb:302:1:306:3 | class << ... | | calls.rb:304:15:304:25 | singleton_j | calls.rb:302:1:306:3 | class << ... | -| calls.rb:308:1:308:10 | Singletons | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:308:1:308:22 | call to singleton_j | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:310:1:321:3 | SelfNew | calls.rb:1:1:632:1 | calls.rb | +| calls.rb:308:1:308:10 | Singletons | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:308:1:308:22 | call to singleton_j | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:310:1:321:3 | SelfNew | calls.rb:1:1:651:24 | calls.rb | | calls.rb:311:5:314:7 | instance | calls.rb:310:1:321:3 | SelfNew | | calls.rb:312:9:312:31 | call to puts | calls.rb:310:1:321:3 | SelfNew | | calls.rb:312:9:312:31 | self | calls.rb:310:1:321:3 | SelfNew | @@ -1031,110 +1042,110 @@ enclosingModule | calls.rb:320:5:320:7 | call to new | calls.rb:310:1:321:3 | SelfNew | | calls.rb:320:5:320:7 | self | calls.rb:310:1:321:3 | SelfNew | | calls.rb:320:5:320:16 | call to instance | calls.rb:310:1:321:3 | SelfNew | -| calls.rb:323:1:323:7 | SelfNew | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:323:1:323:17 | call to singleton | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:325:1:329:3 | C1 | calls.rb:1:1:632:1 | calls.rb | +| calls.rb:323:1:323:7 | SelfNew | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:323:1:323:17 | call to singleton | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:325:1:329:3 | C1 | calls.rb:1:1:651:24 | calls.rb | | calls.rb:326:5:328:7 | instance | calls.rb:325:1:329:3 | C1 | | calls.rb:327:9:327:26 | call to puts | calls.rb:325:1:329:3 | C1 | | calls.rb:327:9:327:26 | self | calls.rb:325:1:329:3 | C1 | | calls.rb:327:14:327:26 | "C1#instance" | calls.rb:325:1:329:3 | C1 | | calls.rb:327:15:327:25 | C1#instance | calls.rb:325:1:329:3 | C1 | -| calls.rb:331:1:335:3 | C2 | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:331:12:331:13 | C1 | calls.rb:1:1:632:1 | calls.rb | +| calls.rb:331:1:335:3 | C2 | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:331:12:331:13 | C1 | calls.rb:1:1:651:24 | calls.rb | | calls.rb:332:5:334:7 | instance | calls.rb:331:1:335:3 | C2 | | calls.rb:333:9:333:26 | call to puts | calls.rb:331:1:335:3 | C2 | | calls.rb:333:9:333:26 | self | calls.rb:331:1:335:3 | C2 | | calls.rb:333:14:333:26 | "C2#instance" | calls.rb:331:1:335:3 | C2 | | calls.rb:333:15:333:25 | C2#instance | calls.rb:331:1:335:3 | C2 | -| calls.rb:337:1:341:3 | C3 | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:337:12:337:13 | C2 | calls.rb:1:1:632:1 | calls.rb | +| calls.rb:337:1:341:3 | C3 | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:337:12:337:13 | C2 | calls.rb:1:1:651:24 | calls.rb | | calls.rb:338:5:340:7 | instance | calls.rb:337:1:341:3 | C3 | | calls.rb:339:9:339:26 | call to puts | calls.rb:337:1:341:3 | C3 | | calls.rb:339:9:339:26 | self | calls.rb:337:1:341:3 | C3 | | calls.rb:339:14:339:26 | "C3#instance" | calls.rb:337:1:341:3 | C3 | | calls.rb:339:15:339:25 | C3#instance | calls.rb:337:1:341:3 | C3 | -| calls.rb:343:1:359:3 | pattern_dispatch | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:343:22:343:22 | x | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:343:22:343:22 | x | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:344:5:352:7 | case ... | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:344:10:344:10 | x | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:345:5:346:18 | when ... | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:345:10:345:11 | C3 | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:345:12:346:18 | then ... | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:346:9:346:9 | x | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:346:9:346:18 | call to instance | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:347:5:348:18 | when ... | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:347:10:347:11 | C2 | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:347:12:348:18 | then ... | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:348:9:348:9 | x | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:348:9:348:18 | call to instance | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:349:5:350:18 | when ... | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:349:10:349:11 | C1 | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:349:12:350:18 | then ... | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:350:9:350:9 | x | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:350:9:350:18 | call to instance | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:351:5:351:8 | else ... | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:354:5:358:7 | case ... | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:354:10:354:10 | x | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:355:9:355:29 | in ... then ... | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:355:12:355:13 | C3 | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:355:15:355:29 | then ... | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:355:20:355:20 | x | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:355:20:355:29 | call to instance | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:356:9:356:36 | in ... then ... | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:356:12:356:13 | C2 | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:356:12:356:19 | ... => ... | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:356:18:356:19 | c2 | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:356:21:356:36 | then ... | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:356:26:356:27 | c2 | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:356:26:356:36 | call to instance | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:357:9:357:36 | in ... then ... | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:357:12:357:13 | C1 | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:357:12:357:19 | ... => ... | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:357:18:357:19 | c1 | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:357:21:357:36 | then ... | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:357:26:357:27 | c1 | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:357:26:357:36 | call to instance | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:361:1:361:2 | c1 | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:361:1:361:11 | ... = ... | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:361:6:361:7 | C1 | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:361:6:361:11 | call to new | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:362:1:362:2 | c1 | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:362:1:362:11 | call to instance | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:363:1:363:25 | call to pattern_dispatch | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:363:1:363:25 | self | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:363:18:363:25 | ( ... ) | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:363:19:363:20 | C1 | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:363:19:363:24 | call to new | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:364:1:364:25 | call to pattern_dispatch | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:364:1:364:25 | self | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:364:18:364:25 | ( ... ) | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:364:19:364:20 | C2 | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:364:19:364:24 | call to new | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:365:1:365:25 | call to pattern_dispatch | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:365:1:365:25 | self | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:365:18:365:25 | ( ... ) | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:365:19:365:20 | C3 | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:365:19:365:24 | call to new | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:367:1:371:3 | add_singleton | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:367:19:367:19 | x | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:367:19:367:19 | x | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:368:5:370:7 | instance | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:368:9:368:9 | x | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:369:9:369:28 | call to puts | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:369:9:369:28 | self | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:369:14:369:28 | "instance_on x" | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:369:15:369:27 | instance_on x | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:373:1:373:2 | c3 | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:373:1:373:11 | ... = ... | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:373:6:373:7 | C1 | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:373:6:373:11 | call to new | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:374:1:374:16 | call to add_singleton | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:374:1:374:16 | self | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:374:15:374:16 | c3 | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:375:1:375:2 | c3 | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:375:1:375:11 | call to instance | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:377:1:405:3 | SingletonOverride1 | calls.rb:1:1:632:1 | calls.rb | +| calls.rb:343:1:359:3 | pattern_dispatch | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:343:22:343:22 | x | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:343:22:343:22 | x | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:344:5:352:7 | case ... | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:344:10:344:10 | x | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:345:5:346:18 | when ... | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:345:10:345:11 | C3 | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:345:12:346:18 | then ... | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:346:9:346:9 | x | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:346:9:346:18 | call to instance | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:347:5:348:18 | when ... | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:347:10:347:11 | C2 | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:347:12:348:18 | then ... | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:348:9:348:9 | x | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:348:9:348:18 | call to instance | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:349:5:350:18 | when ... | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:349:10:349:11 | C1 | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:349:12:350:18 | then ... | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:350:9:350:9 | x | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:350:9:350:18 | call to instance | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:351:5:351:8 | else ... | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:354:5:358:7 | case ... | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:354:10:354:10 | x | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:355:9:355:29 | in ... then ... | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:355:12:355:13 | C3 | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:355:15:355:29 | then ... | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:355:20:355:20 | x | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:355:20:355:29 | call to instance | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:356:9:356:36 | in ... then ... | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:356:12:356:13 | C2 | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:356:12:356:19 | ... => ... | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:356:18:356:19 | c2 | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:356:21:356:36 | then ... | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:356:26:356:27 | c2 | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:356:26:356:36 | call to instance | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:357:9:357:36 | in ... then ... | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:357:12:357:13 | C1 | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:357:12:357:19 | ... => ... | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:357:18:357:19 | c1 | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:357:21:357:36 | then ... | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:357:26:357:27 | c1 | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:357:26:357:36 | call to instance | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:361:1:361:2 | c1 | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:361:1:361:11 | ... = ... | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:361:6:361:7 | C1 | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:361:6:361:11 | call to new | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:362:1:362:2 | c1 | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:362:1:362:11 | call to instance | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:363:1:363:25 | call to pattern_dispatch | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:363:1:363:25 | self | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:363:18:363:25 | ( ... ) | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:363:19:363:20 | C1 | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:363:19:363:24 | call to new | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:364:1:364:25 | call to pattern_dispatch | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:364:1:364:25 | self | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:364:18:364:25 | ( ... ) | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:364:19:364:20 | C2 | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:364:19:364:24 | call to new | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:365:1:365:25 | call to pattern_dispatch | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:365:1:365:25 | self | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:365:18:365:25 | ( ... ) | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:365:19:365:20 | C3 | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:365:19:365:24 | call to new | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:367:1:371:3 | add_singleton | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:367:19:367:19 | x | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:367:19:367:19 | x | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:368:5:370:7 | instance | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:368:9:368:9 | x | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:369:9:369:28 | call to puts | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:369:9:369:28 | self | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:369:14:369:28 | "instance_on x" | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:369:15:369:27 | instance_on x | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:373:1:373:2 | c3 | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:373:1:373:11 | ... = ... | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:373:6:373:7 | C1 | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:373:6:373:11 | call to new | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:374:1:374:16 | call to add_singleton | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:374:1:374:16 | self | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:374:15:374:16 | c3 | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:375:1:375:2 | c3 | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:375:1:375:11 | call to instance | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:377:1:405:3 | SingletonOverride1 | calls.rb:1:1:651:24 | calls.rb | | calls.rb:378:5:390:7 | class << ... | calls.rb:377:1:405:3 | SingletonOverride1 | | calls.rb:378:14:378:17 | self | calls.rb:377:1:405:3 | SingletonOverride1 | | calls.rb:379:9:381:11 | singleton1 | calls.rb:378:5:390:7 | class << ... | @@ -1166,16 +1177,16 @@ enclosingModule | calls.rb:403:9:403:43 | self | calls.rb:377:1:405:3 | SingletonOverride1 | | calls.rb:403:14:403:43 | "SingletonOverride1#instance1" | calls.rb:377:1:405:3 | SingletonOverride1 | | calls.rb:403:15:403:42 | SingletonOverride1#instance1 | calls.rb:377:1:405:3 | SingletonOverride1 | -| calls.rb:407:1:407:18 | SingletonOverride1 | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:407:1:407:29 | call to singleton1 | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:408:1:408:18 | SingletonOverride1 | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:408:1:408:29 | call to singleton2 | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:409:1:409:18 | SingletonOverride1 | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:409:1:409:34 | call to call_singleton1 | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:410:1:410:18 | SingletonOverride1 | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:410:1:410:34 | call to call_singleton2 | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:412:1:426:3 | SingletonOverride2 | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:412:28:412:45 | SingletonOverride1 | calls.rb:1:1:632:1 | calls.rb | +| calls.rb:407:1:407:18 | SingletonOverride1 | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:407:1:407:29 | call to singleton1 | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:408:1:408:18 | SingletonOverride1 | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:408:1:408:29 | call to singleton2 | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:409:1:409:18 | SingletonOverride1 | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:409:1:409:34 | call to call_singleton1 | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:410:1:410:18 | SingletonOverride1 | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:410:1:410:34 | call to call_singleton2 | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:412:1:426:3 | SingletonOverride2 | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:412:28:412:45 | SingletonOverride1 | calls.rb:1:1:651:24 | calls.rb | | calls.rb:413:5:417:7 | class << ... | calls.rb:412:1:426:3 | SingletonOverride2 | | calls.rb:413:14:413:17 | self | calls.rb:412:1:426:3 | SingletonOverride2 | | calls.rb:414:9:416:11 | singleton1 | calls.rb:413:5:417:7 | class << ... | @@ -1194,15 +1205,15 @@ enclosingModule | calls.rb:424:9:424:43 | self | calls.rb:412:1:426:3 | SingletonOverride2 | | calls.rb:424:14:424:43 | "SingletonOverride2#instance1" | calls.rb:412:1:426:3 | SingletonOverride2 | | calls.rb:424:15:424:42 | SingletonOverride2#instance1 | calls.rb:412:1:426:3 | SingletonOverride2 | -| calls.rb:428:1:428:18 | SingletonOverride2 | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:428:1:428:29 | call to singleton1 | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:429:1:429:18 | SingletonOverride2 | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:429:1:429:29 | call to singleton2 | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:430:1:430:18 | SingletonOverride2 | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:430:1:430:34 | call to call_singleton1 | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:431:1:431:18 | SingletonOverride2 | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:431:1:431:34 | call to call_singleton2 | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:433:1:461:3 | ConditionalInstanceMethods | calls.rb:1:1:632:1 | calls.rb | +| calls.rb:428:1:428:18 | SingletonOverride2 | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:428:1:428:29 | call to singleton1 | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:429:1:429:18 | SingletonOverride2 | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:429:1:429:29 | call to singleton2 | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:430:1:430:18 | SingletonOverride2 | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:430:1:430:34 | call to call_singleton1 | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:431:1:431:18 | SingletonOverride2 | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:431:1:431:34 | call to call_singleton2 | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:433:1:461:3 | ConditionalInstanceMethods | calls.rb:1:1:651:24 | calls.rb | | calls.rb:434:5:438:7 | if ... | calls.rb:433:1:461:3 | ConditionalInstanceMethods | | calls.rb:434:8:434:13 | call to rand | calls.rb:433:1:461:3 | ConditionalInstanceMethods | | calls.rb:434:8:434:13 | self | calls.rb:433:1:461:3 | ConditionalInstanceMethods | @@ -1247,91 +1258,91 @@ enclosingModule | calls.rb:457:17:457:40 | self | calls.rb:433:1:461:3 | ConditionalInstanceMethods | | calls.rb:457:22:457:40 | "AnonymousClass#m5" | calls.rb:433:1:461:3 | ConditionalInstanceMethods | | calls.rb:457:23:457:39 | AnonymousClass#m5 | calls.rb:433:1:461:3 | ConditionalInstanceMethods | -| calls.rb:463:1:463:26 | ConditionalInstanceMethods | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:463:1:463:30 | call to new | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:463:1:463:33 | call to m1 | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:464:1:464:26 | ConditionalInstanceMethods | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:464:1:464:30 | call to new | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:464:1:464:33 | call to m3 | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:465:1:465:26 | ConditionalInstanceMethods | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:465:1:465:30 | call to new | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:465:1:465:33 | call to m2 | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:466:1:466:26 | ConditionalInstanceMethods | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:466:1:466:30 | call to new | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:466:1:466:33 | call to m3 | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:467:1:467:26 | ConditionalInstanceMethods | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:467:1:467:30 | call to new | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:467:1:467:33 | call to m4 | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:468:1:468:26 | ConditionalInstanceMethods | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:468:1:468:30 | call to new | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:468:1:468:33 | call to m5 | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:470:1:470:23 | EsotericInstanceMethods | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:470:1:488:3 | ... = ... | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:470:27:470:31 | Class | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:470:27:488:3 | call to new | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:470:37:488:3 | do ... end | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:471:5:471:11 | Array | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:471:5:471:11 | [...] | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:471:5:471:11 | call to [] | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:471:5:475:7 | call to each | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:471:6:471:6 | 0 | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:471:8:471:8 | 1 | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:471:10:471:10 | 2 | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:471:18:475:7 | do ... end | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:472:9:474:11 | foo | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:473:13:473:22 | call to puts | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:473:13:473:22 | self | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:473:18:473:22 | "foo" | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:473:19:473:21 | foo | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:477:5:477:9 | Class | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:477:5:481:7 | call to new | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:477:5:481:11 | call to new | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:477:5:481:15 | call to bar | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:477:15:481:7 | do ... end | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:478:9:480:11 | bar | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:479:13:479:22 | call to puts | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:479:13:479:22 | self | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:479:18:479:22 | "bar" | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:479:19:479:21 | bar | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:483:5:483:11 | Array | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:483:5:483:11 | [...] | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:483:5:483:11 | call to [] | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:483:5:487:7 | call to each | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:483:6:483:6 | 0 | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:483:8:483:8 | 1 | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:483:10:483:10 | 2 | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:483:18:487:7 | do ... end | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:483:22:483:22 | i | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:483:22:483:22 | i | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:484:9:486:11 | call to define_method | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:484:9:486:11 | self | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:484:23:484:32 | "baz_#{...}" | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:484:24:484:27 | baz_ | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:484:28:484:31 | #{...} | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:484:30:484:30 | i | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:484:35:486:11 | do ... end | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:485:13:485:27 | call to puts | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:485:13:485:27 | self | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:485:18:485:27 | "baz_#{...}" | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:485:19:485:22 | baz_ | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:485:23:485:26 | #{...} | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:485:25:485:25 | i | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:490:1:490:23 | EsotericInstanceMethods | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:490:1:490:27 | call to new | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:490:1:490:31 | call to foo | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:491:1:491:23 | EsotericInstanceMethods | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:491:1:491:27 | call to new | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:491:1:491:31 | call to bar | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:492:1:492:23 | EsotericInstanceMethods | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:492:1:492:27 | call to new | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:492:1:492:33 | call to baz_0 | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:493:1:493:23 | EsotericInstanceMethods | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:493:1:493:27 | call to new | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:493:1:493:33 | call to baz_1 | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:494:1:494:23 | EsotericInstanceMethods | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:494:1:494:27 | call to new | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:494:1:494:33 | call to baz_2 | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:496:1:502:3 | ExtendSingletonMethod | calls.rb:1:1:632:1 | calls.rb | +| calls.rb:463:1:463:26 | ConditionalInstanceMethods | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:463:1:463:30 | call to new | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:463:1:463:33 | call to m1 | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:464:1:464:26 | ConditionalInstanceMethods | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:464:1:464:30 | call to new | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:464:1:464:33 | call to m3 | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:465:1:465:26 | ConditionalInstanceMethods | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:465:1:465:30 | call to new | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:465:1:465:33 | call to m2 | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:466:1:466:26 | ConditionalInstanceMethods | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:466:1:466:30 | call to new | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:466:1:466:33 | call to m3 | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:467:1:467:26 | ConditionalInstanceMethods | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:467:1:467:30 | call to new | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:467:1:467:33 | call to m4 | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:468:1:468:26 | ConditionalInstanceMethods | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:468:1:468:30 | call to new | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:468:1:468:33 | call to m5 | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:470:1:470:23 | EsotericInstanceMethods | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:470:1:488:3 | ... = ... | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:470:27:470:31 | Class | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:470:27:488:3 | call to new | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:470:37:488:3 | do ... end | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:471:5:471:11 | Array | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:471:5:471:11 | [...] | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:471:5:471:11 | call to [] | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:471:5:475:7 | call to each | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:471:6:471:6 | 0 | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:471:8:471:8 | 1 | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:471:10:471:10 | 2 | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:471:18:475:7 | do ... end | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:472:9:474:11 | foo | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:473:13:473:22 | call to puts | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:473:13:473:22 | self | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:473:18:473:22 | "foo" | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:473:19:473:21 | foo | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:477:5:477:9 | Class | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:477:5:481:7 | call to new | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:477:5:481:11 | call to new | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:477:5:481:15 | call to bar | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:477:15:481:7 | do ... end | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:478:9:480:11 | bar | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:479:13:479:22 | call to puts | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:479:13:479:22 | self | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:479:18:479:22 | "bar" | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:479:19:479:21 | bar | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:483:5:483:11 | Array | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:483:5:483:11 | [...] | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:483:5:483:11 | call to [] | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:483:5:487:7 | call to each | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:483:6:483:6 | 0 | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:483:8:483:8 | 1 | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:483:10:483:10 | 2 | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:483:18:487:7 | do ... end | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:483:22:483:22 | i | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:483:22:483:22 | i | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:484:9:486:11 | call to define_method | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:484:9:486:11 | self | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:484:23:484:32 | "baz_#{...}" | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:484:24:484:27 | baz_ | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:484:28:484:31 | #{...} | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:484:30:484:30 | i | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:484:35:486:11 | do ... end | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:485:13:485:27 | call to puts | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:485:13:485:27 | self | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:485:18:485:27 | "baz_#{...}" | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:485:19:485:22 | baz_ | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:485:23:485:26 | #{...} | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:485:25:485:25 | i | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:490:1:490:23 | EsotericInstanceMethods | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:490:1:490:27 | call to new | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:490:1:490:31 | call to foo | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:491:1:491:23 | EsotericInstanceMethods | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:491:1:491:27 | call to new | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:491:1:491:31 | call to bar | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:492:1:492:23 | EsotericInstanceMethods | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:492:1:492:27 | call to new | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:492:1:492:33 | call to baz_0 | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:493:1:493:23 | EsotericInstanceMethods | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:493:1:493:27 | call to new | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:493:1:493:33 | call to baz_1 | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:494:1:494:23 | EsotericInstanceMethods | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:494:1:494:27 | call to new | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:494:1:494:33 | call to baz_2 | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:496:1:502:3 | ExtendSingletonMethod | calls.rb:1:1:651:24 | calls.rb | | calls.rb:497:5:499:7 | singleton | calls.rb:496:1:502:3 | ExtendSingletonMethod | | calls.rb:498:9:498:46 | call to puts | calls.rb:496:1:502:3 | ExtendSingletonMethod | | calls.rb:498:9:498:46 | self | calls.rb:496:1:502:3 | ExtendSingletonMethod | @@ -1340,32 +1351,32 @@ enclosingModule | calls.rb:501:5:501:15 | call to extend | calls.rb:496:1:502:3 | ExtendSingletonMethod | | calls.rb:501:5:501:15 | self | calls.rb:496:1:502:3 | ExtendSingletonMethod | | calls.rb:501:12:501:15 | self | calls.rb:496:1:502:3 | ExtendSingletonMethod | -| calls.rb:504:1:504:21 | ExtendSingletonMethod | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:504:1:504:31 | call to singleton | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:506:1:508:3 | ExtendSingletonMethod2 | calls.rb:1:1:632:1 | calls.rb | +| calls.rb:504:1:504:21 | ExtendSingletonMethod | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:504:1:504:31 | call to singleton | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:506:1:508:3 | ExtendSingletonMethod2 | calls.rb:1:1:651:24 | calls.rb | | calls.rb:507:5:507:32 | call to extend | calls.rb:506:1:508:3 | ExtendSingletonMethod2 | | calls.rb:507:5:507:32 | self | calls.rb:506:1:508:3 | ExtendSingletonMethod2 | | calls.rb:507:12:507:32 | ExtendSingletonMethod | calls.rb:506:1:508:3 | ExtendSingletonMethod2 | -| calls.rb:510:1:510:22 | ExtendSingletonMethod2 | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:510:1:510:32 | call to singleton | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:512:1:513:3 | ExtendSingletonMethod3 | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:515:1:515:22 | ExtendSingletonMethod3 | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:515:1:515:51 | call to extend | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:515:31:515:51 | ExtendSingletonMethod | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:517:1:517:22 | ExtendSingletonMethod3 | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:517:1:517:32 | call to singleton | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:519:1:519:3 | foo | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:519:1:519:13 | ... = ... | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:519:7:519:13 | "hello" | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:519:8:519:12 | hello | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:520:1:520:3 | foo | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:520:1:520:13 | call to singleton | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:521:1:521:3 | foo | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:521:1:521:32 | call to extend | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:521:12:521:32 | ExtendSingletonMethod | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:523:1:523:3 | foo | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:523:1:523:13 | call to singleton | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:525:1:529:3 | ProtectedMethodInModule | calls.rb:1:1:632:1 | calls.rb | +| calls.rb:510:1:510:22 | ExtendSingletonMethod2 | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:510:1:510:32 | call to singleton | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:512:1:513:3 | ExtendSingletonMethod3 | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:515:1:515:22 | ExtendSingletonMethod3 | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:515:1:515:51 | call to extend | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:515:31:515:51 | ExtendSingletonMethod | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:517:1:517:22 | ExtendSingletonMethod3 | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:517:1:517:32 | call to singleton | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:519:1:519:3 | foo | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:519:1:519:13 | ... = ... | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:519:7:519:13 | "hello" | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:519:8:519:12 | hello | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:520:1:520:3 | foo | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:520:1:520:13 | call to singleton | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:521:1:521:3 | foo | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:521:1:521:32 | call to extend | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:521:12:521:32 | ExtendSingletonMethod | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:523:1:523:3 | foo | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:523:1:523:13 | call to singleton | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:525:1:529:3 | ProtectedMethodInModule | calls.rb:1:1:651:24 | calls.rb | | calls.rb:526:5:528:7 | call to protected | calls.rb:525:1:529:3 | ProtectedMethodInModule | | calls.rb:526:5:528:7 | self | calls.rb:525:1:529:3 | ProtectedMethodInModule | | calls.rb:526:15:528:7 | foo | calls.rb:525:1:529:3 | ProtectedMethodInModule | @@ -1373,7 +1384,7 @@ enclosingModule | calls.rb:527:9:527:42 | self | calls.rb:525:1:529:3 | ProtectedMethodInModule | | calls.rb:527:14:527:42 | "ProtectedMethodInModule#foo" | calls.rb:525:1:529:3 | ProtectedMethodInModule | | calls.rb:527:15:527:41 | ProtectedMethodInModule#foo | calls.rb:525:1:529:3 | ProtectedMethodInModule | -| calls.rb:531:1:544:3 | ProtectedMethods | calls.rb:1:1:632:1 | calls.rb | +| calls.rb:531:1:544:3 | ProtectedMethods | calls.rb:1:1:651:24 | calls.rb | | calls.rb:532:5:532:35 | call to include | calls.rb:531:1:544:3 | ProtectedMethods | | calls.rb:532:5:532:35 | self | calls.rb:531:1:544:3 | ProtectedMethods | | calls.rb:532:13:532:35 | ProtectedMethodInModule | calls.rb:531:1:544:3 | ProtectedMethods | @@ -1395,63 +1406,63 @@ enclosingModule | calls.rb:542:9:542:24 | ProtectedMethods | calls.rb:531:1:544:3 | ProtectedMethods | | calls.rb:542:9:542:28 | call to new | calls.rb:531:1:544:3 | ProtectedMethods | | calls.rb:542:9:542:32 | call to bar | calls.rb:531:1:544:3 | ProtectedMethods | -| calls.rb:546:1:546:16 | ProtectedMethods | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:546:1:546:20 | call to new | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:546:1:546:24 | call to foo | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:547:1:547:16 | ProtectedMethods | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:547:1:547:20 | call to new | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:547:1:547:24 | call to bar | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:548:1:548:16 | ProtectedMethods | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:548:1:548:20 | call to new | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:548:1:548:24 | call to baz | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:550:1:555:3 | ProtectedMethodsSub | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:550:29:550:44 | ProtectedMethods | calls.rb:1:1:632:1 | calls.rb | +| calls.rb:546:1:546:16 | ProtectedMethods | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:546:1:546:20 | call to new | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:546:1:546:24 | call to foo | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:547:1:547:16 | ProtectedMethods | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:547:1:547:20 | call to new | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:547:1:547:24 | call to bar | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:548:1:548:16 | ProtectedMethods | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:548:1:548:20 | call to new | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:548:1:548:24 | call to baz | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:550:1:555:3 | ProtectedMethodsSub | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:550:29:550:44 | ProtectedMethods | calls.rb:1:1:651:24 | calls.rb | | calls.rb:551:5:554:7 | baz | calls.rb:550:1:555:3 | ProtectedMethodsSub | | calls.rb:552:9:552:11 | call to foo | calls.rb:550:1:555:3 | ProtectedMethodsSub | | calls.rb:552:9:552:11 | self | calls.rb:550:1:555:3 | ProtectedMethodsSub | | calls.rb:553:9:553:27 | ProtectedMethodsSub | calls.rb:550:1:555:3 | ProtectedMethodsSub | | calls.rb:553:9:553:31 | call to new | calls.rb:550:1:555:3 | ProtectedMethodsSub | | calls.rb:553:9:553:35 | call to foo | calls.rb:550:1:555:3 | ProtectedMethodsSub | -| calls.rb:557:1:557:19 | ProtectedMethodsSub | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:557:1:557:23 | call to new | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:557:1:557:27 | call to foo | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:558:1:558:19 | ProtectedMethodsSub | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:558:1:558:23 | call to new | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:558:1:558:27 | call to bar | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:559:1:559:19 | ProtectedMethodsSub | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:559:1:559:23 | call to new | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:559:1:559:27 | call to baz | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:561:1:561:7 | Array | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:561:1:561:7 | [...] | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:561:1:561:7 | call to [] | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:561:1:561:26 | call to each | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:561:2:561:2 | C | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:561:2:561:6 | call to new | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:561:14:561:26 | { ... } | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:561:17:561:17 | c | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:561:17:561:17 | c | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:561:20:561:20 | c | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:561:20:561:24 | call to baz | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:562:1:562:13 | Array | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:562:1:562:13 | [...] | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:562:1:562:13 | call to [] | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:562:1:562:39 | call to each | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:562:2:562:4 | "a" | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:562:3:562:3 | a | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:562:6:562:8 | "b" | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:562:7:562:7 | b | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:562:10:562:12 | "c" | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:562:11:562:11 | c | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:562:20:562:39 | { ... } | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:562:23:562:23 | s | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:562:23:562:23 | s | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:562:26:562:26 | s | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:562:26:562:37 | call to capitalize | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:564:1:567:3 | SingletonUpCall_Base | calls.rb:1:1:632:1 | calls.rb | +| calls.rb:557:1:557:19 | ProtectedMethodsSub | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:557:1:557:23 | call to new | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:557:1:557:27 | call to foo | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:558:1:558:19 | ProtectedMethodsSub | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:558:1:558:23 | call to new | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:558:1:558:27 | call to bar | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:559:1:559:19 | ProtectedMethodsSub | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:559:1:559:23 | call to new | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:559:1:559:27 | call to baz | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:561:1:561:7 | Array | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:561:1:561:7 | [...] | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:561:1:561:7 | call to [] | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:561:1:561:26 | call to each | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:561:2:561:2 | C | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:561:2:561:6 | call to new | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:561:14:561:26 | { ... } | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:561:17:561:17 | c | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:561:17:561:17 | c | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:561:20:561:20 | c | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:561:20:561:24 | call to baz | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:562:1:562:13 | Array | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:562:1:562:13 | [...] | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:562:1:562:13 | call to [] | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:562:1:562:39 | call to each | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:562:2:562:4 | "a" | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:562:3:562:3 | a | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:562:6:562:8 | "b" | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:562:7:562:7 | b | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:562:10:562:12 | "c" | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:562:11:562:11 | c | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:562:20:562:39 | { ... } | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:562:23:562:23 | s | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:562:23:562:23 | s | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:562:26:562:26 | s | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:562:26:562:37 | call to capitalize | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:564:1:567:3 | SingletonUpCall_Base | calls.rb:1:1:651:24 | calls.rb | | calls.rb:565:5:566:7 | singleton | calls.rb:564:1:567:3 | SingletonUpCall_Base | | calls.rb:565:9:565:12 | self | calls.rb:564:1:567:3 | SingletonUpCall_Base | -| calls.rb:568:1:575:3 | SingletonUpCall_Sub | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:568:29:568:48 | SingletonUpCall_Base | calls.rb:1:1:632:1 | calls.rb | +| calls.rb:568:1:575:3 | SingletonUpCall_Sub | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:568:29:568:48 | SingletonUpCall_Base | calls.rb:1:1:651:24 | calls.rb | | calls.rb:569:5:569:13 | call to singleton | calls.rb:568:1:575:3 | SingletonUpCall_Sub | | calls.rb:569:5:569:13 | self | calls.rb:568:1:575:3 | SingletonUpCall_Sub | | calls.rb:570:5:570:14 | call to singleton2 | calls.rb:568:1:575:3 | SingletonUpCall_Sub | @@ -1462,13 +1473,13 @@ enclosingModule | calls.rb:572:9:572:17 | self | calls.rb:568:1:575:3 | SingletonUpCall_Sub | | calls.rb:573:9:573:18 | call to singleton2 | calls.rb:568:1:575:3 | SingletonUpCall_Sub | | calls.rb:573:9:573:18 | self | calls.rb:568:1:575:3 | SingletonUpCall_Sub | -| calls.rb:576:1:581:3 | SingletonUpCall_SubSub | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:576:32:576:50 | SingletonUpCall_Sub | calls.rb:1:1:632:1 | calls.rb | +| calls.rb:576:1:581:3 | SingletonUpCall_SubSub | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:576:32:576:50 | SingletonUpCall_Sub | calls.rb:1:1:651:24 | calls.rb | | calls.rb:577:5:578:7 | singleton2 | calls.rb:576:1:581:3 | SingletonUpCall_SubSub | | calls.rb:577:9:577:12 | self | calls.rb:576:1:581:3 | SingletonUpCall_SubSub | | calls.rb:580:5:580:14 | call to mid_method | calls.rb:576:1:581:3 | SingletonUpCall_SubSub | | calls.rb:580:5:580:14 | self | calls.rb:576:1:581:3 | SingletonUpCall_SubSub | -| calls.rb:583:1:594:3 | SingletonA | calls.rb:1:1:632:1 | calls.rb | +| calls.rb:583:1:594:3 | SingletonA | calls.rb:1:1:651:24 | calls.rb | | calls.rb:584:5:585:7 | singleton1 | calls.rb:583:1:594:3 | SingletonA | | calls.rb:584:9:584:12 | self | calls.rb:583:1:594:3 | SingletonA | | calls.rb:587:5:589:7 | call_singleton1 | calls.rb:583:1:594:3 | SingletonA | @@ -1479,39 +1490,60 @@ enclosingModule | calls.rb:591:9:591:12 | self | calls.rb:583:1:594:3 | SingletonA | | calls.rb:592:9:592:23 | call to call_singleton1 | calls.rb:583:1:594:3 | SingletonA | | calls.rb:592:9:592:23 | self | calls.rb:583:1:594:3 | SingletonA | -| calls.rb:596:1:603:3 | SingletonB | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:596:20:596:29 | SingletonA | calls.rb:1:1:632:1 | calls.rb | +| calls.rb:596:1:603:3 | SingletonB | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:596:20:596:29 | SingletonA | calls.rb:1:1:651:24 | calls.rb | | calls.rb:597:5:598:7 | singleton1 | calls.rb:596:1:603:3 | SingletonB | | calls.rb:597:9:597:12 | self | calls.rb:596:1:603:3 | SingletonB | | calls.rb:600:5:602:7 | call_singleton1 | calls.rb:596:1:603:3 | SingletonB | | calls.rb:600:9:600:12 | self | calls.rb:596:1:603:3 | SingletonB | | calls.rb:601:9:601:18 | call to singleton1 | calls.rb:596:1:603:3 | SingletonB | | calls.rb:601:9:601:18 | self | calls.rb:596:1:603:3 | SingletonB | -| calls.rb:605:1:612:3 | SingletonC | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:605:20:605:29 | SingletonA | calls.rb:1:1:632:1 | calls.rb | +| calls.rb:605:1:612:3 | SingletonC | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:605:20:605:29 | SingletonA | calls.rb:1:1:651:24 | calls.rb | | calls.rb:606:5:607:7 | singleton1 | calls.rb:605:1:612:3 | SingletonC | | calls.rb:606:9:606:12 | self | calls.rb:605:1:612:3 | SingletonC | | calls.rb:609:5:611:7 | call_singleton1 | calls.rb:605:1:612:3 | SingletonC | | calls.rb:609:9:609:12 | self | calls.rb:605:1:612:3 | SingletonC | | calls.rb:610:9:610:18 | call to singleton1 | calls.rb:605:1:612:3 | SingletonC | | calls.rb:610:9:610:18 | self | calls.rb:605:1:612:3 | SingletonC | -| calls.rb:614:1:614:10 | SingletonA | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:614:1:614:31 | call to call_call_singleton1 | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:615:1:615:10 | SingletonB | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:615:1:615:31 | call to call_call_singleton1 | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:616:1:616:10 | SingletonC | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:616:1:616:31 | call to call_call_singleton1 | calls.rb:1:1:632:1 | calls.rb | -| calls.rb:618:1:624:3 | Included | calls.rb:1:1:632:1 | calls.rb | +| calls.rb:614:1:614:10 | SingletonA | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:614:1:614:31 | call to call_call_singleton1 | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:615:1:615:10 | SingletonB | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:615:1:615:31 | call to call_call_singleton1 | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:616:1:616:10 | SingletonC | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:616:1:616:31 | call to call_call_singleton1 | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:618:1:624:3 | Included | calls.rb:1:1:651:24 | calls.rb | | calls.rb:619:5:621:7 | foo | calls.rb:618:1:624:3 | Included | | calls.rb:620:9:620:12 | self | calls.rb:618:1:624:3 | Included | | calls.rb:620:9:620:16 | call to bar | calls.rb:618:1:624:3 | Included | | calls.rb:622:5:623:7 | bar | calls.rb:618:1:624:3 | Included | -| calls.rb:626:1:631:3 | IncludesIncluded | calls.rb:1:1:632:1 | calls.rb | +| calls.rb:626:1:631:3 | IncludesIncluded | calls.rb:1:1:651:24 | calls.rb | | calls.rb:627:5:627:20 | call to include | calls.rb:626:1:631:3 | IncludesIncluded | | calls.rb:627:5:627:20 | self | calls.rb:626:1:631:3 | IncludesIncluded | | calls.rb:627:13:627:20 | Included | calls.rb:626:1:631:3 | IncludesIncluded | | calls.rb:628:5:630:7 | bar | calls.rb:626:1:631:3 | IncludesIncluded | | calls.rb:629:9:629:13 | call to super | calls.rb:626:1:631:3 | IncludesIncluded | +| calls.rb:633:1:637:3 | CustomNew1 | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:634:5:636:7 | new | calls.rb:633:1:637:3 | CustomNew1 | +| calls.rb:634:9:634:12 | self | calls.rb:633:1:637:3 | CustomNew1 | +| calls.rb:635:9:635:10 | C1 | calls.rb:633:1:637:3 | CustomNew1 | +| calls.rb:635:9:635:14 | call to new | calls.rb:633:1:637:3 | CustomNew1 | +| calls.rb:639:1:639:10 | CustomNew1 | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:639:1:639:14 | call to new | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:639:1:639:23 | call to instance | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:641:1:649:3 | CustomNew2 | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:642:5:644:7 | new | calls.rb:641:1:649:3 | CustomNew2 | +| calls.rb:642:9:642:12 | self | calls.rb:641:1:649:3 | CustomNew2 | +| calls.rb:643:9:643:12 | self | calls.rb:641:1:649:3 | CustomNew2 | +| calls.rb:643:9:643:21 | call to allocate | calls.rb:641:1:649:3 | CustomNew2 | +| calls.rb:646:5:648:7 | instance | calls.rb:641:1:649:3 | CustomNew2 | +| calls.rb:647:9:647:34 | call to puts | calls.rb:641:1:649:3 | CustomNew2 | +| calls.rb:647:9:647:34 | self | calls.rb:641:1:649:3 | CustomNew2 | +| calls.rb:647:14:647:34 | "CustomNew2#instance" | calls.rb:641:1:649:3 | CustomNew2 | +| calls.rb:647:15:647:33 | CustomNew2#instance | calls.rb:641:1:649:3 | CustomNew2 | +| calls.rb:651:1:651:10 | CustomNew2 | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:651:1:651:14 | call to new | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:651:1:651:23 | call to instance | calls.rb:1:1:651:24 | calls.rb | | hello.rb:1:1:8:3 | EnglishWords | hello.rb:1:1:22:3 | hello.rb | | hello.rb:2:5:4:7 | hello | hello.rb:1:1:8:3 | EnglishWords | | hello.rb:3:9:3:22 | return | hello.rb:1:1:8:3 | EnglishWords | diff --git a/ruby/ql/test/library-tests/modules/superclasses.expected b/ruby/ql/test/library-tests/modules/superclasses.expected index 58df295f95f..14121b1da31 100644 --- a/ruby/ql/test/library-tests/modules/superclasses.expected +++ b/ruby/ql/test/library-tests/modules/superclasses.expected @@ -136,6 +136,12 @@ calls.rb: # 626| IncludesIncluded #-----| -> Object +# 633| CustomNew1 +#-----| -> Object + +# 641| CustomNew2 +#-----| -> Object + hello.rb: # 1| EnglishWords diff --git a/ruby/ql/test/query-tests/analysis/Definitions.expected b/ruby/ql/test/query-tests/analysis/Definitions.expected index 47f0b049d08..bd04d6207af 100644 --- a/ruby/ql/test/query-tests/analysis/Definitions.expected +++ b/ruby/ql/test/query-tests/analysis/Definitions.expected @@ -12,3 +12,4 @@ | Definitions.rb:41:7:41:9 | @@b | Definitions.rb:27:5:27:7 | @@b | class variable | | Definitions.rb:46:1:46:1 | C | Definitions.rb:19:1:44:3 | C | constant | | Definitions.rb:46:1:46:4 | D | Definitions.rb:26:3:43:5 | D | constant | +| Definitions.rb:46:1:46:8 | call to new | Definitions.rb:29:5:33:7 | initialize | method | diff --git a/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowImpl.qll b/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowImpl.qll index 6741ccc2f06..1228d00b6ba 100644 --- a/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowImpl.qll +++ b/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowImpl.qll @@ -622,7 +622,11 @@ private predicate parameterFlowThroughAllowed(ParamNodeEx p, ReturnKindExt kind) } private module Stage1 implements StageSig { - class Ap = Unit; + class Ap extends int { + // workaround for bad functionality-induced joins (happens when using `Unit`) + pragma[nomagic] + Ap() { this in [0 .. 1] and this < 1 } + } private class Cc = boolean; @@ -1327,8 +1331,8 @@ private module MkStage { */ pragma[nomagic] additional predicate fwdFlow( - NodeEx node, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - Ap ap, ApApprox apa, Configuration config + NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, + ApApprox apa, Configuration config ) { fwdFlow0(node, state, cc, summaryCtx, argAp, ap, apa, config) and PrevStage::revFlow(node, state, apa, config) and @@ -1337,21 +1341,21 @@ private module MkStage { pragma[inline] additional predicate fwdFlow( - NodeEx node, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - Ap ap, Configuration config + NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, + Configuration config ) { fwdFlow(node, state, cc, summaryCtx, argAp, ap, _, config) } pragma[nomagic] private predicate fwdFlow0( - NodeEx node, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - Ap ap, ApApprox apa, Configuration config + NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, + ApApprox apa, Configuration config ) { sourceNode(node, state, config) and (if hasSourceCallCtx(config) then cc = ccSomeCall() else cc = ccNone()) and argAp = apNone() and - summaryCtx = TParameterPositionNone() and + summaryCtx = TParamNodeNone() and ap = getApNil(node) and apa = getApprox(ap) or @@ -1372,7 +1376,7 @@ private module MkStage { fwdFlow(mid, pragma[only_bind_into](state), _, _, _, ap, apa, pragma[only_bind_into](config)) and jumpStep(mid, node, config) and cc = ccNone() and - summaryCtx = TParameterPositionNone() and + summaryCtx = TParamNodeNone() and argAp = apNone() ) or @@ -1380,7 +1384,7 @@ private module MkStage { fwdFlow(mid, state, _, _, _, nil, pragma[only_bind_into](config)) and additionalJumpStep(mid, node, config) and cc = ccNone() and - summaryCtx = TParameterPositionNone() and + summaryCtx = TParamNodeNone() and argAp = apNone() and ap = getApNil(node) and apa = getApprox(ap) @@ -1390,7 +1394,7 @@ private module MkStage { fwdFlow(mid, state0, _, _, _, nil, pragma[only_bind_into](config)) and additionalJumpStateStep(mid, state0, node, state, config) and cc = ccNone() and - summaryCtx = TParameterPositionNone() and + summaryCtx = TParamNodeNone() and argAp = apNone() and ap = getApNil(node) and apa = getApprox(ap) @@ -1414,10 +1418,10 @@ private module MkStage { fwdFlowIn(_, node, state, _, cc, _, _, ap, apa, config) and if PrevStage::parameterMayFlowThrough(node, apa, config) then ( - summaryCtx = TParameterPositionSome(node.(ParamNodeEx).getPosition()) and + summaryCtx = TParamNodeSome(node.asNode()) and argAp = apSome(ap) ) else ( - summaryCtx = TParameterPositionNone() and argAp = apNone() + summaryCtx = TParamNodeNone() and argAp = apNone() ) or // flow out of a callable @@ -1433,16 +1437,19 @@ private module MkStage { ) or // flow through a callable - exists(DataFlowCall call, ParameterPosition summaryCtx0, Ap argAp0 | - fwdFlowOutFromArg(call, node, state, summaryCtx0, argAp0, ap, apa, config) and - fwdFlowIsEntered(call, cc, summaryCtx, argAp, summaryCtx0, argAp0, config) + exists( + DataFlowCall call, CcCall ccc, RetNodeEx ret, boolean allowsFieldFlow, ApApprox innerArgApa + | + fwdFlowThrough(call, cc, state, ccc, summaryCtx, argAp, ap, apa, ret, innerArgApa, config) and + flowThroughOutOfCall(call, ccc, ret, node, allowsFieldFlow, innerArgApa, apa, config) and + if allowsFieldFlow = false then ap instanceof ApNil else any() ) } pragma[nomagic] private predicate fwdFlowStore( NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, FlowState state, Cc cc, - ParameterPositionOption summaryCtx, ApOption argAp, Configuration config + ParamNodeOption summaryCtx, ApOption argAp, Configuration config ) { exists(DataFlowType contentType, ApApprox apa1 | fwdFlow(node1, state, cc, summaryCtx, argAp, ap1, apa1, config) and @@ -1473,8 +1480,8 @@ private module MkStage { pragma[nomagic] private predicate fwdFlowRead0( - NodeEx node1, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - ApNonNil ap, Configuration config + NodeEx node1, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, ApNonNil ap, + Configuration config ) { fwdFlow(node1, state, cc, summaryCtx, argAp, ap, config) and PrevStage::readStepCand(node1, _, _, config) @@ -1483,7 +1490,7 @@ private module MkStage { pragma[nomagic] private predicate fwdFlowRead( Ap ap, Content c, NodeEx node1, NodeEx node2, FlowState state, Cc cc, - ParameterPositionOption summaryCtx, ApOption argAp, Configuration config + ParamNodeOption summaryCtx, ApOption argAp, Configuration config ) { fwdFlowRead0(node1, state, cc, summaryCtx, argAp, ap, config) and PrevStage::readStepCand(node1, c, node2, config) and @@ -1493,7 +1500,7 @@ private module MkStage { pragma[nomagic] private predicate fwdFlowIn( DataFlowCall call, ParamNodeEx p, FlowState state, Cc outercc, CcCall innercc, - ParameterPositionOption summaryCtx, ApOption argAp, Ap ap, ApApprox apa, Configuration config + ParamNodeOption summaryCtx, ApOption argAp, Ap ap, ApApprox apa, Configuration config ) { exists(ArgNodeEx arg, boolean allowsFieldFlow | fwdFlow(arg, state, outercc, summaryCtx, argAp, ap, apa, config) and @@ -1505,64 +1512,38 @@ private module MkStage { pragma[nomagic] private predicate fwdFlowRetFromArg( - RetNodeEx ret, FlowState state, CcCall ccc, ParameterPosition summaryCtx, ParamNodeEx p, - Ap argAp, ApApprox argApa, Ap ap, ApApprox apa, Configuration config + RetNodeEx ret, FlowState state, CcCall ccc, ParamNodeEx summaryCtx, Ap argAp, ApApprox argApa, + Ap ap, ApApprox apa, Configuration config ) { - exists(DataFlowCallable c, ReturnKindExt kind | + exists(ReturnKindExt kind | fwdFlow(pragma[only_bind_into](ret), state, ccc, - TParameterPositionSome(pragma[only_bind_into](summaryCtx)), apSome(argAp), ap, apa, config) and - getApprox(argAp) = argApa and - c = ret.getEnclosingCallable() and + TParamNodeSome(pragma[only_bind_into](summaryCtx.asNode())), + pragma[only_bind_into](apSome(argAp)), ap, pragma[only_bind_into](apa), + pragma[only_bind_into](config)) and kind = ret.getKind() and - p.isParameterOf(c, pragma[only_bind_into](summaryCtx)) and - parameterFlowThroughAllowed(p, kind) + parameterFlowThroughAllowed(summaryCtx, kind) and + argApa = getApprox(argAp) and + PrevStage::returnMayFlowThrough(ret, argApa, apa, kind, pragma[only_bind_into](config)) ) } pragma[inline] - private predicate fwdFlowInMayFlowThrough( - DataFlowCall call, Cc cc, CcCall innerCc, ParameterPositionOption summaryCtx, ApOption argAp, - ParamNodeEx param, Ap ap, ApApprox apa, Configuration config + private predicate fwdFlowThrough0( + DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, + ApOption argAp, Ap ap, ApApprox apa, RetNodeEx ret, ParamNodeEx innerSummaryCtx, + Ap innerArgAp, ApApprox innerArgApa, Configuration config ) { - fwdFlowIn(call, pragma[only_bind_into](param), _, cc, innerCc, summaryCtx, argAp, ap, - pragma[only_bind_into](apa), pragma[only_bind_into](config)) and - PrevStage::parameterMayFlowThrough(param, apa, config) - } - - // dedup before joining with `flowThroughOutOfCall` - pragma[nomagic] - private predicate fwdFlowInMayFlowThroughProj( - DataFlowCall call, CcCall innerCc, ApApprox apa, Configuration config - ) { - fwdFlowInMayFlowThrough(call, _, innerCc, _, _, _, _, apa, config) - } - - /** - * Same as `flowThroughOutOfCall`, but restricted to calls that are reached - * in the flow covered by `fwdFlow`, where data might flow through the target - * callable and back out at `call`. - */ - pragma[nomagic] - private predicate fwdFlowThroughOutOfCall( - DataFlowCall call, CcCall ccc, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow, - ApApprox argApa, ApApprox apa, Configuration config - ) { - fwdFlowInMayFlowThroughProj(call, ccc, argApa, config) and - flowThroughOutOfCall(call, ccc, ret, out, allowsFieldFlow, argApa, apa, config) + fwdFlowRetFromArg(ret, state, ccc, innerSummaryCtx, innerArgAp, innerArgApa, ap, apa, config) and + fwdFlowIsEntered(call, cc, ccc, summaryCtx, argAp, innerSummaryCtx, innerArgAp, config) } pragma[nomagic] - private predicate fwdFlowOutFromArg( - DataFlowCall call, NodeEx out, FlowState state, ParameterPosition summaryCtx, Ap argAp, Ap ap, - ApApprox apa, Configuration config + private predicate fwdFlowThrough( + DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, + ApOption argAp, Ap ap, ApApprox apa, RetNodeEx ret, ApApprox innerArgApa, Configuration config ) { - exists(RetNodeEx ret, boolean allowsFieldFlow, CcCall ccc, ApApprox argApa | - fwdFlowRetFromArg(pragma[only_bind_into](ret), state, pragma[only_bind_into](ccc), - summaryCtx, _, argAp, pragma[only_bind_into](argApa), ap, pragma[only_bind_into](apa), - config) and - fwdFlowThroughOutOfCall(call, ccc, ret, out, allowsFieldFlow, argApa, apa, config) and - (if allowsFieldFlow = false then ap instanceof ApNil else any()) - ) + fwdFlowThrough0(call, cc, state, ccc, summaryCtx, argAp, ap, apa, ret, _, _, innerArgApa, + config) } /** @@ -1571,12 +1552,14 @@ private module MkStage { */ pragma[nomagic] private predicate fwdFlowIsEntered( - DataFlowCall call, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - ParameterPosition pos, Ap ap, Configuration config + DataFlowCall call, Cc cc, CcCall innerCc, ParamNodeOption summaryCtx, ApOption argAp, + ParamNodeEx p, Ap ap, Configuration config ) { - exists(ParamNodeEx param | - fwdFlowInMayFlowThrough(call, cc, _, summaryCtx, argAp, param, ap, _, config) and - pos = param.getPosition() + exists(ApApprox apa | + fwdFlowIn(call, pragma[only_bind_into](p), _, cc, innerCc, summaryCtx, argAp, ap, + pragma[only_bind_into](apa), pragma[only_bind_into](config)) and + PrevStage::parameterMayFlowThrough(p, apa, config) and + PrevStage::callMayFlowThroughRev(call, pragma[only_bind_into](config)) ) } @@ -1596,23 +1579,31 @@ private module MkStage { fwdFlowConsCand(ap1, c, ap2, config) } + pragma[nomagic] + private predicate returnFlowsThrough0( + DataFlowCall call, FlowState state, CcCall ccc, Ap ap, ApApprox apa, RetNodeEx ret, + ParamNodeEx innerSummaryCtx, Ap innerArgAp, ApApprox innerArgApa, Configuration config + ) { + fwdFlowThrough0(call, _, state, ccc, _, _, ap, apa, ret, innerSummaryCtx, innerArgAp, + innerArgApa, config) + } + pragma[nomagic] private predicate returnFlowsThrough( - RetNodeEx ret, ReturnKindExt kind, FlowState state, CcCall ccc, ParamNodeEx p, Ap argAp, + RetNodeEx ret, ReturnPosition pos, FlowState state, CcCall ccc, ParamNodeEx p, Ap argAp, Ap ap, Configuration config ) { - exists(boolean allowsFieldFlow, ApApprox argApa, ApApprox apa | - fwdFlowRetFromArg(pragma[only_bind_into](ret), state, pragma[only_bind_into](ccc), _, p, - argAp, pragma[only_bind_into](argApa), ap, pragma[only_bind_into](apa), config) and - kind = ret.getKind() and - fwdFlowThroughOutOfCall(_, ccc, ret, _, allowsFieldFlow, argApa, apa, config) and - (if allowsFieldFlow = false then ap instanceof ApNil else any()) + exists(DataFlowCall call, ApApprox apa, boolean allowsFieldFlow, ApApprox innerArgApa | + returnFlowsThrough0(call, state, ccc, ap, apa, ret, p, argAp, innerArgApa, config) and + flowThroughOutOfCall(call, ccc, ret, _, allowsFieldFlow, innerArgApa, apa, config) and + pos = ret.getReturnPosition() and + if allowsFieldFlow = false then ap instanceof ApNil else any() ) } pragma[nomagic] private predicate flowThroughIntoCall( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap argAp, + DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap argAp, Ap ap, Configuration config ) { exists(ApApprox argApa | @@ -1620,7 +1611,7 @@ private module MkStage { allowsFieldFlow, argApa, pragma[only_bind_into](config)) and fwdFlow(arg, _, _, _, _, pragma[only_bind_into](argAp), argApa, pragma[only_bind_into](config)) and - returnFlowsThrough(_, _, _, _, p, pragma[only_bind_into](argAp), _, + returnFlowsThrough(_, _, _, _, p, pragma[only_bind_into](argAp), ap, pragma[only_bind_into](config)) and if allowsFieldFlow = false then argAp instanceof ApNil else any() ) @@ -1639,12 +1630,13 @@ private module MkStage { pragma[nomagic] private predicate flowOutOfCallAp( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, boolean allowsFieldFlow, + DataFlowCall call, RetNodeEx ret, ReturnPosition pos, NodeEx out, boolean allowsFieldFlow, Ap ap, Configuration config ) { exists(ApApprox apa | - flowOutOfCallApa(call, ret, kind, out, allowsFieldFlow, apa, config) and - fwdFlow(ret, _, _, _, _, ap, apa, config) + flowOutOfCallApa(call, ret, _, out, allowsFieldFlow, apa, config) and + fwdFlow(ret, _, _, _, _, ap, apa, config) and + pos = ret.getReturnPosition() ) } @@ -1739,17 +1731,17 @@ private module MkStage { ) or // flow through a callable - exists(DataFlowCall call, ReturnKindExt returnKind0, Ap returnAp0 | - revFlowInToReturn(call, node, state, returnKind0, returnAp0, ap, config) and - revFlowIsReturned(call, returnCtx, returnAp, returnKind0, returnAp0, config) + exists(DataFlowCall call, ParamNodeEx p, ReturnPosition pos, Ap innerReturnAp | + revFlowThrough(call, returnCtx, p, state, pos, returnAp, ap, innerReturnAp, config) and + flowThroughIntoCall(call, node, p, _, ap, innerReturnAp, config) ) or // flow out of a callable - exists(ReturnKindExt kind | - revFlowOut(_, node, kind, state, _, _, ap, config) and - if returnFlowsThrough(node, kind, state, _, _, _, ap, config) + exists(ReturnPosition pos | + revFlowOut(_, node, pos, state, _, _, ap, config) and + if returnFlowsThrough(node, pos, state, _, _, _, ap, config) then ( - returnCtx = TReturnCtxMaybeFlowThrough(kind) and + returnCtx = TReturnCtxMaybeFlowThrough(pos) and returnAp = apSome(ap) ) else ( returnCtx = TReturnCtxNoFlowThrough() and returnAp = apNone() @@ -1782,47 +1774,33 @@ private module MkStage { pragma[nomagic] private predicate revFlowOut( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, FlowState state, ReturnCtx returnCtx, + DataFlowCall call, RetNodeEx ret, ReturnPosition pos, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap, Configuration config ) { exists(NodeEx out, boolean allowsFieldFlow | revFlow(out, state, returnCtx, returnAp, ap, config) and - flowOutOfCallAp(call, ret, kind, out, allowsFieldFlow, ap, config) and + flowOutOfCallAp(call, ret, pos, out, allowsFieldFlow, ap, config) and if allowsFieldFlow = false then ap instanceof ApNil else any() ) } - /** - * Same as `flowThroughIntoCall`, but restricted to calls that are reached - * in the flow covered by `revFlow`, where data might flow through the target - * callable and back out at `call`. - */ - pragma[nomagic] - private predicate revFlowThroughIntoCall( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap argAp, - Configuration config - ) { - flowThroughIntoCall(call, arg, p, allowsFieldFlow, argAp, config) and - revFlowIsReturned(call, _, _, _, _, config) - } - pragma[nomagic] private predicate revFlowParamToReturn( - ParamNodeEx p, FlowState state, ReturnKindExt kind, Ap returnAp, Ap ap, Configuration config + ParamNodeEx p, FlowState state, ReturnPosition pos, Ap returnAp, Ap ap, Configuration config ) { - revFlow(p, state, TReturnCtxMaybeFlowThrough(kind), apSome(returnAp), ap, config) and - parameterFlowThroughAllowed(p, kind) + revFlow(pragma[only_bind_into](p), state, TReturnCtxMaybeFlowThrough(pos), apSome(returnAp), + pragma[only_bind_into](ap), pragma[only_bind_into](config)) and + parameterFlowThroughAllowed(p, pos.getKind()) and + PrevStage::parameterMayFlowThrough(p, getApprox(ap), config) } pragma[nomagic] - private predicate revFlowInToReturn( - DataFlowCall call, ArgNodeEx arg, FlowState state, ReturnKindExt kind, Ap returnAp, Ap ap, - Configuration config + private predicate revFlowThrough( + DataFlowCall call, ReturnCtx returnCtx, ParamNodeEx p, FlowState state, ReturnPosition pos, + ApOption returnAp, Ap ap, Ap innerReturnAp, Configuration config ) { - exists(ParamNodeEx p, boolean allowsFieldFlow | - revFlowParamToReturn(p, state, kind, returnAp, ap, config) and - revFlowThroughIntoCall(call, arg, p, allowsFieldFlow, ap, config) - ) + revFlowParamToReturn(p, state, pos, innerReturnAp, ap, config) and + revFlowIsReturned(call, returnCtx, returnAp, pos, innerReturnAp, config) } /** @@ -1832,12 +1810,12 @@ private module MkStage { */ pragma[nomagic] private predicate revFlowIsReturned( - DataFlowCall call, ReturnCtx returnCtx, ApOption returnAp, ReturnKindExt kind, Ap ap, + DataFlowCall call, ReturnCtx returnCtx, ApOption returnAp, ReturnPosition pos, Ap ap, Configuration config ) { exists(RetNodeEx ret, FlowState state, CcCall ccc | - revFlowOut(call, ret, kind, state, returnCtx, returnAp, ap, config) and - returnFlowsThrough(ret, kind, state, ccc, _, _, ap, config) and + revFlowOut(call, ret, pos, state, returnCtx, returnAp, ap, config) and + returnFlowsThrough(ret, pos, state, ccc, _, _, ap, config) and matchesCall(ccc, call) ) } @@ -1915,17 +1893,17 @@ private module MkStage { pragma[nomagic] private predicate parameterFlowsThroughRev( - ParamNodeEx p, Ap ap, ReturnKindExt kind, Ap returnAp, Configuration config + ParamNodeEx p, Ap ap, ReturnPosition pos, Ap returnAp, Configuration config ) { - revFlow(p, _, TReturnCtxMaybeFlowThrough(kind), apSome(returnAp), ap, config) and - parameterFlowThroughAllowed(p, kind) + revFlow(p, _, TReturnCtxMaybeFlowThrough(pos), apSome(returnAp), ap, config) and + parameterFlowThroughAllowed(p, pos.getKind()) } pragma[nomagic] predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap, Configuration config) { - exists(RetNodeEx ret, ReturnKindExt kind | - returnFlowsThrough(ret, kind, _, _, p, ap, _, config) and - parameterFlowsThroughRev(p, ap, kind, _, config) + exists(RetNodeEx ret, ReturnPosition pos | + returnFlowsThrough(ret, pos, _, _, p, ap, _, config) and + parameterFlowsThroughRev(p, ap, pos, _, config) ) } @@ -1933,20 +1911,21 @@ private module MkStage { predicate returnMayFlowThrough( RetNodeEx ret, Ap argAp, Ap ap, ReturnKindExt kind, Configuration config ) { - exists(ParamNodeEx p | - returnFlowsThrough(ret, kind, _, _, p, argAp, ap, config) and - parameterFlowsThroughRev(p, argAp, kind, ap, config) + exists(ParamNodeEx p, ReturnPosition pos | + returnFlowsThrough(ret, pos, _, _, p, argAp, ap, config) and + parameterFlowsThroughRev(p, argAp, pos, ap, config) and + kind = pos.getKind() ) } pragma[nomagic] - predicate revFlowInToReturnIsReturned( + private predicate revFlowThroughArg( DataFlowCall call, ArgNodeEx arg, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap, Configuration config ) { - exists(ReturnKindExt returnKind0, Ap returnAp0 | - revFlowInToReturn(call, arg, state, returnKind0, returnAp0, ap, config) and - revFlowIsReturned(call, returnCtx, returnAp, returnKind0, returnAp0, config) + exists(ParamNodeEx p, ReturnPosition pos, Ap innerReturnAp | + revFlowThrough(call, returnCtx, p, state, pos, returnAp, ap, innerReturnAp, config) and + flowThroughIntoCall(call, arg, p, _, ap, innerReturnAp, config) ) } @@ -1954,7 +1933,7 @@ private module MkStage { predicate callMayFlowThroughRev(DataFlowCall call, Configuration config) { exists(ArgNodeEx arg, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap | revFlow(arg, state, returnCtx, returnAp, ap, config) and - revFlowInToReturnIsReturned(call, arg, state, returnCtx, returnAp, ap, config) + revFlowThroughArg(call, arg, state, returnCtx, returnAp, ap, config) ) } @@ -1967,8 +1946,9 @@ private module MkStage { conscand = count(TypedContent f0, Ap ap | fwdConsCand(f0, ap, config)) and states = count(FlowState state | fwdFlow(_, state, _, _, _, _, config)) and tuples = - count(NodeEx n, FlowState state, Cc cc, ParameterPositionOption summaryCtx, ApOption argAp, - Ap ap | fwdFlow(n, state, cc, summaryCtx, argAp, ap, config)) + count(NodeEx n, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap | + fwdFlow(n, state, cc, summaryCtx, argAp, ap, config) + ) or fwd = false and nodes = count(NodeEx node | revFlow(node, _, _, _, _, config)) and @@ -2823,13 +2803,12 @@ private Configuration unbindConf(Configuration conf) { pragma[nomagic] private predicate nodeMayUseSummary0( - NodeEx n, DataFlowCallable c, ParameterPosition pos, FlowState state, AccessPathApprox apa, - Configuration config + NodeEx n, ParamNodeEx p, FlowState state, AccessPathApprox apa, Configuration config ) { exists(AccessPathApprox apa0 | - c = n.getEnclosingCallable() and + Stage5::parameterMayFlowThrough(p, _, _) and Stage5::revFlow(n, state, TReturnCtxMaybeFlowThrough(_), _, apa0, config) and - Stage5::fwdFlow(n, state, any(CallContextCall ccc), TParameterPositionSome(pos), + Stage5::fwdFlow(n, state, any(CallContextCall ccc), TParamNodeSome(p.asNode()), TAccessPathApproxSome(apa), apa0, config) ) } @@ -2838,10 +2817,9 @@ pragma[nomagic] private predicate nodeMayUseSummary( NodeEx n, FlowState state, AccessPathApprox apa, Configuration config ) { - exists(DataFlowCallable c, ParameterPosition pos, ParamNodeEx p | + exists(ParamNodeEx p | Stage5::parameterMayFlowThrough(p, apa, config) and - nodeMayUseSummary0(n, c, pos, state, apa, config) and - p.isParameterOf(c, pos) + nodeMayUseSummary0(n, p, state, apa, config) ) } diff --git a/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowImplCommon.qll b/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowImplCommon.qll index c66aefced8d..9aa6a529a5b 100644 --- a/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowImplCommon.qll +++ b/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowImplCommon.qll @@ -916,15 +916,15 @@ private module Cached { TDataFlowCallSome(DataFlowCall call) cached - newtype TParameterPositionOption = - TParameterPositionNone() or - TParameterPositionSome(ParameterPosition pos) + newtype TParamNodeOption = + TParamNodeNone() or + TParamNodeSome(ParamNode p) cached newtype TReturnCtx = TReturnCtxNone() or TReturnCtxNoFlowThrough() or - TReturnCtxMaybeFlowThrough(ReturnKindExt kind) + TReturnCtxMaybeFlowThrough(ReturnPosition pos) cached newtype TTypedContentApprox = @@ -1343,15 +1343,15 @@ class DataFlowCallOption extends TDataFlowCallOption { } } -/** An optional `ParameterPosition`. */ -class ParameterPositionOption extends TParameterPositionOption { +/** An optional `ParamNode`. */ +class ParamNodeOption extends TParamNodeOption { string toString() { - this = TParameterPositionNone() and + this = TParamNodeNone() and result = "(none)" or - exists(ParameterPosition pos | - this = TParameterPositionSome(pos) and - result = pos.toString() + exists(ParamNode p | + this = TParamNodeSome(p) and + result = p.toString() ) } } @@ -1363,7 +1363,7 @@ class ParameterPositionOption extends TParameterPositionOption { * * - `TReturnCtxNone()`: no return flow. * - `TReturnCtxNoFlowThrough()`: return flow, but flow through is not possible. - * - `TReturnCtxMaybeFlowThrough(ReturnKindExt kind)`: return flow, of kind `kind`, and + * - `TReturnCtxMaybeFlowThrough(ReturnPosition pos)`: return flow, of kind `pos`, and * flow through may be possible. */ class ReturnCtx extends TReturnCtx { @@ -1374,9 +1374,9 @@ class ReturnCtx extends TReturnCtx { this = TReturnCtxNoFlowThrough() and result = "(no flow through)" or - exists(ReturnKindExt kind | - this = TReturnCtxMaybeFlowThrough(kind) and - result = kind.toString() + exists(ReturnPosition pos | + this = TReturnCtxMaybeFlowThrough(pos) and + result = pos.toString() ) } } diff --git a/swift/ql/lib/codeql/swift/dataflow/internal/FlowSummaryImpl.qll b/swift/ql/lib/codeql/swift/dataflow/internal/FlowSummaryImpl.qll index 61c541d8882..b61142c33a7 100644 --- a/swift/ql/lib/codeql/swift/dataflow/internal/FlowSummaryImpl.qll +++ b/swift/ql/lib/codeql/swift/dataflow/internal/FlowSummaryImpl.qll @@ -241,9 +241,15 @@ module Public { } /** - * Holds if the summary is auto generated. + * Holds if the summary is auto generated and not manually generated. */ predicate isAutoGenerated() { none() } + + /** + * Holds if the summary has the given provenance where `true` is + * `generated` and `false` is `manual`. + */ + predicate hasProvenance(boolean generated) { none() } } /** A callable where there is no flow via the callable. */ @@ -1012,6 +1018,10 @@ module Private { } override predicate isAutoGenerated() { this.relevantSummaryElementGenerated(_, _, _) } + + override predicate hasProvenance(boolean generated) { + summaryElement(this, _, _, _, generated) + } } /** Holds if component `c` of specification `spec` cannot be parsed. */ diff --git a/swift/ql/lib/codeql/swift/frameworks/StandardLibrary/WebView.qll b/swift/ql/lib/codeql/swift/frameworks/StandardLibrary/WebView.qll index b16c6aba370..702933644e5 100644 --- a/swift/ql/lib/codeql/swift/frameworks/StandardLibrary/WebView.qll +++ b/swift/ql/lib/codeql/swift/frameworks/StandardLibrary/WebView.qll @@ -125,7 +125,8 @@ private class JsExportedSource extends RemoteFlowSource { base.getEnclosingDecl() instanceof JsExportedProto and adopter.getEnclosingDecl() instanceof JsExportedType | - this.asExpr().(MemberRefExpr).getMember() = adopter and adopter.getName() = base.getName() + this.asExpr().(MemberRefExpr).getMember() = adopter and + pragma[only_bind_out](adopter.getName()) = pragma[only_bind_out](base.getName()) ) } diff --git a/swift/ql/src/queries/Security/CWE-094/UnsafeJsEval.ql b/swift/ql/src/queries/Security/CWE-094/UnsafeJsEval.ql index e553df216fe..9219b4f5f55 100644 --- a/swift/ql/src/queries/Security/CWE-094/UnsafeJsEval.ql +++ b/swift/ql/src/queries/Security/CWE-094/UnsafeJsEval.ql @@ -127,9 +127,6 @@ class UnsafeJsEvalConfig extends TaintTracking::Configuration { ) or exists(MemberRefExpr e, Expr self, VarDecl member | - self.getType().getName() = "String" and - member.getName() = ["utf8", "utf16", "utf8CString"] - or self.getType().getName().matches(["Unsafe%Buffer%", "Unsafe%Pointer%"]) and member.getName() = "baseAddress" |