mirror of
https://github.com/github/codeql.git
synced 2025-12-20 10:46:30 +01:00
Merge branch 'main' into port-url-redirect-query
This commit is contained in:
@@ -39,6 +39,16 @@ class Function extends Function_, Scope, AstNode {
|
||||
exists(YieldFrom y | y.getScope() = this)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if this function represents a lambda.
|
||||
*
|
||||
* The extractor reifies each lambda expression as a (local) function with the name
|
||||
* "lambda". As `lambda` is a keyword in Python, it's impossible to create a function with this
|
||||
* name otherwise, and so it's impossible to get a non-lambda function accidentally
|
||||
* classified as a lambda.
|
||||
*/
|
||||
predicate isLambda() { this.getName() = "lambda" }
|
||||
|
||||
/** Whether this function is declared in a class and is named `__init__` */
|
||||
predicate isInitMethod() { this.isMethod() and this.getName() = "__init__" }
|
||||
|
||||
|
||||
@@ -11,103 +11,138 @@ private import semmle.python.essa.SsaCompute
|
||||
//--------
|
||||
predicate isExpressionNode(ControlFlowNode node) { node.getNode() instanceof Expr }
|
||||
|
||||
/** A data flow node for which we should synthesise an associated pre-update node. */
|
||||
abstract class NeedsSyntheticPreUpdateNode extends Node {
|
||||
/** A label for this kind of node. This will figure in the textual representation of the synthesized pre-update node. */
|
||||
abstract string label();
|
||||
}
|
||||
/** A module collecting the different reasons for synthesising a pre-update node. */
|
||||
module syntheticPreUpdateNode {
|
||||
class SyntheticPreUpdateNode extends Node, TSyntheticPreUpdateNode {
|
||||
NeedsSyntheticPreUpdateNode post;
|
||||
|
||||
class SyntheticPreUpdateNode extends Node, TSyntheticPreUpdateNode {
|
||||
NeedsSyntheticPreUpdateNode post;
|
||||
SyntheticPreUpdateNode() { this = TSyntheticPreUpdateNode(post) }
|
||||
|
||||
SyntheticPreUpdateNode() { this = TSyntheticPreUpdateNode(post) }
|
||||
/** Gets the node for which this is a synthetic pre-update node. */
|
||||
Node getPostUpdateNode() { result = post }
|
||||
|
||||
/** Gets the node for which this is a synthetic pre-update node. */
|
||||
Node getPostUpdateNode() { result = post }
|
||||
override string toString() { result = "[pre " + post.label() + "] " + post.toString() }
|
||||
|
||||
override string toString() { result = "[pre " + post.label() + "] " + post.toString() }
|
||||
override Scope getScope() { result = post.getScope() }
|
||||
|
||||
override Scope getScope() { result = post.getScope() }
|
||||
|
||||
override Location getLocation() { result = post.getLocation() }
|
||||
}
|
||||
|
||||
/** A data flow node for which we should synthesise an associated post-update node. */
|
||||
abstract class NeedsSyntheticPostUpdateNode extends Node {
|
||||
/** A label for this kind of node. This will figure in the textual representation of the synthesized post-update node. */
|
||||
abstract string label();
|
||||
}
|
||||
|
||||
/** An argument might have its value changed as a result of a call. */
|
||||
class ArgumentPreUpdateNode extends NeedsSyntheticPostUpdateNode, ArgumentNode {
|
||||
// Certain arguments, such as implicit self arguments are already post-update nodes
|
||||
// and should not have an extra node synthesised.
|
||||
ArgumentPreUpdateNode() {
|
||||
this = any(FunctionCall c).getArg(_)
|
||||
or
|
||||
// Avoid argument 0 of method calls as those have read post-update nodes.
|
||||
exists(MethodCall c, int n | n > 0 | this = c.getArg(n))
|
||||
or
|
||||
this = any(SpecialCall c).getArg(_)
|
||||
or
|
||||
// Avoid argument 0 of class calls as those have non-synthetic post-update nodes.
|
||||
exists(ClassCall c, int n | n > 0 | this = c.getArg(n))
|
||||
override Location getLocation() { result = post.getLocation() }
|
||||
}
|
||||
|
||||
override string label() { result = "arg" }
|
||||
/** A data flow node for which we should synthesise an associated pre-update node. */
|
||||
class NeedsSyntheticPreUpdateNode extends PostUpdateNode {
|
||||
NeedsSyntheticPreUpdateNode() { this = objectCreationNode() }
|
||||
|
||||
override Node getPreUpdateNode() { result.(SyntheticPreUpdateNode).getPostUpdateNode() = this }
|
||||
|
||||
/**
|
||||
* A label for this kind of node. This will figure in the textual representation of the synthesized pre-update node.
|
||||
*
|
||||
* There is currently only one reason for needing a pre-update node, so we always use that as the label.
|
||||
*/
|
||||
string label() { result = "objCreate" }
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls to constructors are treated as post-update nodes for the synthesized argument
|
||||
* that is mapped to the `self` parameter. That way, constructor calls represent the value of the
|
||||
* object after the constructor (currently only `__init__`) has run.
|
||||
*/
|
||||
CfgNode objectCreationNode() { result.getNode().(CallNode) = any(ClassCall c).getNode() }
|
||||
}
|
||||
|
||||
/** An object might have its value changed after a store. */
|
||||
class StorePreUpdateNode extends NeedsSyntheticPostUpdateNode, CfgNode {
|
||||
StorePreUpdateNode() {
|
||||
import syntheticPreUpdateNode
|
||||
|
||||
/** A module collecting the different reasons for synthesising a post-update node. */
|
||||
module syntheticPostUpdateNode {
|
||||
/** A post-update node is synthesized for all nodes which satisfy `NeedsSyntheticPostUpdateNode`. */
|
||||
class SyntheticPostUpdateNode extends PostUpdateNode, TSyntheticPostUpdateNode {
|
||||
NeedsSyntheticPostUpdateNode pre;
|
||||
|
||||
SyntheticPostUpdateNode() { this = TSyntheticPostUpdateNode(pre) }
|
||||
|
||||
override Node getPreUpdateNode() { result = pre }
|
||||
|
||||
override string toString() { result = "[post " + pre.label() + "] " + pre.toString() }
|
||||
|
||||
override Scope getScope() { result = pre.getScope() }
|
||||
|
||||
override Location getLocation() { result = pre.getLocation() }
|
||||
}
|
||||
|
||||
/** A data flow node for which we should synthesise an associated post-update node. */
|
||||
class NeedsSyntheticPostUpdateNode extends Node {
|
||||
NeedsSyntheticPostUpdateNode() {
|
||||
this = argumentPreUpdateNode()
|
||||
or
|
||||
this = storePreUpdateNode()
|
||||
or
|
||||
this = readPreUpdateNode()
|
||||
}
|
||||
|
||||
/**
|
||||
* A label for this kind of node. This will figure in the textual representation of the synthesized post-update node.
|
||||
* We favour being an arguments as the reason for the post-update node in case multiple reasons apply.
|
||||
*/
|
||||
string label() {
|
||||
if this = argumentPreUpdateNode()
|
||||
then result = "arg"
|
||||
else
|
||||
if this = storePreUpdateNode()
|
||||
then result = "store"
|
||||
else result = "read"
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An argument might have its value changed as a result of a call.
|
||||
* Certain arguments, such as implicit self arguments are already post-update nodes
|
||||
* and should not have an extra node synthesised.
|
||||
*/
|
||||
ArgumentNode argumentPreUpdateNode() {
|
||||
result = any(FunctionCall c).getArg(_)
|
||||
or
|
||||
// Avoid argument 0 of method calls as those have read post-update nodes.
|
||||
exists(MethodCall c, int n | n > 0 | result = c.getArg(n))
|
||||
or
|
||||
result = any(SpecialCall c).getArg(_)
|
||||
or
|
||||
// Avoid argument 0 of class calls as those have non-synthetic post-update nodes.
|
||||
exists(ClassCall c, int n | n > 0 | result = c.getArg(n))
|
||||
}
|
||||
|
||||
/** An object might have its value changed after a store. */
|
||||
CfgNode storePreUpdateNode() {
|
||||
exists(Attribute a |
|
||||
node = a.getObject().getAFlowNode() and
|
||||
result.getNode() = a.getObject().getAFlowNode() and
|
||||
a.getCtx() instanceof Store
|
||||
)
|
||||
}
|
||||
|
||||
override string label() { result = "store" }
|
||||
}
|
||||
|
||||
/** A node marking the state change of an object after a read. */
|
||||
class ReadPreUpdateNode extends NeedsSyntheticPostUpdateNode, CfgNode {
|
||||
ReadPreUpdateNode() {
|
||||
/**
|
||||
* A node marking the state change of an object after a read.
|
||||
*
|
||||
* A reverse read happens when the result of a read is modified, e.g. in
|
||||
* ```python
|
||||
* l = [ mutable ]
|
||||
* l[0].mutate()
|
||||
* ```
|
||||
* we may now have changed the content of `l`. To track this, there must be
|
||||
* a postupdate node for `l`.
|
||||
*/
|
||||
CfgNode readPreUpdateNode() {
|
||||
exists(Attribute a |
|
||||
node = a.getObject().getAFlowNode() and
|
||||
result.getNode() = a.getObject().getAFlowNode() and
|
||||
a.getCtx() instanceof Load
|
||||
)
|
||||
or
|
||||
result.getNode() = any(SubscriptNode s).getObject()
|
||||
or
|
||||
// The dictionary argument is read from if the callable has parameters matching the keys.
|
||||
result.getNode().getNode() = any(Call call).getKwargs()
|
||||
}
|
||||
|
||||
override string label() { result = "read" }
|
||||
}
|
||||
|
||||
/** A post-update node is synthesized for all nodes which satisfy `NeedsSyntheticPostUpdateNode`. */
|
||||
class SyntheticPostUpdateNode extends PostUpdateNode, TSyntheticPostUpdateNode {
|
||||
NeedsSyntheticPostUpdateNode pre;
|
||||
|
||||
SyntheticPostUpdateNode() { this = TSyntheticPostUpdateNode(pre) }
|
||||
|
||||
override Node getPreUpdateNode() { result = pre }
|
||||
|
||||
override string toString() { result = "[post " + pre.label() + "] " + pre.toString() }
|
||||
|
||||
override Scope getScope() { result = pre.getScope() }
|
||||
|
||||
override Location getLocation() { result = pre.getLocation() }
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls to constructors are treated as post-update nodes for the synthesized argument
|
||||
* that is mapped to the `self` parameter. That way, constructor calls represent the value of the
|
||||
* object after the constructor (currently only `__init__`) has run.
|
||||
*/
|
||||
class ObjectCreationNode extends PostUpdateNode, NeedsSyntheticPreUpdateNode, CfgNode {
|
||||
ObjectCreationNode() { node.(CallNode) = any(ClassCall c).getNode() }
|
||||
|
||||
override Node getPreUpdateNode() { result.(SyntheticPreUpdateNode).getPostUpdateNode() = this }
|
||||
|
||||
override string label() { result = "objCreate" }
|
||||
}
|
||||
import syntheticPostUpdateNode
|
||||
|
||||
class DataFlowExpr = Expr;
|
||||
|
||||
@@ -126,6 +161,15 @@ module EssaFlow {
|
||||
nodeFrom.(CfgNode).getNode() =
|
||||
nodeTo.(EssaNode).getVar().getDefinition().(AssignmentDefinition).getValue()
|
||||
or
|
||||
// Definition
|
||||
// `[a, b] = iterable`
|
||||
// nodeFrom = `iterable`, cfg node
|
||||
// nodeTo = `TIterableSequence([a, b])`
|
||||
exists(UnpackingAssignmentDirectTarget target |
|
||||
nodeFrom.asExpr() = target.getValue() and
|
||||
nodeTo = TIterableSequenceNode(target)
|
||||
)
|
||||
or
|
||||
// With definition
|
||||
// `with f(42) as x:`
|
||||
// nodeFrom is `f(42)`, cfg node
|
||||
@@ -139,6 +183,10 @@ module EssaFlow {
|
||||
contextManager.strictlyDominates(var)
|
||||
)
|
||||
or
|
||||
// Parameter definition
|
||||
// `def foo(x):`
|
||||
// nodeFrom is `x`, cfgNode
|
||||
// nodeTo is `x`, essa var
|
||||
exists(ParameterDefinition pd |
|
||||
nodeFrom.asCfgNode() = pd.getDefiningNode() and
|
||||
nodeTo.asVar() = pd.getVariable()
|
||||
@@ -161,6 +209,9 @@ module EssaFlow {
|
||||
// If expressions
|
||||
nodeFrom.asCfgNode() = nodeTo.asCfgNode().(IfExprNode).getAnOperand()
|
||||
or
|
||||
// Flow inside an unpacking assignment
|
||||
unpackingAssignmentFlowStep(nodeFrom, nodeTo)
|
||||
or
|
||||
// Overflow keyword argument
|
||||
exists(CallNode call, CallableValue callable |
|
||||
call = callable.getACall() and
|
||||
@@ -419,7 +470,7 @@ module ArgumentPassing {
|
||||
// argument unpacked from dict
|
||||
exists(string name |
|
||||
call_unpacks(call, mapping, callable, name, paramN) and
|
||||
result = TKwUnpacked(call, callable, name)
|
||||
result = TKwUnpackedNode(call, callable, name)
|
||||
)
|
||||
)
|
||||
}
|
||||
@@ -484,10 +535,12 @@ import ArgumentPassing
|
||||
*/
|
||||
newtype TDataFlowCallable =
|
||||
TCallableValue(CallableValue callable) {
|
||||
callable instanceof FunctionValue
|
||||
callable instanceof FunctionValue and
|
||||
not callable.(FunctionValue).isLambda()
|
||||
or
|
||||
callable instanceof ClassValue
|
||||
} or
|
||||
TLambda(Function lambda) { lambda.isLambda() } or
|
||||
TModule(Module m)
|
||||
|
||||
/** Represents a callable. */
|
||||
@@ -530,6 +583,27 @@ class DataFlowCallableValue extends DataFlowCallable, TCallableValue {
|
||||
override CallableValue getCallableValue() { result = callable }
|
||||
}
|
||||
|
||||
/** A class representing a callable lambda. */
|
||||
class DataFlowLambda extends DataFlowCallable, TLambda {
|
||||
Function lambda;
|
||||
|
||||
DataFlowLambda() { this = TLambda(lambda) }
|
||||
|
||||
override string toString() { result = lambda.toString() }
|
||||
|
||||
override CallNode getACall() { result = getCallableValue().getACall() }
|
||||
|
||||
override Scope getScope() { result = lambda.getEvaluatingScope() }
|
||||
|
||||
override NameNode getParameter(int n) { result = getParameter(getCallableValue(), n) }
|
||||
|
||||
override string getName() { result = "Lambda callable" }
|
||||
|
||||
override FunctionValue getCallableValue() {
|
||||
result.getOrigin().getNode() = lambda.getDefinition()
|
||||
}
|
||||
}
|
||||
|
||||
/** A class representing the scope in which a `ModuleVariableNode` appears. */
|
||||
class DataFlowModuleScope extends DataFlowCallable, TModule {
|
||||
Module mod;
|
||||
@@ -703,17 +777,6 @@ class SpecialCall extends DataFlowCall, TSpecialCall {
|
||||
}
|
||||
}
|
||||
|
||||
/** A data flow node that represents a call argument. */
|
||||
class ArgumentNode extends Node {
|
||||
ArgumentNode() { this = any(DataFlowCall c).getArg(_) }
|
||||
|
||||
/** Holds if this argument occurs at the given position in the given call. */
|
||||
predicate argumentOf(DataFlowCall call, int pos) { this = call.getArg(pos) }
|
||||
|
||||
/** Gets the call in which this node is an argument. */
|
||||
final DataFlowCall getCall() { this.argumentOf(result, _) }
|
||||
}
|
||||
|
||||
/** Gets a viable run-time target for the call `call`. */
|
||||
DataFlowCallable viableCallable(DataFlowCall call) { result = call.getCallable() }
|
||||
|
||||
@@ -844,6 +907,8 @@ predicate storeStep(Node nodeFrom, Content c, Node nodeTo) {
|
||||
or
|
||||
comprehensionStoreStep(nodeFrom, c, nodeTo)
|
||||
or
|
||||
unpackingAssignmentStoreStep(nodeFrom, c, nodeTo)
|
||||
or
|
||||
attributeStoreStep(nodeFrom, c, nodeTo)
|
||||
or
|
||||
posOverflowStoreStep(nodeFrom, c, nodeTo)
|
||||
@@ -859,6 +924,7 @@ predicate listStoreStep(CfgNode nodeFrom, ListElementContent c, CfgNode nodeTo)
|
||||
// nodeTo is the list, `[..., 42, ...]`, cfg node
|
||||
// c denotes element of list
|
||||
nodeTo.getNode().(ListNode).getAnElement() = nodeFrom.getNode() and
|
||||
not nodeTo.getNode() instanceof UnpackingAssignmentSequenceTarget and
|
||||
// Suppress unused variable warning
|
||||
c = c
|
||||
}
|
||||
@@ -884,6 +950,7 @@ predicate tupleStoreStep(CfgNode nodeFrom, TupleElementContent c, CfgNode nodeTo
|
||||
// c denotes element of tuple and index of nodeFrom
|
||||
exists(int n |
|
||||
nodeTo.getNode().(TupleNode).getElement(n) = nodeFrom.getNode() and
|
||||
not nodeTo.getNode() instanceof UnpackingAssignmentSequenceTarget and
|
||||
c.getIndex() = n
|
||||
)
|
||||
}
|
||||
@@ -974,6 +1041,8 @@ predicate kwOverflowStoreStep(CfgNode nodeFrom, DictionaryElementContent c, Node
|
||||
predicate readStep(Node nodeFrom, Content c, Node nodeTo) {
|
||||
subscriptReadStep(nodeFrom, c, nodeTo)
|
||||
or
|
||||
unpackingAssignmentReadStep(nodeFrom, c, nodeTo)
|
||||
or
|
||||
popReadStep(nodeFrom, c, nodeTo)
|
||||
or
|
||||
comprehensionReadStep(nodeFrom, c, nodeTo)
|
||||
@@ -1006,6 +1075,322 @@ predicate subscriptReadStep(CfgNode nodeFrom, Content c, CfgNode nodeTo) {
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* The unpacking assignment takes the general form
|
||||
* ```python
|
||||
* sequence = iterable
|
||||
* ```
|
||||
* where `sequence` is either a tuple or a list and it can contain wildcards.
|
||||
* The iterable can be any iterable, which means that (CodeQL modeling of) content
|
||||
* will need to change type if it should be transferred from the LHS to the RHS.
|
||||
*
|
||||
* Note that (CodeQL modeling of) content does not have to change type on data-flow
|
||||
* paths _inside_ the LHS, as the different allowed syntaxes here are merely a convenience.
|
||||
* Consequently, we model all LHS sequences as tuples, which have the more precise content
|
||||
* model, making flow to the elements more precise. If an element is a starred variable,
|
||||
* we will have to mutate the content type to be list content.
|
||||
*
|
||||
* We may for instance have
|
||||
* ```python
|
||||
* (a, b) = ["a", SOURCE] # RHS has content `ListElementContent`
|
||||
* ```
|
||||
* Due to the abstraction for list content, we do not know whether `SOURCE`
|
||||
* ends up in `a` or in `b`, so we want to overapproximate and see it in both.
|
||||
*
|
||||
* Using wildcards we may have
|
||||
* ```python
|
||||
* (a, *b) = ("a", "b", SOURCE) # RHS has content `TupleElementContent(2)`
|
||||
* ```
|
||||
* Since the starred variables are always assigned (Python-)type list, `*b` will be
|
||||
* `["b", SOURCE]`, and we will again overapproximate and assign it
|
||||
* content corresponding to anything found in the RHS.
|
||||
*
|
||||
* For a precise transfer
|
||||
* ```python
|
||||
* (a, b) = ("a", SOURCE) # RHS has content `TupleElementContent(1)`
|
||||
* ```
|
||||
* we wish to keep the precision, so only `b` receives the tuple content at index 1.
|
||||
*
|
||||
* Finally, `sequence` is actually a pattern and can have a more complicated structure,
|
||||
* such as
|
||||
* ```python
|
||||
* (a, [b, *c]) = ("a", ["b", SOURCE]) # RHS has content `TupleElementContent(1); ListElementContent`
|
||||
* ```
|
||||
* where `a` should not receive content, but `b` and `c` should. `c` will be `[SOURCE]` so
|
||||
* should have the content transferred, while `b` should read it.
|
||||
*
|
||||
* To transfer content from RHS to the elements of the LHS in the expression `sequence = iterable`,
|
||||
* we use two synthetic nodes:
|
||||
*
|
||||
* - `TIterableSequence(sequence)` which captures the content-modeling the entire `sequence` will have
|
||||
* (essentially just a copy of the content-modeling the RHS has)
|
||||
*
|
||||
* - `TIterableElement(sequence)` which captures the content-modeling that will be assigned to an element.
|
||||
* Note that an empty access path means that the value we are tracking flows directly to the element.
|
||||
*
|
||||
*
|
||||
* The `TIterableSequence(sequence)` is at this point superflous but becomes useful when handling recursive
|
||||
* structures in the LHS, where `sequence` is some internal sequence node. We can have a uniform treatment
|
||||
* by always having these two synthetic nodes. So we transfer to (or, in the recursive case, read into)
|
||||
* `TIterableSequence(sequence)`, from which we take a read step to `TIterableElement(sequence)` and then a
|
||||
* store step to `sequence`.
|
||||
*
|
||||
* This allows the unknown content from the RHS to be read into `TIterableElement(sequence)` and tuple content
|
||||
* to then be stored into `sequence`. If the content is already tuple content, this inderection creates crosstalk
|
||||
* between indices. Therefore, tuple content is never read into `TIterableElement(sequence)`; it is instead
|
||||
* transferred directly from `TIterableSequence(sequence)` to `sequence` via a flow step. Such a flow step will
|
||||
* also transfer other content, but only tuple content is further read from `sequence` into its elements.
|
||||
*
|
||||
* The strategy is then via several read-, store-, and flow steps:
|
||||
* 1. [Flow] Content is transferred from `iterable` to `TIterableSequence(sequence)` via a
|
||||
* flow step. From here, everything happens on the LHS.
|
||||
*
|
||||
* 2. [Flow] Content is transferred from `TIterableSequence(sequence)` to `sequence` via a
|
||||
* flow step. (Here only tuple content is relevant.)
|
||||
*
|
||||
* 3. [Read] Content is read from `TIterableSequence(sequence)` into `TIterableElement(sequence)`.
|
||||
* As `sequence` is modeled as a tuple, we will not read tuple content as that would allow
|
||||
* crosstalk.
|
||||
*
|
||||
* 4. [Store] Content is stored from `TIterableElement(sequence)` to `sequence`.
|
||||
* Content type is `TupleElementContent` with indices taken from the syntax.
|
||||
* For instance, if `sequence` is `(a, *b, c)`, content is written to index 0, 1, and 2.
|
||||
* This is adequate as the route through `TIterableElement(sequence)` does not transfer precise content.
|
||||
*
|
||||
* 5. [Read] Content is read from `sequence` to its elements.
|
||||
* a) If the element is a plain variable, the target is the corresponding essa node.
|
||||
*
|
||||
* b) If the element is itself a sequence, with control-flow node `seq`, the target is `TIterableSequence(seq)`.
|
||||
*
|
||||
* c) If the element is a starred variable, with control-flow node `v`, the target is `TIterableElement(v)`.
|
||||
*
|
||||
* 6. [Store] Content is stored from `TIterableElement(v)` to the essa variable for `v`, with
|
||||
* content type `ListElementContent`.
|
||||
*
|
||||
* 7. [Flow, Read, Store] Steps 2 through 7 are repeated for all recursive elements which are sequences.
|
||||
*
|
||||
*
|
||||
* We illustrate the above steps on the assignment
|
||||
*
|
||||
* ```python
|
||||
* (a, b) = ["a", SOURCE]
|
||||
* ```
|
||||
*
|
||||
* Looking at the content propagation to `a`:
|
||||
* `["a", SOURCE]`: [ListElementContent]
|
||||
*
|
||||
* --Step 1-->
|
||||
*
|
||||
* `TIterableSequence((a, b))`: [ListElementContent]
|
||||
*
|
||||
* --Step 3-->
|
||||
*
|
||||
* `TIterableElement((a, b))`: []
|
||||
*
|
||||
* --Step 4-->
|
||||
*
|
||||
* `(a, b)`: [TupleElementContent(0)]
|
||||
*
|
||||
* --Step 5a-->
|
||||
*
|
||||
* `a`: []
|
||||
*
|
||||
* Meaning there is data-flow from the RHS to `a` (an over approximation). The same logic would be applied to show there is data-flow to `b`. Note that _Step 3_ and _Step 4_ would not have been needed if the RHS had been a tuple (since that would have been able to use _Step 2_ instead).
|
||||
*
|
||||
* Another, more complicated example:
|
||||
* ```python
|
||||
* (a, [b, *c]) = ["a", [SOURCE]]
|
||||
* ```
|
||||
* where the path to `c` is
|
||||
*
|
||||
* `["a", [SOURCE]]`: [ListElementContent; ListElementContent]
|
||||
*
|
||||
* --Step 1-->
|
||||
*
|
||||
* `TIterableSequence((a, [b, *c]))`: [ListElementContent; ListElementContent]
|
||||
*
|
||||
* --Step 3-->
|
||||
*
|
||||
* `TIterableElement((a, [b, *c]))`: [ListElementContent]
|
||||
*
|
||||
* --Step 4-->
|
||||
*
|
||||
* `(a, [b, *c])`: [TupleElementContent(1); ListElementContent]
|
||||
*
|
||||
* --Step 5b-->
|
||||
*
|
||||
* `TIterableSequence([b, *c])`: [ListElementContent]
|
||||
*
|
||||
* --Step 3-->
|
||||
*
|
||||
* `TIterableElement([b, *c])`: []
|
||||
*
|
||||
* --Step 4-->
|
||||
*
|
||||
* `[b, *c]`: [TupleElementContent(1)]
|
||||
*
|
||||
* --Step 5c-->
|
||||
*
|
||||
* `TIterableElement(c)`: []
|
||||
*
|
||||
* --Step 6-->
|
||||
*
|
||||
* `c`: [ListElementContent]
|
||||
*/
|
||||
module UnpackingAssignment {
|
||||
/** A direct (or top-level) target of an unpacking assignment. */
|
||||
class UnpackingAssignmentDirectTarget extends ControlFlowNode {
|
||||
Expr value;
|
||||
|
||||
UnpackingAssignmentDirectTarget() {
|
||||
this instanceof SequenceNode and
|
||||
exists(Assign assign | this.getNode() = assign.getATarget() | value = assign.getValue())
|
||||
}
|
||||
|
||||
Expr getValue() { result = value }
|
||||
}
|
||||
|
||||
/** A (possibly recursive) target of an unpacking assignment. */
|
||||
class UnpackingAssignmentTarget extends ControlFlowNode {
|
||||
UnpackingAssignmentTarget() {
|
||||
this instanceof UnpackingAssignmentDirectTarget
|
||||
or
|
||||
this = any(UnpackingAssignmentSequenceTarget parent).getAnElement()
|
||||
}
|
||||
}
|
||||
|
||||
/** A (possibly recursive) target of an unpacking assignment which is also a sequence. */
|
||||
class UnpackingAssignmentSequenceTarget extends UnpackingAssignmentTarget {
|
||||
UnpackingAssignmentSequenceTarget() { this instanceof SequenceNode }
|
||||
|
||||
ControlFlowNode getElement(int i) { result = this.(SequenceNode).getElement(i) }
|
||||
|
||||
ControlFlowNode getAnElement() { result = this.getElement(_) }
|
||||
}
|
||||
|
||||
/**
|
||||
* Step 2
|
||||
* Data flows from `TIterableSequence(sequence)` to `sequence`
|
||||
*/
|
||||
predicate unpackingAssignmentFlowStep(Node nodeFrom, Node nodeTo) {
|
||||
exists(UnpackingAssignmentSequenceTarget target |
|
||||
nodeFrom = TIterableSequenceNode(target) and
|
||||
nodeTo.asCfgNode() = target
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Step 3
|
||||
* Data flows from `TIterableSequence(sequence)` into `TIterableElement(sequence)`.
|
||||
* As `sequence` is modeled as a tuple, we will not read tuple content as that would allow
|
||||
* crosstalk.
|
||||
*/
|
||||
predicate unpackingAssignmentConvertingReadStep(Node nodeFrom, Content c, Node nodeTo) {
|
||||
exists(UnpackingAssignmentSequenceTarget target |
|
||||
nodeFrom = TIterableSequenceNode(target) and
|
||||
nodeTo = TIterableElementNode(target) and
|
||||
(
|
||||
c instanceof ListElementContent
|
||||
or
|
||||
c instanceof SetElementContent
|
||||
// TODO: dict content in iterable unpacking not handled
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Step 4
|
||||
* Data flows from `TIterableElement(sequence)` to `sequence`.
|
||||
* Content type is `TupleElementContent` with indices taken from the syntax.
|
||||
* For instance, if `sequence` is `(a, *b, c)`, content is written to index 0, 1, and 2.
|
||||
*/
|
||||
predicate unpackingAssignmentConvertingStoreStep(Node nodeFrom, Content c, Node nodeTo) {
|
||||
exists(UnpackingAssignmentSequenceTarget target |
|
||||
nodeFrom = TIterableElementNode(target) and
|
||||
nodeTo.asCfgNode() = target and
|
||||
exists(int index | exists(target.getElement(index)) |
|
||||
c.(TupleElementContent).getIndex() = index
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Step 5
|
||||
* For a sequence node inside an iterable unpacking, data flows from the sequence to its elements. There are
|
||||
* three cases for what `toNode` should be:
|
||||
* a) If the element is a plain variable, `toNode` is the corresponding essa node.
|
||||
*
|
||||
* b) If the element is itself a sequence, with control-flow node `seq`, `toNode` is `TIterableSequence(seq)`.
|
||||
*
|
||||
* c) If the element is a starred variable, with control-flow node `v`, `toNode` is `TIterableElement(v)`.
|
||||
*/
|
||||
predicate unpackingAssignmentElementReadStep(Node nodeFrom, Content c, Node nodeTo) {
|
||||
exists(
|
||||
UnpackingAssignmentSequenceTarget target, int index, ControlFlowNode element, int starIndex
|
||||
|
|
||||
target.getElement(starIndex) instanceof StarredNode
|
||||
or
|
||||
not exists(target.getAnElement().(StarredNode)) and
|
||||
starIndex = -1
|
||||
|
|
||||
nodeFrom.asCfgNode() = target and
|
||||
element = target.getElement(index) and
|
||||
(
|
||||
if starIndex = -1 or index < starIndex
|
||||
then c.(TupleElementContent).getIndex() = index
|
||||
else
|
||||
// This could get big if big tuples exist
|
||||
if index = starIndex
|
||||
then c.(TupleElementContent).getIndex() >= index
|
||||
else c.(TupleElementContent).getIndex() >= index - 1
|
||||
) and
|
||||
(
|
||||
if element instanceof SequenceNode
|
||||
then
|
||||
// Step 5b
|
||||
nodeTo = TIterableSequenceNode(element)
|
||||
else
|
||||
if element instanceof StarredNode
|
||||
then
|
||||
// Step 5c
|
||||
nodeTo = TIterableElementNode(element)
|
||||
else
|
||||
// Step 5a
|
||||
nodeTo.asVar().getDefinition().(MultiAssignmentDefinition).getDefiningNode() = element
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Step 6
|
||||
* Data flows from `TIterableElement(v)` to the essa variable for `v`, with
|
||||
* content type `ListElementContent`.
|
||||
*/
|
||||
predicate unpackingAssignmentStarredElementStoreStep(Node nodeFrom, Content c, Node nodeTo) {
|
||||
exists(ControlFlowNode starred | starred.getNode() instanceof Starred |
|
||||
nodeFrom = TIterableElementNode(starred) and
|
||||
nodeTo.asVar().getDefinition().(MultiAssignmentDefinition).getDefiningNode() = starred and
|
||||
c instanceof ListElementContent
|
||||
)
|
||||
}
|
||||
|
||||
/** All read steps associated with unpacking assignment. */
|
||||
predicate unpackingAssignmentReadStep(Node nodeFrom, Content c, Node nodeTo) {
|
||||
unpackingAssignmentElementReadStep(nodeFrom, c, nodeTo)
|
||||
or
|
||||
unpackingAssignmentConvertingReadStep(nodeFrom, c, nodeTo)
|
||||
}
|
||||
|
||||
/** All store steps associated with unpacking assignment. */
|
||||
predicate unpackingAssignmentStoreStep(Node nodeFrom, Content c, Node nodeTo) {
|
||||
unpackingAssignmentStarredElementStoreStep(nodeFrom, c, nodeTo)
|
||||
or
|
||||
unpackingAssignmentConvertingStoreStep(nodeFrom, c, nodeTo)
|
||||
}
|
||||
}
|
||||
|
||||
import UnpackingAssignment
|
||||
|
||||
/** Data flows from a sequence to a call to `pop` on the sequence. */
|
||||
predicate popReadStep(CfgNode nodeFrom, Content c, CfgNode nodeTo) {
|
||||
// set.pop or list.pop
|
||||
@@ -1092,7 +1477,7 @@ predicate attributeReadStep(CfgNode nodeFrom, AttributeContent c, CfgNode nodeTo
|
||||
predicate kwUnpackReadStep(CfgNode nodeFrom, DictionaryElementContent c, Node nodeTo) {
|
||||
exists(CallNode call, CallableValue callable, string name |
|
||||
nodeFrom.asCfgNode() = call.getNode().getKwargs().getAFlowNode() and
|
||||
nodeTo = TKwUnpacked(call, callable, name) and
|
||||
nodeTo = TKwUnpackedNode(call, callable, name) and
|
||||
name = c.getKey()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -58,9 +58,18 @@ newtype TNode =
|
||||
* That is, `call` contains argument `**{"foo": bar}` which is passed
|
||||
* to parameter `foo` of `callable`.
|
||||
*/
|
||||
TKwUnpacked(CallNode call, CallableValue callable, string name) {
|
||||
TKwUnpackedNode(CallNode call, CallableValue callable, string name) {
|
||||
call_unpacks(call, _, callable, name, _)
|
||||
}
|
||||
} or
|
||||
/**
|
||||
* A synthetic node representing that an iterable sequence flows to consumer.
|
||||
*/
|
||||
TIterableSequenceNode(UnpackingAssignmentSequenceTarget consumer) or
|
||||
/**
|
||||
* A synthetic node representing that there may be an iterable element
|
||||
* for `consumer` to consume.
|
||||
*/
|
||||
TIterableElementNode(UnpackingAssignmentTarget consumer)
|
||||
|
||||
/** Helper for `Node::getEnclosingCallable`. */
|
||||
private DataFlowCallable getCallableScope(Scope s) {
|
||||
@@ -179,7 +188,12 @@ ExprNode exprNode(DataFlowExpr e) { result.getNode().getNode() = e }
|
||||
class ParameterNode extends CfgNode {
|
||||
ParameterDefinition def;
|
||||
|
||||
ParameterNode() { node = def.getDefiningNode() }
|
||||
ParameterNode() {
|
||||
node = def.getDefiningNode() and
|
||||
// Disregard parameters that we cannot resolve
|
||||
// TODO: Make this unnecessary
|
||||
exists(DataFlowCallable c | node = c.getParameter(_))
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if this node is the parameter of callable `c` at the
|
||||
@@ -193,6 +207,17 @@ class ParameterNode extends CfgNode {
|
||||
Parameter getParameter() { result = def.getParameter() }
|
||||
}
|
||||
|
||||
/** A data flow node that represents a call argument. */
|
||||
class ArgumentNode extends Node {
|
||||
ArgumentNode() { this = any(DataFlowCall c).getArg(_) }
|
||||
|
||||
/** Holds if this argument occurs at the given position in the given call. */
|
||||
predicate argumentOf(DataFlowCall call, int pos) { this = call.getArg(pos) }
|
||||
|
||||
/** Gets the call in which this node is an argument. */
|
||||
final DataFlowCall getCall() { this.argumentOf(result, _) }
|
||||
}
|
||||
|
||||
/**
|
||||
* A node associated with an object after an operation that might have
|
||||
* changed its state.
|
||||
@@ -322,11 +347,11 @@ class KwOverflowNode extends Node, TKwOverflowNode {
|
||||
* The node representing the synthetic argument of a call that is unpacked from a dictionary
|
||||
* argument.
|
||||
*/
|
||||
class KwUnpacked extends Node, TKwUnpacked {
|
||||
class KwUnpackedNode extends Node, TKwUnpackedNode {
|
||||
CallNode call;
|
||||
string name;
|
||||
|
||||
KwUnpacked() { this = TKwUnpacked(call, _, name) }
|
||||
KwUnpackedNode() { this = TKwUnpackedNode(call, _, name) }
|
||||
|
||||
override string toString() { result = "KwUnpacked " + name }
|
||||
|
||||
@@ -340,6 +365,42 @@ class KwUnpacked extends Node, TKwUnpacked {
|
||||
override Location getLocation() { result = call.getLocation() }
|
||||
}
|
||||
|
||||
/**
|
||||
* A synthetic node representing an iterable sequence. Used for changing content type
|
||||
* for instance from a `ListElement` to a `TupleElement`, especially if the content is
|
||||
* transferred via a read step which cannot be broken up into a read and a store. The
|
||||
* read step then targets TIterableSequence, and the conversion can happen via a read
|
||||
* step to TIterableElement followed by a store step to the target.
|
||||
*/
|
||||
class IterableSequenceNode extends Node, TIterableSequenceNode {
|
||||
CfgNode consumer;
|
||||
|
||||
IterableSequenceNode() { this = TIterableSequenceNode(consumer.getNode()) }
|
||||
|
||||
override string toString() { result = "IterableSequence" }
|
||||
|
||||
override DataFlowCallable getEnclosingCallable() { result = consumer.getEnclosingCallable() }
|
||||
|
||||
override Location getLocation() { result = consumer.getLocation() }
|
||||
}
|
||||
|
||||
/**
|
||||
* A synthetic node representing an iterable element. Used for changing content type
|
||||
* for instance from a `ListElement` to a `TupleElement`. This would happen via a
|
||||
* read step from the list to IterableElement followed by a store step to the tuple.
|
||||
*/
|
||||
class IterableElementNode extends Node, TIterableElementNode {
|
||||
CfgNode consumer;
|
||||
|
||||
IterableElementNode() { this = TIterableElementNode(consumer.getNode()) }
|
||||
|
||||
override string toString() { result = "IterableElement" }
|
||||
|
||||
override DataFlowCallable getEnclosingCallable() { result = consumer.getEnclosingCallable() }
|
||||
|
||||
override Location getLocation() { result = consumer.getLocation() }
|
||||
}
|
||||
|
||||
/**
|
||||
* A node that controls whether other nodes are evaluated.
|
||||
*/
|
||||
|
||||
@@ -68,5 +68,11 @@ Node importNode(string name) {
|
||||
// Because named imports are modelled as `AttrRead`s, the statement `from foo import bar as baz`
|
||||
// is interpreted as if it was an assignment `baz = foo.bar`, which means `baz` gets tracked as a
|
||||
// reference to `foo.bar`, as desired.
|
||||
result.asCfgNode().getNode() = any(ImportExpr i | i.getName() = name)
|
||||
exists(ImportExpr imp_expr |
|
||||
imp_expr.getName() = name and
|
||||
result.asCfgNode().getNode() = imp_expr and
|
||||
// in `import foo.bar` we DON'T want to give a result for `importNode("foo.bar")`,
|
||||
// only for `importNode("foo")`. We exclude those cases with the following clause.
|
||||
not exists(Import imp | imp.getAName().getValue() = imp_expr)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1938,7 +1938,23 @@ private module Django {
|
||||
private class DjangoUrlsRePathCall extends DjangoRegexRouteSetup {
|
||||
override CallNode node;
|
||||
|
||||
DjangoUrlsRePathCall() { node.getFunction() = django::urls::re_path().asCfgNode() }
|
||||
DjangoUrlsRePathCall() {
|
||||
node.getFunction() = django::urls::re_path().asCfgNode() and
|
||||
// `django.conf.urls.url` (which we support directly with
|
||||
// `DjangoConfUrlsUrlCall`), is implemented in Django 2+ as backward compatibility
|
||||
// using `django.urls.re_path`. See
|
||||
// https://github.com/django/django/blob/stable/3.2.x/django/conf/urls/__init__.py#L22
|
||||
// Since we're still installing dependencies and analyzing their source code,
|
||||
// without explicitly filtering out this call, we would be double-counting such
|
||||
// route-setups :( One practical negative side effect of double-counting it, is
|
||||
// that since we can't figure out the URL in the library code calling `django.urls.re_path`
|
||||
// (because we only consider local flow), we will for all those cases mark ANY parameter
|
||||
// as being a routed-parameter, which can lead to FPs.
|
||||
not exists(Module mod |
|
||||
mod.getName() = "django.conf.urls.__init__" and
|
||||
node.getEnclosingModule() = mod
|
||||
)
|
||||
}
|
||||
|
||||
override DataFlow::Node getUrlPatternArg() {
|
||||
result.asCfgNode() = [node.getArg(0), node.getArgByName("route")]
|
||||
|
||||
@@ -227,6 +227,17 @@ private module Tornado {
|
||||
/** Gets a reference the `redirect` method. */
|
||||
DataFlow::Node redirectMethod() { result = redirectMethod(DataFlow::TypeTracker::end()) }
|
||||
|
||||
/** Gets a reference to the `write` method. */
|
||||
private DataFlow::Node writeMethod(DataFlow::TypeTracker t) {
|
||||
t.startInAttr("write") and
|
||||
result = instance()
|
||||
or
|
||||
exists(DataFlow::TypeTracker t2 | result = writeMethod(t2).track(t2, t))
|
||||
}
|
||||
|
||||
/** Gets a reference to the `write` method. */
|
||||
DataFlow::Node writeMethod() { result = writeMethod(DataFlow::TypeTracker::end()) }
|
||||
|
||||
private class AdditionalTaintStep extends TaintTracking::AdditionalTaintStep {
|
||||
override predicate step(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) {
|
||||
// Method access
|
||||
@@ -575,6 +586,26 @@ private module Tornado {
|
||||
override DataFlow::Node getBody() { none() }
|
||||
|
||||
override string getMimetypeDefault() { none() }
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to `tornado.web.RequestHandler.write` method.
|
||||
*
|
||||
* See https://www.tornadoweb.org/en/stable/web.html?highlight=write#tornado.web.RequestHandler.write
|
||||
*/
|
||||
private class TornadoRequestHandlerWriteCall extends HTTP::Server::HttpResponse::Range,
|
||||
DataFlow::CfgNode {
|
||||
override CallNode node;
|
||||
|
||||
TornadoRequestHandlerWriteCall() {
|
||||
node.getFunction() = tornado::web::RequestHandler::writeMethod().asCfgNode()
|
||||
}
|
||||
|
||||
override DataFlow::Node getBody() {
|
||||
result.asCfgNode() in [node.getArg(0), node.getArgByName("chunk")]
|
||||
}
|
||||
|
||||
override string getMimetypeDefault() { result = "text/html" }
|
||||
|
||||
override DataFlow::Node getMimetypeOrContentTypeArg() { none() }
|
||||
}
|
||||
|
||||
@@ -720,6 +720,9 @@ abstract class FunctionValue extends CallableValue {
|
||||
|
||||
/** Gets a class that this function may return */
|
||||
abstract ClassValue getAnInferredReturnType();
|
||||
|
||||
/** Holds if this function represents a lambda. */
|
||||
predicate isLambda() { this.getOrigin().getNode() instanceof Lambda }
|
||||
}
|
||||
|
||||
/** Class representing Python functions */
|
||||
|
||||
40
python/ql/test/experimental/dataflow/TestUtil/FlowTest.qll
Normal file
40
python/ql/test/experimental/dataflow/TestUtil/FlowTest.qll
Normal file
@@ -0,0 +1,40 @@
|
||||
import python
|
||||
import semmle.python.dataflow.new.DataFlow
|
||||
import TestUtilities.InlineExpectationsTest
|
||||
import experimental.dataflow.TestUtil.PrintNode
|
||||
|
||||
abstract class FlowTest extends InlineExpectationsTest {
|
||||
bindingset[this]
|
||||
FlowTest() { any() }
|
||||
|
||||
abstract string flowTag();
|
||||
|
||||
abstract predicate relevantFlow(DataFlow::Node fromNode, DataFlow::Node toNode);
|
||||
|
||||
override string getARelevantTag() { result = this.flowTag() }
|
||||
|
||||
override predicate hasActualResult(Location location, string element, string tag, string value) {
|
||||
exists(DataFlow::Node fromNode, DataFlow::Node toNode | this.relevantFlow(fromNode, toNode) |
|
||||
location = toNode.getLocation() and
|
||||
tag = this.flowTag() and
|
||||
value =
|
||||
"\"" + prettyNode(fromNode).replaceAll("\"", "'") + lineStr(fromNode, toNode) + " -> " +
|
||||
prettyNode(toNode).replaceAll("\"", "'") + "\"" and
|
||||
element = toNode.toString()
|
||||
)
|
||||
}
|
||||
|
||||
pragma[inline]
|
||||
private string lineStr(DataFlow::Node fromNode, DataFlow::Node toNode) {
|
||||
exists(int delta |
|
||||
delta = fromNode.getLocation().getStartLine() - toNode.getLocation().getStartLine()
|
||||
|
|
||||
if delta = 0
|
||||
then result = ""
|
||||
else
|
||||
if delta > 0
|
||||
then result = ", l:+" + delta.toString()
|
||||
else result = ", l:" + delta.toString()
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
import python
|
||||
import semmle.python.dataflow.new.DataFlow
|
||||
import FlowTest
|
||||
|
||||
class LocalFlowStepTest extends FlowTest {
|
||||
LocalFlowStepTest() { this = "LocalFlowStepTest" }
|
||||
|
||||
override string flowTag() { result = "step" }
|
||||
|
||||
override predicate relevantFlow(DataFlow::Node fromNode, DataFlow::Node toNode) {
|
||||
DataFlow::localFlowStep(fromNode, toNode)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
import python
|
||||
import semmle.python.dataflow.new.DataFlow
|
||||
private import semmle.python.dataflow.new.internal.DataFlowPrivate
|
||||
import FlowTest
|
||||
|
||||
class MaximalFlowTest extends FlowTest {
|
||||
MaximalFlowTest() { this = "MaximalFlowTest" }
|
||||
|
||||
override string flowTag() { result = "flow" }
|
||||
|
||||
override predicate relevantFlow(DataFlow::Node source, DataFlow::Node sink) {
|
||||
source != sink and
|
||||
exists(MaximalFlowsConfig cfg | cfg.hasFlow(source, sink))
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A configuration to find all "maximal" flows.
|
||||
* To be used on small programs.
|
||||
*/
|
||||
class MaximalFlowsConfig extends DataFlow::Configuration {
|
||||
MaximalFlowsConfig() { this = "MaximalFlowsConfig" }
|
||||
|
||||
override predicate isSource(DataFlow::Node node) {
|
||||
exists(node.getLocation().getFile().getRelativePath()) and
|
||||
not node.asCfgNode() instanceof CallNode and
|
||||
not node.asCfgNode().getNode() instanceof Return and
|
||||
not node instanceof DataFlow::ParameterNode and
|
||||
not node instanceof DataFlow::PostUpdateNode and
|
||||
// not node.asExpr() instanceof FunctionExpr and
|
||||
// not node.asExpr() instanceof ClassExpr and
|
||||
not exists(DataFlow::Node pred | DataFlow::localFlowStep(pred, node))
|
||||
}
|
||||
|
||||
override predicate isSink(DataFlow::Node node) {
|
||||
exists(node.getLocation().getFile().getRelativePath()) and
|
||||
not any(CallNode c).getArg(_) = node.asCfgNode() and
|
||||
not node instanceof DataFlow::ArgumentNode and
|
||||
not node.asCfgNode().(NameNode).getId().matches("SINK%") and
|
||||
not exists(DataFlow::Node succ | DataFlow::localFlowStep(node, succ))
|
||||
}
|
||||
}
|
||||
31
python/ql/test/experimental/dataflow/TestUtil/PrintNode.qll
Normal file
31
python/ql/test/experimental/dataflow/TestUtil/PrintNode.qll
Normal file
@@ -0,0 +1,31 @@
|
||||
import python
|
||||
import semmle.python.dataflow.new.DataFlow
|
||||
|
||||
string prettyExp(Expr e) {
|
||||
not e instanceof Num and
|
||||
not e instanceof StrConst and
|
||||
not e instanceof Subscript and
|
||||
not e instanceof Call and
|
||||
not e instanceof Attribute and
|
||||
result = e.toString()
|
||||
or
|
||||
result = e.(Num).getN()
|
||||
or
|
||||
result =
|
||||
e.(StrConst).getPrefix() + e.(StrConst).getText() +
|
||||
e.(StrConst).getPrefix().regexpReplaceAll("[a-zA-Z]+", "")
|
||||
or
|
||||
result = prettyExp(e.(Subscript).getObject()) + "[" + prettyExp(e.(Subscript).getIndex()) + "]"
|
||||
or
|
||||
(
|
||||
if exists(e.(Call).getAnArg()) or exists(e.(Call).getANamedArg())
|
||||
then result = prettyExp(e.(Call).getFunc()) + "(..)"
|
||||
else result = prettyExp(e.(Call).getFunc()) + "()"
|
||||
)
|
||||
or
|
||||
result = prettyExp(e.(Attribute).getObject()) + "." + e.(Attribute).getName()
|
||||
}
|
||||
|
||||
string prettyNode(DataFlow::Node node) {
|
||||
if exists(node.asExpr()) then result = prettyExp(node.asExpr()) else result = node.toString()
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
import python
|
||||
import semmle.python.dataflow.new.DataFlow
|
||||
import TestUtilities.InlineExpectationsTest
|
||||
import experimental.dataflow.TestUtil.PrintNode
|
||||
|
||||
/**
|
||||
* A routing test is designed to test that values are routed to the
|
||||
* correct arguments of the correct functions. It is assumed that
|
||||
* the functions tested sink their arguments sequentially, that is
|
||||
* `SINK1(arg1)`, etc.
|
||||
*/
|
||||
abstract class RoutingTest extends InlineExpectationsTest {
|
||||
bindingset[this]
|
||||
RoutingTest() { any() }
|
||||
|
||||
abstract string flowTag();
|
||||
|
||||
abstract predicate relevantFlow(DataFlow::Node fromNode, DataFlow::Node toNode);
|
||||
|
||||
override string getARelevantTag() { result in ["func", this.flowTag()] }
|
||||
|
||||
override predicate hasActualResult(Location location, string element, string tag, string value) {
|
||||
exists(DataFlow::Node fromNode, DataFlow::Node toNode | this.relevantFlow(fromNode, toNode) |
|
||||
location = fromNode.getLocation() and
|
||||
element = fromNode.toString() and
|
||||
(
|
||||
tag = this.flowTag() and
|
||||
if "\"" + tag + "\"" = fromValue(fromNode) then value = "" else value = fromValue(fromNode)
|
||||
or
|
||||
tag = "func" and
|
||||
value = toFunc(toNode) and
|
||||
not value = fromFunc(fromNode)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
pragma[inline]
|
||||
private string fromValue(DataFlow::Node fromNode) {
|
||||
result = "\"" + prettyNode(fromNode).replaceAll("\"", "'") + "\""
|
||||
}
|
||||
|
||||
pragma[inline]
|
||||
private string fromFunc(DataFlow::ArgumentNode fromNode) {
|
||||
result = fromNode.getCall().getNode().(CallNode).getFunction().getNode().(Name).getId()
|
||||
}
|
||||
|
||||
pragma[inline]
|
||||
private string toFunc(DataFlow::Node toNode) {
|
||||
result = toNode.getEnclosingCallable().getCallableValue().getScope().getQualifiedName() // TODO: More robust pretty printing?
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
import experimental.dataflow.TestUtil.LocalFlowStepTest
|
||||
@@ -0,0 +1 @@
|
||||
import experimental.dataflow.TestUtil.MaximalFlowTest
|
||||
@@ -1,7 +1,7 @@
|
||||
def obfuscated_id(x):
|
||||
y = x
|
||||
z = y
|
||||
return z
|
||||
def obfuscated_id(x): #$ step="FunctionExpr -> GSSA Variable obfuscated_id" step="x -> SSA variable x"
|
||||
y = x #$ step="x -> SSA variable y" step="SSA variable x, l:-1 -> x"
|
||||
z = y #$ step="y -> SSA variable z" step="SSA variable y, l:-1 -> y"
|
||||
return z #$ flow="42, l:+2 -> z" step="SSA variable z, l:-1 -> z"
|
||||
|
||||
a = 42
|
||||
b = obfuscated_id(a)
|
||||
a = 42 #$ step="42 -> GSSA Variable a"
|
||||
b = obfuscated_id(a) #$ flow="42, l:-1 -> GSSA Variable b" flow="FunctionExpr, l:-6 -> obfuscated_id" step="obfuscated_id(..) -> GSSA Variable b" step="GSSA Variable obfuscated_id, l:-6 -> obfuscated_id" step="GSSA Variable a, l:-1 -> a"
|
||||
|
||||
@@ -11,7 +11,7 @@ class CallGraphConfig extends DataFlow::Configuration {
|
||||
override predicate isSource(DataFlow::Node node) {
|
||||
node instanceof DataFlowPrivate::ReturnNode
|
||||
or
|
||||
node instanceof DataFlowPrivate::ArgumentNode
|
||||
node instanceof DataFlow::ArgumentNode
|
||||
}
|
||||
|
||||
override predicate isSink(DataFlow::Node node) {
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
uniqueEnclosingCallable
|
||||
| test.py:239:27:239:27 | ControlFlowNode for p | Node should have one enclosing callable but has 0. |
|
||||
uniqueType
|
||||
uniqueNodeLocation
|
||||
missingLocation
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
| test.py:239:27:239:27 | Parameter | There is no `ParameterNode` associated with this parameter. |
|
||||
@@ -0,0 +1,7 @@
|
||||
import python
|
||||
import semmle.python.dataflow.new.DataFlow
|
||||
|
||||
query predicate parameterWithoutNode(Parameter p, string msg) {
|
||||
not exists(DataFlow::ParameterNode node | p = node.getParameter()) and
|
||||
msg = "There is no `ParameterNode` associated with this parameter."
|
||||
}
|
||||
@@ -249,3 +249,10 @@ def synth_arg_kwOverflow():
|
||||
|
||||
def synth_arg_kwUnpacked():
|
||||
overflowCallee(**{"p": "42"})
|
||||
|
||||
def split_lambda(cond):
|
||||
if cond:
|
||||
pass
|
||||
foo = lambda x: False
|
||||
if cond:
|
||||
pass
|
||||
|
||||
@@ -86,12 +86,12 @@ def argument_passing(
|
||||
|
||||
@expects(7)
|
||||
def test_argument_passing1():
|
||||
argument_passing(arg1, *(arg2, arg3, arg4), e=arg5, **{"f": arg6, "g": arg7})
|
||||
argument_passing(arg1, *(arg2, arg3, arg4), e=arg5, **{"f": arg6, "g": arg7}) #$ arg1 arg7 func=argument_passing MISSING: arg2 arg3="arg3 arg4 arg5 arg6
|
||||
|
||||
|
||||
@expects(7)
|
||||
def test_argument_passing2():
|
||||
argument_passing(arg1, arg2, arg3, f=arg6)
|
||||
argument_passing(arg1, arg2, arg3, f=arg6) #$ arg1 arg2 arg3
|
||||
|
||||
|
||||
def with_pos_only(a, /, b):
|
||||
@@ -101,9 +101,9 @@ def with_pos_only(a, /, b):
|
||||
|
||||
@expects(6)
|
||||
def test_pos_only():
|
||||
with_pos_only(arg1, arg2)
|
||||
with_pos_only(arg1, b=arg2)
|
||||
with_pos_only(arg1, *(arg2,))
|
||||
with_pos_only(arg1, arg2) #$ arg1 arg2
|
||||
with_pos_only(arg1, b=arg2) #$ arg1 arg2
|
||||
with_pos_only(arg1, *(arg2,)) #$ arg1 MISSING: arg2
|
||||
|
||||
|
||||
def with_multiple_kw_args(a, b, c):
|
||||
@@ -114,13 +114,13 @@ def with_multiple_kw_args(a, b, c):
|
||||
|
||||
@expects(12)
|
||||
def test_multiple_kw_args():
|
||||
with_multiple_kw_args(b=arg2, c=arg3, a=arg1)
|
||||
with_multiple_kw_args(arg1, *(arg2,), arg3)
|
||||
with_multiple_kw_args(arg1, **{"c": arg3}, b=arg2)
|
||||
with_multiple_kw_args(**{"b": arg2}, **{"c": arg3}, **{"a": arg1})
|
||||
with_multiple_kw_args(b=arg2, c=arg3, a=arg1) #$ arg1 arg2 arg3
|
||||
with_multiple_kw_args(arg1, *(arg2,), arg3) #$ arg1 MISSING: arg2 arg3
|
||||
with_multiple_kw_args(arg1, **{"c": arg3}, b=arg2) #$ arg1 arg3 func=with_multiple_kw_args MISSING: arg2
|
||||
with_multiple_kw_args(**{"b": arg2}, **{"c": arg3}, **{"a": arg1}) #$ arg1 arg2 arg3 func=with_multiple_kw_args
|
||||
|
||||
|
||||
def with_default_arguments(a=arg1, b=arg2, c=arg3):
|
||||
def with_default_arguments(a=arg1, b=arg2, c=arg3): # Need a mechanism to test default arguments
|
||||
SINK1(a)
|
||||
SINK2(b)
|
||||
SINK3(c)
|
||||
@@ -129,9 +129,9 @@ def with_default_arguments(a=arg1, b=arg2, c=arg3):
|
||||
@expects(12)
|
||||
def test_default_arguments():
|
||||
with_default_arguments()
|
||||
with_default_arguments(arg1)
|
||||
with_default_arguments(b=arg2)
|
||||
with_default_arguments(**{"c": arg3})
|
||||
with_default_arguments(arg1) #$ arg1
|
||||
with_default_arguments(b=arg2) #$ arg2
|
||||
with_default_arguments(**{"c": arg3}) #$ arg3 func=with_default_arguments
|
||||
|
||||
|
||||
# Nested constructor pattern
|
||||
@@ -157,7 +157,7 @@ def grab_baz(baz):
|
||||
|
||||
@expects(4)
|
||||
def test_grab():
|
||||
grab_foo_bar_baz(baz=arg3, bar=arg2, foo=arg1)
|
||||
grab_foo_bar_baz(baz=arg3, bar=arg2, foo=arg1) #$ arg1 arg2 arg3 func=grab_bar_baz func=grab_baz
|
||||
|
||||
|
||||
# All combinations
|
||||
@@ -165,14 +165,14 @@ def test_pos_pos():
|
||||
def with_pos(a):
|
||||
SINK1(a)
|
||||
|
||||
with_pos(arg1)
|
||||
with_pos(arg1) #$ arg1 func=test_pos_pos.with_pos
|
||||
|
||||
|
||||
def test_pos_pos_only():
|
||||
def with_pos_only(a, /):
|
||||
SINK1(a)
|
||||
|
||||
with_pos_only(arg1)
|
||||
with_pos_only(arg1) #$ arg1 func=test_pos_pos_only.with_pos_only
|
||||
|
||||
|
||||
def test_pos_star():
|
||||
@@ -180,32 +180,32 @@ def test_pos_star():
|
||||
if len(a) > 0:
|
||||
SINK1(a[0])
|
||||
|
||||
with_star(arg1)
|
||||
with_star(arg1) #$ arg1 func=test_pos_star.with_star
|
||||
|
||||
|
||||
def test_pos_kw():
|
||||
def with_kw(a=""):
|
||||
SINK1(a)
|
||||
|
||||
with_kw(arg1)
|
||||
with_kw(arg1) #$ arg1 func=test_pos_kw.with_kw
|
||||
|
||||
|
||||
def test_kw_pos():
|
||||
def with_pos(a):
|
||||
SINK1(a)
|
||||
|
||||
with_pos(a=arg1)
|
||||
with_pos(a=arg1) #$ arg1 func=test_kw_pos.with_pos
|
||||
|
||||
|
||||
def test_kw_kw():
|
||||
def with_kw(a=""):
|
||||
SINK1(a)
|
||||
|
||||
with_kw(a=arg1)
|
||||
with_kw(a=arg1) #$ arg1 func=test_kw_kw.with_kw
|
||||
|
||||
|
||||
def test_kw_doublestar():
|
||||
def with_doublestar(**a):
|
||||
SINK1(a["a"])
|
||||
|
||||
with_doublestar(a=arg1)
|
||||
with_doublestar(a=arg1) #$ arg1 func=test_kw_doublestar.with_doublestar
|
||||
|
||||
@@ -0,0 +1,263 @@
|
||||
import python
|
||||
import semmle.python.dataflow.new.DataFlow
|
||||
private import semmle.python.dataflow.new.internal.DataFlowPrivate as DataFlowPrivate
|
||||
import experimental.dataflow.TestUtil.RoutingTest
|
||||
|
||||
class Argument1RoutingTest extends RoutingTest {
|
||||
Argument1RoutingTest() { this = "Argument1RoutingTest" }
|
||||
|
||||
override string flowTag() { result = "arg1" }
|
||||
|
||||
override predicate relevantFlow(DataFlow::Node source, DataFlow::Node sink) {
|
||||
exists(Argument1RoutingConfig cfg | cfg.hasFlow(source, sink))
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A configuration to check routing of arguments through magic methods.
|
||||
*/
|
||||
class Argument1RoutingConfig extends DataFlow::Configuration {
|
||||
Argument1RoutingConfig() { this = "Argument1RoutingConfig" }
|
||||
|
||||
override predicate isSource(DataFlow::Node node) {
|
||||
node.(DataFlow::CfgNode).getNode().(NameNode).getId() = "arg1"
|
||||
or
|
||||
exists(AssignmentDefinition def, DataFlowPrivate::DataFlowCall call |
|
||||
def.getVariable() = node.(DataFlow::EssaNode).getVar() and
|
||||
def.getValue() = call.getNode() and
|
||||
call.getNode().(CallNode).getFunction().(NameNode).getId().matches("With\\_%")
|
||||
) and
|
||||
node.(DataFlow::EssaNode).getVar().getName().matches("with\\_%")
|
||||
}
|
||||
|
||||
override predicate isSink(DataFlow::Node node) {
|
||||
exists(CallNode call |
|
||||
call.getFunction().(NameNode).getId() = "SINK1" and
|
||||
node.(DataFlow::CfgNode).getNode() = call.getAnArg()
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* We want to be able to use `arg` in a sequence of calls such as `func(kw=arg); ... ; func(arg)`.
|
||||
* Use-use flow lets the argument to the first call reach the sink inside the second call,
|
||||
* making it seem like we handle all cases even if we only handle the last one.
|
||||
* We make the test honest by preventing flow into source nodes.
|
||||
*/
|
||||
override predicate isBarrierIn(DataFlow::Node node) { isSource(node) }
|
||||
}
|
||||
|
||||
class Argument2RoutingTest extends RoutingTest {
|
||||
Argument2RoutingTest() { this = "Argument2RoutingTest" }
|
||||
|
||||
override string flowTag() { result = "arg2" }
|
||||
|
||||
override predicate relevantFlow(DataFlow::Node source, DataFlow::Node sink) {
|
||||
exists(Argument2RoutingConfig cfg | cfg.hasFlow(source, sink))
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A configuration to check routing of arguments through magic methods.
|
||||
*/
|
||||
class Argument2RoutingConfig extends DataFlow::Configuration {
|
||||
Argument2RoutingConfig() { this = "Argument2RoutingConfig" }
|
||||
|
||||
override predicate isSource(DataFlow::Node node) {
|
||||
node.(DataFlow::CfgNode).getNode().(NameNode).getId() = "arg2"
|
||||
}
|
||||
|
||||
override predicate isSink(DataFlow::Node node) {
|
||||
exists(CallNode call |
|
||||
call.getFunction().(NameNode).getId() = "SINK2" and
|
||||
node.(DataFlow::CfgNode).getNode() = call.getAnArg()
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* We want to be able to use `arg` in a sequence of calls such as `func(kw=arg); ... ; func(arg)`.
|
||||
* Use-use flow lets the argument to the first call reach the sink inside the second call,
|
||||
* making it seem like we handle all cases even if we only handle the last one.
|
||||
* We make the test honest by preventing flow into source nodes.
|
||||
*/
|
||||
override predicate isBarrierIn(DataFlow::Node node) { isSource(node) }
|
||||
}
|
||||
|
||||
class Argument3RoutingTest extends RoutingTest {
|
||||
Argument3RoutingTest() { this = "Argument3RoutingTest" }
|
||||
|
||||
override string flowTag() { result = "arg3" }
|
||||
|
||||
override predicate relevantFlow(DataFlow::Node source, DataFlow::Node sink) {
|
||||
exists(Argument3RoutingConfig cfg | cfg.hasFlow(source, sink))
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A configuration to check routing of arguments through magic methods.
|
||||
*/
|
||||
class Argument3RoutingConfig extends DataFlow::Configuration {
|
||||
Argument3RoutingConfig() { this = "Argument3RoutingConfig" }
|
||||
|
||||
override predicate isSource(DataFlow::Node node) {
|
||||
node.(DataFlow::CfgNode).getNode().(NameNode).getId() = "arg3"
|
||||
}
|
||||
|
||||
override predicate isSink(DataFlow::Node node) {
|
||||
exists(CallNode call |
|
||||
call.getFunction().(NameNode).getId() = "SINK3" and
|
||||
node.(DataFlow::CfgNode).getNode() = call.getAnArg()
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* We want to be able to use `arg` in a sequence of calls such as `func(kw=arg); ... ; func(arg)`.
|
||||
* Use-use flow lets the argument to the first call reach the sink inside the second call,
|
||||
* making it seem like we handle all cases even if we only handle the last one.
|
||||
* We make the test honest by preventing flow into source nodes.
|
||||
*/
|
||||
override predicate isBarrierIn(DataFlow::Node node) { isSource(node) }
|
||||
}
|
||||
|
||||
class Argument4RoutingTest extends RoutingTest {
|
||||
Argument4RoutingTest() { this = "Argument4RoutingTest" }
|
||||
|
||||
override string flowTag() { result = "arg4" }
|
||||
|
||||
override predicate relevantFlow(DataFlow::Node source, DataFlow::Node sink) {
|
||||
exists(Argument4RoutingConfig cfg | cfg.hasFlow(source, sink))
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A configuration to check routing of arguments through magic methods.
|
||||
*/
|
||||
class Argument4RoutingConfig extends DataFlow::Configuration {
|
||||
Argument4RoutingConfig() { this = "Argument4RoutingConfig" }
|
||||
|
||||
override predicate isSource(DataFlow::Node node) {
|
||||
node.(DataFlow::CfgNode).getNode().(NameNode).getId() = "arg4"
|
||||
}
|
||||
|
||||
override predicate isSink(DataFlow::Node node) {
|
||||
exists(CallNode call |
|
||||
call.getFunction().(NameNode).getId() = "SINK4" and
|
||||
node.(DataFlow::CfgNode).getNode() = call.getAnArg()
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* We want to be able to use `arg` in a sequence of calls such as `func(kw=arg); ... ; func(arg)`.
|
||||
* Use-use flow lets the argument to the first call reach the sink inside the second call,
|
||||
* making it seem like we handle all cases even if we only handle the last one.
|
||||
* We make the test honest by preventing flow into source nodes.
|
||||
*/
|
||||
override predicate isBarrierIn(DataFlow::Node node) { isSource(node) }
|
||||
}
|
||||
|
||||
class Argument5RoutingTest extends RoutingTest {
|
||||
Argument5RoutingTest() { this = "Argument5RoutingTest" }
|
||||
|
||||
override string flowTag() { result = "arg5" }
|
||||
|
||||
override predicate relevantFlow(DataFlow::Node source, DataFlow::Node sink) {
|
||||
exists(Argument5RoutingConfig cfg | cfg.hasFlow(source, sink))
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A configuration to check routing of arguments through magic methods.
|
||||
*/
|
||||
class Argument5RoutingConfig extends DataFlow::Configuration {
|
||||
Argument5RoutingConfig() { this = "Argument5RoutingConfig" }
|
||||
|
||||
override predicate isSource(DataFlow::Node node) {
|
||||
node.(DataFlow::CfgNode).getNode().(NameNode).getId() = "arg5"
|
||||
}
|
||||
|
||||
override predicate isSink(DataFlow::Node node) {
|
||||
exists(CallNode call |
|
||||
call.getFunction().(NameNode).getId() = "SINK5" and
|
||||
node.(DataFlow::CfgNode).getNode() = call.getAnArg()
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* We want to be able to use `arg` in a sequence of calls such as `func(kw=arg); ... ; func(arg)`.
|
||||
* Use-use flow lets the argument to the first call reach the sink inside the second call,
|
||||
* making it seem like we handle all cases even if we only handle the last one.
|
||||
* We make the test honest by preventing flow into source nodes.
|
||||
*/
|
||||
override predicate isBarrierIn(DataFlow::Node node) { isSource(node) }
|
||||
}
|
||||
|
||||
class Argument6RoutingTest extends RoutingTest {
|
||||
Argument6RoutingTest() { this = "Argument6RoutingTest" }
|
||||
|
||||
override string flowTag() { result = "arg6" }
|
||||
|
||||
override predicate relevantFlow(DataFlow::Node source, DataFlow::Node sink) {
|
||||
exists(Argument6RoutingConfig cfg | cfg.hasFlow(source, sink))
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A configuration to check routing of arguments through magic methods.
|
||||
*/
|
||||
class Argument6RoutingConfig extends DataFlow::Configuration {
|
||||
Argument6RoutingConfig() { this = "Argument6RoutingConfig" }
|
||||
|
||||
override predicate isSource(DataFlow::Node node) {
|
||||
node.(DataFlow::CfgNode).getNode().(NameNode).getId() = "arg6"
|
||||
}
|
||||
|
||||
override predicate isSink(DataFlow::Node node) {
|
||||
exists(CallNode call |
|
||||
call.getFunction().(NameNode).getId() = "SINK6" and
|
||||
node.(DataFlow::CfgNode).getNode() = call.getAnArg()
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* We want to be able to use `arg` in a sequence of calls such as `func(kw=arg); ... ; func(arg)`.
|
||||
* Use-use flow lets the argument to the first call reach the sink inside the second call,
|
||||
* making it seem like we handle all cases even if we only handle the last one.
|
||||
* We make the test honest by preventing flow into source nodes.
|
||||
*/
|
||||
override predicate isBarrierIn(DataFlow::Node node) { isSource(node) }
|
||||
}
|
||||
|
||||
class Argument7RoutingTest extends RoutingTest {
|
||||
Argument7RoutingTest() { this = "Argument7RoutingTest" }
|
||||
|
||||
override string flowTag() { result = "arg7" }
|
||||
|
||||
override predicate relevantFlow(DataFlow::Node source, DataFlow::Node sink) {
|
||||
exists(Argument7RoutingConfig cfg | cfg.hasFlow(source, sink))
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A configuration to check routing of arguments through magic methods.
|
||||
*/
|
||||
class Argument7RoutingConfig extends DataFlow::Configuration {
|
||||
Argument7RoutingConfig() { this = "Argument7RoutingConfig" }
|
||||
|
||||
override predicate isSource(DataFlow::Node node) {
|
||||
node.(DataFlow::CfgNode).getNode().(NameNode).getId() = "arg7"
|
||||
}
|
||||
|
||||
override predicate isSink(DataFlow::Node node) {
|
||||
exists(CallNode call |
|
||||
call.getFunction().(NameNode).getId() = "SINK7" and
|
||||
node.(DataFlow::CfgNode).getNode() = call.getAnArg()
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* We want to be able to use `arg` in a sequence of calls such as `func(kw=arg); ... ; func(arg)`.
|
||||
* Use-use flow lets the argument to the first call reach the sink inside the second call,
|
||||
* making it seem like we handle all cases even if we only handle the last one.
|
||||
* We make the test honest by preventing flow into source nodes.
|
||||
*/
|
||||
override predicate isBarrierIn(DataFlow::Node node) { isSource(node) }
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -11,7 +11,7 @@ class CallGraphConfig extends DataFlow::Configuration {
|
||||
node instanceof DataFlowPrivate::ReturnNode
|
||||
or
|
||||
// These sources should allow for the non-standard call syntax
|
||||
node instanceof DataFlowPrivate::ArgumentNode
|
||||
node instanceof DataFlow::ArgumentNode
|
||||
}
|
||||
|
||||
override predicate isSink(DataFlow::Node node) {
|
||||
|
||||
@@ -1,69 +1,13 @@
|
||||
edges
|
||||
| datamodel.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module datamodel | datamodel.py:152:14:152:19 | ControlFlowNode for SOURCE |
|
||||
| datamodel.py:13:1:13:6 | GSSA Variable SOURCE | datamodel.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module datamodel |
|
||||
| datamodel.py:13:10:13:17 | ControlFlowNode for Str | datamodel.py:13:1:13:6 | GSSA Variable SOURCE |
|
||||
| datamodel.py:13:10:13:17 | ControlFlowNode for Str | datamodel.py:38:8:38:13 | ControlFlowNode for SOURCE |
|
||||
| datamodel.py:13:10:13:17 | ControlFlowNode for Str | datamodel.py:71:15:71:20 | ControlFlowNode for SOURCE |
|
||||
| datamodel.py:13:10:13:17 | ControlFlowNode for Str | datamodel.py:72:18:72:23 | ControlFlowNode for SOURCE |
|
||||
| datamodel.py:13:10:13:17 | ControlFlowNode for Str | datamodel.py:80:20:80:25 | ControlFlowNode for SOURCE |
|
||||
| datamodel.py:13:10:13:17 | ControlFlowNode for Str | datamodel.py:81:20:81:25 | ControlFlowNode for SOURCE |
|
||||
| datamodel.py:38:8:38:13 | ControlFlowNode for SOURCE | datamodel.py:38:6:38:17 | ControlFlowNode for f() |
|
||||
| datamodel.py:38:8:38:13 | ControlFlowNode for SOURCE | datamodel.py:71:15:71:20 | ControlFlowNode for SOURCE |
|
||||
| datamodel.py:38:8:38:13 | ControlFlowNode for SOURCE | datamodel.py:72:18:72:23 | ControlFlowNode for SOURCE |
|
||||
| datamodel.py:38:8:38:13 | ControlFlowNode for SOURCE | datamodel.py:80:20:80:25 | ControlFlowNode for SOURCE |
|
||||
| datamodel.py:38:8:38:13 | ControlFlowNode for SOURCE | datamodel.py:81:20:81:25 | ControlFlowNode for SOURCE |
|
||||
| datamodel.py:71:15:71:20 | ControlFlowNode for SOURCE | datamodel.py:71:6:71:24 | ControlFlowNode for Attribute() |
|
||||
| datamodel.py:71:15:71:20 | ControlFlowNode for SOURCE | datamodel.py:72:18:72:23 | ControlFlowNode for SOURCE |
|
||||
| datamodel.py:71:15:71:20 | ControlFlowNode for SOURCE | datamodel.py:80:20:80:25 | ControlFlowNode for SOURCE |
|
||||
| datamodel.py:71:15:71:20 | ControlFlowNode for SOURCE | datamodel.py:81:20:81:25 | ControlFlowNode for SOURCE |
|
||||
| datamodel.py:72:18:72:23 | ControlFlowNode for SOURCE | datamodel.py:72:6:72:27 | ControlFlowNode for Attribute() |
|
||||
| datamodel.py:72:18:72:23 | ControlFlowNode for SOURCE | datamodel.py:80:20:80:25 | ControlFlowNode for SOURCE |
|
||||
| datamodel.py:72:18:72:23 | ControlFlowNode for SOURCE | datamodel.py:81:20:81:25 | ControlFlowNode for SOURCE |
|
||||
| datamodel.py:73:18:73:23 | ControlFlowNode for SOURCE | datamodel.py:80:20:80:25 | ControlFlowNode for SOURCE |
|
||||
| datamodel.py:73:18:73:23 | ControlFlowNode for SOURCE | datamodel.py:81:20:81:25 | ControlFlowNode for SOURCE |
|
||||
| datamodel.py:80:20:80:25 | ControlFlowNode for SOURCE | datamodel.py:80:6:80:26 | ControlFlowNode for Attribute() |
|
||||
| datamodel.py:80:20:80:25 | ControlFlowNode for SOURCE | datamodel.py:81:20:81:25 | ControlFlowNode for SOURCE |
|
||||
| datamodel.py:81:20:81:25 | ControlFlowNode for SOURCE | datamodel.py:81:6:81:26 | ControlFlowNode for Attribute() |
|
||||
| datamodel.py:152:5:152:8 | [post store] ControlFlowNode for self [Attribute b] | datamodel.py:155:14:155:25 | ControlFlowNode for Customized() [Attribute b] |
|
||||
| datamodel.py:152:14:152:19 | ControlFlowNode for SOURCE | datamodel.py:152:5:152:8 | [post store] ControlFlowNode for self [Attribute b] |
|
||||
| datamodel.py:155:14:155:25 | ControlFlowNode for Customized() [Attribute b] | datamodel.py:159:6:159:15 | ControlFlowNode for customized [Attribute b] |
|
||||
| datamodel.py:159:6:159:15 | ControlFlowNode for customized [Attribute b] | datamodel.py:159:6:159:17 | ControlFlowNode for Attribute |
|
||||
| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:42:21:42:26 | ControlFlowNode for SOURCE |
|
||||
| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:55:9:55:14 | ControlFlowNode for SOURCE |
|
||||
| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:87:10:87:15 | ControlFlowNode for SOURCE |
|
||||
| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:93:10:93:15 | ControlFlowNode for SOURCE |
|
||||
| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:103:10:103:15 | ControlFlowNode for SOURCE |
|
||||
| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:108:22:108:27 | ControlFlowNode for SOURCE |
|
||||
| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:113:10:113:15 | ControlFlowNode for SOURCE |
|
||||
| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:125:10:125:15 | ControlFlowNode for SOURCE |
|
||||
| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:130:10:130:15 | ControlFlowNode for SOURCE |
|
||||
| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:135:22:135:27 | ControlFlowNode for SOURCE |
|
||||
| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:140:10:140:15 | ControlFlowNode for SOURCE |
|
||||
| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:152:15:152:20 | ControlFlowNode for SOURCE |
|
||||
| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:157:15:157:20 | ControlFlowNode for SOURCE |
|
||||
| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:183:23:183:28 | ControlFlowNode for SOURCE |
|
||||
| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:188:25:188:30 | ControlFlowNode for SOURCE |
|
||||
| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:199:34:199:39 | ControlFlowNode for SOURCE |
|
||||
| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:336:11:336:16 | ControlFlowNode for SOURCE |
|
||||
| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:340:11:340:16 | ControlFlowNode for SOURCE |
|
||||
| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:344:16:344:21 | ControlFlowNode for SOURCE |
|
||||
| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:367:28:367:33 | ControlFlowNode for SOURCE |
|
||||
| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:375:30:375:35 | ControlFlowNode for SOURCE |
|
||||
| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:383:36:383:41 | ControlFlowNode for SOURCE |
|
||||
| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:391:33:391:38 | ControlFlowNode for SOURCE |
|
||||
| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:399:39:399:44 | ControlFlowNode for SOURCE |
|
||||
| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:420:10:420:15 | ControlFlowNode for SOURCE |
|
||||
| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:428:34:428:39 | ControlFlowNode for SOURCE |
|
||||
| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:452:12:452:17 | ControlFlowNode for SOURCE |
|
||||
| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:459:28:459:33 | ControlFlowNode for SOURCE |
|
||||
| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:473:30:473:35 | ControlFlowNode for SOURCE |
|
||||
| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:487:36:487:41 | ControlFlowNode for SOURCE |
|
||||
| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:492:33:492:38 | ControlFlowNode for SOURCE |
|
||||
| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:497:39:497:44 | ControlFlowNode for SOURCE |
|
||||
| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:509:9:509:14 | ControlFlowNode for SOURCE |
|
||||
| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:588:16:588:21 | ControlFlowNode for SOURCE |
|
||||
| test.py:20:1:20:6 | GSSA Variable SOURCE | test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test |
|
||||
| test.py:20:10:20:17 | ControlFlowNode for Str | test.py:20:1:20:6 | GSSA Variable SOURCE |
|
||||
| test.py:42:10:42:26 | ControlFlowNode for Tuple [Tuple element at index 1] | test.py:43:9:43:9 | ControlFlowNode for x [Tuple element at index 1] |
|
||||
| test.py:42:21:42:26 | ControlFlowNode for SOURCE | test.py:42:10:42:26 | ControlFlowNode for Tuple [Tuple element at index 1] |
|
||||
| test.py:43:9:43:9 | ControlFlowNode for x [Tuple element at index 1] | test.py:43:9:43:12 | ControlFlowNode for Subscript |
|
||||
@@ -151,47 +95,204 @@ edges
|
||||
| test.py:199:33:199:40 | ControlFlowNode for List [List element] | test.py:199:28:199:28 | SSA variable z |
|
||||
| test.py:199:34:199:39 | ControlFlowNode for SOURCE | test.py:199:33:199:40 | ControlFlowNode for List [List element] |
|
||||
| test.py:200:10:200:10 | ControlFlowNode for x [List element] | test.py:200:10:200:13 | ControlFlowNode for Subscript |
|
||||
| test.py:336:11:336:16 | ControlFlowNode for SOURCE | test.py:336:11:336:17 | ControlFlowNode for Tuple [Tuple element at index 0] |
|
||||
| test.py:336:11:336:17 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:336:10:336:21 | ControlFlowNode for Subscript |
|
||||
| test.py:340:10:340:17 | ControlFlowNode for List [List element] | test.py:340:10:340:20 | ControlFlowNode for Subscript |
|
||||
| test.py:340:11:340:16 | ControlFlowNode for SOURCE | test.py:340:10:340:17 | ControlFlowNode for List [List element] |
|
||||
| test.py:344:10:344:22 | ControlFlowNode for Dict [Dictionary element at key s] | test.py:344:10:344:27 | ControlFlowNode for Subscript |
|
||||
| test.py:344:16:344:21 | ControlFlowNode for SOURCE | test.py:344:10:344:22 | ControlFlowNode for Dict [Dictionary element at key s] |
|
||||
| test.py:367:28:367:33 | ControlFlowNode for SOURCE | test.py:367:10:367:34 | ControlFlowNode for second() |
|
||||
| test.py:375:30:375:35 | ControlFlowNode for SOURCE | test.py:375:10:375:36 | ControlFlowNode for second() |
|
||||
| test.py:383:10:383:43 | KwUnpacked b | test.py:383:10:383:43 | ControlFlowNode for second() |
|
||||
| test.py:383:30:383:42 | ControlFlowNode for Dict [Dictionary element at key b] | test.py:383:10:383:43 | KwUnpacked b |
|
||||
| test.py:383:36:383:41 | ControlFlowNode for SOURCE | test.py:383:30:383:42 | ControlFlowNode for Dict [Dictionary element at key b] |
|
||||
| test.py:391:10:391:39 | PosOverflowNode for f_extra_pos() [Tuple element at index 0] | test.py:391:10:391:39 | ControlFlowNode for f_extra_pos() |
|
||||
| test.py:391:33:391:38 | ControlFlowNode for SOURCE | test.py:391:10:391:39 | PosOverflowNode for f_extra_pos() [Tuple element at index 0] |
|
||||
| test.py:399:10:399:45 | KwOverflowNode for f_extra_keyword() [Dictionary element at key b] | test.py:399:10:399:45 | ControlFlowNode for f_extra_keyword() |
|
||||
| test.py:399:39:399:44 | ControlFlowNode for SOURCE | test.py:399:10:399:45 | KwOverflowNode for f_extra_keyword() [Dictionary element at key b] |
|
||||
| test.py:420:10:420:15 | ControlFlowNode for SOURCE | test.py:420:10:420:38 | ControlFlowNode for IfExp |
|
||||
| test.py:428:34:428:39 | ControlFlowNode for SOURCE | test.py:428:10:428:39 | ControlFlowNode for IfExp |
|
||||
| test.py:452:12:452:17 | ControlFlowNode for SOURCE | test.py:452:10:452:18 | ControlFlowNode for f() |
|
||||
| test.py:459:28:459:33 | ControlFlowNode for SOURCE | test.py:459:10:459:34 | ControlFlowNode for second() |
|
||||
| test.py:473:30:473:35 | ControlFlowNode for SOURCE | test.py:473:10:473:36 | ControlFlowNode for second() |
|
||||
| test.py:487:10:487:43 | KwUnpacked b | test.py:487:10:487:43 | ControlFlowNode for second() |
|
||||
| test.py:487:30:487:42 | ControlFlowNode for Dict [Dictionary element at key b] | test.py:487:10:487:43 | KwUnpacked b |
|
||||
| test.py:487:36:487:41 | ControlFlowNode for SOURCE | test.py:487:30:487:42 | ControlFlowNode for Dict [Dictionary element at key b] |
|
||||
| test.py:492:10:492:39 | PosOverflowNode for f_extra_pos() [Tuple element at index 0] | test.py:492:10:492:39 | ControlFlowNode for f_extra_pos() |
|
||||
| test.py:492:33:492:38 | ControlFlowNode for SOURCE | test.py:492:10:492:39 | PosOverflowNode for f_extra_pos() [Tuple element at index 0] |
|
||||
| test.py:497:10:497:45 | KwOverflowNode for f_extra_keyword() [Dictionary element at key b] | test.py:497:10:497:45 | ControlFlowNode for f_extra_keyword() |
|
||||
| test.py:497:39:497:44 | ControlFlowNode for SOURCE | test.py:497:10:497:45 | KwOverflowNode for f_extra_keyword() [Dictionary element at key b] |
|
||||
| test.py:509:9:509:14 | ControlFlowNode for SOURCE | test.py:511:10:511:10 | ControlFlowNode for a |
|
||||
| test.py:509:9:509:14 | ControlFlowNode for SOURCE | test.py:516:10:516:10 | ControlFlowNode for b |
|
||||
| test.py:588:16:588:21 | ControlFlowNode for SOURCE | test.py:591:10:591:36 | ControlFlowNode for return_from_inner_scope() |
|
||||
| test.py:349:11:349:16 | ControlFlowNode for SOURCE | test.py:349:11:349:17 | ControlFlowNode for Tuple [Tuple element at index 0] |
|
||||
| test.py:349:11:349:17 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:349:10:349:21 | ControlFlowNode for Subscript |
|
||||
| test.py:353:10:353:17 | ControlFlowNode for List [List element] | test.py:353:10:353:20 | ControlFlowNode for Subscript |
|
||||
| test.py:353:11:353:16 | ControlFlowNode for SOURCE | test.py:353:10:353:17 | ControlFlowNode for List [List element] |
|
||||
| test.py:357:10:357:22 | ControlFlowNode for Dict [Dictionary element at key s] | test.py:357:10:357:27 | ControlFlowNode for Subscript |
|
||||
| test.py:357:16:357:21 | ControlFlowNode for SOURCE | test.py:357:10:357:22 | ControlFlowNode for Dict [Dictionary element at key s] |
|
||||
| test.py:380:28:380:33 | ControlFlowNode for SOURCE | test.py:380:10:380:34 | ControlFlowNode for second() |
|
||||
| test.py:388:30:388:35 | ControlFlowNode for SOURCE | test.py:388:10:388:36 | ControlFlowNode for second() |
|
||||
| test.py:396:10:396:43 | KwUnpacked b | test.py:396:10:396:43 | ControlFlowNode for second() |
|
||||
| test.py:396:30:396:42 | ControlFlowNode for Dict [Dictionary element at key b] | test.py:396:10:396:43 | KwUnpacked b |
|
||||
| test.py:396:36:396:41 | ControlFlowNode for SOURCE | test.py:396:30:396:42 | ControlFlowNode for Dict [Dictionary element at key b] |
|
||||
| test.py:404:10:404:39 | PosOverflowNode for f_extra_pos() [Tuple element at index 0] | test.py:404:10:404:39 | ControlFlowNode for f_extra_pos() |
|
||||
| test.py:404:33:404:38 | ControlFlowNode for SOURCE | test.py:404:10:404:39 | PosOverflowNode for f_extra_pos() [Tuple element at index 0] |
|
||||
| test.py:412:10:412:45 | KwOverflowNode for f_extra_keyword() [Dictionary element at key b] | test.py:412:10:412:45 | ControlFlowNode for f_extra_keyword() |
|
||||
| test.py:412:39:412:44 | ControlFlowNode for SOURCE | test.py:412:10:412:45 | KwOverflowNode for f_extra_keyword() [Dictionary element at key b] |
|
||||
| test.py:433:10:433:15 | ControlFlowNode for SOURCE | test.py:433:10:433:38 | ControlFlowNode for IfExp |
|
||||
| test.py:441:34:441:39 | ControlFlowNode for SOURCE | test.py:441:10:441:39 | ControlFlowNode for IfExp |
|
||||
| test.py:465:12:465:17 | ControlFlowNode for SOURCE | test.py:465:10:465:18 | ControlFlowNode for f() |
|
||||
| test.py:472:28:472:33 | ControlFlowNode for SOURCE | test.py:472:10:472:34 | ControlFlowNode for second() |
|
||||
| test.py:486:30:486:35 | ControlFlowNode for SOURCE | test.py:486:10:486:36 | ControlFlowNode for second() |
|
||||
| test.py:500:10:500:43 | KwUnpacked b | test.py:500:10:500:43 | ControlFlowNode for second() |
|
||||
| test.py:500:30:500:42 | ControlFlowNode for Dict [Dictionary element at key b] | test.py:500:10:500:43 | KwUnpacked b |
|
||||
| test.py:500:36:500:41 | ControlFlowNode for SOURCE | test.py:500:30:500:42 | ControlFlowNode for Dict [Dictionary element at key b] |
|
||||
| test.py:505:10:505:39 | PosOverflowNode for f_extra_pos() [Tuple element at index 0] | test.py:505:10:505:39 | ControlFlowNode for f_extra_pos() |
|
||||
| test.py:505:33:505:38 | ControlFlowNode for SOURCE | test.py:505:10:505:39 | PosOverflowNode for f_extra_pos() [Tuple element at index 0] |
|
||||
| test.py:510:10:510:45 | KwOverflowNode for f_extra_keyword() [Dictionary element at key b] | test.py:510:10:510:45 | ControlFlowNode for f_extra_keyword() |
|
||||
| test.py:510:39:510:44 | ControlFlowNode for SOURCE | test.py:510:10:510:45 | KwOverflowNode for f_extra_keyword() [Dictionary element at key b] |
|
||||
| test.py:522:9:522:14 | ControlFlowNode for SOURCE | test.py:524:10:524:10 | ControlFlowNode for a |
|
||||
| test.py:522:9:522:14 | ControlFlowNode for SOURCE | test.py:529:10:529:10 | ControlFlowNode for b |
|
||||
| test.py:534:10:534:15 | ControlFlowNode for SOURCE | test.py:534:10:534:26 | ControlFlowNode for Tuple [Tuple element at index 0] |
|
||||
| test.py:534:10:534:26 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:535:5:535:8 | ControlFlowNode for Tuple [Tuple element at index 0] |
|
||||
| test.py:535:5:535:5 | SSA variable a | test.py:536:10:536:10 | ControlFlowNode for a |
|
||||
| test.py:535:5:535:8 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:535:5:535:5 | SSA variable a |
|
||||
| test.py:542:10:542:15 | ControlFlowNode for SOURCE | test.py:542:10:542:36 | ControlFlowNode for Tuple [Tuple element at index 0] |
|
||||
| test.py:542:10:542:36 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:543:5:543:13 | ControlFlowNode for Tuple [Tuple element at index 0] |
|
||||
| test.py:542:10:542:36 | ControlFlowNode for Tuple [Tuple element at index 1, Tuple element at index 1] | test.py:543:5:543:13 | ControlFlowNode for Tuple [Tuple element at index 1, Tuple element at index 1] |
|
||||
| test.py:542:19:542:35 | ControlFlowNode for Tuple [Tuple element at index 1] | test.py:542:10:542:36 | ControlFlowNode for Tuple [Tuple element at index 1, Tuple element at index 1] |
|
||||
| test.py:542:30:542:35 | ControlFlowNode for SOURCE | test.py:542:19:542:35 | ControlFlowNode for Tuple [Tuple element at index 1] |
|
||||
| test.py:543:5:543:5 | SSA variable a | test.py:544:10:544:10 | ControlFlowNode for a |
|
||||
| test.py:543:5:543:13 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:543:5:543:5 | SSA variable a |
|
||||
| test.py:543:5:543:13 | ControlFlowNode for Tuple [Tuple element at index 1, Tuple element at index 1] | test.py:543:9:543:12 | IterableSequence [Tuple element at index 1] |
|
||||
| test.py:543:9:543:12 | ControlFlowNode for Tuple [Tuple element at index 1] | test.py:543:12:543:12 | SSA variable c |
|
||||
| test.py:543:9:543:12 | IterableSequence [Tuple element at index 1] | test.py:543:9:543:12 | ControlFlowNode for Tuple [Tuple element at index 1] |
|
||||
| test.py:543:12:543:12 | SSA variable c | test.py:546:10:546:10 | ControlFlowNode for c |
|
||||
| test.py:551:9:551:33 | ControlFlowNode for List [List element, List element, List element, List element] | test.py:552:5:552:14 | IterableSequence [List element, List element, List element, List element] |
|
||||
| test.py:551:10:551:21 | ControlFlowNode for List [List element, List element, List element] | test.py:551:9:551:33 | ControlFlowNode for List [List element, List element, List element, List element] |
|
||||
| test.py:551:11:551:20 | ControlFlowNode for List [List element, List element] | test.py:551:10:551:21 | ControlFlowNode for List [List element, List element, List element] |
|
||||
| test.py:551:12:551:19 | ControlFlowNode for List [List element] | test.py:551:11:551:20 | ControlFlowNode for List [List element, List element] |
|
||||
| test.py:551:13:551:18 | ControlFlowNode for SOURCE | test.py:551:12:551:19 | ControlFlowNode for List [List element] |
|
||||
| test.py:552:5:552:11 | ControlFlowNode for List [Tuple element at index 0, List element, List element] | test.py:552:6:552:10 | IterableSequence [List element, List element] |
|
||||
| test.py:552:5:552:11 | IterableElement [List element, List element] | test.py:552:5:552:11 | ControlFlowNode for List [Tuple element at index 0, List element, List element] |
|
||||
| test.py:552:5:552:11 | IterableSequence [List element, List element, List element] | test.py:552:5:552:11 | IterableElement [List element, List element] |
|
||||
| test.py:552:5:552:14 | ControlFlowNode for Tuple [Tuple element at index 0, List element, List element, List element] | test.py:552:5:552:11 | IterableSequence [List element, List element, List element] |
|
||||
| test.py:552:5:552:14 | IterableElement [List element, List element, List element] | test.py:552:5:552:14 | ControlFlowNode for Tuple [Tuple element at index 0, List element, List element, List element] |
|
||||
| test.py:552:5:552:14 | IterableSequence [List element, List element, List element, List element] | test.py:552:5:552:14 | IterableElement [List element, List element, List element] |
|
||||
| test.py:552:6:552:10 | ControlFlowNode for List [Tuple element at index 0, List element] | test.py:552:7:552:9 | IterableSequence [List element] |
|
||||
| test.py:552:6:552:10 | IterableElement [List element] | test.py:552:6:552:10 | ControlFlowNode for List [Tuple element at index 0, List element] |
|
||||
| test.py:552:6:552:10 | IterableSequence [List element, List element] | test.py:552:6:552:10 | IterableElement [List element] |
|
||||
| test.py:552:7:552:9 | ControlFlowNode for List [Tuple element at index 0] | test.py:552:8:552:8 | SSA variable a |
|
||||
| test.py:552:7:552:9 | IterableElement | test.py:552:7:552:9 | ControlFlowNode for List [Tuple element at index 0] |
|
||||
| test.py:552:7:552:9 | IterableSequence [List element] | test.py:552:7:552:9 | IterableElement |
|
||||
| test.py:552:8:552:8 | SSA variable a | test.py:553:10:553:10 | ControlFlowNode for a |
|
||||
| test.py:559:10:559:15 | ControlFlowNode for SOURCE | test.py:559:10:559:34 | ControlFlowNode for Tuple [Tuple element at index 0] |
|
||||
| test.py:559:10:559:34 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:560:5:560:12 | ControlFlowNode for Tuple [Tuple element at index 0] |
|
||||
| test.py:559:10:559:34 | ControlFlowNode for Tuple [Tuple element at index 1] | test.py:560:5:560:12 | ControlFlowNode for Tuple [Tuple element at index 1] |
|
||||
| test.py:559:18:559:23 | ControlFlowNode for SOURCE | test.py:559:10:559:34 | ControlFlowNode for Tuple [Tuple element at index 1] |
|
||||
| test.py:560:5:560:5 | SSA variable a | test.py:561:10:561:10 | ControlFlowNode for a |
|
||||
| test.py:560:5:560:12 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:560:5:560:5 | SSA variable a |
|
||||
| test.py:560:5:560:12 | ControlFlowNode for Tuple [Tuple element at index 1] | test.py:560:8:560:9 | IterableElement |
|
||||
| test.py:560:5:560:12 | ControlFlowNode for Tuple [Tuple element at index 1] | test.py:560:12:560:12 | SSA variable c |
|
||||
| test.py:560:8:560:9 | IterableElement | test.py:560:8:560:9 | SSA variable b [List element] |
|
||||
| test.py:560:8:560:9 | SSA variable b [List element] | test.py:563:10:563:10 | ControlFlowNode for b [List element] |
|
||||
| test.py:560:12:560:12 | SSA variable c | test.py:564:12:564:12 | ControlFlowNode for c |
|
||||
| test.py:563:10:563:10 | ControlFlowNode for b [List element] | test.py:563:10:563:13 | ControlFlowNode for Subscript |
|
||||
| test.py:569:10:569:15 | ControlFlowNode for SOURCE | test.py:569:10:569:23 | ControlFlowNode for Tuple [Tuple element at index 0] |
|
||||
| test.py:569:10:569:23 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:570:5:570:12 | ControlFlowNode for Tuple [Tuple element at index 0] |
|
||||
| test.py:569:10:569:23 | ControlFlowNode for Tuple [Tuple element at index 1] | test.py:570:5:570:12 | ControlFlowNode for Tuple [Tuple element at index 1] |
|
||||
| test.py:569:18:569:23 | ControlFlowNode for SOURCE | test.py:569:10:569:23 | ControlFlowNode for Tuple [Tuple element at index 1] |
|
||||
| test.py:570:5:570:5 | SSA variable a | test.py:571:10:571:10 | ControlFlowNode for a |
|
||||
| test.py:570:5:570:12 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:570:5:570:5 | SSA variable a |
|
||||
| test.py:570:5:570:12 | ControlFlowNode for Tuple [Tuple element at index 1] | test.py:570:12:570:12 | SSA variable c |
|
||||
| test.py:570:12:570:12 | SSA variable c | test.py:573:10:573:10 | ControlFlowNode for c |
|
||||
| test.py:578:10:578:61 | ControlFlowNode for List [List element, List element] | test.py:581:6:581:23 | IterableSequence [List element, List element] |
|
||||
| test.py:578:10:578:61 | ControlFlowNode for List [List element, List element] | test.py:589:5:589:24 | IterableSequence [List element, List element] |
|
||||
| test.py:578:10:578:61 | ControlFlowNode for List [List element, List element] | test.py:597:6:597:23 | IterableSequence [List element, List element] |
|
||||
| test.py:578:11:578:37 | ControlFlowNode for List [List element] | test.py:578:10:578:61 | ControlFlowNode for List [List element, List element] |
|
||||
| test.py:578:12:578:17 | ControlFlowNode for SOURCE | test.py:578:11:578:37 | ControlFlowNode for List [List element] |
|
||||
| test.py:578:31:578:36 | ControlFlowNode for SOURCE | test.py:578:11:578:37 | ControlFlowNode for List [List element] |
|
||||
| test.py:578:40:578:47 | ControlFlowNode for List [List element] | test.py:578:10:578:61 | ControlFlowNode for List [List element, List element] |
|
||||
| test.py:578:41:578:46 | ControlFlowNode for SOURCE | test.py:578:40:578:47 | ControlFlowNode for List [List element] |
|
||||
| test.py:581:6:581:23 | ControlFlowNode for Tuple [Tuple element at index 0, List element] | test.py:581:7:581:16 | IterableSequence [List element] |
|
||||
| test.py:581:6:581:23 | IterableElement [List element] | test.py:581:6:581:23 | ControlFlowNode for Tuple [Tuple element at index 0, List element] |
|
||||
| test.py:581:6:581:23 | IterableSequence [List element, List element] | test.py:581:6:581:23 | IterableElement [List element] |
|
||||
| test.py:581:7:581:8 | SSA variable a1 | test.py:582:10:582:11 | ControlFlowNode for a1 |
|
||||
| test.py:581:7:581:16 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:581:7:581:8 | SSA variable a1 |
|
||||
| test.py:581:7:581:16 | ControlFlowNode for Tuple [Tuple element at index 1] | test.py:581:11:581:12 | SSA variable a2 |
|
||||
| test.py:581:7:581:16 | ControlFlowNode for Tuple [Tuple element at index 2] | test.py:581:15:581:16 | SSA variable a3 |
|
||||
| test.py:581:7:581:16 | IterableElement | test.py:581:7:581:16 | ControlFlowNode for Tuple [Tuple element at index 0] |
|
||||
| test.py:581:7:581:16 | IterableElement | test.py:581:7:581:16 | ControlFlowNode for Tuple [Tuple element at index 1] |
|
||||
| test.py:581:7:581:16 | IterableElement | test.py:581:7:581:16 | ControlFlowNode for Tuple [Tuple element at index 2] |
|
||||
| test.py:581:7:581:16 | IterableSequence [List element] | test.py:581:7:581:16 | IterableElement |
|
||||
| test.py:581:11:581:12 | SSA variable a2 | test.py:583:12:583:13 | ControlFlowNode for a2 |
|
||||
| test.py:581:15:581:16 | SSA variable a3 | test.py:584:10:584:11 | ControlFlowNode for a3 |
|
||||
| test.py:589:5:589:24 | ControlFlowNode for List [Tuple element at index 0, List element] | test.py:589:7:589:16 | IterableSequence [List element] |
|
||||
| test.py:589:5:589:24 | IterableElement [List element] | test.py:589:5:589:24 | ControlFlowNode for List [Tuple element at index 0, List element] |
|
||||
| test.py:589:5:589:24 | IterableSequence [List element, List element] | test.py:589:5:589:24 | IterableElement [List element] |
|
||||
| test.py:589:7:589:8 | SSA variable a1 | test.py:590:10:590:11 | ControlFlowNode for a1 |
|
||||
| test.py:589:7:589:16 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:589:7:589:8 | SSA variable a1 |
|
||||
| test.py:589:7:589:16 | ControlFlowNode for Tuple [Tuple element at index 1] | test.py:589:11:589:12 | SSA variable a2 |
|
||||
| test.py:589:7:589:16 | ControlFlowNode for Tuple [Tuple element at index 2] | test.py:589:15:589:16 | SSA variable a3 |
|
||||
| test.py:589:7:589:16 | IterableElement | test.py:589:7:589:16 | ControlFlowNode for Tuple [Tuple element at index 0] |
|
||||
| test.py:589:7:589:16 | IterableElement | test.py:589:7:589:16 | ControlFlowNode for Tuple [Tuple element at index 1] |
|
||||
| test.py:589:7:589:16 | IterableElement | test.py:589:7:589:16 | ControlFlowNode for Tuple [Tuple element at index 2] |
|
||||
| test.py:589:7:589:16 | IterableSequence [List element] | test.py:589:7:589:16 | IterableElement |
|
||||
| test.py:589:11:589:12 | SSA variable a2 | test.py:591:12:591:13 | ControlFlowNode for a2 |
|
||||
| test.py:589:15:589:16 | SSA variable a3 | test.py:592:10:592:11 | ControlFlowNode for a3 |
|
||||
| test.py:597:6:597:17 | ControlFlowNode for List [Tuple element at index 0] | test.py:597:7:597:8 | SSA variable a1 |
|
||||
| test.py:597:6:597:17 | ControlFlowNode for List [Tuple element at index 1] | test.py:597:11:597:12 | SSA variable a2 |
|
||||
| test.py:597:6:597:17 | ControlFlowNode for List [Tuple element at index 2] | test.py:597:15:597:16 | SSA variable a3 |
|
||||
| test.py:597:6:597:17 | IterableElement | test.py:597:6:597:17 | ControlFlowNode for List [Tuple element at index 0] |
|
||||
| test.py:597:6:597:17 | IterableElement | test.py:597:6:597:17 | ControlFlowNode for List [Tuple element at index 1] |
|
||||
| test.py:597:6:597:17 | IterableElement | test.py:597:6:597:17 | ControlFlowNode for List [Tuple element at index 2] |
|
||||
| test.py:597:6:597:17 | IterableSequence [List element] | test.py:597:6:597:17 | IterableElement |
|
||||
| test.py:597:6:597:23 | ControlFlowNode for Tuple [Tuple element at index 0, List element] | test.py:597:6:597:17 | IterableSequence [List element] |
|
||||
| test.py:597:6:597:23 | IterableElement [List element] | test.py:597:6:597:23 | ControlFlowNode for Tuple [Tuple element at index 0, List element] |
|
||||
| test.py:597:6:597:23 | IterableSequence [List element, List element] | test.py:597:6:597:23 | IterableElement [List element] |
|
||||
| test.py:597:7:597:8 | SSA variable a1 | test.py:598:10:598:11 | ControlFlowNode for a1 |
|
||||
| test.py:597:11:597:12 | SSA variable a2 | test.py:599:12:599:13 | ControlFlowNode for a2 |
|
||||
| test.py:597:15:597:16 | SSA variable a3 | test.py:600:10:600:11 | ControlFlowNode for a3 |
|
||||
| test.py:606:11:606:47 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | test.py:609:5:609:19 | ControlFlowNode for List [Tuple element at index 0, Tuple element at index 0] |
|
||||
| test.py:606:11:606:47 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | test.py:618:6:618:18 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] |
|
||||
| test.py:606:11:606:47 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | test.py:627:5:627:19 | ControlFlowNode for List [Tuple element at index 0, Tuple element at index 0] |
|
||||
| test.py:606:11:606:47 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | test.py:636:6:636:18 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] |
|
||||
| test.py:606:11:606:47 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 2] | test.py:609:5:609:19 | ControlFlowNode for List [Tuple element at index 0, Tuple element at index 2] |
|
||||
| test.py:606:11:606:47 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 2] | test.py:618:6:618:18 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 2] |
|
||||
| test.py:606:11:606:47 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 2] | test.py:627:5:627:19 | ControlFlowNode for List [Tuple element at index 0, Tuple element at index 2] |
|
||||
| test.py:606:11:606:47 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 2] | test.py:636:6:636:18 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 2] |
|
||||
| test.py:606:12:606:17 | ControlFlowNode for SOURCE | test.py:606:12:606:36 | ControlFlowNode for Tuple [Tuple element at index 0] |
|
||||
| test.py:606:12:606:36 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:606:11:606:47 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] |
|
||||
| test.py:606:12:606:36 | ControlFlowNode for Tuple [Tuple element at index 2] | test.py:606:11:606:47 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 2] |
|
||||
| test.py:606:31:606:36 | ControlFlowNode for SOURCE | test.py:606:12:606:36 | ControlFlowNode for Tuple [Tuple element at index 2] |
|
||||
| test.py:609:5:609:19 | ControlFlowNode for List [Tuple element at index 0, Tuple element at index 0] | test.py:609:6:609:14 | IterableSequence [Tuple element at index 0] |
|
||||
| test.py:609:5:609:19 | ControlFlowNode for List [Tuple element at index 0, Tuple element at index 2] | test.py:609:6:609:14 | IterableSequence [Tuple element at index 2] |
|
||||
| test.py:609:6:609:14 | ControlFlowNode for List [Tuple element at index 0] | test.py:609:7:609:8 | SSA variable a1 |
|
||||
| test.py:609:6:609:14 | ControlFlowNode for List [Tuple element at index 2] | test.py:609:11:609:13 | IterableElement |
|
||||
| test.py:609:6:609:14 | IterableSequence [Tuple element at index 0] | test.py:609:6:609:14 | ControlFlowNode for List [Tuple element at index 0] |
|
||||
| test.py:609:6:609:14 | IterableSequence [Tuple element at index 2] | test.py:609:6:609:14 | ControlFlowNode for List [Tuple element at index 2] |
|
||||
| test.py:609:7:609:8 | SSA variable a1 | test.py:610:10:610:11 | ControlFlowNode for a1 |
|
||||
| test.py:609:11:609:13 | IterableElement | test.py:609:11:609:13 | SSA variable a2 [List element] |
|
||||
| test.py:609:11:609:13 | SSA variable a2 [List element] | test.py:612:12:612:13 | ControlFlowNode for a2 [List element] |
|
||||
| test.py:609:11:609:13 | SSA variable a2 [List element] | test.py:613:10:613:11 | ControlFlowNode for a2 [List element] |
|
||||
| test.py:612:12:612:13 | ControlFlowNode for a2 [List element] | test.py:612:12:612:16 | ControlFlowNode for Subscript |
|
||||
| test.py:613:10:613:11 | ControlFlowNode for a2 [List element] | test.py:613:10:613:14 | ControlFlowNode for Subscript |
|
||||
| test.py:618:6:618:18 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | test.py:618:7:618:13 | IterableSequence [Tuple element at index 0] |
|
||||
| test.py:618:6:618:18 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 2] | test.py:618:7:618:13 | IterableSequence [Tuple element at index 2] |
|
||||
| test.py:618:7:618:8 | SSA variable a1 | test.py:619:10:619:11 | ControlFlowNode for a1 |
|
||||
| test.py:618:7:618:13 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:618:7:618:8 | SSA variable a1 |
|
||||
| test.py:618:7:618:13 | ControlFlowNode for Tuple [Tuple element at index 2] | test.py:618:11:618:13 | IterableElement |
|
||||
| test.py:618:7:618:13 | IterableSequence [Tuple element at index 0] | test.py:618:7:618:13 | ControlFlowNode for Tuple [Tuple element at index 0] |
|
||||
| test.py:618:7:618:13 | IterableSequence [Tuple element at index 2] | test.py:618:7:618:13 | ControlFlowNode for Tuple [Tuple element at index 2] |
|
||||
| test.py:618:11:618:13 | IterableElement | test.py:618:11:618:13 | SSA variable a2 [List element] |
|
||||
| test.py:618:11:618:13 | SSA variable a2 [List element] | test.py:621:12:621:13 | ControlFlowNode for a2 [List element] |
|
||||
| test.py:618:11:618:13 | SSA variable a2 [List element] | test.py:622:10:622:11 | ControlFlowNode for a2 [List element] |
|
||||
| test.py:621:12:621:13 | ControlFlowNode for a2 [List element] | test.py:621:12:621:16 | ControlFlowNode for Subscript |
|
||||
| test.py:622:10:622:11 | ControlFlowNode for a2 [List element] | test.py:622:10:622:14 | ControlFlowNode for Subscript |
|
||||
| test.py:627:5:627:19 | ControlFlowNode for List [Tuple element at index 0, Tuple element at index 0] | test.py:627:7:627:13 | IterableSequence [Tuple element at index 0] |
|
||||
| test.py:627:5:627:19 | ControlFlowNode for List [Tuple element at index 0, Tuple element at index 2] | test.py:627:7:627:13 | IterableSequence [Tuple element at index 2] |
|
||||
| test.py:627:7:627:8 | SSA variable a1 | test.py:628:10:628:11 | ControlFlowNode for a1 |
|
||||
| test.py:627:7:627:13 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:627:7:627:8 | SSA variable a1 |
|
||||
| test.py:627:7:627:13 | ControlFlowNode for Tuple [Tuple element at index 2] | test.py:627:11:627:13 | IterableElement |
|
||||
| test.py:627:7:627:13 | IterableSequence [Tuple element at index 0] | test.py:627:7:627:13 | ControlFlowNode for Tuple [Tuple element at index 0] |
|
||||
| test.py:627:7:627:13 | IterableSequence [Tuple element at index 2] | test.py:627:7:627:13 | ControlFlowNode for Tuple [Tuple element at index 2] |
|
||||
| test.py:627:11:627:13 | IterableElement | test.py:627:11:627:13 | SSA variable a2 [List element] |
|
||||
| test.py:627:11:627:13 | SSA variable a2 [List element] | test.py:630:12:630:13 | ControlFlowNode for a2 [List element] |
|
||||
| test.py:627:11:627:13 | SSA variable a2 [List element] | test.py:631:10:631:11 | ControlFlowNode for a2 [List element] |
|
||||
| test.py:630:12:630:13 | ControlFlowNode for a2 [List element] | test.py:630:12:630:16 | ControlFlowNode for Subscript |
|
||||
| test.py:631:10:631:11 | ControlFlowNode for a2 [List element] | test.py:631:10:631:14 | ControlFlowNode for Subscript |
|
||||
| test.py:636:6:636:14 | ControlFlowNode for List [Tuple element at index 0] | test.py:636:7:636:8 | SSA variable a1 |
|
||||
| test.py:636:6:636:14 | ControlFlowNode for List [Tuple element at index 2] | test.py:636:11:636:13 | IterableElement |
|
||||
| test.py:636:6:636:14 | IterableSequence [Tuple element at index 0] | test.py:636:6:636:14 | ControlFlowNode for List [Tuple element at index 0] |
|
||||
| test.py:636:6:636:14 | IterableSequence [Tuple element at index 2] | test.py:636:6:636:14 | ControlFlowNode for List [Tuple element at index 2] |
|
||||
| test.py:636:6:636:18 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | test.py:636:6:636:14 | IterableSequence [Tuple element at index 0] |
|
||||
| test.py:636:6:636:18 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 2] | test.py:636:6:636:14 | IterableSequence [Tuple element at index 2] |
|
||||
| test.py:636:7:636:8 | SSA variable a1 | test.py:637:10:637:11 | ControlFlowNode for a1 |
|
||||
| test.py:636:11:636:13 | IterableElement | test.py:636:11:636:13 | SSA variable a2 [List element] |
|
||||
| test.py:636:11:636:13 | SSA variable a2 [List element] | test.py:639:12:639:13 | ControlFlowNode for a2 [List element] |
|
||||
| test.py:636:11:636:13 | SSA variable a2 [List element] | test.py:640:10:640:11 | ControlFlowNode for a2 [List element] |
|
||||
| test.py:639:12:639:13 | ControlFlowNode for a2 [List element] | test.py:639:12:639:16 | ControlFlowNode for Subscript |
|
||||
| test.py:640:10:640:11 | ControlFlowNode for a2 [List element] | test.py:640:10:640:14 | ControlFlowNode for Subscript |
|
||||
| test.py:647:19:647:24 | ControlFlowNode for SOURCE | test.py:648:10:648:10 | ControlFlowNode for a |
|
||||
| test.py:739:16:739:21 | ControlFlowNode for SOURCE | test.py:742:10:742:36 | ControlFlowNode for return_from_inner_scope() |
|
||||
nodes
|
||||
| datamodel.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module datamodel | semmle.label | ModuleVariableNode for Global Variable SOURCE in Module datamodel |
|
||||
| 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:8:38:13 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE |
|
||||
| datamodel.py:71:6:71:24 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
|
||||
| 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:18:72:23 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE |
|
||||
| datamodel.py:73:18:73:23 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE |
|
||||
| datamodel.py:80:6:80:26 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
|
||||
| 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() |
|
||||
@@ -201,9 +302,6 @@ nodes
|
||||
| datamodel.py:155:14:155:25 | ControlFlowNode for Customized() [Attribute b] | semmle.label | ControlFlowNode for Customized() [Attribute b] |
|
||||
| datamodel.py:159:6:159:15 | ControlFlowNode for customized [Attribute b] | semmle.label | ControlFlowNode for customized [Attribute b] |
|
||||
| datamodel.py:159:6:159:17 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
|
||||
| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | semmle.label | ModuleVariableNode for Global Variable SOURCE in Module test |
|
||||
| test.py:20:1:20:6 | GSSA Variable SOURCE | semmle.label | GSSA Variable SOURCE |
|
||||
| test.py:20:10:20:17 | ControlFlowNode for Str | semmle.label | ControlFlowNode for Str |
|
||||
| test.py:42:10:42:26 | ControlFlowNode for Tuple [Tuple element at index 1] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 1] |
|
||||
| test.py:42:21:42:26 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE |
|
||||
| test.py:43:9:43:9 | ControlFlowNode for x [Tuple element at index 1] | semmle.label | ControlFlowNode for x [Tuple element at index 1] |
|
||||
@@ -311,150 +409,319 @@ nodes
|
||||
| test.py:199:34:199:39 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE |
|
||||
| test.py:200:10:200:10 | ControlFlowNode for x [List element] | semmle.label | ControlFlowNode for x [List element] |
|
||||
| test.py:200:10:200:13 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript |
|
||||
| test.py:336:10:336:21 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript |
|
||||
| test.py:336:11:336:16 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE |
|
||||
| test.py:336:11:336:17 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] |
|
||||
| test.py:340:10:340:17 | ControlFlowNode for List [List element] | semmle.label | ControlFlowNode for List [List element] |
|
||||
| test.py:340:10:340:20 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript |
|
||||
| test.py:340:11:340:16 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE |
|
||||
| test.py:344:10:344:22 | ControlFlowNode for Dict [Dictionary element at key s] | semmle.label | ControlFlowNode for Dict [Dictionary element at key s] |
|
||||
| test.py:344:10:344:27 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript |
|
||||
| test.py:344:16:344:21 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE |
|
||||
| test.py:367:10:367:34 | ControlFlowNode for second() | semmle.label | ControlFlowNode for second() |
|
||||
| test.py:367:28:367:33 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE |
|
||||
| test.py:375:10:375:36 | ControlFlowNode for second() | semmle.label | ControlFlowNode for second() |
|
||||
| test.py:375:30:375:35 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE |
|
||||
| test.py:383:10:383:43 | ControlFlowNode for second() | semmle.label | ControlFlowNode for second() |
|
||||
| test.py:383:10:383:43 | KwUnpacked b | semmle.label | KwUnpacked b |
|
||||
| test.py:383:30:383:42 | ControlFlowNode for Dict [Dictionary element at key b] | semmle.label | ControlFlowNode for Dict [Dictionary element at key b] |
|
||||
| test.py:383:36:383:41 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE |
|
||||
| test.py:391:10:391:39 | ControlFlowNode for f_extra_pos() | semmle.label | ControlFlowNode for f_extra_pos() |
|
||||
| test.py:391:10:391:39 | PosOverflowNode for f_extra_pos() [Tuple element at index 0] | semmle.label | PosOverflowNode for f_extra_pos() [Tuple element at index 0] |
|
||||
| test.py:391:33:391:38 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE |
|
||||
| test.py:399:10:399:45 | ControlFlowNode for f_extra_keyword() | semmle.label | ControlFlowNode for f_extra_keyword() |
|
||||
| test.py:399:10:399:45 | KwOverflowNode for f_extra_keyword() [Dictionary element at key b] | semmle.label | KwOverflowNode for f_extra_keyword() [Dictionary element at key b] |
|
||||
| test.py:399:39:399:44 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE |
|
||||
| test.py:420:10:420:15 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE |
|
||||
| test.py:420:10:420:38 | ControlFlowNode for IfExp | semmle.label | ControlFlowNode for IfExp |
|
||||
| test.py:428:10:428:39 | ControlFlowNode for IfExp | semmle.label | ControlFlowNode for IfExp |
|
||||
| test.py:428:34:428:39 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE |
|
||||
| test.py:452:10:452:18 | ControlFlowNode for f() | semmle.label | ControlFlowNode for f() |
|
||||
| test.py:452:12:452:17 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE |
|
||||
| test.py:459:10:459:34 | ControlFlowNode for second() | semmle.label | ControlFlowNode for second() |
|
||||
| test.py:459:28:459:33 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE |
|
||||
| test.py:473:10:473:36 | ControlFlowNode for second() | semmle.label | ControlFlowNode for second() |
|
||||
| test.py:473:30:473:35 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE |
|
||||
| test.py:487:10:487:43 | ControlFlowNode for second() | semmle.label | ControlFlowNode for second() |
|
||||
| test.py:487:10:487:43 | KwUnpacked b | semmle.label | KwUnpacked b |
|
||||
| test.py:487:30:487:42 | ControlFlowNode for Dict [Dictionary element at key b] | semmle.label | ControlFlowNode for Dict [Dictionary element at key b] |
|
||||
| test.py:487:36:487:41 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE |
|
||||
| test.py:492:10:492:39 | ControlFlowNode for f_extra_pos() | semmle.label | ControlFlowNode for f_extra_pos() |
|
||||
| test.py:492:10:492:39 | PosOverflowNode for f_extra_pos() [Tuple element at index 0] | semmle.label | PosOverflowNode for f_extra_pos() [Tuple element at index 0] |
|
||||
| test.py:492:33:492:38 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE |
|
||||
| test.py:497:10:497:45 | ControlFlowNode for f_extra_keyword() | semmle.label | ControlFlowNode for f_extra_keyword() |
|
||||
| test.py:497:10:497:45 | KwOverflowNode for f_extra_keyword() [Dictionary element at key b] | semmle.label | KwOverflowNode for f_extra_keyword() [Dictionary element at key b] |
|
||||
| test.py:497:39:497:44 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE |
|
||||
| test.py:509:9:509:14 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE |
|
||||
| test.py:511:10:511:10 | ControlFlowNode for a | semmle.label | ControlFlowNode for a |
|
||||
| test.py:516:10:516:10 | ControlFlowNode for b | semmle.label | ControlFlowNode for b |
|
||||
| test.py:588:16:588:21 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE |
|
||||
| test.py:591:10:591:36 | ControlFlowNode for return_from_inner_scope() | semmle.label | ControlFlowNode for return_from_inner_scope() |
|
||||
| test.py:349:10:349:21 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript |
|
||||
| test.py:349:11:349:16 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE |
|
||||
| test.py:349:11:349:17 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] |
|
||||
| test.py:353:10:353:17 | ControlFlowNode for List [List element] | semmle.label | ControlFlowNode for List [List element] |
|
||||
| test.py:353:10:353:20 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript |
|
||||
| test.py:353:11:353:16 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE |
|
||||
| test.py:357:10:357:22 | ControlFlowNode for Dict [Dictionary element at key s] | semmle.label | ControlFlowNode for Dict [Dictionary element at key s] |
|
||||
| test.py:357:10:357:27 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript |
|
||||
| test.py:357:16:357:21 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE |
|
||||
| test.py:380:10:380:34 | ControlFlowNode for second() | semmle.label | ControlFlowNode for second() |
|
||||
| test.py:380:28:380:33 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE |
|
||||
| test.py:388:10:388:36 | ControlFlowNode for second() | semmle.label | ControlFlowNode for second() |
|
||||
| test.py:388:30:388:35 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE |
|
||||
| test.py:396:10:396:43 | ControlFlowNode for second() | semmle.label | ControlFlowNode for second() |
|
||||
| test.py:396:10:396:43 | KwUnpacked b | semmle.label | KwUnpacked b |
|
||||
| test.py:396:30:396:42 | ControlFlowNode for Dict [Dictionary element at key b] | semmle.label | ControlFlowNode for Dict [Dictionary element at key b] |
|
||||
| test.py:396:36:396:41 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE |
|
||||
| test.py:404:10:404:39 | ControlFlowNode for f_extra_pos() | semmle.label | ControlFlowNode for f_extra_pos() |
|
||||
| test.py:404:10:404:39 | PosOverflowNode for f_extra_pos() [Tuple element at index 0] | semmle.label | PosOverflowNode for f_extra_pos() [Tuple element at index 0] |
|
||||
| test.py:404:33:404:38 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE |
|
||||
| test.py:412:10:412:45 | ControlFlowNode for f_extra_keyword() | semmle.label | ControlFlowNode for f_extra_keyword() |
|
||||
| test.py:412:10:412:45 | KwOverflowNode for f_extra_keyword() [Dictionary element at key b] | semmle.label | KwOverflowNode for f_extra_keyword() [Dictionary element at key b] |
|
||||
| test.py:412:39:412:44 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE |
|
||||
| test.py:433:10:433:15 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE |
|
||||
| test.py:433:10:433:38 | ControlFlowNode for IfExp | semmle.label | ControlFlowNode for IfExp |
|
||||
| test.py:441:10:441:39 | ControlFlowNode for IfExp | semmle.label | ControlFlowNode for IfExp |
|
||||
| test.py:441:34:441:39 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE |
|
||||
| test.py:465:10:465:18 | ControlFlowNode for f() | semmle.label | ControlFlowNode for f() |
|
||||
| test.py:465:12:465:17 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE |
|
||||
| test.py:472:10:472:34 | ControlFlowNode for second() | semmle.label | ControlFlowNode for second() |
|
||||
| test.py:472:28:472:33 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE |
|
||||
| test.py:486:10:486:36 | ControlFlowNode for second() | semmle.label | ControlFlowNode for second() |
|
||||
| test.py:486:30:486:35 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE |
|
||||
| test.py:500:10:500:43 | ControlFlowNode for second() | semmle.label | ControlFlowNode for second() |
|
||||
| test.py:500:10:500:43 | KwUnpacked b | semmle.label | KwUnpacked b |
|
||||
| test.py:500:30:500:42 | ControlFlowNode for Dict [Dictionary element at key b] | semmle.label | ControlFlowNode for Dict [Dictionary element at key b] |
|
||||
| test.py:500:36:500:41 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE |
|
||||
| test.py:505:10:505:39 | ControlFlowNode for f_extra_pos() | semmle.label | ControlFlowNode for f_extra_pos() |
|
||||
| test.py:505:10:505:39 | PosOverflowNode for f_extra_pos() [Tuple element at index 0] | semmle.label | PosOverflowNode for f_extra_pos() [Tuple element at index 0] |
|
||||
| test.py:505:33:505:38 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE |
|
||||
| test.py:510:10:510:45 | ControlFlowNode for f_extra_keyword() | semmle.label | ControlFlowNode for f_extra_keyword() |
|
||||
| test.py:510:10:510:45 | KwOverflowNode for f_extra_keyword() [Dictionary element at key b] | semmle.label | KwOverflowNode for f_extra_keyword() [Dictionary element at key b] |
|
||||
| test.py:510:39:510:44 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE |
|
||||
| test.py:522:9:522:14 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE |
|
||||
| test.py:524:10:524:10 | ControlFlowNode for a | semmle.label | ControlFlowNode for a |
|
||||
| test.py:529:10:529:10 | ControlFlowNode for b | semmle.label | ControlFlowNode for b |
|
||||
| test.py:534:10:534:15 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE |
|
||||
| test.py:534:10:534:26 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] |
|
||||
| test.py:535:5:535:5 | SSA variable a | semmle.label | SSA variable a |
|
||||
| test.py:535:5:535:8 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] |
|
||||
| test.py:536:10:536:10 | ControlFlowNode for a | semmle.label | ControlFlowNode for a |
|
||||
| test.py:542:10:542:15 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE |
|
||||
| test.py:542:10:542:36 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] |
|
||||
| test.py:542:10:542:36 | ControlFlowNode for Tuple [Tuple element at index 1, Tuple element at index 1] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 1, Tuple element at index 1] |
|
||||
| test.py:542:19:542:35 | ControlFlowNode for Tuple [Tuple element at index 1] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 1] |
|
||||
| test.py:542:30:542:35 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE |
|
||||
| test.py:543:5:543:5 | SSA variable a | semmle.label | SSA variable a |
|
||||
| test.py:543:5:543:13 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] |
|
||||
| test.py:543:5:543:13 | ControlFlowNode for Tuple [Tuple element at index 1, Tuple element at index 1] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 1, Tuple element at index 1] |
|
||||
| test.py:543:9:543:12 | ControlFlowNode for Tuple [Tuple element at index 1] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 1] |
|
||||
| test.py:543:9:543:12 | IterableSequence [Tuple element at index 1] | semmle.label | IterableSequence [Tuple element at index 1] |
|
||||
| test.py:543:12:543:12 | SSA variable c | semmle.label | SSA variable c |
|
||||
| test.py:544:10:544:10 | ControlFlowNode for a | semmle.label | ControlFlowNode for a |
|
||||
| test.py:546:10:546:10 | ControlFlowNode for c | semmle.label | ControlFlowNode for c |
|
||||
| test.py:551:9:551:33 | ControlFlowNode for List [List element, List element, List element, List element] | semmle.label | ControlFlowNode for List [List element, List element, List element, List element] |
|
||||
| test.py:551:10:551:21 | ControlFlowNode for List [List element, List element, List element] | semmle.label | ControlFlowNode for List [List element, List element, List element] |
|
||||
| test.py:551:11:551:20 | ControlFlowNode for List [List element, List element] | semmle.label | ControlFlowNode for List [List element, List element] |
|
||||
| test.py:551:12:551:19 | ControlFlowNode for List [List element] | semmle.label | ControlFlowNode for List [List element] |
|
||||
| test.py:551:13:551:18 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE |
|
||||
| test.py:552:5:552:11 | ControlFlowNode for List [Tuple element at index 0, List element, List element] | semmle.label | ControlFlowNode for List [Tuple element at index 0, List element, List element] |
|
||||
| test.py:552:5:552:11 | IterableElement [List element, List element] | semmle.label | IterableElement [List element, List element] |
|
||||
| test.py:552:5:552:11 | IterableSequence [List element, List element, List element] | semmle.label | IterableSequence [List element, List element, List element] |
|
||||
| test.py:552:5:552:14 | ControlFlowNode for Tuple [Tuple element at index 0, List element, List element, List element] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0, List element, List element, List element] |
|
||||
| test.py:552:5:552:14 | IterableElement [List element, List element, List element] | semmle.label | IterableElement [List element, List element, List element] |
|
||||
| test.py:552:5:552:14 | IterableSequence [List element, List element, List element, List element] | semmle.label | IterableSequence [List element, List element, List element, List element] |
|
||||
| test.py:552:6:552:10 | ControlFlowNode for List [Tuple element at index 0, List element] | semmle.label | ControlFlowNode for List [Tuple element at index 0, List element] |
|
||||
| test.py:552:6:552:10 | IterableElement [List element] | semmle.label | IterableElement [List element] |
|
||||
| test.py:552:6:552:10 | IterableSequence [List element, List element] | semmle.label | IterableSequence [List element, List element] |
|
||||
| test.py:552:7:552:9 | ControlFlowNode for List [Tuple element at index 0] | semmle.label | ControlFlowNode for List [Tuple element at index 0] |
|
||||
| test.py:552:7:552:9 | IterableElement | semmle.label | IterableElement |
|
||||
| test.py:552:7:552:9 | IterableSequence [List element] | semmle.label | IterableSequence [List element] |
|
||||
| test.py:552:8:552:8 | SSA variable a | semmle.label | SSA variable a |
|
||||
| test.py:553:10:553:10 | ControlFlowNode for a | semmle.label | ControlFlowNode for a |
|
||||
| test.py:559:10:559:15 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE |
|
||||
| test.py:559:10:559:34 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] |
|
||||
| test.py:559:10:559:34 | ControlFlowNode for Tuple [Tuple element at index 1] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 1] |
|
||||
| test.py:559:18:559:23 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE |
|
||||
| test.py:560:5:560:5 | SSA variable a | semmle.label | SSA variable a |
|
||||
| test.py:560:5:560:12 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] |
|
||||
| test.py:560:5:560:12 | ControlFlowNode for Tuple [Tuple element at index 1] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 1] |
|
||||
| test.py:560:8:560:9 | IterableElement | semmle.label | IterableElement |
|
||||
| test.py:560:8:560:9 | SSA variable b [List element] | semmle.label | SSA variable b [List element] |
|
||||
| test.py:560:12:560:12 | SSA variable c | semmle.label | SSA variable c |
|
||||
| test.py:561:10:561:10 | ControlFlowNode for a | semmle.label | ControlFlowNode for a |
|
||||
| test.py:563:10:563:10 | ControlFlowNode for b [List element] | semmle.label | ControlFlowNode for b [List element] |
|
||||
| test.py:563:10:563:13 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript |
|
||||
| test.py:564:12:564:12 | ControlFlowNode for c | semmle.label | ControlFlowNode for c |
|
||||
| test.py:569:10:569:15 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE |
|
||||
| test.py:569:10:569:23 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] |
|
||||
| test.py:569:10:569:23 | ControlFlowNode for Tuple [Tuple element at index 1] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 1] |
|
||||
| test.py:569:18:569:23 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE |
|
||||
| test.py:570:5:570:5 | SSA variable a | semmle.label | SSA variable a |
|
||||
| test.py:570:5:570:12 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] |
|
||||
| test.py:570:5:570:12 | ControlFlowNode for Tuple [Tuple element at index 1] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 1] |
|
||||
| test.py:570:12:570:12 | SSA variable c | semmle.label | SSA variable c |
|
||||
| test.py:571:10:571:10 | ControlFlowNode for a | semmle.label | ControlFlowNode for a |
|
||||
| test.py:573:10:573:10 | ControlFlowNode for c | semmle.label | ControlFlowNode for c |
|
||||
| test.py:578:10:578:61 | ControlFlowNode for List [List element, List element] | semmle.label | ControlFlowNode for List [List element, List element] |
|
||||
| test.py:578:11:578:37 | ControlFlowNode for List [List element] | semmle.label | ControlFlowNode for List [List element] |
|
||||
| test.py:578:12:578:17 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE |
|
||||
| test.py:578:31:578:36 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE |
|
||||
| test.py:578:40:578:47 | ControlFlowNode for List [List element] | semmle.label | ControlFlowNode for List [List element] |
|
||||
| test.py:578:41:578:46 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE |
|
||||
| test.py:581:6:581:23 | ControlFlowNode for Tuple [Tuple element at index 0, List element] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0, List element] |
|
||||
| test.py:581:6:581:23 | IterableElement [List element] | semmle.label | IterableElement [List element] |
|
||||
| test.py:581:6:581:23 | IterableSequence [List element, List element] | semmle.label | IterableSequence [List element, List element] |
|
||||
| test.py:581:7:581:8 | SSA variable a1 | semmle.label | SSA variable a1 |
|
||||
| test.py:581:7:581:16 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] |
|
||||
| test.py:581:7:581:16 | ControlFlowNode for Tuple [Tuple element at index 1] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 1] |
|
||||
| test.py:581:7:581:16 | ControlFlowNode for Tuple [Tuple element at index 2] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 2] |
|
||||
| test.py:581:7:581:16 | IterableElement | semmle.label | IterableElement |
|
||||
| test.py:581:7:581:16 | IterableSequence [List element] | semmle.label | IterableSequence [List element] |
|
||||
| test.py:581:11:581:12 | SSA variable a2 | semmle.label | SSA variable a2 |
|
||||
| test.py:581:15:581:16 | SSA variable a3 | semmle.label | SSA variable a3 |
|
||||
| test.py:582:10:582:11 | ControlFlowNode for a1 | semmle.label | ControlFlowNode for a1 |
|
||||
| test.py:583:12:583:13 | ControlFlowNode for a2 | semmle.label | ControlFlowNode for a2 |
|
||||
| test.py:584:10:584:11 | ControlFlowNode for a3 | semmle.label | ControlFlowNode for a3 |
|
||||
| test.py:589:5:589:24 | ControlFlowNode for List [Tuple element at index 0, List element] | semmle.label | ControlFlowNode for List [Tuple element at index 0, List element] |
|
||||
| test.py:589:5:589:24 | IterableElement [List element] | semmle.label | IterableElement [List element] |
|
||||
| test.py:589:5:589:24 | IterableSequence [List element, List element] | semmle.label | IterableSequence [List element, List element] |
|
||||
| test.py:589:7:589:8 | SSA variable a1 | semmle.label | SSA variable a1 |
|
||||
| test.py:589:7:589:16 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] |
|
||||
| test.py:589:7:589:16 | ControlFlowNode for Tuple [Tuple element at index 1] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 1] |
|
||||
| test.py:589:7:589:16 | ControlFlowNode for Tuple [Tuple element at index 2] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 2] |
|
||||
| test.py:589:7:589:16 | IterableElement | semmle.label | IterableElement |
|
||||
| test.py:589:7:589:16 | IterableSequence [List element] | semmle.label | IterableSequence [List element] |
|
||||
| test.py:589:11:589:12 | SSA variable a2 | semmle.label | SSA variable a2 |
|
||||
| test.py:589:15:589:16 | SSA variable a3 | semmle.label | SSA variable a3 |
|
||||
| test.py:590:10:590:11 | ControlFlowNode for a1 | semmle.label | ControlFlowNode for a1 |
|
||||
| test.py:591:12:591:13 | ControlFlowNode for a2 | semmle.label | ControlFlowNode for a2 |
|
||||
| test.py:592:10:592:11 | ControlFlowNode for a3 | semmle.label | ControlFlowNode for a3 |
|
||||
| test.py:597:6:597:17 | ControlFlowNode for List [Tuple element at index 0] | semmle.label | ControlFlowNode for List [Tuple element at index 0] |
|
||||
| test.py:597:6:597:17 | ControlFlowNode for List [Tuple element at index 1] | semmle.label | ControlFlowNode for List [Tuple element at index 1] |
|
||||
| test.py:597:6:597:17 | ControlFlowNode for List [Tuple element at index 2] | semmle.label | ControlFlowNode for List [Tuple element at index 2] |
|
||||
| test.py:597:6:597:17 | IterableElement | semmle.label | IterableElement |
|
||||
| test.py:597:6:597:17 | IterableSequence [List element] | semmle.label | IterableSequence [List element] |
|
||||
| test.py:597:6:597:23 | ControlFlowNode for Tuple [Tuple element at index 0, List element] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0, List element] |
|
||||
| test.py:597:6:597:23 | IterableElement [List element] | semmle.label | IterableElement [List element] |
|
||||
| test.py:597:6:597:23 | IterableSequence [List element, List element] | semmle.label | IterableSequence [List element, List element] |
|
||||
| test.py:597:7:597:8 | SSA variable a1 | semmle.label | SSA variable a1 |
|
||||
| test.py:597:11:597:12 | SSA variable a2 | semmle.label | SSA variable a2 |
|
||||
| test.py:597:15:597:16 | SSA variable a3 | semmle.label | SSA variable a3 |
|
||||
| test.py:598:10:598:11 | ControlFlowNode for a1 | semmle.label | ControlFlowNode for a1 |
|
||||
| test.py:599:12:599:13 | ControlFlowNode for a2 | semmle.label | ControlFlowNode for a2 |
|
||||
| test.py:600:10:600:11 | ControlFlowNode for a3 | semmle.label | ControlFlowNode for a3 |
|
||||
| test.py:606:11:606:47 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] |
|
||||
| test.py:606:11:606:47 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 2] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 2] |
|
||||
| test.py:606:12:606:17 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE |
|
||||
| test.py:606:12:606:36 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] |
|
||||
| test.py:606:12:606:36 | ControlFlowNode for Tuple [Tuple element at index 2] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 2] |
|
||||
| test.py:606:31:606:36 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE |
|
||||
| test.py:609:5:609:19 | ControlFlowNode for List [Tuple element at index 0, Tuple element at index 0] | semmle.label | ControlFlowNode for List [Tuple element at index 0, Tuple element at index 0] |
|
||||
| test.py:609:5:609:19 | ControlFlowNode for List [Tuple element at index 0, Tuple element at index 2] | semmle.label | ControlFlowNode for List [Tuple element at index 0, Tuple element at index 2] |
|
||||
| test.py:609:6:609:14 | ControlFlowNode for List [Tuple element at index 0] | semmle.label | ControlFlowNode for List [Tuple element at index 0] |
|
||||
| test.py:609:6:609:14 | ControlFlowNode for List [Tuple element at index 2] | semmle.label | ControlFlowNode for List [Tuple element at index 2] |
|
||||
| test.py:609:6:609:14 | IterableSequence [Tuple element at index 0] | semmle.label | IterableSequence [Tuple element at index 0] |
|
||||
| test.py:609:6:609:14 | IterableSequence [Tuple element at index 2] | semmle.label | IterableSequence [Tuple element at index 2] |
|
||||
| test.py:609:7:609:8 | SSA variable a1 | semmle.label | SSA variable a1 |
|
||||
| test.py:609:11:609:13 | IterableElement | semmle.label | IterableElement |
|
||||
| test.py:609:11:609:13 | SSA variable a2 [List element] | semmle.label | SSA variable a2 [List element] |
|
||||
| test.py:610:10:610:11 | ControlFlowNode for a1 | semmle.label | ControlFlowNode for a1 |
|
||||
| test.py:612:12:612:13 | ControlFlowNode for a2 [List element] | semmle.label | ControlFlowNode for a2 [List element] |
|
||||
| test.py:612:12:612:16 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript |
|
||||
| test.py:613:10:613:11 | ControlFlowNode for a2 [List element] | semmle.label | ControlFlowNode for a2 [List element] |
|
||||
| test.py:613:10:613:14 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript |
|
||||
| test.py:618:6:618:18 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] |
|
||||
| test.py:618:6:618:18 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 2] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 2] |
|
||||
| test.py:618:7:618:8 | SSA variable a1 | semmle.label | SSA variable a1 |
|
||||
| test.py:618:7:618:13 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] |
|
||||
| test.py:618:7:618:13 | ControlFlowNode for Tuple [Tuple element at index 2] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 2] |
|
||||
| test.py:618:7:618:13 | IterableSequence [Tuple element at index 0] | semmle.label | IterableSequence [Tuple element at index 0] |
|
||||
| test.py:618:7:618:13 | IterableSequence [Tuple element at index 2] | semmle.label | IterableSequence [Tuple element at index 2] |
|
||||
| test.py:618:11:618:13 | IterableElement | semmle.label | IterableElement |
|
||||
| test.py:618:11:618:13 | SSA variable a2 [List element] | semmle.label | SSA variable a2 [List element] |
|
||||
| test.py:619:10:619:11 | ControlFlowNode for a1 | semmle.label | ControlFlowNode for a1 |
|
||||
| test.py:621:12:621:13 | ControlFlowNode for a2 [List element] | semmle.label | ControlFlowNode for a2 [List element] |
|
||||
| test.py:621:12:621:16 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript |
|
||||
| test.py:622:10:622:11 | ControlFlowNode for a2 [List element] | semmle.label | ControlFlowNode for a2 [List element] |
|
||||
| test.py:622:10:622:14 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript |
|
||||
| test.py:627:5:627:19 | ControlFlowNode for List [Tuple element at index 0, Tuple element at index 0] | semmle.label | ControlFlowNode for List [Tuple element at index 0, Tuple element at index 0] |
|
||||
| test.py:627:5:627:19 | ControlFlowNode for List [Tuple element at index 0, Tuple element at index 2] | semmle.label | ControlFlowNode for List [Tuple element at index 0, Tuple element at index 2] |
|
||||
| test.py:627:7:627:8 | SSA variable a1 | semmle.label | SSA variable a1 |
|
||||
| test.py:627:7:627:13 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] |
|
||||
| test.py:627:7:627:13 | ControlFlowNode for Tuple [Tuple element at index 2] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 2] |
|
||||
| test.py:627:7:627:13 | IterableSequence [Tuple element at index 0] | semmle.label | IterableSequence [Tuple element at index 0] |
|
||||
| test.py:627:7:627:13 | IterableSequence [Tuple element at index 2] | semmle.label | IterableSequence [Tuple element at index 2] |
|
||||
| test.py:627:11:627:13 | IterableElement | semmle.label | IterableElement |
|
||||
| test.py:627:11:627:13 | SSA variable a2 [List element] | semmle.label | SSA variable a2 [List element] |
|
||||
| test.py:628:10:628:11 | ControlFlowNode for a1 | semmle.label | ControlFlowNode for a1 |
|
||||
| test.py:630:12:630:13 | ControlFlowNode for a2 [List element] | semmle.label | ControlFlowNode for a2 [List element] |
|
||||
| test.py:630:12:630:16 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript |
|
||||
| test.py:631:10:631:11 | ControlFlowNode for a2 [List element] | semmle.label | ControlFlowNode for a2 [List element] |
|
||||
| test.py:631:10:631:14 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript |
|
||||
| test.py:636:6:636:14 | ControlFlowNode for List [Tuple element at index 0] | semmle.label | ControlFlowNode for List [Tuple element at index 0] |
|
||||
| test.py:636:6:636:14 | ControlFlowNode for List [Tuple element at index 2] | semmle.label | ControlFlowNode for List [Tuple element at index 2] |
|
||||
| test.py:636:6:636:14 | IterableSequence [Tuple element at index 0] | semmle.label | IterableSequence [Tuple element at index 0] |
|
||||
| test.py:636:6:636:14 | IterableSequence [Tuple element at index 2] | semmle.label | IterableSequence [Tuple element at index 2] |
|
||||
| test.py:636:6:636:18 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] |
|
||||
| test.py:636:6:636:18 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 2] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 2] |
|
||||
| test.py:636:7:636:8 | SSA variable a1 | semmle.label | SSA variable a1 |
|
||||
| test.py:636:11:636:13 | IterableElement | semmle.label | IterableElement |
|
||||
| test.py:636:11:636:13 | SSA variable a2 [List element] | semmle.label | SSA variable a2 [List element] |
|
||||
| test.py:637:10:637:11 | ControlFlowNode for a1 | semmle.label | ControlFlowNode for a1 |
|
||||
| test.py:639:12:639:13 | ControlFlowNode for a2 [List element] | semmle.label | ControlFlowNode for a2 [List element] |
|
||||
| test.py:639:12:639:16 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript |
|
||||
| test.py:640:10:640:11 | ControlFlowNode for a2 [List element] | semmle.label | ControlFlowNode for a2 [List element] |
|
||||
| test.py:640:10:640:14 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript |
|
||||
| test.py:647:19:647:24 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE |
|
||||
| test.py:648:10:648:10 | ControlFlowNode for a | semmle.label | ControlFlowNode for a |
|
||||
| test.py:739:16:739:21 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE |
|
||||
| test.py:742:10:742:36 | ControlFlowNode for return_from_inner_scope() | semmle.label | ControlFlowNode for return_from_inner_scope() |
|
||||
#select
|
||||
| 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() | Flow found |
|
||||
| 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() | Flow found |
|
||||
| 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() | Flow found |
|
||||
| datamodel.py:71:6:71:24 | ControlFlowNode for Attribute() | datamodel.py:38:8:38:13 | ControlFlowNode for SOURCE | datamodel.py:71:6:71:24 | ControlFlowNode for Attribute() | Flow found |
|
||||
| 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() | Flow found |
|
||||
| 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() | Flow found |
|
||||
| datamodel.py:72:6:72:27 | ControlFlowNode for Attribute() | datamodel.py:38:8:38:13 | ControlFlowNode for SOURCE | datamodel.py:72:6:72:27 | ControlFlowNode for Attribute() | Flow found |
|
||||
| datamodel.py:72:6:72:27 | ControlFlowNode for Attribute() | datamodel.py:71:15:71:20 | ControlFlowNode for SOURCE | datamodel.py:72:6:72:27 | ControlFlowNode for Attribute() | Flow found |
|
||||
| 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() | Flow found |
|
||||
| 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() | Flow found |
|
||||
| datamodel.py:80:6:80:26 | ControlFlowNode for Attribute() | datamodel.py:38:8:38:13 | ControlFlowNode for SOURCE | datamodel.py:80:6:80:26 | ControlFlowNode for Attribute() | Flow found |
|
||||
| datamodel.py:80:6:80:26 | ControlFlowNode for Attribute() | datamodel.py:71:15:71:20 | ControlFlowNode for SOURCE | datamodel.py:80:6:80:26 | ControlFlowNode for Attribute() | Flow found |
|
||||
| datamodel.py:80:6:80:26 | ControlFlowNode for Attribute() | datamodel.py:72:18:72:23 | ControlFlowNode for SOURCE | datamodel.py:80:6:80:26 | ControlFlowNode for Attribute() | Flow found |
|
||||
| datamodel.py:80:6:80:26 | ControlFlowNode for Attribute() | datamodel.py:73:18:73:23 | ControlFlowNode for SOURCE | datamodel.py:80:6:80:26 | ControlFlowNode for Attribute() | Flow found |
|
||||
| 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() | Flow found |
|
||||
| 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() | Flow found |
|
||||
| datamodel.py:81:6:81:26 | ControlFlowNode for Attribute() | datamodel.py:38:8:38:13 | ControlFlowNode for SOURCE | datamodel.py:81:6:81:26 | ControlFlowNode for Attribute() | Flow found |
|
||||
| datamodel.py:81:6:81:26 | ControlFlowNode for Attribute() | datamodel.py:71:15:71:20 | ControlFlowNode for SOURCE | datamodel.py:81:6:81:26 | ControlFlowNode for Attribute() | Flow found |
|
||||
| datamodel.py:81:6:81:26 | ControlFlowNode for Attribute() | datamodel.py:72:18:72:23 | ControlFlowNode for SOURCE | datamodel.py:81:6:81:26 | ControlFlowNode for Attribute() | Flow found |
|
||||
| datamodel.py:81:6:81:26 | ControlFlowNode for Attribute() | datamodel.py:73:18:73:23 | ControlFlowNode for SOURCE | datamodel.py:81:6:81:26 | ControlFlowNode for Attribute() | Flow found |
|
||||
| datamodel.py:81:6:81:26 | ControlFlowNode for Attribute() | datamodel.py:80:20:80:25 | ControlFlowNode for SOURCE | datamodel.py:81:6:81:26 | ControlFlowNode for Attribute() | Flow found |
|
||||
| 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() | Flow found |
|
||||
| datamodel.py:159:6:159:17 | ControlFlowNode for Attribute | datamodel.py:13:10:13:17 | ControlFlowNode for Str | datamodel.py:159:6:159:17 | ControlFlowNode for Attribute | Flow found |
|
||||
| datamodel.py:159:6:159:17 | ControlFlowNode for Attribute | datamodel.py:152:14:152:19 | ControlFlowNode for SOURCE | datamodel.py:159:6:159:17 | ControlFlowNode for Attribute | Flow found |
|
||||
| test.py:44:10:44:10 | ControlFlowNode for y | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:44:10:44:10 | ControlFlowNode for y | Flow found |
|
||||
| test.py:44:10:44:10 | ControlFlowNode for y | test.py:42:21:42:26 | ControlFlowNode for SOURCE | test.py:44:10:44:10 | ControlFlowNode for y | Flow found |
|
||||
| test.py:56:10:56:10 | ControlFlowNode for x | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:56:10:56:10 | ControlFlowNode for x | Flow found |
|
||||
| test.py:56:10:56:10 | ControlFlowNode for x | test.py:55:9:55:14 | ControlFlowNode for SOURCE | test.py:56:10:56:10 | ControlFlowNode for x | Flow found |
|
||||
| test.py:62:10:62:10 | ControlFlowNode for x | test.py:61:9:61:16 | ControlFlowNode for Str | test.py:62:10:62:10 | ControlFlowNode for x | Flow found |
|
||||
| test.py:67:10:67:10 | ControlFlowNode for x | test.py:66:9:66:17 | ControlFlowNode for Str | test.py:67:10:67:10 | ControlFlowNode for x | Flow found |
|
||||
| test.py:72:10:72:10 | ControlFlowNode for x | test.py:71:9:71:10 | ControlFlowNode for IntegerLiteral | test.py:72:10:72:10 | ControlFlowNode for x | Flow found |
|
||||
| test.py:77:10:77:10 | ControlFlowNode for x | test.py:76:9:76:12 | ControlFlowNode for FloatLiteral | test.py:77:10:77:10 | ControlFlowNode for x | Flow found |
|
||||
| test.py:88:10:88:10 | ControlFlowNode for x | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:88:10:88:10 | ControlFlowNode for x | Flow found |
|
||||
| test.py:88:10:88:10 | ControlFlowNode for x | test.py:87:10:87:15 | ControlFlowNode for SOURCE | test.py:88:10:88:10 | ControlFlowNode for x | Flow found |
|
||||
| test.py:94:10:94:13 | ControlFlowNode for Subscript | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:94:10:94:13 | ControlFlowNode for Subscript | Flow found |
|
||||
| test.py:94:10:94:13 | ControlFlowNode for Subscript | test.py:93:10:93:15 | ControlFlowNode for SOURCE | test.py:94:10:94:13 | ControlFlowNode for Subscript | Flow found |
|
||||
| test.py:104:10:104:13 | ControlFlowNode for Subscript | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:104:10:104:13 | ControlFlowNode for Subscript | Flow found |
|
||||
| test.py:104:10:104:13 | ControlFlowNode for Subscript | test.py:103:10:103:15 | ControlFlowNode for SOURCE | test.py:104:10:104:13 | ControlFlowNode for Subscript | Flow found |
|
||||
| test.py:109:10:109:13 | ControlFlowNode for Subscript | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:109:10:109:13 | ControlFlowNode for Subscript | Flow found |
|
||||
| test.py:109:10:109:13 | ControlFlowNode for Subscript | test.py:108:22:108:27 | ControlFlowNode for SOURCE | test.py:109:10:109:13 | ControlFlowNode for Subscript | Flow found |
|
||||
| test.py:115:10:115:13 | ControlFlowNode for Subscript | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:115:10:115:13 | ControlFlowNode for Subscript | Flow found |
|
||||
| test.py:115:10:115:13 | ControlFlowNode for Subscript | test.py:113:10:113:15 | ControlFlowNode for SOURCE | test.py:115:10:115:13 | ControlFlowNode for Subscript | Flow found |
|
||||
| test.py:126:10:126:16 | ControlFlowNode for Attribute() | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:126:10:126:16 | ControlFlowNode for Attribute() | Flow found |
|
||||
| test.py:126:10:126:16 | ControlFlowNode for Attribute() | test.py:125:10:125:15 | ControlFlowNode for SOURCE | test.py:126:10:126:16 | ControlFlowNode for Attribute() | Flow found |
|
||||
| test.py:131:10:131:16 | ControlFlowNode for Attribute() | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:131:10:131:16 | ControlFlowNode for Attribute() | Flow found |
|
||||
| test.py:131:10:131:16 | ControlFlowNode for Attribute() | test.py:130:10:130:15 | ControlFlowNode for SOURCE | test.py:131:10:131:16 | ControlFlowNode for Attribute() | Flow found |
|
||||
| test.py:136:10:136:16 | ControlFlowNode for Attribute() | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:136:10:136:16 | ControlFlowNode for Attribute() | Flow found |
|
||||
| test.py:136:10:136:16 | ControlFlowNode for Attribute() | test.py:135:22:135:27 | ControlFlowNode for SOURCE | test.py:136:10:136:16 | ControlFlowNode for Attribute() | Flow found |
|
||||
| test.py:142:10:142:16 | ControlFlowNode for Attribute() | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:142:10:142:16 | ControlFlowNode for Attribute() | Flow found |
|
||||
| test.py:142:10:142:16 | ControlFlowNode for Attribute() | test.py:140:10:140:15 | ControlFlowNode for SOURCE | test.py:142:10:142:16 | ControlFlowNode for Attribute() | Flow found |
|
||||
| test.py:153:10:153:15 | ControlFlowNode for Subscript | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:153:10:153:15 | ControlFlowNode for Subscript | Flow found |
|
||||
| test.py:153:10:153:15 | ControlFlowNode for Subscript | test.py:152:15:152:20 | ControlFlowNode for SOURCE | test.py:153:10:153:15 | ControlFlowNode for Subscript | Flow found |
|
||||
| test.py:158:10:158:19 | ControlFlowNode for Attribute() | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:158:10:158:19 | ControlFlowNode for Attribute() | Flow found |
|
||||
| test.py:158:10:158:19 | ControlFlowNode for Attribute() | test.py:157:15:157:20 | ControlFlowNode for SOURCE | test.py:158:10:158:19 | ControlFlowNode for Attribute() | Flow found |
|
||||
| test.py:184:10:184:13 | ControlFlowNode for Subscript | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:184:10:184:13 | ControlFlowNode for Subscript | Flow found |
|
||||
| test.py:184:10:184:13 | ControlFlowNode for Subscript | test.py:183:23:183:28 | ControlFlowNode for SOURCE | test.py:184:10:184:13 | ControlFlowNode for Subscript | Flow found |
|
||||
| test.py:189:10:189:13 | ControlFlowNode for Subscript | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:189:10:189:13 | ControlFlowNode for Subscript | Flow found |
|
||||
| test.py:189:10:189:13 | ControlFlowNode for Subscript | test.py:188:25:188:30 | ControlFlowNode for SOURCE | test.py:189:10:189:13 | ControlFlowNode for Subscript | Flow found |
|
||||
| test.py:200:10:200:13 | ControlFlowNode for Subscript | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:200:10:200:13 | ControlFlowNode for Subscript | Flow found |
|
||||
| test.py:200:10:200:13 | ControlFlowNode for Subscript | test.py:199:34:199:39 | ControlFlowNode for SOURCE | test.py:200:10:200:13 | ControlFlowNode for Subscript | Flow found |
|
||||
| test.py:336:10:336:21 | ControlFlowNode for Subscript | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:336:10:336:21 | ControlFlowNode for Subscript | Flow found |
|
||||
| test.py:336:10:336:21 | ControlFlowNode for Subscript | test.py:336:11:336:16 | ControlFlowNode for SOURCE | test.py:336:10:336:21 | ControlFlowNode for Subscript | Flow found |
|
||||
| test.py:340:10:340:20 | ControlFlowNode for Subscript | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:340:10:340:20 | ControlFlowNode for Subscript | Flow found |
|
||||
| test.py:340:10:340:20 | ControlFlowNode for Subscript | test.py:340:11:340:16 | ControlFlowNode for SOURCE | test.py:340:10:340:20 | ControlFlowNode for Subscript | Flow found |
|
||||
| test.py:344:10:344:27 | ControlFlowNode for Subscript | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:344:10:344:27 | ControlFlowNode for Subscript | Flow found |
|
||||
| test.py:344:10:344:27 | ControlFlowNode for Subscript | test.py:344:16:344:21 | ControlFlowNode for SOURCE | test.py:344:10:344:27 | ControlFlowNode for Subscript | Flow found |
|
||||
| test.py:367:10:367:34 | ControlFlowNode for second() | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:367:10:367:34 | ControlFlowNode for second() | Flow found |
|
||||
| test.py:367:10:367:34 | ControlFlowNode for second() | test.py:367:28:367:33 | ControlFlowNode for SOURCE | test.py:367:10:367:34 | ControlFlowNode for second() | Flow found |
|
||||
| test.py:375:10:375:36 | ControlFlowNode for second() | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:375:10:375:36 | ControlFlowNode for second() | Flow found |
|
||||
| test.py:375:10:375:36 | ControlFlowNode for second() | test.py:375:30:375:35 | ControlFlowNode for SOURCE | test.py:375:10:375:36 | ControlFlowNode for second() | Flow found |
|
||||
| test.py:383:10:383:43 | ControlFlowNode for second() | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:383:10:383:43 | ControlFlowNode for second() | Flow found |
|
||||
| test.py:383:10:383:43 | ControlFlowNode for second() | test.py:383:36:383:41 | ControlFlowNode for SOURCE | test.py:383:10:383:43 | ControlFlowNode for second() | Flow found |
|
||||
| test.py:391:10:391:39 | ControlFlowNode for f_extra_pos() | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:391:10:391:39 | ControlFlowNode for f_extra_pos() | Flow found |
|
||||
| test.py:391:10:391:39 | ControlFlowNode for f_extra_pos() | test.py:391:33:391:38 | ControlFlowNode for SOURCE | test.py:391:10:391:39 | ControlFlowNode for f_extra_pos() | Flow found |
|
||||
| test.py:399:10:399:45 | ControlFlowNode for f_extra_keyword() | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:399:10:399:45 | ControlFlowNode for f_extra_keyword() | Flow found |
|
||||
| test.py:399:10:399:45 | ControlFlowNode for f_extra_keyword() | test.py:399:39:399:44 | ControlFlowNode for SOURCE | test.py:399:10:399:45 | ControlFlowNode for f_extra_keyword() | Flow found |
|
||||
| test.py:420:10:420:38 | ControlFlowNode for IfExp | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:420:10:420:38 | ControlFlowNode for IfExp | Flow found |
|
||||
| test.py:420:10:420:38 | ControlFlowNode for IfExp | test.py:420:10:420:15 | ControlFlowNode for SOURCE | test.py:420:10:420:38 | ControlFlowNode for IfExp | Flow found |
|
||||
| test.py:428:10:428:39 | ControlFlowNode for IfExp | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:428:10:428:39 | ControlFlowNode for IfExp | Flow found |
|
||||
| test.py:428:10:428:39 | ControlFlowNode for IfExp | test.py:428:34:428:39 | ControlFlowNode for SOURCE | test.py:428:10:428:39 | ControlFlowNode for IfExp | Flow found |
|
||||
| test.py:452:10:452:18 | ControlFlowNode for f() | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:452:10:452:18 | ControlFlowNode for f() | Flow found |
|
||||
| test.py:452:10:452:18 | ControlFlowNode for f() | test.py:452:12:452:17 | ControlFlowNode for SOURCE | test.py:452:10:452:18 | ControlFlowNode for f() | Flow found |
|
||||
| test.py:459:10:459:34 | ControlFlowNode for second() | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:459:10:459:34 | ControlFlowNode for second() | Flow found |
|
||||
| test.py:459:10:459:34 | ControlFlowNode for second() | test.py:459:28:459:33 | ControlFlowNode for SOURCE | test.py:459:10:459:34 | ControlFlowNode for second() | Flow found |
|
||||
| test.py:473:10:473:36 | ControlFlowNode for second() | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:473:10:473:36 | ControlFlowNode for second() | Flow found |
|
||||
| test.py:473:10:473:36 | ControlFlowNode for second() | test.py:473:30:473:35 | ControlFlowNode for SOURCE | test.py:473:10:473:36 | ControlFlowNode for second() | Flow found |
|
||||
| test.py:487:10:487:43 | ControlFlowNode for second() | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:487:10:487:43 | ControlFlowNode for second() | Flow found |
|
||||
| test.py:487:10:487:43 | ControlFlowNode for second() | test.py:487:36:487:41 | ControlFlowNode for SOURCE | test.py:487:10:487:43 | ControlFlowNode for second() | Flow found |
|
||||
| test.py:492:10:492:39 | ControlFlowNode for f_extra_pos() | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:492:10:492:39 | ControlFlowNode for f_extra_pos() | Flow found |
|
||||
| test.py:492:10:492:39 | ControlFlowNode for f_extra_pos() | test.py:492:33:492:38 | ControlFlowNode for SOURCE | test.py:492:10:492:39 | ControlFlowNode for f_extra_pos() | Flow found |
|
||||
| test.py:497:10:497:45 | ControlFlowNode for f_extra_keyword() | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:497:10:497:45 | ControlFlowNode for f_extra_keyword() | Flow found |
|
||||
| test.py:497:10:497:45 | ControlFlowNode for f_extra_keyword() | test.py:497:39:497:44 | ControlFlowNode for SOURCE | test.py:497:10:497:45 | ControlFlowNode for f_extra_keyword() | Flow found |
|
||||
| test.py:511:10:511:10 | ControlFlowNode for a | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:511:10:511:10 | ControlFlowNode for a | Flow found |
|
||||
| test.py:511:10:511:10 | ControlFlowNode for a | test.py:509:9:509:14 | ControlFlowNode for SOURCE | test.py:511:10:511:10 | ControlFlowNode for a | Flow found |
|
||||
| test.py:516:10:516:10 | ControlFlowNode for b | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:516:10:516:10 | ControlFlowNode for b | Flow found |
|
||||
| test.py:516:10:516:10 | ControlFlowNode for b | test.py:509:9:509:14 | ControlFlowNode for SOURCE | test.py:516:10:516:10 | ControlFlowNode for b | Flow found |
|
||||
| test.py:591:10:591:36 | ControlFlowNode for return_from_inner_scope() | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:591:10:591:36 | ControlFlowNode for return_from_inner_scope() | Flow found |
|
||||
| test.py:591:10:591:36 | ControlFlowNode for return_from_inner_scope() | test.py:588:16:588:21 | ControlFlowNode for SOURCE | test.py:591:10:591:36 | ControlFlowNode for return_from_inner_scope() | Flow found |
|
||||
| test.py:349:10:349:21 | ControlFlowNode for Subscript | test.py:349:11:349:16 | ControlFlowNode for SOURCE | test.py:349:10:349:21 | ControlFlowNode for Subscript | Flow found |
|
||||
| test.py:353:10:353:20 | ControlFlowNode for Subscript | test.py:353:11:353:16 | ControlFlowNode for SOURCE | test.py:353:10:353:20 | ControlFlowNode for Subscript | Flow found |
|
||||
| test.py:357:10:357:27 | ControlFlowNode for Subscript | test.py:357:16:357:21 | ControlFlowNode for SOURCE | test.py:357:10:357:27 | ControlFlowNode for Subscript | Flow found |
|
||||
| test.py:380:10:380:34 | ControlFlowNode for second() | test.py:380:28:380:33 | ControlFlowNode for SOURCE | test.py:380:10:380:34 | ControlFlowNode for second() | Flow found |
|
||||
| test.py:388:10:388:36 | ControlFlowNode for second() | test.py:388:30:388:35 | ControlFlowNode for SOURCE | test.py:388:10:388:36 | ControlFlowNode for second() | Flow found |
|
||||
| test.py:396:10:396:43 | ControlFlowNode for second() | test.py:396:36:396:41 | ControlFlowNode for SOURCE | test.py:396:10:396:43 | ControlFlowNode for second() | Flow found |
|
||||
| test.py:404:10:404:39 | ControlFlowNode for f_extra_pos() | test.py:404:33:404:38 | ControlFlowNode for SOURCE | test.py:404:10:404:39 | ControlFlowNode for f_extra_pos() | Flow found |
|
||||
| test.py:412:10:412:45 | ControlFlowNode for f_extra_keyword() | test.py:412:39:412:44 | ControlFlowNode for SOURCE | test.py:412:10:412:45 | ControlFlowNode for f_extra_keyword() | Flow found |
|
||||
| test.py:433:10:433:38 | ControlFlowNode for IfExp | test.py:433:10:433:15 | ControlFlowNode for SOURCE | test.py:433:10:433:38 | ControlFlowNode for IfExp | Flow found |
|
||||
| test.py:441:10:441:39 | ControlFlowNode for IfExp | test.py:441:34:441:39 | ControlFlowNode for SOURCE | test.py:441:10:441:39 | ControlFlowNode for IfExp | Flow found |
|
||||
| test.py:465:10:465:18 | ControlFlowNode for f() | test.py:465:12:465:17 | ControlFlowNode for SOURCE | test.py:465:10:465:18 | ControlFlowNode for f() | Flow found |
|
||||
| test.py:472:10:472:34 | ControlFlowNode for second() | test.py:472:28:472:33 | ControlFlowNode for SOURCE | test.py:472:10:472:34 | ControlFlowNode for second() | Flow found |
|
||||
| test.py:486:10:486:36 | ControlFlowNode for second() | test.py:486:30:486:35 | ControlFlowNode for SOURCE | test.py:486:10:486:36 | ControlFlowNode for second() | Flow found |
|
||||
| test.py:500:10:500:43 | ControlFlowNode for second() | test.py:500:36:500:41 | ControlFlowNode for SOURCE | test.py:500:10:500:43 | ControlFlowNode for second() | Flow found |
|
||||
| test.py:505:10:505:39 | ControlFlowNode for f_extra_pos() | test.py:505:33:505:38 | ControlFlowNode for SOURCE | test.py:505:10:505:39 | ControlFlowNode for f_extra_pos() | Flow found |
|
||||
| test.py:510:10:510:45 | ControlFlowNode for f_extra_keyword() | test.py:510:39:510:44 | ControlFlowNode for SOURCE | test.py:510:10:510:45 | ControlFlowNode for f_extra_keyword() | Flow found |
|
||||
| test.py:524:10:524:10 | ControlFlowNode for a | test.py:522:9:522:14 | ControlFlowNode for SOURCE | test.py:524:10:524:10 | ControlFlowNode for a | Flow found |
|
||||
| test.py:529:10:529:10 | ControlFlowNode for b | test.py:522:9:522:14 | ControlFlowNode for SOURCE | test.py:529:10:529:10 | ControlFlowNode for b | Flow found |
|
||||
| test.py:536:10:536:10 | ControlFlowNode for a | test.py:534:10:534:15 | ControlFlowNode for SOURCE | test.py:536:10:536:10 | ControlFlowNode for a | Flow found |
|
||||
| test.py:544:10:544:10 | ControlFlowNode for a | test.py:542:10:542:15 | ControlFlowNode for SOURCE | test.py:544:10:544:10 | ControlFlowNode for a | Flow found |
|
||||
| test.py:546:10:546:10 | ControlFlowNode for c | test.py:542:30:542:35 | ControlFlowNode for SOURCE | test.py:546:10:546:10 | ControlFlowNode for c | Flow found |
|
||||
| test.py:553:10:553:10 | ControlFlowNode for a | test.py:551:13:551:18 | ControlFlowNode for SOURCE | test.py:553:10:553:10 | ControlFlowNode for a | Flow found |
|
||||
| test.py:561:10:561:10 | ControlFlowNode for a | test.py:559:10:559:15 | ControlFlowNode for SOURCE | test.py:561:10:561:10 | ControlFlowNode for a | Flow found |
|
||||
| test.py:563:10:563:13 | ControlFlowNode for Subscript | test.py:559:18:559:23 | ControlFlowNode for SOURCE | test.py:563:10:563:13 | ControlFlowNode for Subscript | Flow found |
|
||||
| test.py:564:12:564:12 | ControlFlowNode for c | test.py:559:18:559:23 | ControlFlowNode for SOURCE | test.py:564:12:564:12 | ControlFlowNode for c | Flow found |
|
||||
| test.py:571:10:571:10 | ControlFlowNode for a | test.py:569:10:569:15 | ControlFlowNode for SOURCE | test.py:571:10:571:10 | ControlFlowNode for a | Flow found |
|
||||
| test.py:573:10:573:10 | ControlFlowNode for c | test.py:569:18:569:23 | ControlFlowNode for SOURCE | test.py:573:10:573:10 | ControlFlowNode for c | Flow found |
|
||||
| test.py:582:10:582:11 | ControlFlowNode for a1 | test.py:578:12:578:17 | ControlFlowNode for SOURCE | test.py:582:10:582:11 | ControlFlowNode for a1 | Flow found |
|
||||
| test.py:582:10:582:11 | ControlFlowNode for a1 | test.py:578:31:578:36 | ControlFlowNode for SOURCE | test.py:582:10:582:11 | ControlFlowNode for a1 | Flow found |
|
||||
| test.py:582:10:582:11 | ControlFlowNode for a1 | test.py:578:41:578:46 | ControlFlowNode for SOURCE | test.py:582:10:582:11 | ControlFlowNode for a1 | Flow found |
|
||||
| test.py:583:12:583:13 | ControlFlowNode for a2 | test.py:578:12:578:17 | ControlFlowNode for SOURCE | test.py:583:12:583:13 | ControlFlowNode for a2 | Flow found |
|
||||
| test.py:583:12:583:13 | ControlFlowNode for a2 | test.py:578:31:578:36 | ControlFlowNode for SOURCE | test.py:583:12:583:13 | ControlFlowNode for a2 | Flow found |
|
||||
| test.py:583:12:583:13 | ControlFlowNode for a2 | test.py:578:41:578:46 | ControlFlowNode for SOURCE | test.py:583:12:583:13 | ControlFlowNode for a2 | Flow found |
|
||||
| test.py:584:10:584:11 | ControlFlowNode for a3 | test.py:578:12:578:17 | ControlFlowNode for SOURCE | test.py:584:10:584:11 | ControlFlowNode for a3 | Flow found |
|
||||
| test.py:584:10:584:11 | ControlFlowNode for a3 | test.py:578:31:578:36 | ControlFlowNode for SOURCE | test.py:584:10:584:11 | ControlFlowNode for a3 | Flow found |
|
||||
| test.py:584:10:584:11 | ControlFlowNode for a3 | test.py:578:41:578:46 | ControlFlowNode for SOURCE | test.py:584:10:584:11 | ControlFlowNode for a3 | Flow found |
|
||||
| test.py:590:10:590:11 | ControlFlowNode for a1 | test.py:578:12:578:17 | ControlFlowNode for SOURCE | test.py:590:10:590:11 | ControlFlowNode for a1 | Flow found |
|
||||
| test.py:590:10:590:11 | ControlFlowNode for a1 | test.py:578:31:578:36 | ControlFlowNode for SOURCE | test.py:590:10:590:11 | ControlFlowNode for a1 | Flow found |
|
||||
| test.py:590:10:590:11 | ControlFlowNode for a1 | test.py:578:41:578:46 | ControlFlowNode for SOURCE | test.py:590:10:590:11 | ControlFlowNode for a1 | Flow found |
|
||||
| test.py:591:12:591:13 | ControlFlowNode for a2 | test.py:578:12:578:17 | ControlFlowNode for SOURCE | test.py:591:12:591:13 | ControlFlowNode for a2 | Flow found |
|
||||
| test.py:591:12:591:13 | ControlFlowNode for a2 | test.py:578:31:578:36 | ControlFlowNode for SOURCE | test.py:591:12:591:13 | ControlFlowNode for a2 | Flow found |
|
||||
| test.py:591:12:591:13 | ControlFlowNode for a2 | test.py:578:41:578:46 | ControlFlowNode for SOURCE | test.py:591:12:591:13 | ControlFlowNode for a2 | Flow found |
|
||||
| test.py:592:10:592:11 | ControlFlowNode for a3 | test.py:578:12:578:17 | ControlFlowNode for SOURCE | test.py:592:10:592:11 | ControlFlowNode for a3 | Flow found |
|
||||
| test.py:592:10:592:11 | ControlFlowNode for a3 | test.py:578:31:578:36 | ControlFlowNode for SOURCE | test.py:592:10:592:11 | ControlFlowNode for a3 | Flow found |
|
||||
| test.py:592:10:592:11 | ControlFlowNode for a3 | test.py:578:41:578:46 | ControlFlowNode for SOURCE | test.py:592:10:592:11 | ControlFlowNode for a3 | Flow found |
|
||||
| test.py:598:10:598:11 | ControlFlowNode for a1 | test.py:578:12:578:17 | ControlFlowNode for SOURCE | test.py:598:10:598:11 | ControlFlowNode for a1 | Flow found |
|
||||
| test.py:598:10:598:11 | ControlFlowNode for a1 | test.py:578:31:578:36 | ControlFlowNode for SOURCE | test.py:598:10:598:11 | ControlFlowNode for a1 | Flow found |
|
||||
| test.py:598:10:598:11 | ControlFlowNode for a1 | test.py:578:41:578:46 | ControlFlowNode for SOURCE | test.py:598:10:598:11 | ControlFlowNode for a1 | Flow found |
|
||||
| test.py:599:12:599:13 | ControlFlowNode for a2 | test.py:578:12:578:17 | ControlFlowNode for SOURCE | test.py:599:12:599:13 | ControlFlowNode for a2 | Flow found |
|
||||
| test.py:599:12:599:13 | ControlFlowNode for a2 | test.py:578:31:578:36 | ControlFlowNode for SOURCE | test.py:599:12:599:13 | ControlFlowNode for a2 | Flow found |
|
||||
| test.py:599:12:599:13 | ControlFlowNode for a2 | test.py:578:41:578:46 | ControlFlowNode for SOURCE | test.py:599:12:599:13 | ControlFlowNode for a2 | Flow found |
|
||||
| test.py:600:10:600:11 | ControlFlowNode for a3 | test.py:578:12:578:17 | ControlFlowNode for SOURCE | test.py:600:10:600:11 | ControlFlowNode for a3 | Flow found |
|
||||
| test.py:600:10:600:11 | ControlFlowNode for a3 | test.py:578:31:578:36 | ControlFlowNode for SOURCE | test.py:600:10:600:11 | ControlFlowNode for a3 | Flow found |
|
||||
| test.py:600:10:600:11 | ControlFlowNode for a3 | test.py:578:41:578:46 | ControlFlowNode for SOURCE | test.py:600:10:600:11 | ControlFlowNode for a3 | Flow found |
|
||||
| test.py:610:10:610:11 | ControlFlowNode for a1 | test.py:606:12:606:17 | ControlFlowNode for SOURCE | test.py:610:10:610:11 | ControlFlowNode for a1 | Flow found |
|
||||
| test.py:612:12:612:16 | ControlFlowNode for Subscript | test.py:606:31:606:36 | ControlFlowNode for SOURCE | test.py:612:12:612:16 | ControlFlowNode for Subscript | Flow found |
|
||||
| test.py:613:10:613:14 | ControlFlowNode for Subscript | test.py:606:31:606:36 | ControlFlowNode for SOURCE | test.py:613:10:613:14 | ControlFlowNode for Subscript | Flow found |
|
||||
| test.py:619:10:619:11 | ControlFlowNode for a1 | test.py:606:12:606:17 | ControlFlowNode for SOURCE | test.py:619:10:619:11 | ControlFlowNode for a1 | Flow found |
|
||||
| test.py:621:12:621:16 | ControlFlowNode for Subscript | test.py:606:31:606:36 | ControlFlowNode for SOURCE | test.py:621:12:621:16 | ControlFlowNode for Subscript | Flow found |
|
||||
| test.py:622:10:622:14 | ControlFlowNode for Subscript | test.py:606:31:606:36 | ControlFlowNode for SOURCE | test.py:622:10:622:14 | ControlFlowNode for Subscript | Flow found |
|
||||
| test.py:628:10:628:11 | ControlFlowNode for a1 | test.py:606:12:606:17 | ControlFlowNode for SOURCE | test.py:628:10:628:11 | ControlFlowNode for a1 | Flow found |
|
||||
| test.py:630:12:630:16 | ControlFlowNode for Subscript | test.py:606:31:606:36 | ControlFlowNode for SOURCE | test.py:630:12:630:16 | ControlFlowNode for Subscript | Flow found |
|
||||
| test.py:631:10:631:14 | ControlFlowNode for Subscript | test.py:606:31:606:36 | ControlFlowNode for SOURCE | test.py:631:10:631:14 | ControlFlowNode for Subscript | Flow found |
|
||||
| test.py:637:10:637:11 | ControlFlowNode for a1 | test.py:606:12:606:17 | ControlFlowNode for SOURCE | test.py:637:10:637:11 | ControlFlowNode for a1 | Flow found |
|
||||
| test.py:639:12:639:16 | ControlFlowNode for Subscript | test.py:606:31:606:36 | ControlFlowNode for SOURCE | test.py:639:12:639:16 | ControlFlowNode for Subscript | Flow found |
|
||||
| test.py:640:10:640:14 | ControlFlowNode for Subscript | test.py:606:31:606:36 | ControlFlowNode for SOURCE | test.py:640:10:640:14 | ControlFlowNode for Subscript | Flow found |
|
||||
| test.py:648:10:648:10 | ControlFlowNode for a | test.py:647:19:647:24 | ControlFlowNode for SOURCE | test.py:648:10:648:10 | ControlFlowNode for a | Flow found |
|
||||
| test.py:742:10:742:36 | ControlFlowNode for return_from_inner_scope() | test.py:739:16:739:21 | ControlFlowNode for SOURCE | test.py:742:10:742:36 | ControlFlowNode for return_from_inner_scope() | Flow found |
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
import python
|
||||
import experimental.dataflow.TestUtil.FlowTest
|
||||
import experimental.dataflow.testConfig
|
||||
|
||||
class DataFlowTest extends FlowTest {
|
||||
DataFlowTest() { this = "DataFlowTest" }
|
||||
|
||||
override string flowTag() { result = "flow" }
|
||||
|
||||
override predicate relevantFlow(DataFlow::Node source, DataFlow::Node sink) {
|
||||
exists(TestConfiguration cfg | cfg.hasFlow(source, sink))
|
||||
}
|
||||
}
|
||||
@@ -35,7 +35,7 @@ def SINK_F(x):
|
||||
def f(a, b):
|
||||
return a
|
||||
|
||||
SINK(f(SOURCE, 3))
|
||||
SINK(f(SOURCE, 3)) #$ flow="SOURCE -> f(..)"
|
||||
|
||||
# Instance methods
|
||||
# An instance method object combines a class, a class instance and any callable object (normally a user-defined function).
|
||||
@@ -68,18 +68,18 @@ c = C()
|
||||
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))
|
||||
SINK(c.method(SOURCE, C)) #$ flow="SOURCE -> c.method(..)"
|
||||
SINK(C.method(c, SOURCE, C)) #$ flow="SOURCE -> C.method(..)"
|
||||
SINK(func_obj(c, SOURCE, C)) #$ MISSING: flow="SOURCE -> func_obj(..)"
|
||||
|
||||
|
||||
# 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))
|
||||
SINK(c.classmethod(SOURCE)) #$ flow="SOURCE -> c.classmethod(..)"
|
||||
SINK(C.classmethod(SOURCE)) #$ flow="SOURCE -> C.classmethod(..)"
|
||||
SINK(c_func_obj(C, SOURCE)) #$ MISSING: flow="SOURCE -> c_func_obj(..)"
|
||||
|
||||
# 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 iterator’s 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.
|
||||
@@ -153,7 +153,7 @@ class Customized:
|
||||
|
||||
# testing __new__ and __init__
|
||||
customized = Customized()
|
||||
SINK(Customized.a)
|
||||
SINK(Customized.a) #$ MISSING:flow="SOURCE, l:-8 -> customized.a"
|
||||
SINK_F(Customized.b)
|
||||
SINK(customized.a)
|
||||
SINK(customized.b) # Flow found
|
||||
SINK(customized.a) #$ MISSING:flow="SOURCE, l:-10 -> customized.a"
|
||||
SINK(customized.b) #$ flow="SOURCE, l:-7 -> customized.b"
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
| test.py:187:1:187:53 | GSSA Variable SINK | test.py:189:5:189:8 | ControlFlowNode for SINK |
|
||||
| test.py:187:1:187:53 | GSSA Variable SOURCE | test.py:188:25:188:30 | ControlFlowNode for SOURCE |
|
||||
| test.py:188:5:188:5 | SSA variable x | test.py:189:10:189:10 | ControlFlowNode for x |
|
||||
| test.py:188:9:188:68 | ControlFlowNode for .0 | test.py:188:9:188:68 | SSA variable .0 |
|
||||
| test.py:188:9:188:68 | ControlFlowNode for ListComp | test.py:188:5:188:5 | SSA variable x |
|
||||
| test.py:188:9:188:68 | SSA variable .0 | test.py:188:9:188:68 | ControlFlowNode for .0 |
|
||||
| test.py:188:16:188:16 | SSA variable v | test.py:188:45:188:45 | ControlFlowNode for v |
|
||||
|
||||
@@ -41,7 +41,7 @@ def SINK_F(x):
|
||||
def test_tuple_with_local_flow():
|
||||
x = (NONSOURCE, SOURCE)
|
||||
y = x[1]
|
||||
SINK(y)
|
||||
SINK(y) #$ flow="SOURCE, l:-2 -> y"
|
||||
|
||||
|
||||
def test_tuple_negative():
|
||||
@@ -53,45 +53,45 @@ def test_tuple_negative():
|
||||
# 6.2.1. Identifiers (Names)
|
||||
def test_names():
|
||||
x = SOURCE
|
||||
SINK(x)
|
||||
SINK(x) #$ flow="SOURCE, l:-1 -> x"
|
||||
|
||||
|
||||
# 6.2.2. Literals
|
||||
def test_string_literal():
|
||||
x = "source"
|
||||
SINK(x)
|
||||
SINK(x) #$ flow="'source', l:-1 -> x"
|
||||
|
||||
|
||||
def test_bytes_literal():
|
||||
x = b"source"
|
||||
SINK(x)
|
||||
SINK(x) #$ flow="b'source', l:-1 -> x"
|
||||
|
||||
|
||||
def test_integer_literal():
|
||||
x = 42
|
||||
SINK(x)
|
||||
SINK(x) #$ flow="42, l:-1 -> x"
|
||||
|
||||
|
||||
def test_floatnumber_literal():
|
||||
x = 42.0
|
||||
SINK(x)
|
||||
SINK(x) #$ flow="42.0, l:-1 -> x"
|
||||
|
||||
|
||||
def test_imagnumber_literal():
|
||||
x = 42j
|
||||
SINK(x) # Flow missing
|
||||
SINK(x) #$ MISSING:flow="42j, l:-1 -> x"
|
||||
|
||||
|
||||
# 6.2.3. Parenthesized forms
|
||||
def test_parenthesized_form():
|
||||
x = (SOURCE)
|
||||
SINK(x)
|
||||
SINK(x) #$ flow="SOURCE, l:-1 -> x"
|
||||
|
||||
|
||||
# 6.2.5. List displays
|
||||
def test_list_display():
|
||||
x = [SOURCE]
|
||||
SINK(x[0])
|
||||
SINK(x[0]) #$ flow="SOURCE, l:-1 -> x[0]"
|
||||
|
||||
|
||||
def test_list_display_negative():
|
||||
@@ -101,109 +101,120 @@ def test_list_display_negative():
|
||||
|
||||
def test_list_comprehension():
|
||||
x = [SOURCE for y in [NONSOURCE]]
|
||||
SINK(x[0])
|
||||
SINK(x[0]) #$ flow="SOURCE, l:-1 -> x[0]"
|
||||
|
||||
|
||||
def test_list_comprehension_flow():
|
||||
x = [y for y in [SOURCE]]
|
||||
SINK(x[0])
|
||||
SINK(x[0]) #$ flow="SOURCE, l:-1 -> x[0]"
|
||||
|
||||
|
||||
def test_list_comprehension_inflow():
|
||||
l = [SOURCE]
|
||||
x = [y for y in l]
|
||||
SINK(x[0])
|
||||
SINK(x[0]) #$ flow="SOURCE, l:-2 -> x[0]"
|
||||
|
||||
|
||||
def test_nested_list_display():
|
||||
x = [*[SOURCE]]
|
||||
SINK(x[0]) # Flow missing
|
||||
SINK(x[0]) #$ MISSING:flow="SOURCE, l:-1 -> x[0]"
|
||||
|
||||
|
||||
# 6.2.6. Set displays
|
||||
def test_set_display():
|
||||
x = {SOURCE}
|
||||
SINK(x.pop())
|
||||
SINK(x.pop()) #$ flow="SOURCE, l:-1 -> x.pop()"
|
||||
|
||||
|
||||
def test_set_comprehension():
|
||||
x = {SOURCE for y in [NONSOURCE]}
|
||||
SINK(x.pop())
|
||||
SINK(x.pop()) #$ flow="SOURCE, l:-1 -> x.pop()"
|
||||
|
||||
|
||||
def test_set_comprehension_flow():
|
||||
x = {y for y in [SOURCE]}
|
||||
SINK(x.pop())
|
||||
SINK(x.pop()) #$ flow="SOURCE, l:-1 -> x.pop()"
|
||||
|
||||
|
||||
def test_set_comprehension_inflow():
|
||||
l = {SOURCE}
|
||||
x = {y for y in l}
|
||||
SINK(x.pop())
|
||||
SINK(x.pop()) #$ flow="SOURCE, l:-2 -> x.pop()"
|
||||
|
||||
|
||||
def test_nested_set_display():
|
||||
x = {*{SOURCE}}
|
||||
SINK(x.pop()) # Flow missing
|
||||
SINK(x.pop()) #$ MISSING:flow="SOURCE, l:-1 -> x.pop()"
|
||||
|
||||
|
||||
# 6.2.7. Dictionary displays
|
||||
def test_dict_display():
|
||||
x = {"s": SOURCE}
|
||||
SINK(x["s"])
|
||||
SINK(x["s"]) #$ flow="SOURCE, l:-1 -> x['s']"
|
||||
|
||||
|
||||
def test_dict_display_pop():
|
||||
x = {"s": SOURCE}
|
||||
SINK(x.pop("s"))
|
||||
SINK(x.pop("s")) #$ flow="SOURCE, l:-1 -> x.pop(..)"
|
||||
|
||||
|
||||
def test_dict_comprehension():
|
||||
x = {y: SOURCE for y in ["s"]}
|
||||
SINK(x["s"]) # Flow missing
|
||||
SINK(x["s"]) #$ MISSING:flow="SOURCE, l:-1 -> x['s']"
|
||||
|
||||
|
||||
def test_dict_comprehension_pop():
|
||||
x = {y: SOURCE for y in ["s"]}
|
||||
SINK(x.pop("s")) # Flow missing
|
||||
SINK(x.pop("s")) #$ MISSING:flow="SOURCE, l:-1 -> x.pop()"
|
||||
|
||||
|
||||
def test_nested_dict_display():
|
||||
x = {**{"s": SOURCE}}
|
||||
SINK(x["s"]) # Flow missing
|
||||
SINK(x["s"]) #$ MISSING:flow="SOURCE, l:-1 -> x['s']"
|
||||
|
||||
|
||||
def test_nested_dict_display_pop():
|
||||
x = {**{"s": SOURCE}}
|
||||
SINK(x.pop("s")) # Flow missing
|
||||
SINK(x.pop("s")) #$ MISSING:flow="SOURCE, l:-1 -> x.pop()"
|
||||
|
||||
|
||||
# Nested comprehensions
|
||||
def test_nested_comprehension():
|
||||
x = [y for z in [[SOURCE]] for y in z]
|
||||
SINK(x[0])
|
||||
SINK(x[0]) #$ flow="SOURCE, l:-1 -> x[0]"
|
||||
|
||||
|
||||
def test_nested_comprehension_deep_with_local_flow():
|
||||
x = [y for v in [[[[SOURCE]]]] for u in v for z in u for y in z]
|
||||
SINK(x[0])
|
||||
SINK(x[0]) #$ flow="SOURCE, l:-1 -> x[0]"
|
||||
|
||||
|
||||
def test_nested_comprehension_dict():
|
||||
d = {"s": [SOURCE]}
|
||||
x = [y for k, v in d.items() for y in v]
|
||||
SINK(x[0]) # Flow missing
|
||||
SINK(x[0]) #$ MISSING:flow="SOURCE, l:-1 -> x[0]"
|
||||
|
||||
|
||||
def test_nested_comprehension_paren():
|
||||
x = [y for y in (z for z in [SOURCE])]
|
||||
SINK(x[0])
|
||||
SINK(x[0]) #$ flow="SOURCE, l:-1 -> x[0]"
|
||||
|
||||
|
||||
# Iterable unpacking in comprehensions
|
||||
def test_unpacking_comprehension():
|
||||
x = [a for (a, b) in [(SOURCE, NONSOURCE)]]
|
||||
SINK(x[0]) # Flow missing
|
||||
|
||||
|
||||
def test_star_unpacking_comprehension():
|
||||
x = [a[0] for (*a, b) in [(SOURCE, NONSOURCE)]]
|
||||
SINK(x[0]) # Flow missing
|
||||
|
||||
|
||||
# 6.2.8. Generator expressions
|
||||
def test_generator():
|
||||
x = (SOURCE for y in [NONSOURCE])
|
||||
SINK([*x][0]) # Flow missing
|
||||
SINK([*x][0]) #$ MISSING:flow="SOURCE, l:-1 -> List[0]"
|
||||
|
||||
|
||||
# 6.2.9. Yield expressions
|
||||
@@ -213,7 +224,7 @@ def gen(x):
|
||||
|
||||
def test_yield():
|
||||
g = gen(SOURCE)
|
||||
SINK(next(g)) # Flow missing
|
||||
SINK(next(g)) #$ MISSING:flow="SOURCE, l:-1 -> next()"
|
||||
|
||||
|
||||
def gen_from(x):
|
||||
@@ -222,19 +233,19 @@ def gen_from(x):
|
||||
|
||||
def test_yield_from():
|
||||
g = gen_from(SOURCE)
|
||||
SINK(next(g)) # Flow missing
|
||||
SINK(next(g)) #$ MISSING:flow="SOURCE, l:-1 -> next()"
|
||||
|
||||
|
||||
# a statement rather than an expression, but related to generators
|
||||
def test_for():
|
||||
for x in gen(SOURCE):
|
||||
SINK(x) # Flow missing
|
||||
SINK(x) #$ MISSING:flow="SOURCE, l:-1 -> x"
|
||||
|
||||
|
||||
# 6.2.9.1. Generator-iterator methods
|
||||
def test___next__():
|
||||
g = gen(SOURCE)
|
||||
SINK(g.__next__()) # Flow missing
|
||||
SINK(g.__next__()) #$ MISSING:flow="SOURCE, l:-1 -> g.__next__()"
|
||||
|
||||
|
||||
def gen2(x):
|
||||
@@ -246,7 +257,7 @@ def gen2(x):
|
||||
def test_send():
|
||||
g = gen2(NONSOURCE)
|
||||
n = next(g)
|
||||
SINK(g.send(SOURCE)) # Flow missing
|
||||
SINK(g.send(SOURCE)) #$ MISSING:flow="SOURCE -> g.send()"
|
||||
|
||||
|
||||
def gen_ex(x):
|
||||
@@ -259,7 +270,7 @@ def gen_ex(x):
|
||||
def test_throw():
|
||||
g = gen_ex(SOURCE)
|
||||
n = next(g)
|
||||
SINK(g.throw(TypeError)) # Flow missing
|
||||
SINK(g.throw(TypeError)) #$ MISSING:flow="SOURCE, l:-2 -> g.throw()"
|
||||
|
||||
|
||||
# no `test_close` as `close` involves no data flow
|
||||
@@ -280,7 +291,7 @@ def runa(a):
|
||||
|
||||
async def atest___anext__():
|
||||
g = agen(SOURCE)
|
||||
SINK(await g.__anext__()) # Flow missing
|
||||
SINK(await g.__anext__()) #$ MISSING:flow="SOURCE, l:-1 -> g.__anext__()"
|
||||
|
||||
|
||||
def test___anext__():
|
||||
@@ -296,7 +307,7 @@ async def agen2(x):
|
||||
async def atest_asend():
|
||||
g = agen2(NONSOURCE)
|
||||
n = await g.__anext__()
|
||||
SINK(await g.asend(SOURCE)) # Flow missing
|
||||
SINK(await g.asend(SOURCE)) #$ MISSING:flow="SOURCE -> g.asend()"
|
||||
|
||||
|
||||
def test_asend():
|
||||
@@ -313,7 +324,7 @@ async def agen_ex(x):
|
||||
async def atest_athrow():
|
||||
g = agen_ex(SOURCE)
|
||||
n = await g.__anext__()
|
||||
SINK(await g.athrow(TypeError)) # Flow missing
|
||||
SINK(await g.athrow(TypeError)) #$ MISSING:flow="SOURCE, l:-2 -> g.athrow()"
|
||||
|
||||
|
||||
def test_athrow():
|
||||
@@ -325,23 +336,25 @@ class C:
|
||||
a = SOURCE
|
||||
|
||||
|
||||
@expects(2)
|
||||
def test_attribute_reference():
|
||||
SINK(C.a) # Flow missing
|
||||
|
||||
SINK(C.a) #$ MISSING:flow="SOURCE, l:-4 -> C.a"
|
||||
c = C()
|
||||
SINK(c.a) #$ MISSING:flow="SOURCE, l:-6 -> c.a"
|
||||
|
||||
# overriding __getattr__ should be tested by the class coverage tests
|
||||
|
||||
# 6.3.2. Subscriptions
|
||||
def test_subscription_tuple():
|
||||
SINK((SOURCE,)[0])
|
||||
SINK((SOURCE,)[0]) #$ flow="SOURCE -> Tuple[0]"
|
||||
|
||||
|
||||
def test_subscription_list():
|
||||
SINK([SOURCE][0])
|
||||
SINK([SOURCE][0]) #$ flow="SOURCE -> List[0]"
|
||||
|
||||
|
||||
def test_subscription_mapping():
|
||||
SINK({"s": SOURCE}["s"])
|
||||
SINK({"s": SOURCE}["s"]) #$ flow="SOURCE -> Dict['s']"
|
||||
|
||||
|
||||
# overriding __getitem__ should be tested by the class coverage tests
|
||||
@@ -353,7 +366,7 @@ l = [SOURCE]
|
||||
|
||||
def test_slicing():
|
||||
s = l[0:1:1]
|
||||
SINK(s[0]) # Flow missing
|
||||
SINK(s[0]) #$ MISSING:flow="SOURCE -> s[0]"
|
||||
|
||||
|
||||
# The grammar seems to allow `l[0:1:1, 0:1]`, but the interpreter does not like it
|
||||
@@ -364,7 +377,7 @@ def second(a, b):
|
||||
|
||||
|
||||
def test_call_positional():
|
||||
SINK(second(NONSOURCE, SOURCE))
|
||||
SINK(second(NONSOURCE, SOURCE)) #$ flow="SOURCE -> second(..)"
|
||||
|
||||
|
||||
def test_call_positional_negative():
|
||||
@@ -372,15 +385,15 @@ def test_call_positional_negative():
|
||||
|
||||
|
||||
def test_call_keyword():
|
||||
SINK(second(NONSOURCE, b=SOURCE))
|
||||
SINK(second(NONSOURCE, b=SOURCE)) #$ flow="SOURCE -> second(..)"
|
||||
|
||||
|
||||
def test_call_unpack_iterable():
|
||||
SINK(second(NONSOURCE, *[SOURCE])) # Flow missing
|
||||
SINK(second(NONSOURCE, *[SOURCE])) #$ MISSING:flow="SOURCE -> second(..)"
|
||||
|
||||
|
||||
def test_call_unpack_mapping():
|
||||
SINK(second(NONSOURCE, **{"b": SOURCE}))
|
||||
SINK(second(NONSOURCE, **{"b": SOURCE})) #$ flow="SOURCE -> second(..)"
|
||||
|
||||
|
||||
def f_extra_pos(a, *b):
|
||||
@@ -388,7 +401,7 @@ def f_extra_pos(a, *b):
|
||||
|
||||
|
||||
def test_call_extra_pos():
|
||||
SINK(f_extra_pos(NONSOURCE, SOURCE))
|
||||
SINK(f_extra_pos(NONSOURCE, SOURCE)) #$ flow="SOURCE -> f_extra_pos(..)"
|
||||
|
||||
|
||||
def f_extra_keyword(a, **b):
|
||||
@@ -396,7 +409,7 @@ def f_extra_keyword(a, **b):
|
||||
|
||||
|
||||
def test_call_extra_keyword():
|
||||
SINK(f_extra_keyword(NONSOURCE, b=SOURCE))
|
||||
SINK(f_extra_keyword(NONSOURCE, b=SOURCE)) #$ flow="SOURCE -> f_extra_keyword(..)"
|
||||
|
||||
|
||||
# return the name of the first extra keyword argument
|
||||
@@ -406,18 +419,18 @@ def f_extra_keyword_flow(**a):
|
||||
|
||||
# call the function with our source as the name of the keyword arguemnt
|
||||
def test_call_extra_keyword_flow():
|
||||
SINK(f_extra_keyword_flow(**{SOURCE: None})) # Flow missing
|
||||
SINK(f_extra_keyword_flow(**{SOURCE: None})) #$ MISSING:flow="SOURCE -> f_extra_keyword(..)"
|
||||
|
||||
|
||||
# 6.12. Assignment expressions
|
||||
def test_assignment_expression():
|
||||
x = NONSOURCE
|
||||
SINK(x := SOURCE) # Flow missing
|
||||
SINK(x := SOURCE) #$ MISSING:flow="SOURCE -> x"
|
||||
|
||||
|
||||
# 6.13. Conditional expressions
|
||||
def test_conditional_true():
|
||||
SINK(SOURCE if True else NONSOURCE)
|
||||
SINK(SOURCE if True else NONSOURCE) #$ flow="SOURCE -> IfExp"
|
||||
|
||||
|
||||
def test_conditional_true_guards():
|
||||
@@ -425,7 +438,7 @@ def test_conditional_true_guards():
|
||||
|
||||
|
||||
def test_conditional_false():
|
||||
SINK(NONSOURCE if False else SOURCE)
|
||||
SINK(NONSOURCE if False else SOURCE) #$ flow="SOURCE -> IfExp"
|
||||
|
||||
|
||||
def test_conditional_false_guards():
|
||||
@@ -435,13 +448,13 @@ def test_conditional_false_guards():
|
||||
# Condition is evaluated first, so x is SOURCE once chosen
|
||||
def test_conditional_evaluation_true():
|
||||
x = NONSOURCE
|
||||
SINK(x if (SOURCE == (x := SOURCE)) else NONSOURCE) # Flow missing
|
||||
SINK(x if (SOURCE == (x := SOURCE)) else NONSOURCE) #$ MISSING:flow="SOURCE -> IfExp"
|
||||
|
||||
|
||||
# Condition is evaluated first, so x is SOURCE once chosen
|
||||
def test_conditional_evaluation_false():
|
||||
x = NONSOURCE
|
||||
SINK(NONSOURCE if (NONSOURCE == (x := SOURCE)) else x) # Flow missing
|
||||
SINK(NONSOURCE if (NONSOURCE == (x := SOURCE)) else x) #$ MISSING:flow="SOURCE -> IfExp"
|
||||
|
||||
|
||||
# 6.14. Lambdas
|
||||
@@ -449,14 +462,14 @@ def test_lambda():
|
||||
def f(x):
|
||||
return x
|
||||
|
||||
SINK(f(SOURCE))
|
||||
SINK(f(SOURCE)) #$ flow="SOURCE -> f(..)"
|
||||
|
||||
|
||||
def test_lambda_positional():
|
||||
def second(a, b):
|
||||
return b
|
||||
|
||||
SINK(second(NONSOURCE, SOURCE))
|
||||
SINK(second(NONSOURCE, SOURCE)) #$ flow="SOURCE -> second(..)"
|
||||
|
||||
|
||||
def test_lambda_positional_negative():
|
||||
@@ -470,50 +483,188 @@ def test_lambda_keyword():
|
||||
def second(a, b):
|
||||
return b
|
||||
|
||||
SINK(second(NONSOURCE, b=SOURCE))
|
||||
SINK(second(NONSOURCE, b=SOURCE)) #$ flow="SOURCE -> second(..)"
|
||||
|
||||
|
||||
def test_lambda_unpack_iterable():
|
||||
def second(a, b):
|
||||
return b
|
||||
|
||||
SINK(second(NONSOURCE, *[SOURCE])) # Flow missing
|
||||
SINK(second(NONSOURCE, *[SOURCE])) #$ MISSING:flow="SOURCE -> second(..)" # Flow missing
|
||||
|
||||
|
||||
def test_lambda_unpack_mapping():
|
||||
def second(a, b):
|
||||
return b
|
||||
|
||||
SINK(second(NONSOURCE, **{"b": SOURCE}))
|
||||
SINK(second(NONSOURCE, **{"b": SOURCE})) #$ flow="SOURCE -> second(..)"
|
||||
|
||||
|
||||
def test_lambda_extra_pos():
|
||||
f_extra_pos = lambda a, *b: b[0]
|
||||
SINK(f_extra_pos(NONSOURCE, SOURCE))
|
||||
SINK(f_extra_pos(NONSOURCE, SOURCE)) #$ flow="SOURCE -> f_extra_pos(..)"
|
||||
|
||||
|
||||
def test_lambda_extra_keyword():
|
||||
f_extra_keyword = lambda a, **b: b["b"]
|
||||
SINK(f_extra_keyword(NONSOURCE, b=SOURCE))
|
||||
SINK(f_extra_keyword(NONSOURCE, b=SOURCE)) #$ flow="SOURCE -> f_extra_keyword(..)"
|
||||
|
||||
|
||||
# call the function with our source as the name of the keyword argument
|
||||
def test_lambda_extra_keyword_flow():
|
||||
# return the name of the first extra keyword argument
|
||||
f_extra_keyword_flow = lambda **a: [*a][0]
|
||||
SINK(f_extra_keyword_flow(**{SOURCE: None})) # Flow missing
|
||||
SINK(f_extra_keyword_flow(**{SOURCE: None})) #$ MISSING:flow="SOURCE -> f_extra_keyword(..)"
|
||||
|
||||
|
||||
@expects(4)
|
||||
def test_swap():
|
||||
a = SOURCE
|
||||
b = NONSOURCE
|
||||
SINK(a)
|
||||
SINK(a) #$ flow="SOURCE, l:-2 -> a"
|
||||
SINK_F(b)
|
||||
|
||||
a, b = b, a
|
||||
SINK_F(a)
|
||||
SINK(b)
|
||||
SINK(b) #$ flow="SOURCE, l:-7 -> b"
|
||||
|
||||
|
||||
@expects(2)
|
||||
def test_unpacking_assignment():
|
||||
t = (SOURCE, NONSOURCE)
|
||||
a, b = t
|
||||
SINK(a) #$ flow="SOURCE, l:-2 -> a"
|
||||
SINK_F(b)
|
||||
|
||||
|
||||
@expects(3)
|
||||
def test_nested_unpacking_assignment():
|
||||
t = (SOURCE, (NONSOURCE, SOURCE))
|
||||
a, (b, c) = t
|
||||
SINK(a) #$ flow="SOURCE, l:-2 -> a"
|
||||
SINK_F(b)
|
||||
SINK(c) #$ flow="SOURCE, l:-4 -> c"
|
||||
|
||||
|
||||
@expects(2)
|
||||
def test_deeply_nested_unpacking_assignment():
|
||||
t = [[[[SOURCE]]], NONSOURCE]
|
||||
[[[a]]], b = t
|
||||
SINK(a) #$ flow="SOURCE, l:-2 -> a"
|
||||
SINK_F(b)
|
||||
|
||||
|
||||
@expects(4)
|
||||
def test_iterated_unpacking_assignment():
|
||||
t = (SOURCE, SOURCE, NONSOURCE)
|
||||
a, *b, c = t
|
||||
SINK(a) #$ flow="SOURCE, l:-2 -> a"
|
||||
SINK_F(b)
|
||||
SINK(b[0]) #$ flow="SOURCE, l:-4 -> b[0]"
|
||||
SINK_F(c) #$ SPURIOUS: flow="SOURCE, l:-5 -> c" # We do not track tuple sizes
|
||||
|
||||
|
||||
@expects(3)
|
||||
def test_iterated_unpacking_assignment_shrink():
|
||||
t = (SOURCE, SOURCE)
|
||||
a, *b, c = t
|
||||
SINK(a) #$ flow="SOURCE, l:-2 -> a"
|
||||
SINK_F(b)
|
||||
SINK(c) #$ flow="SOURCE, l:-4 -> c"
|
||||
|
||||
|
||||
@expects(15)
|
||||
def test_unpacking_assignment_conversion():
|
||||
ll = [[SOURCE, NONSOURCE, SOURCE], [SOURCE], [NONSOURCE]]
|
||||
|
||||
# tuple
|
||||
((a1, a2, a3), b, c) = ll
|
||||
SINK(a1) #$ flow="SOURCE, l:-4 -> a1"
|
||||
SINK_F(a2) #$ SPURIOUS: flow="SOURCE, l:-5 -> a2" # We expect an FP as all elements are tainted
|
||||
SINK(a3) #$ flow="SOURCE, l:-6 -> a3"
|
||||
SINK_F(b) # The list itself is not tainted
|
||||
SINK_F(c)
|
||||
|
||||
# mixed
|
||||
[(a1, a2, a3), b, c] = ll
|
||||
SINK(a1) #$ flow="SOURCE, l:-12 -> a1"
|
||||
SINK_F(a2) #$ SPURIOUS: flow="SOURCE, l:-13 -> a2" # We expect an FP as all elements are tainted
|
||||
SINK(a3) #$ flow="SOURCE, l:-14 -> a3"
|
||||
SINK_F(b) # The list itself is not tainted
|
||||
SINK_F(c)
|
||||
|
||||
# mixed differently
|
||||
([a1, a2, a3], b, c) = ll
|
||||
SINK(a1) #$ flow="SOURCE, l:-20 -> a1"
|
||||
SINK_F(a2) #$ SPURIOUS: flow="SOURCE, l:-21 -> a2" # We expect an FP as all elements are tainted
|
||||
SINK(a3) #$ flow="SOURCE, l:-22 -> a3"
|
||||
SINK_F(b) # The list itself is not tainted
|
||||
SINK_F(c)
|
||||
|
||||
@expects(24)
|
||||
def test_iterated_unpacking_assignment_conversion():
|
||||
tt = ((SOURCE, NONSOURCE, SOURCE),NONSOURCE)
|
||||
|
||||
# list
|
||||
[[a1, *a2], *b] = tt
|
||||
SINK(a1) #$ flow="SOURCE, l:-4 -> a1"
|
||||
SINK_F(a2) # The list itself is not tainted
|
||||
SINK_F(a2[0]) #$ SPURIOUS: flow="SOURCE, l:-6 -> a2[0]" # FP here due to list abstraction
|
||||
SINK(a2[1]) #$ flow="SOURCE, l:-7 -> a2[1]"
|
||||
SINK_F(b) # The list itself is not tainted
|
||||
SINK_F(b[0])
|
||||
|
||||
# tuple
|
||||
((a1, *a2), *b) = tt
|
||||
SINK(a1) #$ flow="SOURCE, l:-13 -> a1"
|
||||
SINK_F(a2) # The list itself is not tainted
|
||||
SINK_F(a2[0]) #$ SPURIOUS: flow="SOURCE, l:-15 -> a2[0]" # FP here due to list abstraction
|
||||
SINK(a2[1]) #$ flow="SOURCE, l:-16 -> a2[1]"
|
||||
SINK_F(b) # The list itself is not tainted
|
||||
SINK_F(b[0])
|
||||
|
||||
# mixed
|
||||
[(a1, *a2), *b] = tt
|
||||
SINK(a1) #$ flow="SOURCE, l:-22 -> a1"
|
||||
SINK_F(a2) # The list itself is not tainted
|
||||
SINK_F(a2[0]) #$ SPURIOUS: flow="SOURCE, l:-24 -> a2[0]" # FP here due to list abstraction
|
||||
SINK(a2[1]) #$ flow="SOURCE, l:-25 -> a2[1]"
|
||||
SINK_F(b) # The list itself is not tainted
|
||||
SINK_F(b[0])
|
||||
|
||||
# mixed differently
|
||||
([a1, *a2], *b) = tt
|
||||
SINK(a1) #$ flow="SOURCE, l:-31 -> a1"
|
||||
SINK_F(a2) # The list itself is not tainted
|
||||
SINK_F(a2[0]) #$ SPURIOUS: flow="SOURCE, l:-33 -> a2[0]" # FP here due to list abstraction
|
||||
SINK(a2[1]) #$ flow="SOURCE, l:-34 -> a2[1]"
|
||||
SINK_F(b) # The list itself is not tainted
|
||||
SINK_F(b[0])
|
||||
|
||||
|
||||
@expects(3)
|
||||
def test_iterable_repacking():
|
||||
a, *(b, c) = (SOURCE, NONSOURCE, SOURCE)
|
||||
SINK(a) #$ flow="SOURCE, l:-1 -> a"
|
||||
SINK_F(b)
|
||||
SINK(c) #$ MISSING: flow="SOURCE, l:-3 -> c"
|
||||
|
||||
|
||||
@expects(4)
|
||||
def test_iterable_unpacking_in_for():
|
||||
tl = [(SOURCE, NONSOURCE), (SOURCE, NONSOURCE)]
|
||||
for x,y in tl:
|
||||
SINK(x) #$ MISSING: flow="SOURCE, l:-2 -> x"
|
||||
SINK_F(y)
|
||||
|
||||
|
||||
@expects(6)
|
||||
def test_iterable_star_unpacking_in_for():
|
||||
tl = [(SOURCE, NONSOURCE), (SOURCE, NONSOURCE)]
|
||||
for *x,y in tl:
|
||||
SINK_F(x)
|
||||
SINK(x[0]) #$ MISSING: flow="SOURCE, l:-3 -> x[0]"
|
||||
SINK_F(y)
|
||||
|
||||
|
||||
def test_deep_callgraph():
|
||||
@@ -538,7 +689,7 @@ def test_deep_callgraph():
|
||||
return f5(arg)
|
||||
|
||||
x = f6(SOURCE)
|
||||
SINK(x) # Flow missing
|
||||
SINK(x) #$ MISSING:flow="SOURCE, l:-1 -> x"
|
||||
|
||||
|
||||
@expects(2)
|
||||
@@ -547,7 +698,7 @@ def test_dynamic_tuple_creation_1():
|
||||
tup += (SOURCE,)
|
||||
tup += (NONSOURCE,)
|
||||
|
||||
SINK(tup[0]) # Flow missing
|
||||
SINK(tup[0]) #$ MISSING:flow="SOURCE, l:-3 -> tup[0]"
|
||||
SINK_F(tup[1])
|
||||
|
||||
|
||||
@@ -557,7 +708,7 @@ def test_dynamic_tuple_creation_2():
|
||||
tup += (SOURCE,)
|
||||
tup += (NONSOURCE,)
|
||||
|
||||
SINK(tup[0]) # Flow missing
|
||||
SINK(tup[0]) #$ MISSING:flow="SOURCE, l:-3 -> tup[0]"
|
||||
SINK_F(tup[1])
|
||||
|
||||
|
||||
@@ -567,7 +718,7 @@ def test_dynamic_tuple_creation_3():
|
||||
tup2 = (NONSOURCE,)
|
||||
tup = tup1 + tup2
|
||||
|
||||
SINK(tup[0]) # Flow missing
|
||||
SINK(tup[0]) #$ MISSING:flow="SOURCE, l:-4 -> tup[0]"
|
||||
SINK_F(tup[1])
|
||||
|
||||
|
||||
@@ -578,7 +729,7 @@ def test_dynamic_tuple_creation_4():
|
||||
for item in [SOURCE, NONSOURCE]:
|
||||
tup += (item,)
|
||||
|
||||
SINK(tup[0]) # Flow missing
|
||||
SINK(tup[0]) #$ MISSING:flow="SOURCE, l:-3 -> tup[0]"
|
||||
SINK_F(tup[1])
|
||||
|
||||
def return_from_inner_scope(x):
|
||||
@@ -588,4 +739,36 @@ def return_from_inner_scope(x):
|
||||
return SOURCE
|
||||
|
||||
def test_return_from_inner_scope():
|
||||
SINK(return_from_inner_scope([]))
|
||||
SINK(return_from_inner_scope([])) #$ flow="SOURCE, l:-3 -> return_from_inner_scope(..)"
|
||||
|
||||
|
||||
# Inspired by reverse read inconsistency check
|
||||
def insertAtA(d):
|
||||
d["a"] = SOURCE
|
||||
|
||||
def test_reverse_read_subscript():
|
||||
d = {"a": NONSOURCE}
|
||||
l = [d]
|
||||
insertAtA(l[0])
|
||||
SINK(d["a"]) #$ MISSING:flow="SOURCE, l-6 -> d['a']""
|
||||
|
||||
def test_reverse_read_dict_arg():
|
||||
d = {"a": NONSOURCE}
|
||||
dd = {"d": d}
|
||||
insertAtA(**dd)
|
||||
SINK(d["a"]) #$ MISSING:flow="SOURCE, l-12 -> d['a']""
|
||||
|
||||
|
||||
class WithA:
|
||||
def setA(self, v):
|
||||
self.a = v
|
||||
|
||||
def __init__(self):
|
||||
self.a = ""
|
||||
|
||||
|
||||
def test_reverse_read_subscript_cls():
|
||||
withA = WithA()
|
||||
l = [withA]
|
||||
l[0].setA(SOURCE)
|
||||
SINK(withA.a) #$ MISSING:flow="SOURCE, l:-1 -> self.a"
|
||||
|
||||
@@ -1,34 +1,17 @@
|
||||
edges
|
||||
| examples.py:27:8:27:12 | [post arg] ControlFlowNode for myobj [Attribute foo] | examples.py:28:6:28:10 | ControlFlowNode for myobj [Attribute foo] |
|
||||
| examples.py:27:15:27:20 | ControlFlowNode for SOURCE | examples.py:27:8:27:12 | [post arg] ControlFlowNode for myobj [Attribute foo] |
|
||||
| examples.py:27:15:27:20 | ControlFlowNode for SOURCE | examples.py:35:13:35:13 | ControlFlowNode for x |
|
||||
| examples.py:27:15:27:20 | ControlFlowNode for SOURCE | examples.py:49:13:49:18 | ControlFlowNode for SOURCE |
|
||||
| examples.py:27:15:27:20 | ControlFlowNode for SOURCE | examples.py:59:29:59:34 | ControlFlowNode for SOURCE |
|
||||
| examples.py:28:6:28:10 | ControlFlowNode for myobj [Attribute foo] | examples.py:28:6:28:14 | ControlFlowNode for Attribute |
|
||||
| examples.py:31:5:31:10 | ControlFlowNode for SOURCE | examples.py:35:13:35:13 | ControlFlowNode for x |
|
||||
| examples.py:31:5:31:10 | ControlFlowNode for SOURCE | examples.py:49:13:49:18 | ControlFlowNode for SOURCE |
|
||||
| examples.py:31:5:31:10 | ControlFlowNode for SOURCE | examples.py:59:29:59:34 | ControlFlowNode for SOURCE |
|
||||
| examples.py:35:1:35:1 | [post read] ControlFlowNode for a [Attribute obj, Attribute foo] | examples.py:37:6:37:6 | ControlFlowNode for a [Attribute obj, Attribute foo] |
|
||||
| examples.py:35:1:35:5 | [post store] ControlFlowNode for Attribute [Attribute foo] | examples.py:35:1:35:1 | [post read] ControlFlowNode for a [Attribute obj, Attribute foo] |
|
||||
| examples.py:35:13:35:13 | ControlFlowNode for x | examples.py:35:1:35:5 | [post store] ControlFlowNode for Attribute [Attribute foo] |
|
||||
| examples.py:37:6:37:6 | ControlFlowNode for a [Attribute obj, Attribute foo] | examples.py:37:6:37:10 | ControlFlowNode for Attribute [Attribute foo] |
|
||||
| examples.py:37:6:37:10 | ControlFlowNode for Attribute [Attribute foo] | examples.py:37:6:37:14 | ControlFlowNode for Attribute |
|
||||
| examples.py:40:5:40:10 | ControlFlowNode for SOURCE | examples.py:49:13:49:18 | ControlFlowNode for SOURCE |
|
||||
| examples.py:40:5:40:10 | ControlFlowNode for SOURCE | examples.py:59:29:59:34 | ControlFlowNode for SOURCE |
|
||||
| examples.py:49:7:49:19 | ControlFlowNode for MyObj() [Attribute foo] | examples.py:50:6:50:8 | ControlFlowNode for obj [Attribute foo] |
|
||||
| examples.py:49:13:49:18 | ControlFlowNode for SOURCE | examples.py:49:7:49:19 | ControlFlowNode for MyObj() [Attribute foo] |
|
||||
| examples.py:49:13:49:18 | ControlFlowNode for SOURCE | examples.py:59:29:59:34 | ControlFlowNode for SOURCE |
|
||||
| examples.py:50:6:50:8 | ControlFlowNode for obj [Attribute foo] | examples.py:50:6:50:12 | ControlFlowNode for Attribute |
|
||||
| examples.py:59:29:59:34 | ControlFlowNode for SOURCE | examples.py:59:6:59:35 | ControlFlowNode for fields_with_local_flow() |
|
||||
| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:49:19:49:24 | ControlFlowNode for SOURCE |
|
||||
| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:56:18:56:23 | ControlFlowNode for SOURCE |
|
||||
| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:61:9:61:14 | ControlFlowNode for SOURCE |
|
||||
| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:71:9:71:14 | ControlFlowNode for SOURCE |
|
||||
| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:81:17:81:22 | ControlFlowNode for SOURCE |
|
||||
| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:86:21:86:26 | ControlFlowNode for SOURCE |
|
||||
| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:97:33:97:38 | ControlFlowNode for SOURCE |
|
||||
| test.py:3:1:3:6 | GSSA Variable SOURCE | test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test |
|
||||
| test.py:3:10:3:17 | ControlFlowNode for Str | test.py:3:1:3:6 | GSSA Variable SOURCE |
|
||||
| test.py:49:12:49:16 | [post arg] ControlFlowNode for myobj [Attribute foo] | test.py:50:10:50:14 | ControlFlowNode for myobj [Attribute foo] |
|
||||
| test.py:49:19:49:24 | ControlFlowNode for SOURCE | test.py:49:12:49:16 | [post arg] ControlFlowNode for myobj [Attribute foo] |
|
||||
| test.py:50:10:50:14 | ControlFlowNode for myobj [Attribute foo] | test.py:50:10:50:18 | ControlFlowNode for Attribute |
|
||||
@@ -66,16 +49,12 @@ nodes
|
||||
| examples.py:37:6:37:6 | ControlFlowNode for a [Attribute obj, Attribute foo] | semmle.label | ControlFlowNode for a [Attribute obj, Attribute foo] |
|
||||
| examples.py:37:6:37:10 | ControlFlowNode for Attribute [Attribute foo] | semmle.label | ControlFlowNode for Attribute [Attribute foo] |
|
||||
| examples.py:37:6:37:14 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
|
||||
| examples.py:40:5:40:10 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE |
|
||||
| examples.py:49:7:49:19 | ControlFlowNode for MyObj() [Attribute foo] | semmle.label | ControlFlowNode for MyObj() [Attribute foo] |
|
||||
| examples.py:49:13:49:18 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE |
|
||||
| examples.py:50:6:50:8 | ControlFlowNode for obj [Attribute foo] | semmle.label | ControlFlowNode for obj [Attribute foo] |
|
||||
| examples.py:50:6:50:12 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
|
||||
| examples.py:59:6:59:35 | ControlFlowNode for fields_with_local_flow() | semmle.label | ControlFlowNode for fields_with_local_flow() |
|
||||
| examples.py:59:29:59:34 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE |
|
||||
| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | semmle.label | ModuleVariableNode for Global Variable SOURCE in Module test |
|
||||
| test.py:3:1:3:6 | GSSA Variable SOURCE | semmle.label | GSSA Variable SOURCE |
|
||||
| test.py:3:10:3:17 | ControlFlowNode for Str | semmle.label | ControlFlowNode for Str |
|
||||
| test.py:49:12:49:16 | [post arg] ControlFlowNode for myobj [Attribute foo] | semmle.label | [post arg] ControlFlowNode for myobj [Attribute foo] |
|
||||
| test.py:49:19:49:24 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE |
|
||||
| test.py:50:10:50:14 | ControlFlowNode for myobj [Attribute foo] | semmle.label | ControlFlowNode for myobj [Attribute foo] |
|
||||
@@ -110,28 +89,13 @@ nodes
|
||||
| test.py:97:33:97:38 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE |
|
||||
#select
|
||||
| examples.py:28:6:28:14 | ControlFlowNode for Attribute | examples.py:27:15:27:20 | ControlFlowNode for SOURCE | examples.py:28:6:28:14 | ControlFlowNode for Attribute | Flow found |
|
||||
| examples.py:37:6:37:14 | ControlFlowNode for Attribute | examples.py:27:15:27:20 | ControlFlowNode for SOURCE | examples.py:37:6:37:14 | ControlFlowNode for Attribute | Flow found |
|
||||
| examples.py:37:6:37:14 | ControlFlowNode for Attribute | examples.py:31:5:31:10 | ControlFlowNode for SOURCE | examples.py:37:6:37:14 | ControlFlowNode for Attribute | Flow found |
|
||||
| examples.py:50:6:50:12 | ControlFlowNode for Attribute | examples.py:27:15:27:20 | ControlFlowNode for SOURCE | examples.py:50:6:50:12 | ControlFlowNode for Attribute | Flow found |
|
||||
| examples.py:50:6:50:12 | ControlFlowNode for Attribute | examples.py:31:5:31:10 | ControlFlowNode for SOURCE | examples.py:50:6:50:12 | ControlFlowNode for Attribute | Flow found |
|
||||
| examples.py:50:6:50:12 | ControlFlowNode for Attribute | examples.py:40:5:40:10 | ControlFlowNode for SOURCE | examples.py:50:6:50:12 | ControlFlowNode for Attribute | Flow found |
|
||||
| examples.py:50:6:50:12 | ControlFlowNode for Attribute | examples.py:49:13:49:18 | ControlFlowNode for SOURCE | examples.py:50:6:50:12 | ControlFlowNode for Attribute | Flow found |
|
||||
| examples.py:59:6:59:35 | ControlFlowNode for fields_with_local_flow() | examples.py:27:15:27:20 | ControlFlowNode for SOURCE | examples.py:59:6:59:35 | ControlFlowNode for fields_with_local_flow() | Flow found |
|
||||
| examples.py:59:6:59:35 | ControlFlowNode for fields_with_local_flow() | examples.py:31:5:31:10 | ControlFlowNode for SOURCE | examples.py:59:6:59:35 | ControlFlowNode for fields_with_local_flow() | Flow found |
|
||||
| examples.py:59:6:59:35 | ControlFlowNode for fields_with_local_flow() | examples.py:40:5:40:10 | ControlFlowNode for SOURCE | examples.py:59:6:59:35 | ControlFlowNode for fields_with_local_flow() | Flow found |
|
||||
| examples.py:59:6:59:35 | ControlFlowNode for fields_with_local_flow() | examples.py:49:13:49:18 | ControlFlowNode for SOURCE | examples.py:59:6:59:35 | ControlFlowNode for fields_with_local_flow() | Flow found |
|
||||
| examples.py:59:6:59:35 | ControlFlowNode for fields_with_local_flow() | examples.py:59:29:59:34 | ControlFlowNode for SOURCE | examples.py:59:6:59:35 | ControlFlowNode for fields_with_local_flow() | Flow found |
|
||||
| test.py:50:10:50:18 | ControlFlowNode for Attribute | test.py:3:10:3:17 | ControlFlowNode for Str | test.py:50:10:50:18 | ControlFlowNode for Attribute | Flow found |
|
||||
| test.py:50:10:50:18 | ControlFlowNode for Attribute | test.py:49:19:49:24 | ControlFlowNode for SOURCE | test.py:50:10:50:18 | ControlFlowNode for Attribute | Flow found |
|
||||
| test.py:57:10:57:18 | ControlFlowNode for Attribute | test.py:3:10:3:17 | ControlFlowNode for Str | test.py:57:10:57:18 | ControlFlowNode for Attribute | Flow found |
|
||||
| test.py:57:10:57:18 | ControlFlowNode for Attribute | test.py:56:18:56:23 | ControlFlowNode for SOURCE | test.py:57:10:57:18 | ControlFlowNode for Attribute | Flow found |
|
||||
| test.py:67:10:67:18 | ControlFlowNode for Attribute | test.py:3:10:3:17 | ControlFlowNode for Str | test.py:67:10:67:18 | ControlFlowNode for Attribute | Flow found |
|
||||
| test.py:67:10:67:18 | ControlFlowNode for Attribute | test.py:61:9:61:14 | ControlFlowNode for SOURCE | test.py:67:10:67:18 | ControlFlowNode for Attribute | Flow found |
|
||||
| test.py:77:10:77:18 | ControlFlowNode for Attribute | test.py:3:10:3:17 | ControlFlowNode for Str | test.py:77:10:77:18 | ControlFlowNode for Attribute | Flow found |
|
||||
| test.py:77:10:77:18 | ControlFlowNode for Attribute | test.py:71:9:71:14 | ControlFlowNode for SOURCE | test.py:77:10:77:18 | ControlFlowNode for Attribute | Flow found |
|
||||
| test.py:82:10:82:16 | ControlFlowNode for Attribute | test.py:3:10:3:17 | ControlFlowNode for Str | test.py:82:10:82:16 | ControlFlowNode for Attribute | Flow found |
|
||||
| test.py:82:10:82:16 | ControlFlowNode for Attribute | test.py:81:17:81:22 | ControlFlowNode for SOURCE | test.py:82:10:82:16 | ControlFlowNode for Attribute | Flow found |
|
||||
| test.py:87:10:87:16 | ControlFlowNode for Attribute | test.py:3:10:3:17 | ControlFlowNode for Str | test.py:87:10:87:16 | ControlFlowNode for Attribute | Flow found |
|
||||
| test.py:87:10:87:16 | ControlFlowNode for Attribute | test.py:86:21:86:26 | ControlFlowNode for SOURCE | test.py:87:10:87:16 | ControlFlowNode for Attribute | Flow found |
|
||||
| test.py:97:10:97:39 | ControlFlowNode for fields_with_local_flow() | test.py:3:10:3:17 | ControlFlowNode for Str | test.py:97:10:97:39 | ControlFlowNode for fields_with_local_flow() | Flow found |
|
||||
| test.py:97:10:97:39 | ControlFlowNode for fields_with_local_flow() | test.py:97:33:97:38 | ControlFlowNode for SOURCE | test.py:97:10:97:39 | ControlFlowNode for fields_with_local_flow() | Flow found |
|
||||
|
||||
@@ -4,9 +4,7 @@
|
||||
| test2.py:1:19:1:21 | ControlFlowNode for ImportMember | mypkg.foo |
|
||||
| test2.py:1:24:1:26 | ControlFlowNode for ImportMember | mypkg.bar |
|
||||
| test3.py:1:8:1:16 | ControlFlowNode for ImportExpr | mypkg |
|
||||
| test3.py:1:8:1:16 | ControlFlowNode for ImportExpr | mypkg.foo |
|
||||
| test3.py:2:8:2:16 | ControlFlowNode for ImportExpr | mypkg |
|
||||
| test3.py:2:8:2:16 | ControlFlowNode for ImportExpr | mypkg.bar |
|
||||
| test4.py:1:8:1:16 | ControlFlowNode for ImportExpr | mypkg.foo |
|
||||
| test4.py:2:8:2:16 | ControlFlowNode for ImportExpr | mypkg.bar |
|
||||
| test5.py:1:8:1:12 | ControlFlowNode for ImportExpr | mypkg |
|
||||
@@ -14,10 +12,12 @@
|
||||
| test5.py:9:19:9:29 | ControlFlowNode for ImportMember | mypkg.bar |
|
||||
| test6.py:1:8:1:12 | ControlFlowNode for ImportExpr | mypkg |
|
||||
| test6.py:5:8:5:16 | ControlFlowNode for ImportExpr | mypkg |
|
||||
| test6.py:5:8:5:16 | ControlFlowNode for ImportExpr | mypkg.foo |
|
||||
| test7.py:1:6:1:10 | ControlFlowNode for ImportExpr | mypkg |
|
||||
| test7.py:1:19:1:21 | ControlFlowNode for ImportMember | mypkg.foo |
|
||||
| test7.py:5:8:5:16 | ControlFlowNode for ImportExpr | mypkg |
|
||||
| test7.py:5:8:5:16 | ControlFlowNode for ImportExpr | mypkg.foo |
|
||||
| test7.py:9:6:9:10 | ControlFlowNode for ImportExpr | mypkg |
|
||||
| test7.py:9:19:9:21 | ControlFlowNode for ImportMember | mypkg.foo |
|
||||
| test_deep.py:1:6:1:21 | ControlFlowNode for ImportExpr | start.middle.end |
|
||||
| test_deep.py:1:6:1:21 | ControlFlowNode for ImportExpr | start.middle.end |
|
||||
| test_deep.py:1:30:1:32 | ControlFlowNode for ImportMember | start.middle.end.foo |
|
||||
| test_deep.py:1:35:1:37 | ControlFlowNode for ImportMember | start.middle.end.bar |
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
from start.middle.end import foo, bar
|
||||
print(foo)
|
||||
print(bar)
|
||||
@@ -1,6 +1,7 @@
|
||||
import python
|
||||
import semmle.python.dataflow.new.TaintTracking
|
||||
import semmle.python.dataflow.new.DataFlow
|
||||
import experimental.dataflow.TestUtil.PrintNode
|
||||
|
||||
class TestTaintTrackingConfiguration extends TaintTracking::Configuration {
|
||||
TestTaintTrackingConfiguration() { this = "TestTaintTrackingConfiguration" }
|
||||
@@ -19,31 +20,6 @@ class TestTaintTrackingConfiguration extends TaintTracking::Configuration {
|
||||
}
|
||||
}
|
||||
|
||||
private string repr(Expr e) {
|
||||
not e instanceof Num and
|
||||
not e instanceof StrConst and
|
||||
not e instanceof Subscript and
|
||||
not e instanceof Call and
|
||||
not e instanceof Attribute and
|
||||
result = e.toString()
|
||||
or
|
||||
result = e.(Num).getN()
|
||||
or
|
||||
result =
|
||||
e.(StrConst).getPrefix() + e.(StrConst).getText() +
|
||||
e.(StrConst).getPrefix().regexpReplaceAll("[a-zA-Z]+", "")
|
||||
or
|
||||
result = repr(e.(Subscript).getObject()) + "[" + repr(e.(Subscript).getIndex()) + "]"
|
||||
or
|
||||
(
|
||||
if exists(e.(Call).getAnArg()) or exists(e.(Call).getANamedArg())
|
||||
then result = repr(e.(Call).getFunc()) + "(..)"
|
||||
else result = repr(e.(Call).getFunc()) + "()"
|
||||
)
|
||||
or
|
||||
result = repr(e.(Attribute).getObject()) + "." + e.(Attribute).getName()
|
||||
}
|
||||
|
||||
query predicate test_taint(string arg_location, string test_res, string scope_name, string repr) {
|
||||
exists(Call call, Expr arg, boolean expected_taint, boolean has_taint |
|
||||
// only consider files that are extracted as part of the test
|
||||
@@ -70,6 +46,6 @@ query predicate test_taint(string arg_location, string test_res, string scope_na
|
||||
arg_location = arg.getLocation().toString() and
|
||||
test_res = test_res and
|
||||
scope_name = call.getScope().getName() and
|
||||
repr = repr(arg)
|
||||
repr = prettyExp(arg)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -44,5 +44,7 @@ class TestConfiguration extends DataFlow::Configuration {
|
||||
)
|
||||
}
|
||||
|
||||
override int explorationLimit() { result = 4 }
|
||||
override predicate isBarrierIn(DataFlow::Node node) { this.isSource(node) }
|
||||
|
||||
override int explorationLimit() { result = 5 }
|
||||
}
|
||||
|
||||
@@ -69,3 +69,54 @@ def redefine_test():
|
||||
expects_int(x) # $int
|
||||
x = str("Hello") # $str
|
||||
expects_string(x) # $str
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Tracking of self in methods
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
class Foo(object):
|
||||
|
||||
def meth1(self):
|
||||
do_stuff(self)
|
||||
|
||||
def meth2(self): # $ MISSING: tracked_self
|
||||
do_stuff(self) # $ MISSING: tracked_self
|
||||
|
||||
def meth3(self): # $ MISSING: tracked_self
|
||||
do_stuff(self) # $ MISSING: tracked_self
|
||||
|
||||
|
||||
class Bar(Foo):
|
||||
|
||||
def meth1(self): # $ tracked_self
|
||||
do_stuff(self) # $ tracked_self
|
||||
|
||||
def meth2(self):
|
||||
do_stuff(self)
|
||||
|
||||
def meth3(self):
|
||||
do_stuff(self)
|
||||
|
||||
def track_self(self): # $ tracked_self
|
||||
self.meth1() # $ tracked_self
|
||||
super().meth2()
|
||||
super(Bar, self).foo3() # $ tracked_self
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Tracking of attribute lookup after "long" import chain
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
def test_long_import_chain():
|
||||
import foo.bar
|
||||
foo.baz
|
||||
x = foo.bar.baz # $ tracked_foo_bar_baz
|
||||
do_stuff(x) # $ tracked_foo_bar_baz
|
||||
|
||||
class Example(foo.bar.baz): # $ tracked_foo_bar_baz
|
||||
pass
|
||||
|
||||
|
||||
def test_long_import_chain_full_path():
|
||||
from foo.bar import baz # $ tracked_foo_bar_baz
|
||||
x = baz # $ tracked_foo_bar_baz
|
||||
do_stuff(x) # $ tracked_foo_bar_baz
|
||||
|
||||
@@ -3,6 +3,9 @@ import semmle.python.dataflow.new.DataFlow
|
||||
import semmle.python.dataflow.new.TypeTracker
|
||||
import TestUtilities.InlineExpectationsTest
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// tracked
|
||||
// -----------------------------------------------------------------------------
|
||||
DataFlow::Node tracked(TypeTracker t) {
|
||||
t.start() and
|
||||
result.asCfgNode() = any(NameNode n | n.getId() = "tracked")
|
||||
@@ -28,6 +31,9 @@ class TrackedTest extends InlineExpectationsTest {
|
||||
}
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// int + str
|
||||
// -----------------------------------------------------------------------------
|
||||
DataFlow::Node int_type(TypeTracker t) {
|
||||
t.start() and
|
||||
result.asCfgNode() = any(CallNode c | c.getFunction().(NameNode).getId() = "int")
|
||||
@@ -73,3 +79,96 @@ class TrackedStringTest extends InlineExpectationsTest {
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// tracked_self
|
||||
// -----------------------------------------------------------------------------
|
||||
DataFlow::Node tracked_self(TypeTracker t) {
|
||||
t.start() and
|
||||
exists(Function f |
|
||||
f.isMethod() and
|
||||
f.getName() = "track_self" and
|
||||
result.(DataFlow::ParameterNode).getParameter() = f.getArg(0)
|
||||
)
|
||||
or
|
||||
exists(TypeTracker t2 | result = tracked_self(t2).track(t2, t))
|
||||
}
|
||||
|
||||
class TrackedSelfTest extends InlineExpectationsTest {
|
||||
TrackedSelfTest() { this = "TrackedSelfTest" }
|
||||
|
||||
override string getARelevantTag() { result = "tracked_self" }
|
||||
|
||||
override predicate hasActualResult(Location location, string element, string tag, string value) {
|
||||
exists(DataFlow::Node e, TypeTracker t |
|
||||
e = tracked_self(t) and
|
||||
// Module variables have no sensible location, and hence can't be annotated.
|
||||
not e instanceof DataFlow::ModuleVariableNode and
|
||||
tag = "tracked_self" and
|
||||
location = e.getLocation() and
|
||||
value = t.getAttr() and
|
||||
element = e.toString()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// tracked_foo_bar_baz
|
||||
// -----------------------------------------------------------------------------
|
||||
// This modeling follows the same pattern that we currently use in our real library modeling.
|
||||
/** Gets a reference to `foo` (fictive module). */
|
||||
private DataFlow::Node foo(DataFlow::TypeTracker t) {
|
||||
t.start() and
|
||||
result = DataFlow::importNode("foo")
|
||||
or
|
||||
exists(DataFlow::TypeTracker t2 | result = foo(t2).track(t2, t))
|
||||
}
|
||||
|
||||
/** Gets a reference to `foo` (fictive module). */
|
||||
DataFlow::Node foo() { result = foo(DataFlow::TypeTracker::end()) }
|
||||
|
||||
/** Gets a reference to `foo.bar` (fictive module). */
|
||||
private DataFlow::Node foo_bar(DataFlow::TypeTracker t) {
|
||||
t.start() and
|
||||
result = DataFlow::importNode("foo.bar")
|
||||
or
|
||||
t.startInAttr("bar") and
|
||||
result = foo()
|
||||
or
|
||||
exists(DataFlow::TypeTracker t2 | result = foo_bar(t2).track(t2, t))
|
||||
}
|
||||
|
||||
/** Gets a reference to `foo.bar` (fictive module). */
|
||||
DataFlow::Node foo_bar() { result = foo_bar(DataFlow::TypeTracker::end()) }
|
||||
|
||||
/** Gets a reference to `foo.bar.baz` (fictive attribute on `foo.bar` module). */
|
||||
private DataFlow::Node foo_bar_baz(DataFlow::TypeTracker t) {
|
||||
t.start() and
|
||||
result = DataFlow::importNode("foo.bar.baz")
|
||||
or
|
||||
t.startInAttr("baz") and
|
||||
result = foo_bar()
|
||||
or
|
||||
exists(DataFlow::TypeTracker t2 | result = foo_bar_baz(t2).track(t2, t))
|
||||
}
|
||||
|
||||
/** Gets a reference to `foo.bar.baz` (fictive attribute on `foo.bar` module). */
|
||||
DataFlow::Node foo_bar_baz() { result = foo_bar_baz(DataFlow::TypeTracker::end()) }
|
||||
|
||||
class TrackedFooBarBaz extends InlineExpectationsTest {
|
||||
TrackedFooBarBaz() { this = "TrackedFooBarBaz" }
|
||||
|
||||
override string getARelevantTag() { result = "tracked_foo_bar_baz" }
|
||||
|
||||
override predicate hasActualResult(Location location, string element, string tag, string value) {
|
||||
exists(DataFlow::Node e |
|
||||
e = foo_bar_baz() and
|
||||
// Module variables have no sensible location, and hence can't be annotated.
|
||||
not e instanceof DataFlow::ModuleVariableNode and
|
||||
tag = "tracked_foo_bar_baz" and
|
||||
location = e.getLocation() and
|
||||
value = "" and
|
||||
element = e.toString()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import python
|
||||
import experimental.meta.ConceptsTest
|
||||
//
|
||||
// class DedicatedResponseTest extends HttpServerHttpResponseTest {
|
||||
// DedicatedResponseTest() { file.getShortName() = "response_test.py" }
|
||||
// }
|
||||
//
|
||||
// class OtherResponseTest extends HttpServerHttpResponseTest {
|
||||
// OtherResponseTest() { not this instanceof DedicatedResponseTest }
|
||||
//
|
||||
// override string getARelevantTag() { result = "HttpResponse" }
|
||||
// }
|
||||
|
||||
class DedicatedResponseTest extends HttpServerHttpResponseTest {
|
||||
DedicatedResponseTest() { file.getShortName() = "response_test.py" }
|
||||
}
|
||||
|
||||
class OtherResponseTest extends HttpServerHttpResponseTest {
|
||||
OtherResponseTest() { not this instanceof DedicatedResponseTest }
|
||||
|
||||
override string getARelevantTag() { result = "HttpResponse" }
|
||||
}
|
||||
|
||||
@@ -3,21 +3,21 @@ import tornado.web
|
||||
|
||||
class BasicHandler(tornado.web.RequestHandler):
|
||||
def get(self): # $ requestHandler
|
||||
self.write("BasicHandler " + self.get_argument("xss"))
|
||||
self.write("BasicHandler " + self.get_argument("xss")) # $ HttpResponse
|
||||
|
||||
def post(self): # $ requestHandler
|
||||
self.write("BasicHandler (POST)")
|
||||
self.write("BasicHandler (POST)") # $ HttpResponse
|
||||
|
||||
|
||||
class DeepInheritance(BasicHandler):
|
||||
def get(self): # $ requestHandler
|
||||
self.write("DeepInheritance" + self.get_argument("also_xss"))
|
||||
self.write("DeepInheritance" + self.get_argument("also_xss")) # $ HttpResponse
|
||||
|
||||
|
||||
class FormHandler(tornado.web.RequestHandler):
|
||||
def post(self): # $ requestHandler
|
||||
name = self.get_body_argument("name")
|
||||
self.write(name)
|
||||
self.write(name) # $ HttpResponse
|
||||
|
||||
|
||||
class RedirectHandler(tornado.web.RequestHandler):
|
||||
@@ -30,7 +30,7 @@ class RedirectHandler(tornado.web.RequestHandler):
|
||||
|
||||
class BaseReverseInheritance(tornado.web.RequestHandler):
|
||||
def get(self): # $ requestHandler
|
||||
self.write("hello from BaseReverseInheritance")
|
||||
self.write("hello from BaseReverseInheritance") # $ HttpResponse
|
||||
|
||||
|
||||
class ReverseInheritance(BaseReverseInheritance):
|
||||
|
||||
@@ -0,0 +1,85 @@
|
||||
import tornado.web
|
||||
import tornado.httputil
|
||||
|
||||
|
||||
class ResponseWriting(tornado.web.RequestHandler):
|
||||
def get(self, type_): # $ requestHandler routedParameter=type_
|
||||
if type_ == "str":
|
||||
self.write("foo") # $ HttpResponse mimetype=text/html responseBody="foo"
|
||||
elif type_ == "bytes":
|
||||
self.write(b"foo") # $ HttpResponse mimetype=text/html responseBody=b"foo"
|
||||
elif type_ == "dict":
|
||||
d = {"foo": 42}
|
||||
# Content-type will be set to `application/json`
|
||||
self.write(d) # $ HttpResponse responseBody=d MISSING: mimetype=application/json SPURIOUS: mimetype=text/html
|
||||
else:
|
||||
raise Exception("Bad type {} {}".format(type_, type(type_)))
|
||||
|
||||
|
||||
class ExplicitContentType(tornado.web.RequestHandler):
|
||||
def get(self): # $ requestHandler
|
||||
# Note: Our current modeling makes it quite hard to give a good annotation here
|
||||
# this write is technically while the HTTP response has mimetype text/html, but
|
||||
# the returned HTTP response will have mimetype text/plain, which is _really_
|
||||
# what matters.
|
||||
|
||||
self.write("foo") # $ HttpResponse mimetype=text/html responseBody="foo"
|
||||
self.set_header("Content-Type", "text/plain; charset=utf-8")
|
||||
|
||||
def post(self): # $ requestHandler
|
||||
self.set_header("Content-Type", "text/plain; charset=utf-8")
|
||||
self.write("foo") # $ HttpResponse responseBody="foo" MISSING: mimetype=text/plain SPURIOUS: mimetype=text/html
|
||||
|
||||
|
||||
class ExampleRedirect(tornado.web.RequestHandler):
|
||||
def get(self): # $ requestHandler
|
||||
self.redirect("http://example.com") # TODO: Model redirect
|
||||
|
||||
|
||||
class ExampleConnectionWrite(tornado.web.RequestHandler):
|
||||
def get(self, stream=False): # $ requestHandler routedParameter=stream
|
||||
|
||||
if not stream:
|
||||
self.request.connection.write_headers(
|
||||
tornado.httputil.ResponseStartLine('', 200, 'OK'),
|
||||
tornado.httputil.HTTPHeaders(),
|
||||
)
|
||||
self.request.connection.write(b"foo") # $ MISSING: HttpResponse responseBody=b"foo"
|
||||
self.request.connection.finish()
|
||||
else:
|
||||
# Note: The documentation says that connection.detach(): "May only be called
|
||||
# during HTTPMessageDelegate.headers_received". Doing it here actually
|
||||
# works, but does make tornado spit out some errors... good enough to
|
||||
# illustrate the behavior.
|
||||
#
|
||||
# https://www.tornadoweb.org/en/stable/http1connection.html#tornado.http1connection.HTTP1Connection.detach
|
||||
stream = self.request.connection.detach()
|
||||
stream.write(b"foo stream") # $ MISSING: HttpResponse responseBody=b"foo stream"
|
||||
stream.close()
|
||||
|
||||
def make_app():
|
||||
return tornado.web.Application(
|
||||
[
|
||||
(r"/ResponseWriting/(str|bytes|dict)", ResponseWriting), # $ routeSetup="/ResponseWriting/(str|bytes|dict)"
|
||||
(r"/ExplicitContentType", ExplicitContentType), # $ routeSetup="/ExplicitContentType"
|
||||
(r"/ExampleRedirect", ExampleRedirect), # $ routeSetup="/ExampleRedirect"
|
||||
(r"/ExampleConnectionWrite", ExampleConnectionWrite), # $ routeSetup="/ExampleConnectionWrite"
|
||||
(r"/ExampleConnectionWrite/(stream)", ExampleConnectionWrite), # $ routeSetup="/ExampleConnectionWrite/(stream)"
|
||||
],
|
||||
debug=True,
|
||||
)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
import tornado.ioloop
|
||||
|
||||
app = make_app()
|
||||
app.listen(8888)
|
||||
tornado.ioloop.IOLoop.current().start()
|
||||
|
||||
# http://localhost:8888/ResponseWriting/str
|
||||
# http://localhost:8888/ResponseWriting/bytes
|
||||
# http://localhost:8888/ResponseWriting/dict
|
||||
# http://localhost:8888/ExplicitContentType
|
||||
# http://localhost:8888/ExampleRedirect
|
||||
# http://localhost:8888/ExampleConnectionWrite
|
||||
@@ -1,35 +0,0 @@
|
||||
import tornado.web
|
||||
|
||||
|
||||
class ResponseWriting(tornado.web.RequestHandler):
|
||||
def get(self, type_): # $ requestHandler routedParameter=type_
|
||||
if type_ == "str":
|
||||
self.write("foo")
|
||||
elif type_ == "bytes":
|
||||
self.write(b"foo")
|
||||
elif type_ == "dict":
|
||||
# Content-type will be set to `application/json`
|
||||
self.write({"foo": 42})
|
||||
else:
|
||||
raise Exception("Bad type {} {}".format(type_, type(type_)))
|
||||
|
||||
|
||||
def make_app():
|
||||
return tornado.web.Application(
|
||||
[
|
||||
(r"/ResponseWriting/(str|bytes|dict)", ResponseWriting), # $ routeSetup="/ResponseWriting/(str|bytes|dict)"
|
||||
],
|
||||
debug=True,
|
||||
)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
import tornado.ioloop
|
||||
|
||||
app = make_app()
|
||||
app.listen(8888)
|
||||
tornado.ioloop.IOLoop.current().start()
|
||||
|
||||
# http://localhost:8888/ResponseWriting/str
|
||||
# http://localhost:8888/ResponseWriting/bytes
|
||||
# http://localhost:8888/ResponseWriting/dict
|
||||
@@ -4,47 +4,47 @@ import tornado.routing
|
||||
|
||||
class FooHandler(tornado.web.RequestHandler):
|
||||
def get(self, x, y=None, not_used=None): # $ requestHandler routedParameter=x routedParameter=y
|
||||
self.write("FooHandler {} {}".format(x, y))
|
||||
self.write("FooHandler {} {}".format(x, y)) # $ HttpResponse
|
||||
|
||||
|
||||
class BarHandler(tornado.web.RequestHandler):
|
||||
def get(self, x, y=None, not_used=None): # $ requestHandler routedParameter=x routedParameter=y SPURIOUS: routedParameter=not_used
|
||||
self.write("BarHandler {} {}".format(x, y))
|
||||
self.write("BarHandler {} {}".format(x, y)) # $ HttpResponse
|
||||
|
||||
|
||||
class BazHandler(tornado.web.RequestHandler):
|
||||
def get(self, x, y=None, not_used=None): # $ requestHandler routedParameter=x routedParameter=y SPURIOUS: routedParameter=not_used
|
||||
self.write("BazHandler {} {}".format(x, y))
|
||||
self.write("BazHandler {} {}".format(x, y)) # $ HttpResponse
|
||||
|
||||
|
||||
class KwArgs(tornado.web.RequestHandler):
|
||||
def get(self, *, x, y=None, not_used=None): # $ requestHandler routedParameter=x routedParameter=y
|
||||
self.write("KwArgs {} {}".format(x, y))
|
||||
self.write("KwArgs {} {}".format(x, y)) # $ HttpResponse
|
||||
|
||||
|
||||
class OnlyLocalhost(tornado.web.RequestHandler):
|
||||
def get(self): # $ requestHandler
|
||||
self.write("OnlyLocalhost")
|
||||
self.write("OnlyLocalhost") # $ HttpResponse
|
||||
|
||||
|
||||
class One(tornado.web.RequestHandler):
|
||||
def get(self): # $ requestHandler
|
||||
self.write("One")
|
||||
self.write("One") # $ HttpResponse
|
||||
|
||||
|
||||
class Two(tornado.web.RequestHandler):
|
||||
def get(self): # $ requestHandler
|
||||
self.write("Two")
|
||||
self.write("Two") # $ HttpResponse
|
||||
|
||||
|
||||
class Three(tornado.web.RequestHandler):
|
||||
def get(self): # $ requestHandler
|
||||
self.write("Three")
|
||||
self.write("Three") # $ HttpResponse
|
||||
|
||||
|
||||
class AddedLater(tornado.web.RequestHandler):
|
||||
def get(self, x, y=None, not_used=None): # $ requestHandler routedParameter=x routedParameter=y
|
||||
self.write("AddedLater {} {}".format(x, y))
|
||||
self.write("AddedLater {} {}".format(x, y)) # $ HttpResponse
|
||||
|
||||
|
||||
class PossiblyNotRouted(tornado.web.RequestHandler):
|
||||
@@ -52,7 +52,7 @@ class PossiblyNotRouted(tornado.web.RequestHandler):
|
||||
# consider it to be a handle incoming HTTP requests
|
||||
|
||||
def get(self): # $ requestHandler
|
||||
self.write("NotRouted")
|
||||
self.write("NotRouted") # $ HttpResponse
|
||||
|
||||
|
||||
def make_app():
|
||||
|
||||
@@ -2,3 +2,4 @@ name: codeql-python-tests
|
||||
version: 0.0.0
|
||||
libraryPathDependencies: codeql-python
|
||||
extractor: python
|
||||
tests: .
|
||||
|
||||
Reference in New Issue
Block a user