Merge branch 'main' of github.com:github/codeql into SharedDataflow_SequenceFlow

This commit is contained in:
Rasmus Lerchedahl Petersen
2020-08-19 11:42:41 +02:00
302 changed files with 12876 additions and 4947 deletions

View File

@@ -26,7 +26,7 @@ predicate all_defined(ModuleValue exporter) {
}
from ImportStar imp, ModuleValue exporter
where import_star(imp, exporter) and not all_defined(exporter)
where import_star(imp, exporter) and not all_defined(exporter) and not exporter.isAbsent()
select imp,
"Import pollutes the enclosing namespace, as the imported module $@ does not define '__all__'.",
exporter, exporter.getName()

View File

@@ -1066,7 +1066,7 @@ private module LocalFlowBigStep {
* Holds if `node` can be the first node in a maximal subsequence of local
* flow steps in a dataflow path.
*/
private predicate localFlowEntry(Node node, Configuration config) {
predicate localFlowEntry(Node node, Configuration config) {
nodeCand2(node, config) and
(
config.isSource(node) or
@@ -1650,53 +1650,53 @@ private class AccessPathOption extends TAccessPathOption {
* Holds if `node` is reachable with access path `ap` from a source in
* the configuration `config`.
*
* The Boolean `fromArg` records whether the node is reached through an
* The call context `cc` records whether the node is reached through an
* argument in a call, and if so, `argAp` records the access path of that
* argument.
*/
private predicate flowFwd(
Node node, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, AccessPath ap,
Node node, CallContext cc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap,
Configuration config
) {
flowFwd0(node, fromArg, argAp, apf, ap, config) and
flowFwd0(node, cc, argAp, apf, ap, config) and
flowCand(node, _, _, apf, config)
}
private predicate flowFwd0(
Node node, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, AccessPath ap,
Node node, CallContext cc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap,
Configuration config
) {
flowCand(node, _, _, _, config) and
config.isSource(node) and
fromArg = false and
cc instanceof CallContextAny and
argAp = TAccessPathNone() and
ap = TNil(getNodeType(node)) and
apf = ap.(AccessPathNil).getFront()
or
flowCand(node, _, _, _, unbind(config)) and
(
exists(Node mid |
flowFwd(mid, fromArg, argAp, apf, ap, config) and
localFlowBigStep(mid, node, true, _, config, _)
exists(Node mid, LocalCallContext localCC |
flowFwdLocalEntry(mid, cc, argAp, apf, ap, localCC, config) and
localFlowBigStep(mid, node, true, _, config, localCC)
)
or
exists(Node mid, AccessPathNil nil |
flowFwd(mid, fromArg, argAp, _, nil, config) and
localFlowBigStep(mid, node, false, apf, config, _) and
exists(Node mid, AccessPathNil nil, LocalCallContext localCC |
flowFwdLocalEntry(mid, cc, argAp, _, nil, localCC, config) and
localFlowBigStep(mid, node, false, apf, config, localCC) and
apf = ap.(AccessPathNil).getFront()
)
or
exists(Node mid |
flowFwd(mid, _, _, apf, ap, config) and
jumpStep(mid, node, config) and
fromArg = false and
cc instanceof CallContextAny and
argAp = TAccessPathNone()
)
or
exists(Node mid, AccessPathNil nil |
flowFwd(mid, _, _, _, nil, config) and
additionalJumpStep(mid, node, config) and
fromArg = false and
cc instanceof CallContextAny and
argAp = TAccessPathNone() and
ap = TNil(getNodeType(node)) and
apf = ap.(AccessPathNil).getFront()
@@ -1704,40 +1704,51 @@ private predicate flowFwd0(
)
or
// store
exists(TypedContent tc | flowFwdStore(node, tc, pop(tc, ap), apf, fromArg, argAp, config))
exists(TypedContent tc | flowFwdStore(node, tc, pop(tc, ap), apf, cc, argAp, config))
or
// read
exists(TypedContent tc |
flowFwdRead(node, _, push(tc, ap), apf, fromArg, argAp, config) and
flowFwdRead(node, _, push(tc, ap), apf, cc, argAp, config) and
flowFwdConsCand(tc, apf, ap, config)
)
or
// flow into a callable
flowFwdIn(_, node, _, _, apf, ap, config) and
fromArg = true and
flowFwdIn(_, node, _, cc, _, apf, ap, config) and
if flowCand(node, true, _, apf, config)
then argAp = TAccessPathSome(ap)
else argAp = TAccessPathNone()
or
// flow out of a callable
exists(DataFlowCall call |
flowFwdOut(call, node, fromArg, argAp, apf, ap, config) and
fromArg = false
exists(DataFlowCallable c |
flowFwdOut(call, node, any(CallContextNoCall innercc), c, argAp, apf, ap, config) and
if reducedViableImplInReturn(c, call) then cc = TReturn(c, call) else cc = TAnyCallContext()
)
or
exists(AccessPath argAp0 |
flowFwdOutFromArg(call, node, argAp0, apf, ap, config) and
flowFwdIsEntered(call, fromArg, argAp, argAp0, config)
flowFwdIsEntered(call, cc, argAp, argAp0, config)
)
)
}
pragma[nomagic]
private predicate flowFwdLocalEntry(
Node node, CallContext cc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap,
LocalCallContext localCC, Configuration config
) {
flowFwd(node, cc, argAp, apf, ap, config) and
localFlowEntry(node, config) and
localCC = getLocalCallContext(cc, node.getEnclosingCallable())
}
pragma[nomagic]
private predicate flowFwdStore(
Node node, TypedContent tc, AccessPath ap0, AccessPathFront apf, boolean fromArg,
Node node, TypedContent tc, AccessPath ap0, AccessPathFront apf, CallContext cc,
AccessPathOption argAp, Configuration config
) {
exists(Node mid, AccessPathFront apf0 |
flowFwd(mid, fromArg, argAp, apf0, ap0, config) and
flowFwd(mid, cc, argAp, apf0, ap0, config) and
flowFwdStore0(mid, tc, node, apf0, apf, config)
)
}
@@ -1764,20 +1775,20 @@ private predicate flowFwdStore0(
pragma[nomagic]
private predicate flowFwdRead0(
Node node1, TypedContent tc, AccessPathFrontHead apf0, AccessPath ap0, Node node2,
boolean fromArg, AccessPathOption argAp, Configuration config
Node node1, TypedContent tc, AccessPathFrontHead apf0, AccessPath ap0, Node node2, CallContext cc,
AccessPathOption argAp, Configuration config
) {
flowFwd(node1, fromArg, argAp, apf0, ap0, config) and
flowFwd(node1, cc, argAp, apf0, ap0, config) and
readCandFwd(node1, tc, apf0, node2, config)
}
pragma[nomagic]
private predicate flowFwdRead(
Node node, AccessPathFrontHead apf0, AccessPath ap0, AccessPathFront apf, boolean fromArg,
Node node, AccessPathFrontHead apf0, AccessPath ap0, AccessPathFront apf, CallContext cc,
AccessPathOption argAp, Configuration config
) {
exists(Node mid, TypedContent tc |
flowFwdRead0(mid, tc, apf0, ap0, node, fromArg, argAp, config) and
flowFwdRead0(mid, tc, apf0, ap0, node, cc, argAp, config) and
flowCand(node, _, _, apf, unbind(config)) and
flowCandConsCand(tc, apf, unbind(config))
)
@@ -1795,13 +1806,16 @@ private predicate flowFwdConsCand(
pragma[nomagic]
private predicate flowFwdIn(
DataFlowCall call, ParameterNode p, boolean fromArg, AccessPathOption argAp, AccessPathFront apf,
AccessPath ap, Configuration config
DataFlowCall call, ParameterNode p, CallContext outercc, CallContext innercc,
AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config
) {
exists(ArgumentNode arg, boolean allowsFieldFlow |
flowFwd(arg, fromArg, argAp, apf, ap, config) and
exists(ArgumentNode arg, boolean allowsFieldFlow, DataFlowCallable c |
flowFwd(arg, outercc, argAp, apf, ap, config) and
flowIntoCallNodeCand2(call, arg, p, allowsFieldFlow, config) and
flowCand(p, _, _, _, unbind(config))
c = p.getEnclosingCallable() and
c = resolveCall(call, outercc) and
flowCand(p, _, _, _, unbind(config)) and
if recordDataFlowCallSite(call, c) then innercc = TSpecificCall(call) else innercc = TSomeCall()
|
ap instanceof AccessPathNil or allowsFieldFlow = true
)
@@ -1809,13 +1823,19 @@ private predicate flowFwdIn(
pragma[nomagic]
private predicate flowFwdOut(
DataFlowCall call, Node node, boolean fromArg, AccessPathOption argAp, AccessPathFront apf,
AccessPath ap, Configuration config
DataFlowCall call, Node node, CallContext innercc, DataFlowCallable innerc,
AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config
) {
exists(ReturnNodeExt ret, boolean allowsFieldFlow |
flowFwd(ret, fromArg, argAp, apf, ap, config) and
flowFwd(ret, innercc, argAp, apf, ap, config) and
flowOutOfCallNodeCand2(call, ret, node, allowsFieldFlow, config) and
flowCand(node, _, _, _, unbind(config))
innerc = ret.getEnclosingCallable() and
flowCand(node, _, _, _, unbind(config)) and
(
resolveReturn(innercc, innerc, call)
or
innercc.(CallContextCall).matchesCall(call)
)
|
ap instanceof AccessPathNil or allowsFieldFlow = true
)
@@ -1826,7 +1846,7 @@ private predicate flowFwdOutFromArg(
DataFlowCall call, Node node, AccessPath argAp, AccessPathFront apf, AccessPath ap,
Configuration config
) {
flowFwdOut(call, node, true, TAccessPathSome(argAp), apf, ap, config)
flowFwdOut(call, node, any(CallContextCall ccc), _, TAccessPathSome(argAp), apf, ap, config)
}
/**
@@ -1834,10 +1854,10 @@ private predicate flowFwdOutFromArg(
*/
pragma[nomagic]
private predicate flowFwdIsEntered(
DataFlowCall call, boolean fromArg, AccessPathOption argAp, AccessPath ap, Configuration config
DataFlowCall call, CallContext cc, AccessPathOption argAp, AccessPath ap, Configuration config
) {
exists(ParameterNode p, AccessPathFront apf |
flowFwdIn(call, p, fromArg, argAp, apf, ap, config) and
flowFwdIn(call, p, cc, _, argAp, apf, ap, config) and
flowCand(p, true, TAccessPathFrontSome(_), apf, config)
)
}
@@ -1920,7 +1940,7 @@ private predicate flow0(
// flow out of a callable
flowOut(_, node, _, _, ap, config) and
toReturn = true and
if flowFwd(node, true, TAccessPathSome(_), _, ap, config)
if flowFwd(node, any(CallContextCall ccc), TAccessPathSome(_), _, ap, config)
then returnAp = TAccessPathSome(ap)
else returnAp = TAccessPathNone()
}
@@ -2006,9 +2026,10 @@ private predicate flowIsReturned(
DataFlowCall call, boolean toReturn, AccessPathOption returnAp, AccessPath ap,
Configuration config
) {
exists(ReturnNodeExt ret |
exists(ReturnNodeExt ret, CallContextCall ccc |
flowOut(call, ret, toReturn, returnAp, ap, config) and
flowFwd(ret, true, TAccessPathSome(_), _, ap, config)
flowFwd(ret, ccc, TAccessPathSome(_), _, ap, config) and
ccc.matchesCall(call)
)
}
@@ -2031,7 +2052,7 @@ private newtype TSummaryCtx =
exists(ReturnNodeExt ret, Configuration config, AccessPath ap0 |
parameterFlow(p, ap, ret.getEnclosingCallable(), config) and
flow(ret, true, TAccessPathSome(_), ap0, config) and
flowFwd(ret, true, TAccessPathSome(ap), _, ap0, config)
flowFwd(ret, any(CallContextCall ccc), TAccessPathSome(ap), _, ap0, config)
)
}
@@ -2352,7 +2373,7 @@ private predicate pathOutOfCallable0(
) {
pos = getReturnPosition(mid.getNode()) and
innercc = mid.getCallContext() and
not innercc instanceof CallContextCall and
innercc instanceof CallContextNoCall and
ap = mid.getAp() and
config = mid.getConfiguration()
}
@@ -2867,7 +2888,7 @@ private module FlowExploration {
) {
pos = getReturnPosition(mid.getNode()) and
innercc = mid.getCallContext() and
not innercc instanceof CallContextCall and
innercc instanceof CallContextNoCall and
ap = mid.getAp() and
config = mid.getConfiguration()
}

View File

@@ -1066,7 +1066,7 @@ private module LocalFlowBigStep {
* Holds if `node` can be the first node in a maximal subsequence of local
* flow steps in a dataflow path.
*/
private predicate localFlowEntry(Node node, Configuration config) {
predicate localFlowEntry(Node node, Configuration config) {
nodeCand2(node, config) and
(
config.isSource(node) or
@@ -1650,53 +1650,53 @@ private class AccessPathOption extends TAccessPathOption {
* Holds if `node` is reachable with access path `ap` from a source in
* the configuration `config`.
*
* The Boolean `fromArg` records whether the node is reached through an
* The call context `cc` records whether the node is reached through an
* argument in a call, and if so, `argAp` records the access path of that
* argument.
*/
private predicate flowFwd(
Node node, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, AccessPath ap,
Node node, CallContext cc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap,
Configuration config
) {
flowFwd0(node, fromArg, argAp, apf, ap, config) and
flowFwd0(node, cc, argAp, apf, ap, config) and
flowCand(node, _, _, apf, config)
}
private predicate flowFwd0(
Node node, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, AccessPath ap,
Node node, CallContext cc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap,
Configuration config
) {
flowCand(node, _, _, _, config) and
config.isSource(node) and
fromArg = false and
cc instanceof CallContextAny and
argAp = TAccessPathNone() and
ap = TNil(getNodeType(node)) and
apf = ap.(AccessPathNil).getFront()
or
flowCand(node, _, _, _, unbind(config)) and
(
exists(Node mid |
flowFwd(mid, fromArg, argAp, apf, ap, config) and
localFlowBigStep(mid, node, true, _, config, _)
exists(Node mid, LocalCallContext localCC |
flowFwdLocalEntry(mid, cc, argAp, apf, ap, localCC, config) and
localFlowBigStep(mid, node, true, _, config, localCC)
)
or
exists(Node mid, AccessPathNil nil |
flowFwd(mid, fromArg, argAp, _, nil, config) and
localFlowBigStep(mid, node, false, apf, config, _) and
exists(Node mid, AccessPathNil nil, LocalCallContext localCC |
flowFwdLocalEntry(mid, cc, argAp, _, nil, localCC, config) and
localFlowBigStep(mid, node, false, apf, config, localCC) and
apf = ap.(AccessPathNil).getFront()
)
or
exists(Node mid |
flowFwd(mid, _, _, apf, ap, config) and
jumpStep(mid, node, config) and
fromArg = false and
cc instanceof CallContextAny and
argAp = TAccessPathNone()
)
or
exists(Node mid, AccessPathNil nil |
flowFwd(mid, _, _, _, nil, config) and
additionalJumpStep(mid, node, config) and
fromArg = false and
cc instanceof CallContextAny and
argAp = TAccessPathNone() and
ap = TNil(getNodeType(node)) and
apf = ap.(AccessPathNil).getFront()
@@ -1704,40 +1704,51 @@ private predicate flowFwd0(
)
or
// store
exists(TypedContent tc | flowFwdStore(node, tc, pop(tc, ap), apf, fromArg, argAp, config))
exists(TypedContent tc | flowFwdStore(node, tc, pop(tc, ap), apf, cc, argAp, config))
or
// read
exists(TypedContent tc |
flowFwdRead(node, _, push(tc, ap), apf, fromArg, argAp, config) and
flowFwdRead(node, _, push(tc, ap), apf, cc, argAp, config) and
flowFwdConsCand(tc, apf, ap, config)
)
or
// flow into a callable
flowFwdIn(_, node, _, _, apf, ap, config) and
fromArg = true and
flowFwdIn(_, node, _, cc, _, apf, ap, config) and
if flowCand(node, true, _, apf, config)
then argAp = TAccessPathSome(ap)
else argAp = TAccessPathNone()
or
// flow out of a callable
exists(DataFlowCall call |
flowFwdOut(call, node, fromArg, argAp, apf, ap, config) and
fromArg = false
exists(DataFlowCallable c |
flowFwdOut(call, node, any(CallContextNoCall innercc), c, argAp, apf, ap, config) and
if reducedViableImplInReturn(c, call) then cc = TReturn(c, call) else cc = TAnyCallContext()
)
or
exists(AccessPath argAp0 |
flowFwdOutFromArg(call, node, argAp0, apf, ap, config) and
flowFwdIsEntered(call, fromArg, argAp, argAp0, config)
flowFwdIsEntered(call, cc, argAp, argAp0, config)
)
)
}
pragma[nomagic]
private predicate flowFwdLocalEntry(
Node node, CallContext cc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap,
LocalCallContext localCC, Configuration config
) {
flowFwd(node, cc, argAp, apf, ap, config) and
localFlowEntry(node, config) and
localCC = getLocalCallContext(cc, node.getEnclosingCallable())
}
pragma[nomagic]
private predicate flowFwdStore(
Node node, TypedContent tc, AccessPath ap0, AccessPathFront apf, boolean fromArg,
Node node, TypedContent tc, AccessPath ap0, AccessPathFront apf, CallContext cc,
AccessPathOption argAp, Configuration config
) {
exists(Node mid, AccessPathFront apf0 |
flowFwd(mid, fromArg, argAp, apf0, ap0, config) and
flowFwd(mid, cc, argAp, apf0, ap0, config) and
flowFwdStore0(mid, tc, node, apf0, apf, config)
)
}
@@ -1764,20 +1775,20 @@ private predicate flowFwdStore0(
pragma[nomagic]
private predicate flowFwdRead0(
Node node1, TypedContent tc, AccessPathFrontHead apf0, AccessPath ap0, Node node2,
boolean fromArg, AccessPathOption argAp, Configuration config
Node node1, TypedContent tc, AccessPathFrontHead apf0, AccessPath ap0, Node node2, CallContext cc,
AccessPathOption argAp, Configuration config
) {
flowFwd(node1, fromArg, argAp, apf0, ap0, config) and
flowFwd(node1, cc, argAp, apf0, ap0, config) and
readCandFwd(node1, tc, apf0, node2, config)
}
pragma[nomagic]
private predicate flowFwdRead(
Node node, AccessPathFrontHead apf0, AccessPath ap0, AccessPathFront apf, boolean fromArg,
Node node, AccessPathFrontHead apf0, AccessPath ap0, AccessPathFront apf, CallContext cc,
AccessPathOption argAp, Configuration config
) {
exists(Node mid, TypedContent tc |
flowFwdRead0(mid, tc, apf0, ap0, node, fromArg, argAp, config) and
flowFwdRead0(mid, tc, apf0, ap0, node, cc, argAp, config) and
flowCand(node, _, _, apf, unbind(config)) and
flowCandConsCand(tc, apf, unbind(config))
)
@@ -1795,13 +1806,16 @@ private predicate flowFwdConsCand(
pragma[nomagic]
private predicate flowFwdIn(
DataFlowCall call, ParameterNode p, boolean fromArg, AccessPathOption argAp, AccessPathFront apf,
AccessPath ap, Configuration config
DataFlowCall call, ParameterNode p, CallContext outercc, CallContext innercc,
AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config
) {
exists(ArgumentNode arg, boolean allowsFieldFlow |
flowFwd(arg, fromArg, argAp, apf, ap, config) and
exists(ArgumentNode arg, boolean allowsFieldFlow, DataFlowCallable c |
flowFwd(arg, outercc, argAp, apf, ap, config) and
flowIntoCallNodeCand2(call, arg, p, allowsFieldFlow, config) and
flowCand(p, _, _, _, unbind(config))
c = p.getEnclosingCallable() and
c = resolveCall(call, outercc) and
flowCand(p, _, _, _, unbind(config)) and
if recordDataFlowCallSite(call, c) then innercc = TSpecificCall(call) else innercc = TSomeCall()
|
ap instanceof AccessPathNil or allowsFieldFlow = true
)
@@ -1809,13 +1823,19 @@ private predicate flowFwdIn(
pragma[nomagic]
private predicate flowFwdOut(
DataFlowCall call, Node node, boolean fromArg, AccessPathOption argAp, AccessPathFront apf,
AccessPath ap, Configuration config
DataFlowCall call, Node node, CallContext innercc, DataFlowCallable innerc,
AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config
) {
exists(ReturnNodeExt ret, boolean allowsFieldFlow |
flowFwd(ret, fromArg, argAp, apf, ap, config) and
flowFwd(ret, innercc, argAp, apf, ap, config) and
flowOutOfCallNodeCand2(call, ret, node, allowsFieldFlow, config) and
flowCand(node, _, _, _, unbind(config))
innerc = ret.getEnclosingCallable() and
flowCand(node, _, _, _, unbind(config)) and
(
resolveReturn(innercc, innerc, call)
or
innercc.(CallContextCall).matchesCall(call)
)
|
ap instanceof AccessPathNil or allowsFieldFlow = true
)
@@ -1826,7 +1846,7 @@ private predicate flowFwdOutFromArg(
DataFlowCall call, Node node, AccessPath argAp, AccessPathFront apf, AccessPath ap,
Configuration config
) {
flowFwdOut(call, node, true, TAccessPathSome(argAp), apf, ap, config)
flowFwdOut(call, node, any(CallContextCall ccc), _, TAccessPathSome(argAp), apf, ap, config)
}
/**
@@ -1834,10 +1854,10 @@ private predicate flowFwdOutFromArg(
*/
pragma[nomagic]
private predicate flowFwdIsEntered(
DataFlowCall call, boolean fromArg, AccessPathOption argAp, AccessPath ap, Configuration config
DataFlowCall call, CallContext cc, AccessPathOption argAp, AccessPath ap, Configuration config
) {
exists(ParameterNode p, AccessPathFront apf |
flowFwdIn(call, p, fromArg, argAp, apf, ap, config) and
flowFwdIn(call, p, cc, _, argAp, apf, ap, config) and
flowCand(p, true, TAccessPathFrontSome(_), apf, config)
)
}
@@ -1920,7 +1940,7 @@ private predicate flow0(
// flow out of a callable
flowOut(_, node, _, _, ap, config) and
toReturn = true and
if flowFwd(node, true, TAccessPathSome(_), _, ap, config)
if flowFwd(node, any(CallContextCall ccc), TAccessPathSome(_), _, ap, config)
then returnAp = TAccessPathSome(ap)
else returnAp = TAccessPathNone()
}
@@ -2006,9 +2026,10 @@ private predicate flowIsReturned(
DataFlowCall call, boolean toReturn, AccessPathOption returnAp, AccessPath ap,
Configuration config
) {
exists(ReturnNodeExt ret |
exists(ReturnNodeExt ret, CallContextCall ccc |
flowOut(call, ret, toReturn, returnAp, ap, config) and
flowFwd(ret, true, TAccessPathSome(_), _, ap, config)
flowFwd(ret, ccc, TAccessPathSome(_), _, ap, config) and
ccc.matchesCall(call)
)
}
@@ -2031,7 +2052,7 @@ private newtype TSummaryCtx =
exists(ReturnNodeExt ret, Configuration config, AccessPath ap0 |
parameterFlow(p, ap, ret.getEnclosingCallable(), config) and
flow(ret, true, TAccessPathSome(_), ap0, config) and
flowFwd(ret, true, TAccessPathSome(ap), _, ap0, config)
flowFwd(ret, any(CallContextCall ccc), TAccessPathSome(ap), _, ap0, config)
)
}
@@ -2352,7 +2373,7 @@ private predicate pathOutOfCallable0(
) {
pos = getReturnPosition(mid.getNode()) and
innercc = mid.getCallContext() and
not innercc instanceof CallContextCall and
innercc instanceof CallContextNoCall and
ap = mid.getAp() and
config = mid.getConfiguration()
}
@@ -2867,7 +2888,7 @@ private module FlowExploration {
) {
pos = getReturnPosition(mid.getNode()) and
innercc = mid.getCallContext() and
not innercc instanceof CallContextCall and
innercc instanceof CallContextNoCall and
ap = mid.getAp() and
config = mid.getConfiguration()
}

View File

@@ -512,13 +512,19 @@ abstract class CallContext extends TCallContext {
abstract predicate relevantFor(DataFlowCallable callable);
}
class CallContextAny extends CallContext, TAnyCallContext {
abstract class CallContextNoCall extends CallContext { }
class CallContextAny extends CallContextNoCall, TAnyCallContext {
override string toString() { result = "CcAny" }
override predicate relevantFor(DataFlowCallable callable) { any() }
}
abstract class CallContextCall extends CallContext { }
abstract class CallContextCall extends CallContext {
/** Holds if this call context may be `call`. */
bindingset[call]
abstract predicate matchesCall(DataFlowCall call);
}
class CallContextSpecificCall extends CallContextCall, TSpecificCall {
override string toString() {
@@ -529,6 +535,8 @@ class CallContextSpecificCall extends CallContextCall, TSpecificCall {
recordDataFlowCallSite(getCall(), callable)
}
override predicate matchesCall(DataFlowCall call) { call = this.getCall() }
DataFlowCall getCall() { this = TSpecificCall(result) }
}
@@ -538,9 +546,11 @@ class CallContextSomeCall extends CallContextCall, TSomeCall {
override predicate relevantFor(DataFlowCallable callable) {
exists(ParameterNode p | p.getEnclosingCallable() = callable)
}
override predicate matchesCall(DataFlowCall call) { any() }
}
class CallContextReturn extends CallContext, TReturn {
class CallContextReturn extends CallContextNoCall, TReturn {
override string toString() {
exists(DataFlowCall call | this = TReturn(_, call) | result = "CcReturn(" + call + ")")
}

View File

@@ -97,8 +97,65 @@ predicate simpleLocalFlowStep(Node nodeFrom, Node nodeTo) {
//--------
// Global flow
//--------
/**
* IPA type for DataFlowCallable.
* A callable is either a callable value or a class.
*/
newtype TDataFlowCallable =
TCallableValue(CallableValue callable) or
TClassValue(ClassValue c)
/** Represents a callable */
class DataFlowCallable = CallableValue;
abstract class DataFlowCallable extends TDataFlowCallable {
/** Gets a textual representation of this element. */
abstract string toString();
/** Gets a call to this callable. */
abstract CallNode getACall();
/** Gets the scope of this callable */
abstract Scope getScope();
/** Gets the specified parameter of this callable */
abstract NameNode getParameter(int n);
/** Gets the name of this callable. */
abstract string getName();
}
class DataFlowCallableValue extends DataFlowCallable, TCallableValue {
CallableValue callable;
DataFlowCallableValue() { this = TCallableValue(callable) }
override string toString() { result = callable.toString() }
override CallNode getACall() { result = callable.getACall() }
override Scope getScope() { result = callable.getScope() }
override NameNode getParameter(int n) { result = callable.getParameter(n) }
override string getName() { result = callable.getName() }
}
class DataFlowClassValue extends DataFlowCallable, TClassValue {
ClassValue c;
DataFlowClassValue() { this = TClassValue(c) }
override string toString() { result = c.toString() }
override CallNode getACall() { result = c.getACall() }
override Scope getScope() { result = c.getScope() }
override NameNode getParameter(int n) {
result.getNode() = c.getScope().getInitMethod().getArg(n + 1).asName()
}
override string getName() { result = c.getName() }
}
/** Represents a call to a callable */
class DataFlowCall extends CallNode {

View File

@@ -1,4 +1,4 @@
import callGraphConfig
import experimental.dataflow.callGraphConfig
from DataFlow::Node source, DataFlow::Node sink
where exists(CallGraphConfig cfg | cfg.hasFlow(source, sink))

View File

@@ -1,4 +1,4 @@
import callGraphConfig
import experimental.dataflow.callGraphConfig
from DataFlow::Node sink
where exists(CallGraphConfig cfg | cfg.isSink(sink))

View File

@@ -1,4 +1,4 @@
import callGraphConfig
import experimental.dataflow.callGraphConfig
from DataFlow::Node source
where exists(CallGraphConfig cfg | cfg.isSource(source))

View File

@@ -103,3 +103,5 @@ argHasPostUpdate
| test.py:74:17:74:17 | ControlFlowNode for t | ArgumentNode is missing PostUpdateNode. |
| test.py:81:13:81:13 | ControlFlowNode for t | ArgumentNode is missing PostUpdateNode. |
| test.py:86:13:86:13 | ControlFlowNode for t | ArgumentNode is missing PostUpdateNode. |
| test.py:158:15:158:15 | ControlFlowNode for l | ArgumentNode is missing PostUpdateNode. |
| test.py:159:15:159:15 | ControlFlowNode for d | ArgumentNode is missing PostUpdateNode. |

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,6 @@
| classes.py:19:12:19:31 | ControlFlowNode for Attribute() | classes.py:19:12:19:31 | ControlFlowNode for Attribute() |
| classes.py:174:7:174:22 | ControlFlowNode for set() | classes.py:174:7:174:22 | ControlFlowNode for set() |
| classes.py:178:7:178:28 | ControlFlowNode for frozenset() | classes.py:178:7:178:28 | ControlFlowNode for frozenset() |
| classes.py:182:7:182:26 | ControlFlowNode for dict() | classes.py:182:7:182:26 | ControlFlowNode for dict() |
| classes.py:303:28:303:51 | ControlFlowNode for dict() | classes.py:303:28:303:51 | ControlFlowNode for dict() |
| classes.py:466:12:466:24 | ControlFlowNode for Attribute() | classes.py:466:12:466:24 | ControlFlowNode for Attribute() |

View File

@@ -0,0 +1,10 @@
import experimental.dataflow.callGraphConfig
from DataFlow::Node source, DataFlow::Node sink
where
source.getLocation().getFile().getBaseName() = "classes.py" and
sink.getLocation().getFile().getBaseName() = "classes.py" and
exists(CallGraphConfig cfg | cfg.hasFlow(source, sink))
select source, sink
// Ideally, we would just have 1-step paths either from argument to parameter
// or from return to call. This gives a bit more, so should be rewritten.

View File

@@ -1,135 +1,263 @@
edges
| test.py:24:10:24:26 | ControlFlowNode for Tuple [Tuple element at index 1] | test.py:25:9:25:9 | ControlFlowNode for x [Tuple element at index 1] |
| test.py:24:21:24:26 | ControlFlowNode for SOURCE | test.py:24:10:24:26 | ControlFlowNode for Tuple [Tuple element at index 1] |
| test.py:25:9:25:9 | ControlFlowNode for x [Tuple element at index 1] | test.py:25:9:25:12 | ControlFlowNode for Subscript |
| test.py:25:9:25:12 | ControlFlowNode for Subscript | test.py:26:10:26:10 | ControlFlowNode for y |
| test.py:35:9:35:14 | ControlFlowNode for SOURCE | test.py:36:10:36:10 | ControlFlowNode for x |
| test.py:40:9:40:16 | ControlFlowNode for Str | test.py:41:10:41:10 | ControlFlowNode for x |
| test.py:44:9:44:17 | ControlFlowNode for Str | test.py:45:10:45:10 | ControlFlowNode for x |
| test.py:48:9:48:10 | ControlFlowNode for IntegerLiteral | test.py:49:10:49:10 | ControlFlowNode for x |
| test.py:52:9:52:12 | ControlFlowNode for FloatLiteral | test.py:53:10:53:10 | ControlFlowNode for x |
| test.py:61:10:61:15 | ControlFlowNode for SOURCE | test.py:62:10:62:10 | ControlFlowNode for x |
| test.py:66:9:66:16 | ControlFlowNode for List [List element] | test.py:67:10:67:10 | ControlFlowNode for x [List element] |
| test.py:66:10:66:15 | ControlFlowNode for SOURCE | test.py:66:9:66:16 | ControlFlowNode for List [List element] |
| test.py:67:10:67:10 | ControlFlowNode for x [List element] | test.py:67:10:67:13 | ControlFlowNode for Subscript |
| test.py:74:9:74:37 | ControlFlowNode for ListComp [List element] | test.py:75:10:75:10 | ControlFlowNode for x [List element] |
| test.py:74:10:74:15 | ControlFlowNode for SOURCE | test.py:74:9:74:37 | ControlFlowNode for ListComp [List element] |
| datamodel.py:13:1:13:6 | GSSA Variable SOURCE | datamodel.py:38:6:38:17 | ControlFlowNode for f() |
| datamodel.py:13:1:13:6 | GSSA Variable SOURCE | datamodel.py:38:6:38:17 | GSSA Variable SOURCE |
| datamodel.py:13:1:13:6 | GSSA Variable SOURCE | datamodel.py:38:8:38:13 | ControlFlowNode for SOURCE |
| datamodel.py:13:10:13:17 | ControlFlowNode for Str | datamodel.py:13:1:13:6 | GSSA Variable SOURCE |
| datamodel.py:38:6:38:17 | GSSA Variable SOURCE | datamodel.py:65:5:65:7 | ControlFlowNode for C() |
| datamodel.py:38:6:38:17 | GSSA Variable SOURCE | datamodel.py:71:6:71:24 | ControlFlowNode for Attribute() |
| datamodel.py:38:6:38:17 | GSSA Variable SOURCE | datamodel.py:71:6:71:24 | GSSA Variable SOURCE |
| datamodel.py:38:6:38:17 | GSSA Variable SOURCE | datamodel.py:71:15:71:20 | ControlFlowNode for SOURCE |
| datamodel.py:38:8:38:13 | ControlFlowNode for SOURCE | datamodel.py:38:6:38:17 | ControlFlowNode for f() |
| datamodel.py:65:1:65:1 | GSSA Variable c | datamodel.py:71:6:71:24 | ControlFlowNode for Attribute() |
| datamodel.py:65:1:65:1 | GSSA Variable c | datamodel.py:71:6:71:24 | GSSA Variable c |
| datamodel.py:65:5:65:7 | ControlFlowNode for C() | datamodel.py:65:1:65:1 | GSSA Variable c |
| datamodel.py:71:6:71:24 | GSSA Variable SOURCE | datamodel.py:72:6:72:27 | ControlFlowNode for Attribute() |
| datamodel.py:71:6:71:24 | GSSA Variable SOURCE | datamodel.py:72:18:72:23 | ControlFlowNode for SOURCE |
| datamodel.py:71:6:71:24 | GSSA Variable SOURCE | datamodel.py:73:6:73:27 | ControlFlowNode for func_obj() |
| datamodel.py:71:6:71:24 | GSSA Variable SOURCE | datamodel.py:80:6:80:26 | ControlFlowNode for Attribute() |
| datamodel.py:71:6:71:24 | GSSA Variable SOURCE | datamodel.py:80:6:80:26 | GSSA Variable SOURCE |
| datamodel.py:71:6:71:24 | GSSA Variable SOURCE | datamodel.py:80:20:80:25 | ControlFlowNode for SOURCE |
| datamodel.py:71:6:71:24 | GSSA Variable c | datamodel.py:72:6:72:27 | ControlFlowNode for Attribute() |
| datamodel.py:71:6:71:24 | GSSA Variable c | datamodel.py:72:6:72:27 | GSSA Variable c |
| datamodel.py:71:15:71:20 | ControlFlowNode for SOURCE | datamodel.py:71:6:71:24 | ControlFlowNode for Attribute() |
| datamodel.py:72:6:72:27 | GSSA Variable c | datamodel.py:73:6:73:27 | ControlFlowNode for func_obj() |
| datamodel.py:72:6:72:27 | GSSA Variable c | datamodel.py:73:6:73:27 | GSSA Variable c |
| datamodel.py:72:18:72:23 | ControlFlowNode for SOURCE | datamodel.py:72:6:72:27 | ControlFlowNode for Attribute() |
| datamodel.py:73:6:73:27 | GSSA Variable c | datamodel.py:80:6:80:26 | ControlFlowNode for Attribute() |
| datamodel.py:73:6:73:27 | GSSA Variable c | datamodel.py:80:6:80:26 | GSSA Variable c |
| datamodel.py:80:6:80:26 | GSSA Variable SOURCE | datamodel.py:81:6:81:26 | ControlFlowNode for Attribute() |
| datamodel.py:80:6:80:26 | GSSA Variable SOURCE | datamodel.py:81:6:81:26 | GSSA Variable SOURCE |
| datamodel.py:80:6:80:26 | GSSA Variable SOURCE | datamodel.py:81:20:81:25 | ControlFlowNode for SOURCE |
| datamodel.py:80:6:80:26 | GSSA Variable c | datamodel.py:81:6:81:26 | ControlFlowNode for Attribute() |
| datamodel.py:80:6:80:26 | GSSA Variable c | datamodel.py:82:6:82:26 | ControlFlowNode for c_func_obj() |
| datamodel.py:80:6:80:26 | GSSA Variable c | datamodel.py:92:8:92:21 | ControlFlowNode for gen() |
| datamodel.py:80:6:80:26 | GSSA Variable c | datamodel.py:93:6:93:20 | ControlFlowNode for Attribute() |
| datamodel.py:80:6:80:26 | GSSA Variable c | datamodel.py:96:9:96:24 | ControlFlowNode for Attribute() |
| datamodel.py:80:6:80:26 | GSSA Variable c | datamodel.py:96:9:96:24 | GSSA Variable c |
| datamodel.py:80:20:80:25 | ControlFlowNode for SOURCE | datamodel.py:80:6:80:26 | ControlFlowNode for Attribute() |
| datamodel.py:81:6:81:26 | GSSA Variable SOURCE | datamodel.py:82:6:82:26 | ControlFlowNode for c_func_obj() |
| datamodel.py:81:6:81:26 | GSSA Variable SOURCE | datamodel.py:92:8:92:21 | ControlFlowNode for gen() |
| datamodel.py:81:6:81:26 | GSSA Variable SOURCE | datamodel.py:92:8:92:21 | GSSA Variable SOURCE |
| datamodel.py:81:20:81:25 | ControlFlowNode for SOURCE | datamodel.py:81:6:81:26 | ControlFlowNode for Attribute() |
| datamodel.py:92:1:92:4 | GSSA Variable iter | datamodel.py:93:6:93:20 | ControlFlowNode for Attribute() |
| datamodel.py:92:1:92:4 | GSSA Variable iter | datamodel.py:93:6:93:20 | GSSA Variable iter |
| datamodel.py:92:8:92:21 | ControlFlowNode for gen() | datamodel.py:92:1:92:4 | GSSA Variable iter |
| datamodel.py:92:8:92:21 | GSSA Variable SOURCE | datamodel.py:93:6:93:20 | ControlFlowNode for Attribute() |
| datamodel.py:92:8:92:21 | GSSA Variable SOURCE | datamodel.py:96:9:96:24 | ControlFlowNode for Attribute() |
| datamodel.py:92:8:92:21 | GSSA Variable SOURCE | datamodel.py:96:9:96:24 | GSSA Variable SOURCE |
| datamodel.py:93:6:93:20 | GSSA Variable iter | datamodel.py:96:9:96:24 | ControlFlowNode for Attribute() |
| datamodel.py:93:6:93:20 | GSSA Variable iter | datamodel.py:97:6:97:21 | ControlFlowNode for Attribute() |
| datamodel.py:93:6:93:20 | GSSA Variable iter | datamodel.py:106:6:106:30 | ControlFlowNode for Attribute() |
| datamodel.py:93:6:93:20 | GSSA Variable iter | datamodel.py:107:6:107:32 | ControlFlowNode for Attribute() |
| datamodel.py:93:6:93:20 | GSSA Variable iter | datamodel.py:119:6:119:30 | ControlFlowNode for Attribute() |
| datamodel.py:96:1:96:5 | GSSA Variable oiter | datamodel.py:97:6:97:21 | ControlFlowNode for Attribute() |
| datamodel.py:96:1:96:5 | GSSA Variable oiter | datamodel.py:97:6:97:21 | GSSA Variable oiter |
| datamodel.py:96:9:96:24 | ControlFlowNode for Attribute() | datamodel.py:96:1:96:5 | GSSA Variable oiter |
| datamodel.py:96:9:96:24 | GSSA Variable SOURCE | datamodel.py:97:6:97:21 | ControlFlowNode for Attribute() |
| datamodel.py:96:9:96:24 | GSSA Variable SOURCE | datamodel.py:106:18:106:29 | GSSA Variable SOURCE |
| datamodel.py:96:9:96:24 | GSSA Variable c | datamodel.py:97:6:97:21 | ControlFlowNode for Attribute() |
| datamodel.py:96:9:96:24 | GSSA Variable c | datamodel.py:106:6:106:30 | ControlFlowNode for Attribute() |
| datamodel.py:96:9:96:24 | GSSA Variable c | datamodel.py:107:18:107:31 | GSSA Variable c |
| datamodel.py:97:6:97:21 | GSSA Variable oiter | datamodel.py:106:6:106:30 | ControlFlowNode for Attribute() |
| datamodel.py:97:6:97:21 | GSSA Variable oiter | datamodel.py:107:6:107:32 | ControlFlowNode for Attribute() |
| datamodel.py:97:6:97:21 | GSSA Variable oiter | datamodel.py:119:6:119:30 | ControlFlowNode for Attribute() |
| datamodel.py:106:18:106:29 | GSSA Variable SOURCE | datamodel.py:106:6:106:30 | ControlFlowNode for Attribute() |
| datamodel.py:106:18:106:29 | GSSA Variable SOURCE | datamodel.py:107:18:107:31 | GSSA Variable SOURCE |
| datamodel.py:107:18:107:31 | GSSA Variable SOURCE | datamodel.py:107:6:107:32 | ControlFlowNode for Attribute() |
| datamodel.py:107:18:107:31 | GSSA Variable SOURCE | datamodel.py:119:18:119:29 | GSSA Variable SOURCE |
| datamodel.py:107:18:107:31 | GSSA Variable c | datamodel.py:107:6:107:32 | ControlFlowNode for Attribute() |
| datamodel.py:107:18:107:31 | GSSA Variable c | datamodel.py:119:6:119:30 | ControlFlowNode for Attribute() |
| datamodel.py:119:18:119:29 | GSSA Variable SOURCE | datamodel.py:119:6:119:30 | ControlFlowNode for Attribute() |
| test.py:32:10:32:26 | ControlFlowNode for Tuple [Tuple element at index 1] | test.py:33:9:33:9 | ControlFlowNode for x [Tuple element at index 1] |
| test.py:32:21:32:26 | ControlFlowNode for SOURCE | test.py:32:10:32:26 | ControlFlowNode for Tuple [Tuple element at index 1] |
| test.py:33:9:33:9 | ControlFlowNode for x [Tuple element at index 1] | test.py:33:9:33:12 | ControlFlowNode for Subscript |
| test.py:33:9:33:12 | ControlFlowNode for Subscript | test.py:34:10:34:10 | ControlFlowNode for y |
| test.py:43:9:43:14 | ControlFlowNode for SOURCE | test.py:44:10:44:10 | ControlFlowNode for x |
| test.py:48:9:48:16 | ControlFlowNode for Str | test.py:49:10:49:10 | ControlFlowNode for x |
| test.py:52:9:52:17 | ControlFlowNode for Str | test.py:53:10:53:10 | ControlFlowNode for x |
| test.py:56:9:56:10 | ControlFlowNode for IntegerLiteral | test.py:57:10:57:10 | ControlFlowNode for x |
| test.py:60:9:60:12 | ControlFlowNode for FloatLiteral | test.py:61:10:61:10 | ControlFlowNode for x |
| test.py:69:10:69:15 | ControlFlowNode for SOURCE | test.py:70:10:70:10 | ControlFlowNode for x |
| test.py:74:9:74:16 | ControlFlowNode for List [List element] | test.py:75:10:75:10 | ControlFlowNode for x [List element] |
| test.py:74:10:74:15 | ControlFlowNode for SOURCE | test.py:74:9:74:16 | ControlFlowNode for List [List element] |
| test.py:75:10:75:10 | ControlFlowNode for x [List element] | test.py:75:10:75:13 | ControlFlowNode for Subscript |
| test.py:78:9:78:29 | ControlFlowNode for ListComp [List element] | test.py:79:10:79:10 | ControlFlowNode for x [List element] |
| test.py:78:10:78:10 | ControlFlowNode for y | test.py:78:9:78:29 | ControlFlowNode for ListComp [List element] |
| test.py:78:16:78:16 | SSA variable y | test.py:78:10:78:10 | ControlFlowNode for y |
| test.py:78:21:78:28 | ControlFlowNode for List [List element] | test.py:78:16:78:16 | SSA variable y |
| test.py:78:22:78:27 | ControlFlowNode for SOURCE | test.py:78:21:78:28 | ControlFlowNode for List [List element] |
| test.py:79:10:79:10 | ControlFlowNode for x [List element] | test.py:79:10:79:13 | ControlFlowNode for Subscript |
| test.py:91:9:91:37 | ControlFlowNode for SetComp [Set element] | test.py:92:10:92:10 | ControlFlowNode for x [Set element] |
| test.py:91:10:91:15 | ControlFlowNode for SOURCE | test.py:91:9:91:37 | ControlFlowNode for SetComp [Set element] |
| test.py:92:10:92:10 | ControlFlowNode for x [Set element] | test.py:92:10:92:16 | ControlFlowNode for Attribute() |
| test.py:95:9:95:29 | ControlFlowNode for SetComp [Set element] | test.py:96:10:96:10 | ControlFlowNode for x [Set element] |
| test.py:95:10:95:10 | ControlFlowNode for y | test.py:95:9:95:29 | ControlFlowNode for SetComp [Set element] |
| test.py:95:16:95:16 | SSA variable y | test.py:95:10:95:10 | ControlFlowNode for y |
| test.py:95:21:95:28 | ControlFlowNode for List [List element] | test.py:95:16:95:16 | SSA variable y |
| test.py:95:22:95:27 | ControlFlowNode for SOURCE | test.py:95:21:95:28 | ControlFlowNode for List [List element] |
| test.py:96:10:96:10 | ControlFlowNode for x [Set element] | test.py:96:10:96:16 | ControlFlowNode for Attribute() |
| test.py:104:9:104:21 | ControlFlowNode for Dict [Dictionary element at key s] | test.py:105:10:105:10 | ControlFlowNode for x [Dictionary element at key s] |
| test.py:104:15:104:20 | ControlFlowNode for SOURCE | test.py:104:9:104:21 | ControlFlowNode for Dict [Dictionary element at key s] |
| test.py:105:10:105:10 | ControlFlowNode for x [Dictionary element at key s] | test.py:105:10:105:15 | ControlFlowNode for Subscript |
| test.py:108:9:108:21 | ControlFlowNode for Dict [Dictionary element at key s] | test.py:109:10:109:10 | ControlFlowNode for x [Dictionary element at key s] |
| test.py:108:15:108:20 | ControlFlowNode for SOURCE | test.py:108:9:108:21 | ControlFlowNode for Dict [Dictionary element at key s] |
| test.py:109:10:109:10 | ControlFlowNode for x [Dictionary element at key s] | test.py:109:10:109:19 | ControlFlowNode for Attribute() |
| test.py:234:11:234:16 | ControlFlowNode for SOURCE | test.py:234:11:234:17 | ControlFlowNode for Tuple [Tuple element at index 0] |
| test.py:234:11:234:17 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:234:10:234:21 | ControlFlowNode for Subscript |
| test.py:237:10:237:17 | ControlFlowNode for List [List element] | test.py:237:10:237:20 | ControlFlowNode for Subscript |
| test.py:237:11:237:16 | ControlFlowNode for SOURCE | test.py:237:10:237:17 | ControlFlowNode for List [List element] |
| test.py:240:10:240:21 | ControlFlowNode for Dict [Dictionary element at key s] | test.py:240:10:240:26 | ControlFlowNode for Subscript |
| test.py:240:15:240:20 | ControlFlowNode for SOURCE | test.py:240:10:240:21 | ControlFlowNode for Dict [Dictionary element at key s] |
| test.py:258:28:258:33 | ControlFlowNode for SOURCE | test.py:258:10:258:34 | ControlFlowNode for second() |
| test.py:317:12:317:17 | ControlFlowNode for SOURCE | test.py:317:10:317:18 | ControlFlowNode for f() |
| test.py:321:28:321:33 | ControlFlowNode for SOURCE | test.py:321:10:321:34 | ControlFlowNode for second() |
| test.py:82:9:82:37 | ControlFlowNode for ListComp [List element] | test.py:83:10:83:10 | ControlFlowNode for x [List element] |
| test.py:82:10:82:15 | ControlFlowNode for SOURCE | test.py:82:9:82:37 | ControlFlowNode for ListComp [List element] |
| test.py:83:10:83:10 | ControlFlowNode for x [List element] | test.py:83:10:83:13 | ControlFlowNode for Subscript |
| test.py:86:9:86:29 | ControlFlowNode for ListComp [List element] | test.py:87:10:87:10 | ControlFlowNode for x [List element] |
| test.py:86:10:86:10 | ControlFlowNode for y | test.py:86:9:86:29 | ControlFlowNode for ListComp [List element] |
| test.py:86:16:86:16 | SSA variable y | test.py:86:10:86:10 | ControlFlowNode for y |
| test.py:86:21:86:28 | ControlFlowNode for List [List element] | test.py:86:16:86:16 | SSA variable y |
| test.py:86:22:86:27 | ControlFlowNode for SOURCE | test.py:86:21:86:28 | ControlFlowNode for List [List element] |
| test.py:87:10:87:10 | ControlFlowNode for x [List element] | test.py:87:10:87:13 | ControlFlowNode for Subscript |
| test.py:99:9:99:37 | ControlFlowNode for SetComp [Set element] | test.py:100:10:100:10 | ControlFlowNode for x [Set element] |
| test.py:99:10:99:15 | ControlFlowNode for SOURCE | test.py:99:9:99:37 | ControlFlowNode for SetComp [Set element] |
| test.py:100:10:100:10 | ControlFlowNode for x [Set element] | test.py:100:10:100:16 | ControlFlowNode for Attribute() |
| test.py:103:9:103:29 | ControlFlowNode for SetComp [Set element] | test.py:104:10:104:10 | ControlFlowNode for x [Set element] |
| test.py:103:10:103:10 | ControlFlowNode for y | test.py:103:9:103:29 | ControlFlowNode for SetComp [Set element] |
| test.py:103:16:103:16 | SSA variable y | test.py:103:10:103:10 | ControlFlowNode for y |
| test.py:103:21:103:28 | ControlFlowNode for List [List element] | test.py:103:16:103:16 | SSA variable y |
| test.py:103:22:103:27 | ControlFlowNode for SOURCE | test.py:103:21:103:28 | ControlFlowNode for List [List element] |
| test.py:104:10:104:10 | ControlFlowNode for x [Set element] | test.py:104:10:104:16 | ControlFlowNode for Attribute() |
| test.py:112:9:112:21 | ControlFlowNode for Dict [Dictionary element at key s] | test.py:113:10:113:10 | ControlFlowNode for x [Dictionary element at key s] |
| test.py:112:15:112:20 | ControlFlowNode for SOURCE | test.py:112:9:112:21 | ControlFlowNode for Dict [Dictionary element at key s] |
| test.py:113:10:113:10 | ControlFlowNode for x [Dictionary element at key s] | test.py:113:10:113:15 | ControlFlowNode for Subscript |
| test.py:116:9:116:21 | ControlFlowNode for Dict [Dictionary element at key s] | test.py:117:10:117:10 | ControlFlowNode for x [Dictionary element at key s] |
| test.py:116:15:116:20 | ControlFlowNode for SOURCE | test.py:116:9:116:21 | ControlFlowNode for Dict [Dictionary element at key s] |
| test.py:117:10:117:10 | ControlFlowNode for x [Dictionary element at key s] | test.py:117:10:117:19 | ControlFlowNode for Attribute() |
| test.py:242:11:242:16 | ControlFlowNode for SOURCE | test.py:242:11:242:17 | ControlFlowNode for Tuple [Tuple element at index 0] |
| test.py:242:11:242:17 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:242:10:242:21 | ControlFlowNode for Subscript |
| test.py:245:10:245:17 | ControlFlowNode for List [List element] | test.py:245:10:245:20 | ControlFlowNode for Subscript |
| test.py:245:11:245:16 | ControlFlowNode for SOURCE | test.py:245:10:245:17 | ControlFlowNode for List [List element] |
| test.py:248:10:248:21 | ControlFlowNode for Dict [Dictionary element at key s] | test.py:248:10:248:26 | ControlFlowNode for Subscript |
| test.py:248:15:248:20 | ControlFlowNode for SOURCE | test.py:248:10:248:21 | ControlFlowNode for Dict [Dictionary element at key s] |
| test.py:266:28:266:33 | ControlFlowNode for SOURCE | test.py:266:10:266:34 | ControlFlowNode for second() |
| test.py:325:12:325:17 | ControlFlowNode for SOURCE | test.py:325:10:325:18 | ControlFlowNode for f() |
| test.py:329:28:329:33 | ControlFlowNode for SOURCE | test.py:329:10:329:34 | ControlFlowNode for second() |
nodes
| test.py:24:10:24:26 | ControlFlowNode for Tuple [Tuple element at index 1] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 1] |
| test.py:24:21:24:26 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE |
| test.py:25:9:25:9 | ControlFlowNode for x [Tuple element at index 1] | semmle.label | ControlFlowNode for x [Tuple element at index 1] |
| test.py:25:9:25:12 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript |
| test.py:26:10:26:10 | ControlFlowNode for y | semmle.label | ControlFlowNode for y |
| test.py:35:9:35:14 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE |
| test.py:36:10:36:10 | ControlFlowNode for x | semmle.label | ControlFlowNode for x |
| test.py:40:9:40:16 | ControlFlowNode for Str | semmle.label | ControlFlowNode for Str |
| test.py:41:10:41:10 | ControlFlowNode for x | semmle.label | ControlFlowNode for x |
| test.py:44:9:44:17 | ControlFlowNode for Str | semmle.label | ControlFlowNode for Str |
| test.py:45:10:45:10 | ControlFlowNode for x | semmle.label | ControlFlowNode for x |
| test.py:48:9:48:10 | ControlFlowNode for IntegerLiteral | semmle.label | ControlFlowNode for IntegerLiteral |
| datamodel.py:13:1:13:6 | GSSA Variable SOURCE | semmle.label | GSSA Variable SOURCE |
| datamodel.py:13:10:13:17 | ControlFlowNode for Str | semmle.label | ControlFlowNode for Str |
| datamodel.py:38:6:38:17 | ControlFlowNode for f() | semmle.label | ControlFlowNode for f() |
| datamodel.py:38:6:38:17 | GSSA Variable SOURCE | semmle.label | GSSA Variable SOURCE |
| datamodel.py:38:8:38:13 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE |
| datamodel.py:65:1:65:1 | GSSA Variable c | semmle.label | GSSA Variable c |
| datamodel.py:65:5:65:7 | ControlFlowNode for C() | semmle.label | ControlFlowNode for C() |
| datamodel.py:71:6:71:24 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
| datamodel.py:71:6:71:24 | GSSA Variable SOURCE | semmle.label | GSSA Variable SOURCE |
| datamodel.py:71:6:71:24 | GSSA Variable c | semmle.label | GSSA Variable c |
| datamodel.py:71:15:71:20 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE |
| datamodel.py:72:6:72:27 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
| datamodel.py:72:6:72:27 | GSSA Variable c | semmle.label | GSSA Variable c |
| datamodel.py:72:18:72:23 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE |
| datamodel.py:73:6:73:27 | ControlFlowNode for func_obj() | semmle.label | ControlFlowNode for func_obj() |
| datamodel.py:73:6:73:27 | GSSA Variable c | semmle.label | GSSA Variable c |
| datamodel.py:80:6:80:26 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
| datamodel.py:80:6:80:26 | GSSA Variable SOURCE | semmle.label | GSSA Variable SOURCE |
| datamodel.py:80:6:80:26 | GSSA Variable c | semmle.label | GSSA Variable c |
| datamodel.py:80:20:80:25 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE |
| datamodel.py:81:6:81:26 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
| datamodel.py:81:6:81:26 | GSSA Variable SOURCE | semmle.label | GSSA Variable SOURCE |
| datamodel.py:81:20:81:25 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE |
| datamodel.py:82:6:82:26 | ControlFlowNode for c_func_obj() | semmle.label | ControlFlowNode for c_func_obj() |
| datamodel.py:92:1:92:4 | GSSA Variable iter | semmle.label | GSSA Variable iter |
| datamodel.py:92:8:92:21 | ControlFlowNode for gen() | semmle.label | ControlFlowNode for gen() |
| datamodel.py:92:8:92:21 | GSSA Variable SOURCE | semmle.label | GSSA Variable SOURCE |
| datamodel.py:93:6:93:20 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
| datamodel.py:93:6:93:20 | GSSA Variable iter | semmle.label | GSSA Variable iter |
| datamodel.py:96:1:96:5 | GSSA Variable oiter | semmle.label | GSSA Variable oiter |
| datamodel.py:96:9:96:24 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
| datamodel.py:96:9:96:24 | GSSA Variable SOURCE | semmle.label | GSSA Variable SOURCE |
| datamodel.py:96:9:96:24 | GSSA Variable c | semmle.label | GSSA Variable c |
| datamodel.py:97:6:97:21 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
| datamodel.py:97:6:97:21 | GSSA Variable oiter | semmle.label | GSSA Variable oiter |
| datamodel.py:106:6:106:30 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
| datamodel.py:106:18:106:29 | GSSA Variable SOURCE | semmle.label | GSSA Variable SOURCE |
| datamodel.py:107:6:107:32 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
| datamodel.py:107:18:107:31 | GSSA Variable SOURCE | semmle.label | GSSA Variable SOURCE |
| datamodel.py:107:18:107:31 | GSSA Variable c | semmle.label | GSSA Variable c |
| datamodel.py:119:6:119:30 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
| datamodel.py:119:18:119:29 | GSSA Variable SOURCE | semmle.label | GSSA Variable SOURCE |
| test.py:32:10:32:26 | ControlFlowNode for Tuple [Tuple element at index 1] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 1] |
| test.py:32:21:32:26 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE |
| test.py:33:9:33:9 | ControlFlowNode for x [Tuple element at index 1] | semmle.label | ControlFlowNode for x [Tuple element at index 1] |
| test.py:33:9:33:12 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript |
| test.py:34:10:34:10 | ControlFlowNode for y | semmle.label | ControlFlowNode for y |
| test.py:43:9:43:14 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE |
| test.py:44:10:44:10 | ControlFlowNode for x | semmle.label | ControlFlowNode for x |
| test.py:48:9:48:16 | ControlFlowNode for Str | semmle.label | ControlFlowNode for Str |
| test.py:49:10:49:10 | ControlFlowNode for x | semmle.label | ControlFlowNode for x |
| test.py:52:9:52:12 | ControlFlowNode for FloatLiteral | semmle.label | ControlFlowNode for FloatLiteral |
| test.py:52:9:52:17 | ControlFlowNode for Str | semmle.label | ControlFlowNode for Str |
| test.py:53:10:53:10 | ControlFlowNode for x | semmle.label | ControlFlowNode for x |
| test.py:61:10:61:15 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE |
| test.py:62:10:62:10 | ControlFlowNode for x | semmle.label | ControlFlowNode for x |
| test.py:66:9:66:16 | ControlFlowNode for List [List element] | semmle.label | ControlFlowNode for List [List element] |
| test.py:66:10:66:15 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE |
| test.py:67:10:67:10 | ControlFlowNode for x [List element] | semmle.label | ControlFlowNode for x [List element] |
| test.py:67:10:67:13 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript |
| test.py:74:9:74:37 | ControlFlowNode for ListComp [List element] | semmle.label | ControlFlowNode for ListComp [List element] |
| test.py:56:9:56:10 | ControlFlowNode for IntegerLiteral | semmle.label | ControlFlowNode for IntegerLiteral |
| test.py:57:10:57:10 | ControlFlowNode for x | semmle.label | ControlFlowNode for x |
| test.py:60:9:60:12 | ControlFlowNode for FloatLiteral | semmle.label | ControlFlowNode for FloatLiteral |
| test.py:61:10:61:10 | ControlFlowNode for x | semmle.label | ControlFlowNode for x |
| test.py:69:10:69:15 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE |
| test.py:70:10:70:10 | ControlFlowNode for x | semmle.label | ControlFlowNode for x |
| test.py:74:9:74:16 | ControlFlowNode for List [List element] | semmle.label | ControlFlowNode for List [List element] |
| test.py:74:10:74:15 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE |
| test.py:75:10:75:10 | ControlFlowNode for x [List element] | semmle.label | ControlFlowNode for x [List element] |
| test.py:75:10:75:13 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript |
| test.py:78:9:78:29 | ControlFlowNode for ListComp [List element] | semmle.label | ControlFlowNode for ListComp [List element] |
| test.py:78:10:78:10 | ControlFlowNode for y | semmle.label | ControlFlowNode for y |
| test.py:78:16:78:16 | SSA variable y | semmle.label | SSA variable y |
| test.py:78:21:78:28 | ControlFlowNode for List [List element] | semmle.label | ControlFlowNode for List [List element] |
| test.py:78:22:78:27 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE |
| test.py:79:10:79:10 | ControlFlowNode for x [List element] | semmle.label | ControlFlowNode for x [List element] |
| test.py:79:10:79:13 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript |
| test.py:91:9:91:37 | ControlFlowNode for SetComp [Set element] | semmle.label | ControlFlowNode for SetComp [Set element] |
| test.py:91:10:91:15 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE |
| test.py:92:10:92:10 | ControlFlowNode for x [Set element] | semmle.label | ControlFlowNode for x [Set element] |
| test.py:92:10:92:16 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
| test.py:95:9:95:29 | ControlFlowNode for SetComp [Set element] | semmle.label | ControlFlowNode for SetComp [Set element] |
| test.py:95:10:95:10 | ControlFlowNode for y | semmle.label | ControlFlowNode for y |
| test.py:95:16:95:16 | SSA variable y | semmle.label | SSA variable y |
| test.py:95:21:95:28 | ControlFlowNode for List [List element] | semmle.label | ControlFlowNode for List [List element] |
| test.py:95:22:95:27 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE |
| test.py:96:10:96:10 | ControlFlowNode for x [Set element] | semmle.label | ControlFlowNode for x [Set element] |
| test.py:96:10:96:16 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
| test.py:104:9:104:21 | ControlFlowNode for Dict [Dictionary element at key s] | semmle.label | ControlFlowNode for Dict [Dictionary element at key s] |
| test.py:104:15:104:20 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE |
| test.py:105:10:105:10 | ControlFlowNode for x [Dictionary element at key s] | semmle.label | ControlFlowNode for x [Dictionary element at key s] |
| test.py:105:10:105:15 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript |
| test.py:108:9:108:21 | ControlFlowNode for Dict [Dictionary element at key s] | semmle.label | ControlFlowNode for Dict [Dictionary element at key s] |
| test.py:108:15:108:20 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE |
| test.py:109:10:109:10 | ControlFlowNode for x [Dictionary element at key s] | semmle.label | ControlFlowNode for x [Dictionary element at key s] |
| test.py:109:10:109:19 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
| test.py:234:10:234:21 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript |
| test.py:234:11:234:16 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE |
| test.py:234:11:234:17 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] |
| test.py:237:10:237:17 | ControlFlowNode for List [List element] | semmle.label | ControlFlowNode for List [List element] |
| test.py:237:10:237:20 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript |
| test.py:237:11:237:16 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE |
| test.py:240:10:240:21 | ControlFlowNode for Dict [Dictionary element at key s] | semmle.label | ControlFlowNode for Dict [Dictionary element at key s] |
| test.py:240:10:240:26 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript |
| test.py:240:15:240:20 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE |
| test.py:258:10:258:34 | ControlFlowNode for second() | semmle.label | ControlFlowNode for second() |
| test.py:258:28:258:33 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE |
| test.py:317:10:317:18 | ControlFlowNode for f() | semmle.label | ControlFlowNode for f() |
| test.py:317:12:317:17 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE |
| test.py:321:10:321:34 | ControlFlowNode for second() | semmle.label | ControlFlowNode for second() |
| test.py:321:28:321:33 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE |
| test.py:82:9:82:37 | ControlFlowNode for ListComp [List element] | semmle.label | ControlFlowNode for ListComp [List element] |
| test.py:82:10:82:15 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE |
| test.py:83:10:83:10 | ControlFlowNode for x [List element] | semmle.label | ControlFlowNode for x [List element] |
| test.py:83:10:83:13 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript |
| test.py:86:9:86:29 | ControlFlowNode for ListComp [List element] | semmle.label | ControlFlowNode for ListComp [List element] |
| test.py:86:10:86:10 | ControlFlowNode for y | semmle.label | ControlFlowNode for y |
| test.py:86:16:86:16 | SSA variable y | semmle.label | SSA variable y |
| test.py:86:21:86:28 | ControlFlowNode for List [List element] | semmle.label | ControlFlowNode for List [List element] |
| test.py:86:22:86:27 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE |
| test.py:87:10:87:10 | ControlFlowNode for x [List element] | semmle.label | ControlFlowNode for x [List element] |
| test.py:87:10:87:13 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript |
| test.py:99:9:99:37 | ControlFlowNode for SetComp [Set element] | semmle.label | ControlFlowNode for SetComp [Set element] |
| test.py:99:10:99:15 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE |
| test.py:100:10:100:10 | ControlFlowNode for x [Set element] | semmle.label | ControlFlowNode for x [Set element] |
| test.py:100:10:100:16 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
| test.py:103:9:103:29 | ControlFlowNode for SetComp [Set element] | semmle.label | ControlFlowNode for SetComp [Set element] |
| test.py:103:10:103:10 | ControlFlowNode for y | semmle.label | ControlFlowNode for y |
| test.py:103:16:103:16 | SSA variable y | semmle.label | SSA variable y |
| test.py:103:21:103:28 | ControlFlowNode for List [List element] | semmle.label | ControlFlowNode for List [List element] |
| test.py:103:22:103:27 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE |
| test.py:104:10:104:10 | ControlFlowNode for x [Set element] | semmle.label | ControlFlowNode for x [Set element] |
| test.py:104:10:104:16 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
| test.py:112:9:112:21 | ControlFlowNode for Dict [Dictionary element at key s] | semmle.label | ControlFlowNode for Dict [Dictionary element at key s] |
| test.py:112:15:112:20 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE |
| test.py:113:10:113:10 | ControlFlowNode for x [Dictionary element at key s] | semmle.label | ControlFlowNode for x [Dictionary element at key s] |
| test.py:113:10:113:15 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript |
| test.py:116:9:116:21 | ControlFlowNode for Dict [Dictionary element at key s] | semmle.label | ControlFlowNode for Dict [Dictionary element at key s] |
| test.py:116:15:116:20 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE |
| test.py:117:10:117:10 | ControlFlowNode for x [Dictionary element at key s] | semmle.label | ControlFlowNode for x [Dictionary element at key s] |
| test.py:117:10:117:19 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
| test.py:242:10:242:21 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript |
| test.py:242:11:242:16 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE |
| test.py:242:11:242:17 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] |
| test.py:245:10:245:17 | ControlFlowNode for List [List element] | semmle.label | ControlFlowNode for List [List element] |
| test.py:245:10:245:20 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript |
| test.py:245:11:245:16 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE |
| test.py:248:10:248:21 | ControlFlowNode for Dict [Dictionary element at key s] | semmle.label | ControlFlowNode for Dict [Dictionary element at key s] |
| test.py:248:10:248:26 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript |
| test.py:248:15:248:20 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE |
| test.py:266:10:266:34 | ControlFlowNode for second() | semmle.label | ControlFlowNode for second() |
| test.py:266:28:266:33 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE |
| test.py:325:10:325:18 | ControlFlowNode for f() | semmle.label | ControlFlowNode for f() |
| test.py:325:12:325:17 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE |
| test.py:329:10:329:34 | ControlFlowNode for second() | semmle.label | ControlFlowNode for second() |
| test.py:329:28:329:33 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE |
#select
| test.py:26:10:26:10 | ControlFlowNode for y | test.py:24:21:24:26 | ControlFlowNode for SOURCE | test.py:26:10:26:10 | ControlFlowNode for y | <message> |
| test.py:36:10:36:10 | ControlFlowNode for x | test.py:35:9:35:14 | ControlFlowNode for SOURCE | test.py:36:10:36:10 | ControlFlowNode for x | <message> |
| test.py:41:10:41:10 | ControlFlowNode for x | test.py:40:9:40:16 | ControlFlowNode for Str | test.py:41:10:41:10 | ControlFlowNode for x | <message> |
| test.py:45:10:45:10 | ControlFlowNode for x | test.py:44:9:44:17 | ControlFlowNode for Str | test.py:45:10:45:10 | ControlFlowNode for x | <message> |
| test.py:49:10:49:10 | ControlFlowNode for x | test.py:48:9:48:10 | ControlFlowNode for IntegerLiteral | test.py:49:10:49:10 | ControlFlowNode for x | <message> |
| test.py:53:10:53:10 | ControlFlowNode for x | test.py:52:9:52:12 | ControlFlowNode for FloatLiteral | test.py:53:10:53:10 | ControlFlowNode for x | <message> |
| test.py:62:10:62:10 | ControlFlowNode for x | test.py:61:10:61:15 | ControlFlowNode for SOURCE | test.py:62:10:62:10 | ControlFlowNode for x | <message> |
| test.py:67:10:67:13 | ControlFlowNode for Subscript | test.py:66:10:66:15 | ControlFlowNode for SOURCE | test.py:67:10:67:13 | ControlFlowNode for Subscript | <message> |
| datamodel.py:38:6:38:17 | ControlFlowNode for f() | datamodel.py:13:10:13:17 | ControlFlowNode for Str | datamodel.py:38:6:38:17 | ControlFlowNode for f() | <message> |
| datamodel.py:38:6:38:17 | ControlFlowNode for f() | datamodel.py:38:8:38:13 | ControlFlowNode for SOURCE | datamodel.py:38:6:38:17 | ControlFlowNode for f() | <message> |
| datamodel.py:71:6:71:24 | ControlFlowNode for Attribute() | datamodel.py:13:10:13:17 | ControlFlowNode for Str | datamodel.py:71:6:71:24 | ControlFlowNode for Attribute() | <message> |
| datamodel.py:71:6:71:24 | ControlFlowNode for Attribute() | datamodel.py:71:15:71:20 | ControlFlowNode for SOURCE | datamodel.py:71:6:71:24 | ControlFlowNode for Attribute() | <message> |
| datamodel.py:72:6:72:27 | ControlFlowNode for Attribute() | datamodel.py:13:10:13:17 | ControlFlowNode for Str | datamodel.py:72:6:72:27 | ControlFlowNode for Attribute() | <message> |
| datamodel.py:72:6:72:27 | ControlFlowNode for Attribute() | datamodel.py:72:18:72:23 | ControlFlowNode for SOURCE | datamodel.py:72:6:72:27 | ControlFlowNode for Attribute() | <message> |
| datamodel.py:73:6:73:27 | ControlFlowNode for func_obj() | datamodel.py:13:10:13:17 | ControlFlowNode for Str | datamodel.py:73:6:73:27 | ControlFlowNode for func_obj() | <message> |
| datamodel.py:80:6:80:26 | ControlFlowNode for Attribute() | datamodel.py:13:10:13:17 | ControlFlowNode for Str | datamodel.py:80:6:80:26 | ControlFlowNode for Attribute() | <message> |
| datamodel.py:80:6:80:26 | ControlFlowNode for Attribute() | datamodel.py:80:20:80:25 | ControlFlowNode for SOURCE | datamodel.py:80:6:80:26 | ControlFlowNode for Attribute() | <message> |
| datamodel.py:81:6:81:26 | ControlFlowNode for Attribute() | datamodel.py:13:10:13:17 | ControlFlowNode for Str | datamodel.py:81:6:81:26 | ControlFlowNode for Attribute() | <message> |
| datamodel.py:81:6:81:26 | ControlFlowNode for Attribute() | datamodel.py:81:20:81:25 | ControlFlowNode for SOURCE | datamodel.py:81:6:81:26 | ControlFlowNode for Attribute() | <message> |
| datamodel.py:82:6:82:26 | ControlFlowNode for c_func_obj() | datamodel.py:13:10:13:17 | ControlFlowNode for Str | datamodel.py:82:6:82:26 | ControlFlowNode for c_func_obj() | <message> |
| datamodel.py:93:6:93:20 | ControlFlowNode for Attribute() | datamodel.py:13:10:13:17 | ControlFlowNode for Str | datamodel.py:93:6:93:20 | ControlFlowNode for Attribute() | <message> |
| datamodel.py:97:6:97:21 | ControlFlowNode for Attribute() | datamodel.py:13:10:13:17 | ControlFlowNode for Str | datamodel.py:97:6:97:21 | ControlFlowNode for Attribute() | <message> |
| datamodel.py:106:6:106:30 | ControlFlowNode for Attribute() | datamodel.py:13:10:13:17 | ControlFlowNode for Str | datamodel.py:106:6:106:30 | ControlFlowNode for Attribute() | <message> |
| datamodel.py:107:6:107:32 | ControlFlowNode for Attribute() | datamodel.py:13:10:13:17 | ControlFlowNode for Str | datamodel.py:107:6:107:32 | ControlFlowNode for Attribute() | <message> |
| datamodel.py:119:6:119:30 | ControlFlowNode for Attribute() | datamodel.py:13:10:13:17 | ControlFlowNode for Str | datamodel.py:119:6:119:30 | ControlFlowNode for Attribute() | <message> |
| test.py:34:10:34:10 | ControlFlowNode for y | test.py:32:21:32:26 | ControlFlowNode for SOURCE | test.py:34:10:34:10 | ControlFlowNode for y | <message> |
| test.py:44:10:44:10 | ControlFlowNode for x | test.py:43:9:43:14 | ControlFlowNode for SOURCE | test.py:44:10:44:10 | ControlFlowNode for x | <message> |
| test.py:49:10:49:10 | ControlFlowNode for x | test.py:48:9:48:16 | ControlFlowNode for Str | test.py:49:10:49:10 | ControlFlowNode for x | <message> |
| test.py:53:10:53:10 | ControlFlowNode for x | test.py:52:9:52:17 | ControlFlowNode for Str | test.py:53:10:53:10 | ControlFlowNode for x | <message> |
| test.py:57:10:57:10 | ControlFlowNode for x | test.py:56:9:56:10 | ControlFlowNode for IntegerLiteral | test.py:57:10:57:10 | ControlFlowNode for x | <message> |
| test.py:61:10:61:10 | ControlFlowNode for x | test.py:60:9:60:12 | ControlFlowNode for FloatLiteral | test.py:61:10:61:10 | ControlFlowNode for x | <message> |
| test.py:70:10:70:10 | ControlFlowNode for x | test.py:69:10:69:15 | ControlFlowNode for SOURCE | test.py:70:10:70:10 | ControlFlowNode for x | <message> |
| test.py:75:10:75:13 | ControlFlowNode for Subscript | test.py:74:10:74:15 | ControlFlowNode for SOURCE | test.py:75:10:75:13 | ControlFlowNode for Subscript | <message> |
| test.py:79:10:79:13 | ControlFlowNode for Subscript | test.py:78:22:78:27 | ControlFlowNode for SOURCE | test.py:79:10:79:13 | ControlFlowNode for Subscript | <message> |
| test.py:92:10:92:16 | ControlFlowNode for Attribute() | test.py:91:10:91:15 | ControlFlowNode for SOURCE | test.py:92:10:92:16 | ControlFlowNode for Attribute() | <message> |
| test.py:96:10:96:16 | ControlFlowNode for Attribute() | test.py:95:22:95:27 | ControlFlowNode for SOURCE | test.py:96:10:96:16 | ControlFlowNode for Attribute() | <message> |
| test.py:105:10:105:15 | ControlFlowNode for Subscript | test.py:104:15:104:20 | ControlFlowNode for SOURCE | test.py:105:10:105:15 | ControlFlowNode for Subscript | <message> |
| test.py:109:10:109:19 | ControlFlowNode for Attribute() | test.py:108:15:108:20 | ControlFlowNode for SOURCE | test.py:109:10:109:19 | ControlFlowNode for Attribute() | <message> |
| test.py:234:10:234:21 | ControlFlowNode for Subscript | test.py:234:11:234:16 | ControlFlowNode for SOURCE | test.py:234:10:234:21 | ControlFlowNode for Subscript | <message> |
| test.py:237:10:237:20 | ControlFlowNode for Subscript | test.py:237:11:237:16 | ControlFlowNode for SOURCE | test.py:237:10:237:20 | ControlFlowNode for Subscript | <message> |
| test.py:240:10:240:26 | ControlFlowNode for Subscript | test.py:240:15:240:20 | ControlFlowNode for SOURCE | test.py:240:10:240:26 | ControlFlowNode for Subscript | <message> |
| test.py:258:10:258:34 | ControlFlowNode for second() | test.py:258:28:258:33 | ControlFlowNode for SOURCE | test.py:258:10:258:34 | ControlFlowNode for second() | <message> |
| test.py:317:10:317:18 | ControlFlowNode for f() | test.py:317:12:317:17 | ControlFlowNode for SOURCE | test.py:317:10:317:18 | ControlFlowNode for f() | <message> |
| test.py:321:10:321:34 | ControlFlowNode for second() | test.py:321:28:321:33 | ControlFlowNode for SOURCE | test.py:321:10:321:34 | ControlFlowNode for second() | <message> |
| test.py:83:10:83:13 | ControlFlowNode for Subscript | test.py:82:10:82:15 | ControlFlowNode for SOURCE | test.py:83:10:83:13 | ControlFlowNode for Subscript | <message> |
| test.py:87:10:87:13 | ControlFlowNode for Subscript | test.py:86:22:86:27 | ControlFlowNode for SOURCE | test.py:87:10:87:13 | ControlFlowNode for Subscript | <message> |
| test.py:100:10:100:16 | ControlFlowNode for Attribute() | test.py:99:10:99:15 | ControlFlowNode for SOURCE | test.py:100:10:100:16 | ControlFlowNode for Attribute() | <message> |
| test.py:104:10:104:16 | ControlFlowNode for Attribute() | test.py:103:22:103:27 | ControlFlowNode for SOURCE | test.py:104:10:104:16 | ControlFlowNode for Attribute() | <message> |
| test.py:113:10:113:15 | ControlFlowNode for Subscript | test.py:112:15:112:20 | ControlFlowNode for SOURCE | test.py:113:10:113:15 | ControlFlowNode for Subscript | <message> |
| test.py:117:10:117:19 | ControlFlowNode for Attribute() | test.py:116:15:116:20 | ControlFlowNode for SOURCE | test.py:117:10:117:19 | ControlFlowNode for Attribute() | <message> |
| test.py:242:10:242:21 | ControlFlowNode for Subscript | test.py:242:11:242:16 | ControlFlowNode for SOURCE | test.py:242:10:242:21 | ControlFlowNode for Subscript | <message> |
| test.py:245:10:245:20 | ControlFlowNode for Subscript | test.py:245:11:245:16 | ControlFlowNode for SOURCE | test.py:245:10:245:20 | ControlFlowNode for Subscript | <message> |
| test.py:248:10:248:26 | ControlFlowNode for Subscript | test.py:248:15:248:20 | ControlFlowNode for SOURCE | test.py:248:10:248:26 | ControlFlowNode for Subscript | <message> |
| test.py:266:10:266:34 | ControlFlowNode for second() | test.py:266:28:266:33 | ControlFlowNode for SOURCE | test.py:266:10:266:34 | ControlFlowNode for second() | <message> |
| test.py:325:10:325:18 | ControlFlowNode for f() | test.py:325:12:325:17 | ControlFlowNode for SOURCE | test.py:325:10:325:18 | ControlFlowNode for f() | <message> |
| test.py:329:10:329:34 | ControlFlowNode for second() | test.py:329:28:329:33 | ControlFlowNode for SOURCE | test.py:329:10:329:34 | ControlFlowNode for second() | <message> |

View File

@@ -0,0 +1,159 @@
# User-defined methods, both instance methods and class methods, can be called in many non-standard ways
# i.e. differently from simply `c.f()` or `C.f()`. For example, a user-defined `__await__` method on a
# class `C` will be called by the syntactic construct `await c` when `c` is an instance of `C`.
#
# These tests are based on the first part of https://docs.python.org/3/reference/datamodel.html.
# A thorough covering of methods in that document is found in classes.py.
#
# Intended sources should be the variable `SOURCE` and intended sinks should be
# arguments to the function `SINK` (see python/ql/test/experimental/dataflow/testConfig.qll).
# These are defined so that we can evaluate the test code.
NONSOURCE = "not a source"
SOURCE = "source"
def is_source(x):
return x == "source" or x == b"source" or x == 42 or x == 42.0 or x == 42j
def SINK(x):
if is_source(x):
print("OK")
else:
print("Unexpected flow", x)
def SINK_F(x):
if is_source(x):
print("Unexpected flow", x)
else:
print("OK")
# Callable types
# These are the types to which the function call operation (see section Calls) can be applied:
# User-defined functions
# A user-defined function object is created by a function definition (see section Function definitions). It should be called with an argument list containing the same number of items as the function's formal parameter list.
def f(a, b):
return a
SINK(f(SOURCE, 3))
# Instance methods
# An instance method object combines a class, a class instance and any callable object (normally a user-defined function).
class C(object):
def method(self, x, cls):
assert cls is self.__class__
return x
@classmethod
def classmethod(cls, x):
return x
@staticmethod
def staticmethod(x):
return x
def gen(self, x, count):
n = count
while n > 0:
yield x
n -= 1
async def coro(self, x):
return x
c = C()
# When an instance method object is created by retrieving a user-defined function object from a class via one of its instances, its __self__ attribute is the instance, and the method object is said to be bound. The new methods __func__ attribute is the original function object.
func_obj = c.method.__func__
# When an instance method object is called, the underlying function (__func__) is called, inserting the class instance (__self__) in front of the argument list. For instance, when C is a class which contains a definition for a function f(), and x is an instance of C, calling x.f(1) is equivalent to calling C.f(x, 1).
SINK(c.method(SOURCE, C))
SINK(C.method(c, SOURCE, C))
SINK(func_obj(c, SOURCE, C))
# When an instance method object is created by retrieving a class method object from a class or instance, its __self__ attribute is the class itself, and its __func__ attribute is the function object underlying the class method.
c_func_obj = C.classmethod.__func__
# When an instance method object is derived from a class method object, the “class instance” stored in __self__ will actually be the class itself, so that calling either x.f(1) or C.f(1) is equivalent to calling f(C,1) where f is the underlying function.
SINK(c.classmethod(SOURCE))
SINK(C.classmethod(SOURCE))
SINK(c_func_obj(C, SOURCE))
# Generator functions
# A function or method which uses the yield statement (see section The yield statement) is called a generator function. Such a function, when called, always returns an iterator object which can be used to execute the body of the function: calling the iterators iterator.__next__() method will cause the function to execute until it provides a value using the yield statement. When the function executes a return statement or falls off the end, a StopIteration exception is raised and the iterator will have reached the end of the set of values to be returned.
def gen(x, count):
n = count
while n > 0:
yield x
n -= 1
iter = gen(SOURCE, 1)
SINK(iter.__next__())
# SINK_F(iter.__next__()) # throws StopIteration, FP
oiter = c.gen(SOURCE, 1)
SINK(oiter.__next__())
# SINK_F(oiter.__next__()) # throws StopIteration, FP
# Coroutine functions
# A function or method which is defined using async def is called a coroutine function. Such a function, when called, returns a coroutine object. It may contain await expressions, as well as async with and async for statements. See also the Coroutine Objects section.
async def coro(x):
return x
import asyncio
SINK(asyncio.run(coro(SOURCE)))
SINK(asyncio.run(c.coro(SOURCE)))
class A:
def __await__(self):
# yield SOURCE -- see https://groups.google.com/g/dev-python/c/_lrrc-vp9TI?pli=1
return (yield from asyncio.coroutine(lambda: SOURCE)())
async def agen(x):
a = A()
return await a
SINK(asyncio.run(agen(SOURCE)))
# Asynchronous generator functions
# A function or method which is defined using async def and which uses the yield statement is called a asynchronous generator function. Such a function, when called, returns an asynchronous iterator object which can be used in an async for statement to execute the body of the function.
# Calling the asynchronous iterators aiterator.__anext__() method will return an awaitable which when awaited will execute until it provides a value using the yield expression. When the function executes an empty return statement or falls off the end, a StopAsyncIteration exception is raised and the asynchronous iterator will have reached the end of the set of values to be yielded.
# Built-in functions
# A built-in function object is a wrapper around a C function. Examples of built-in functions are len() and math.sin() (math is a standard built-in module). The number and type of the arguments are determined by the C function. Special read-only attributes: __doc__ is the functions documentation string, or None if unavailable; __name__ is the functions name; __self__ is set to None (but see the next item); __module__ is the name of the module the function was defined in or None if unavailable.
# Built-in methods
# This is really a different disguise of a built-in function, this time containing an object passed to the C function as an implicit extra argument. An example of a built-in method is alist.append(), assuming alist is a list object. In this case, the special read-only attribute __self__ is set to the object denoted by alist.
# Classes
# Classes are callable. These objects normally act as factories for new instances of themselves, but variations are possible for class types that override __new__(). The arguments of the call are passed to __new__() and, in the typical case, to __init__() to initialize the new instance.
# Class Instances
# Instances of arbitrary classes can be made callable by defining a __call__() method in their class.
# If a class sets __iter__() to None, calling iter() on its instances will raise a TypeError (without falling back to __getitem__()).
# 3.3.1. Basic customization
class Customized:
a = NONSOURCE
b = NONSOURCE
def __new__(cls):
cls.a = SOURCE
return super().__new__(cls)
def __init__(self):
self.b = SOURCE
# testing __new__ and __init__
customized = Customized()
SINK(Customized.a)
SINK_F(Customized.b)
SINK(customized.a)
SINK(customized.b)

View File

@@ -1,7 +1,7 @@
| test.py:24:5:24:5 | SSA variable x | test.py:23:1:23:33 | Exit node for Function test_tuple_with_local_flow |
| test.py:24:5:24:5 | SSA variable x | test.py:25:9:25:9 | ControlFlowNode for x |
| test.py:24:10:24:26 | ControlFlowNode for Tuple | test.py:24:5:24:5 | SSA variable x |
| test.py:25:5:25:5 | SSA variable y | test.py:26:5:26:11 | SSA variable y |
| test.py:25:5:25:5 | SSA variable y | test.py:26:10:26:10 | ControlFlowNode for y |
| test.py:25:9:25:12 | ControlFlowNode for Subscript | test.py:25:5:25:5 | SSA variable y |
| test.py:26:5:26:11 | SSA variable y | test.py:23:1:23:33 | Exit node for Function test_tuple_with_local_flow |
| test.py:32:5:32:5 | SSA variable x | test.py:31:1:31:33 | Exit node for Function test_tuple_with_local_flow |
| test.py:32:5:32:5 | SSA variable x | test.py:33:9:33:9 | ControlFlowNode for x |
| test.py:32:10:32:26 | ControlFlowNode for Tuple | test.py:32:5:32:5 | SSA variable x |
| test.py:33:5:33:5 | SSA variable y | test.py:34:5:34:11 | SSA variable y |
| test.py:33:5:33:5 | SSA variable y | test.py:34:10:34:10 | ControlFlowNode for y |
| test.py:33:9:33:12 | ControlFlowNode for Subscript | test.py:33:5:33:5 | SSA variable y |
| test.py:34:5:34:11 | SSA variable y | test.py:31:1:31:33 | Exit node for Function test_tuple_with_local_flow |

View File

@@ -6,19 +6,27 @@
#
# Functions whose name ends with "_with_local_flow" will also be tested for local flow.
#
# All functions starting with "test_" should run and either
# - print a source (sources are defined in testConfig.qll).
# - print "Unexpected flow: " and a non-source
# (The idea is to later write a script to autimatically confirm this.)
# All functions starting with "test_" should run and print `"OK"`.
# This can be checked by running validTest.py.
# These are defined so that we can evaluate the test code.
NONSOURCE = "not a source"
SOURCE = "source"
def is_source(x):
return x == "source" or x == b"source" or x == 42 or x == 42.0 or x == 42j
def SINK(x):
print(x)
if is_source(x):
print("OK")
else:
print("Unexpected flow", x)
def SINK_F(x):
print("Unexpected flow: ", x)
if is_source(x):
print("Unexpected flow", x)
else:
print("OK")
def test_tuple_with_local_flow():
x = (NONSOURCE, SOURCE)

View File

@@ -0,0 +1,49 @@
def check_output(s, f):
if s == "OK\n":
pass
else:
raise RuntimeError("Function failed", s, f)
def check_test_function(f):
from io import StringIO
import sys
capturer = StringIO()
old_stdout = sys.stdout
sys.stdout = capturer
f()
sys.stdout = old_stdout
check_output(capturer.getvalue(), f)
def check_async_test_function(f):
from io import StringIO
import sys
import asyncio
capturer = StringIO()
old_stdout = sys.stdout
sys.stdout = capturer
asyncio.run(f())
sys.stdout = old_stdout
check_output(capturer.getvalue(), f)
def check_tests_valid(testFile):
import importlib
tests = importlib.import_module(testFile)
for i in dir(tests):
# print("Considering", i)
if i.startswith("test_"):
item = getattr(tests,i)
if callable(item):
print("Checking", testFile, item)
check_test_function(item)
elif i.startswith("atest_"):
item = getattr(tests,i)
if callable(item):
print("Checking", testFile, item)
check_async_test_function(item)
if __name__ == '__main__':
check_tests_valid("classes")
check_tests_valid("test")

View File

@@ -1,2 +1,3 @@
| imports_test.py:21:1:21:20 | from module import * | Using 'from ... import *' pollutes the namespace |
| imports_test.py:22:1:22:32 | from module_without_all import * | Using 'from ... import *' pollutes the namespace |
| imports_test.py:65:1:65:40 | from module_that_does_not_exist import * | Using 'from ... import *' pollutes the namespace |

View File

@@ -61,3 +61,5 @@ import module1 as different
#Use it
different
# FP reported in https://github.com/github/codeql/issues/4003
from module_that_does_not_exist import *