mirror of
https://github.com/github/codeql.git
synced 2025-12-21 03:06:31 +01:00
Merge branch 'main' into python-more-additional-taint-steps
This commit is contained in:
@@ -6,7 +6,7 @@
|
||||
<overview>
|
||||
<p>
|
||||
|
||||
Sanitizing untrusted URLs is an important technique for
|
||||
Sanitizing untrusted URLs is a common technique for
|
||||
preventing attacks such as request forgeries and malicious
|
||||
redirections. Often, this is done by checking that the host of a URL
|
||||
is in a set of allowed hosts.
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<overview>
|
||||
<p>
|
||||
|
||||
Sanitizing untrusted URLs is an important technique for
|
||||
Sanitizing untrusted URLs is a common technique for
|
||||
preventing attacks such as request forgeries and malicious
|
||||
redirections. Usually, this is done by checking that the host of a URL
|
||||
is in a set of allowed hosts.
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
* `DataFlow::localFlowStep` with arguments of type `DataFlow::Node`.
|
||||
*/
|
||||
|
||||
import python
|
||||
private import python
|
||||
|
||||
/**
|
||||
* Provides classes for performing local (intra-procedural) and
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
* `DataFlow::localFlowStep` with arguments of type `DataFlow::Node`.
|
||||
*/
|
||||
|
||||
import python
|
||||
private import python
|
||||
|
||||
/**
|
||||
* Provides classes for performing local (intra-procedural) and
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
* `TaintTracking::localTaintStep` with arguments of type `DataFlow::Node`.
|
||||
*/
|
||||
|
||||
import python
|
||||
private import python
|
||||
|
||||
/**
|
||||
* Provides classes for performing local (intra-procedural) and
|
||||
|
||||
@@ -123,8 +123,18 @@ module Consistency {
|
||||
n.getEnclosingCallable() != call.getEnclosingCallable()
|
||||
}
|
||||
|
||||
// This predicate helps the compiler forget that in some languages
|
||||
// it is impossible for a result of `getPreUpdateNode` to be an
|
||||
// instance of `PostUpdateNode`.
|
||||
private Node getPre(PostUpdateNode n) {
|
||||
result = n.getPreUpdateNode()
|
||||
or
|
||||
none()
|
||||
}
|
||||
|
||||
query predicate postIsNotPre(PostUpdateNode n, string msg) {
|
||||
n.getPreUpdateNode() = n and msg = "PostUpdateNode should not equal its pre-update node."
|
||||
getPre(n) = n and
|
||||
msg = "PostUpdateNode should not equal its pre-update node."
|
||||
}
|
||||
|
||||
query predicate postHasUniquePre(PostUpdateNode n, string msg) {
|
||||
@@ -152,12 +162,6 @@ module Consistency {
|
||||
msg = "Origin of readStep is missing a PostUpdateNode."
|
||||
}
|
||||
|
||||
query predicate storeIsPostUpdate(Node n, string msg) {
|
||||
storeStep(_, _, n) and
|
||||
not n instanceof PostUpdateNode and
|
||||
msg = "Store targets should be PostUpdateNodes."
|
||||
}
|
||||
|
||||
query predicate argHasPostUpdate(ArgumentNode n, string msg) {
|
||||
not hasPost(n) and
|
||||
not isImmutableOrUnobservable(n) and
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
private import python
|
||||
private import DataFlowPublic
|
||||
import semmle.python.SpecialMethods
|
||||
|
||||
//--------
|
||||
// Data flow graph
|
||||
@@ -7,6 +8,39 @@ private import DataFlowPublic
|
||||
//--------
|
||||
// Nodes
|
||||
//--------
|
||||
predicate isExpressionNode(ControlFlowNode node) { node.getNode() instanceof Expr }
|
||||
|
||||
/** A control flow node which is also a dataflow node */
|
||||
class DataFlowCfgNode extends ControlFlowNode {
|
||||
DataFlowCfgNode() { isExpressionNode(this) }
|
||||
}
|
||||
|
||||
/** A data flow node which should have an associated post-update node. */
|
||||
abstract class PreUpdateNode extends Node { }
|
||||
|
||||
/** An argument might have its value changed as a result of a call. */
|
||||
class ArgumentPreUpdateNode extends PreUpdateNode, ArgumentNode { }
|
||||
|
||||
/** An object might have its value changed after a store. */
|
||||
class StorePreUpdateNode extends PreUpdateNode, CfgNode {
|
||||
StorePreUpdateNode() {
|
||||
exists(Attribute a |
|
||||
node = a.getObject().getAFlowNode() and
|
||||
a.getCtx() instanceof Store
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/** A node marking the state change of an object after a read */
|
||||
class ReadPreUpdateNode extends PreUpdateNode, CfgNode {
|
||||
ReadPreUpdateNode() {
|
||||
exists(Attribute a |
|
||||
node = a.getObject().getAFlowNode() and
|
||||
a.getCtx() instanceof Load
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A node associated with an object after an operation that might have
|
||||
* changed its state.
|
||||
@@ -16,12 +50,21 @@ private import DataFlowPublic
|
||||
* an update to the field.
|
||||
*
|
||||
* Nodes corresponding to AST elements, for example `ExprNode`, usually refer
|
||||
* to the value before the update with the exception of `ObjectCreation`,
|
||||
* which represents the value after the constructor has run.
|
||||
* to the value before the update.
|
||||
*/
|
||||
abstract class PostUpdateNode extends Node {
|
||||
class PostUpdateNode extends Node, TPostUpdateNode {
|
||||
PreUpdateNode pre;
|
||||
|
||||
PostUpdateNode() { this = TPostUpdateNode(pre) }
|
||||
|
||||
/** Gets the node before the state update. */
|
||||
abstract Node getPreUpdateNode();
|
||||
Node getPreUpdateNode() { result = pre }
|
||||
|
||||
override string toString() { result = "[post] " + pre.toString() }
|
||||
|
||||
override Scope getScope() { result = pre.getScope() }
|
||||
|
||||
override Location getLocation() { result = pre.getLocation() }
|
||||
}
|
||||
|
||||
class DataFlowExpr = Expr;
|
||||
@@ -90,7 +133,17 @@ module EssaFlow {
|
||||
predicate simpleLocalFlowStep(Node nodeFrom, Node nodeTo) {
|
||||
not nodeFrom.(EssaNode).getVar() instanceof GlobalSsaVariable and
|
||||
not nodeTo.(EssaNode).getVar() instanceof GlobalSsaVariable and
|
||||
EssaFlow::essaFlowStep(nodeFrom, nodeTo)
|
||||
EssaFlow::essaFlowStep(update(nodeFrom), nodeTo)
|
||||
}
|
||||
|
||||
private Node update(Node node) {
|
||||
exists(PostUpdateNode pun |
|
||||
node = pun.getPreUpdateNode() and
|
||||
result = pun
|
||||
)
|
||||
or
|
||||
not exists(PostUpdateNode pun | node = pun.getPreUpdateNode()) and
|
||||
result = node
|
||||
}
|
||||
|
||||
// TODO: Make modules for these headings
|
||||
@@ -157,17 +210,67 @@ class DataFlowClassValue extends DataFlowCallable, TClassValue {
|
||||
override string getName() { result = c.getName() }
|
||||
}
|
||||
|
||||
/** Represents a call to a callable */
|
||||
class DataFlowCall extends CallNode {
|
||||
DataFlowCallable callable;
|
||||
newtype TDataFlowCall =
|
||||
TCallNode(CallNode call) or
|
||||
TSpecialCall(SpecialMethodCallNode special)
|
||||
|
||||
DataFlowCall() { this = callable.getACall() }
|
||||
abstract class DataFlowCall extends TDataFlowCall {
|
||||
/** Gets a textual representation of this element. */
|
||||
abstract string toString();
|
||||
|
||||
/** Get the callable to which this call goes. */
|
||||
DataFlowCallable getCallable() { result = callable }
|
||||
abstract DataFlowCallable getCallable();
|
||||
|
||||
/** Get the specified argument to this call. */
|
||||
abstract ControlFlowNode getArg(int n);
|
||||
|
||||
/** Get the control flow node representing this call. */
|
||||
abstract ControlFlowNode getNode();
|
||||
|
||||
/** Gets the enclosing callable of this call. */
|
||||
DataFlowCallable getEnclosingCallable() { result.getScope() = this.getNode().getScope() }
|
||||
abstract DataFlowCallable getEnclosingCallable();
|
||||
}
|
||||
|
||||
/** Represents a call to a callable. */
|
||||
class CallNodeCall extends DataFlowCall, TCallNode {
|
||||
CallNode call;
|
||||
DataFlowCallable callable;
|
||||
|
||||
CallNodeCall() {
|
||||
this = TCallNode(call) and
|
||||
call = callable.getACall()
|
||||
}
|
||||
|
||||
override string toString() { result = call.toString() }
|
||||
|
||||
override ControlFlowNode getArg(int n) { result = call.getArg(n) }
|
||||
|
||||
override ControlFlowNode getNode() { result = call }
|
||||
|
||||
override DataFlowCallable getCallable() { result = callable }
|
||||
|
||||
override DataFlowCallable getEnclosingCallable() { result.getScope() = call.getNode().getScope() }
|
||||
}
|
||||
|
||||
/** Represents a call to a special method. */
|
||||
class SpecialCall extends DataFlowCall, TSpecialCall {
|
||||
SpecialMethodCallNode special;
|
||||
|
||||
SpecialCall() { this = TSpecialCall(special) }
|
||||
|
||||
override string toString() { result = special.toString() }
|
||||
|
||||
override ControlFlowNode getArg(int n) { result = special.(SpecialMethod::Potential).getArg(n) }
|
||||
|
||||
override ControlFlowNode getNode() { result = special }
|
||||
|
||||
override DataFlowCallable getCallable() {
|
||||
result = TCallableValue(special.getResolvedSpecialMethod())
|
||||
}
|
||||
|
||||
override DataFlowCallable getEnclosingCallable() {
|
||||
result.getScope() = special.getNode().getScope()
|
||||
}
|
||||
}
|
||||
|
||||
/** A data flow node that represents a call argument. */
|
||||
@@ -220,7 +323,7 @@ class OutNode extends CfgNode {
|
||||
* `kind`.
|
||||
*/
|
||||
OutNode getAnOutNode(DataFlowCall call, ReturnKind kind) {
|
||||
call = result.getNode() and
|
||||
call.getNode() = result.getNode() and
|
||||
kind = TNormalReturnKind()
|
||||
}
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* Provides Python-specific definitions for use in the data flow library.
|
||||
*/
|
||||
|
||||
import python
|
||||
private import python
|
||||
private import DataFlowPrivate
|
||||
|
||||
/**
|
||||
@@ -20,7 +20,9 @@ newtype TNode =
|
||||
/** A node corresponding to an SSA variable. */
|
||||
TEssaNode(EssaVariable var) or
|
||||
/** A node corresponding to a control flow node. */
|
||||
TCfgNode(ControlFlowNode node)
|
||||
TCfgNode(DataFlowCfgNode node) or
|
||||
/** A node representing the value of an object after a state change */
|
||||
TPostUpdateNode(PreUpdateNode pre)
|
||||
|
||||
/**
|
||||
* An element, viewed as a node in a data flow graph. Either an SSA variable
|
||||
@@ -58,6 +60,15 @@ class Node extends TNode {
|
||||
) {
|
||||
this.getLocation().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
|
||||
}
|
||||
|
||||
/** Convenience method for casting to EssaNode and calling getVar. */
|
||||
EssaVariable asVar() { none() }
|
||||
|
||||
/** Convenience method for casting to CfgNode and calling getNode. */
|
||||
ControlFlowNode asCfgNode() { none() }
|
||||
|
||||
/** Convenience method for casting to ExprNode and calling getNode and getNode again. */
|
||||
Expr asExpr() { none() }
|
||||
}
|
||||
|
||||
class EssaNode extends Node, TEssaNode {
|
||||
@@ -67,6 +78,8 @@ class EssaNode extends Node, TEssaNode {
|
||||
|
||||
EssaVariable getVar() { result = var }
|
||||
|
||||
override EssaVariable asVar() { result = var }
|
||||
|
||||
/** Gets a textual representation of this element. */
|
||||
override string toString() { result = var.toString() }
|
||||
|
||||
@@ -76,12 +89,14 @@ class EssaNode extends Node, TEssaNode {
|
||||
}
|
||||
|
||||
class CfgNode extends Node, TCfgNode {
|
||||
ControlFlowNode node;
|
||||
DataFlowCfgNode node;
|
||||
|
||||
CfgNode() { this = TCfgNode(node) }
|
||||
|
||||
ControlFlowNode getNode() { result = node }
|
||||
|
||||
override ControlFlowNode asCfgNode() { result = node }
|
||||
|
||||
/** Gets a textual representation of this element. */
|
||||
override string toString() { result = node.toString() }
|
||||
|
||||
@@ -97,10 +112,14 @@ class CfgNode extends Node, TCfgNode {
|
||||
* to multiple `ExprNode`s, just like it may correspond to multiple
|
||||
* `ControlFlow::Node`s.
|
||||
*/
|
||||
class ExprNode extends Node { }
|
||||
class ExprNode extends CfgNode {
|
||||
ExprNode() { isExpressionNode(node) }
|
||||
|
||||
override Expr asExpr() { result = node.getNode() }
|
||||
}
|
||||
|
||||
/** Gets a node corresponding to expression `e`. */
|
||||
ExprNode exprNode(DataFlowExpr e) { none() }
|
||||
ExprNode exprNode(DataFlowExpr e) { result.getNode().getNode() = e }
|
||||
|
||||
/**
|
||||
* The value of a parameter at function entry, viewed as a node in a data
|
||||
|
||||
@@ -46,8 +46,8 @@ predicate localAdditionalTaintStep(DataFlow::Node nodeFrom, DataFlow::Node nodeT
|
||||
* Holds if taint can flow from `nodeFrom` to `nodeTo` with a step related to concatenation.
|
||||
*
|
||||
* Note that since we cannot easily distinguish interesting types (like string, list, tuple),
|
||||
* we consider any `+` operation to propagate taint. After consulting with the JS team, this
|
||||
* doesn't sound like it is a big problem in practice.
|
||||
* we consider any `+` operation to propagate taint. This is what is done in the JS libraries,
|
||||
* and isn't a big problem in practice.
|
||||
*/
|
||||
predicate concatStep(DataFlow::CfgNode nodeFrom, DataFlow::CfgNode nodeTo) {
|
||||
exists(BinaryExprNode add | add = nodeTo.getNode() |
|
||||
|
||||
117
python/ql/src/semmle/python/SpecialMethods.qll
Normal file
117
python/ql/src/semmle/python/SpecialMethods.qll
Normal file
@@ -0,0 +1,117 @@
|
||||
/**
|
||||
* Provides support for special methods.
|
||||
* This is done in two steps:
|
||||
* - A subset of `ControlFlowNode`s are labelled as potentially corresponding to
|
||||
* a special method call (by being an instance of `SpecialMethod::Potential`).
|
||||
* - A subset of the potential special method calls are labelled as being actual
|
||||
* special method calls (`SpecialMethodCallNode`) if the appropriate method is defined.
|
||||
* Extend `SpecialMethod::Potential` to capture more cases.
|
||||
*/
|
||||
|
||||
import python
|
||||
|
||||
/** A control flow node which might correspond to a special method call. */
|
||||
class PotentialSpecialMethodCallNode extends ControlFlowNode {
|
||||
PotentialSpecialMethodCallNode() { this instanceof SpecialMethod::Potential }
|
||||
}
|
||||
|
||||
/**
|
||||
* Machinery for detecting special method calls.
|
||||
* Extend `SpecialMethod::Potential` to capture more cases.
|
||||
*/
|
||||
module SpecialMethod {
|
||||
/** A control flow node which might correspond to a special method call. */
|
||||
abstract class Potential extends ControlFlowNode {
|
||||
/** Gets the name of the method that would be called. */
|
||||
abstract string getSpecialMethodName();
|
||||
|
||||
/** Gets the control flow node that would be passed as the specified argument. */
|
||||
abstract ControlFlowNode getArg(int n);
|
||||
|
||||
/**
|
||||
* Gets the control flow node corresponding to the instance
|
||||
* that would define the special method.
|
||||
*/
|
||||
ControlFlowNode getSelf() { result = this.getArg(0) }
|
||||
}
|
||||
|
||||
/** A binary expression node that might correspond to a special method call. */
|
||||
class SpecialBinOp extends Potential, BinaryExprNode {
|
||||
Operator operator;
|
||||
|
||||
SpecialBinOp() { this.getOp() = operator }
|
||||
|
||||
override string getSpecialMethodName() { result = operator.getSpecialMethodName() }
|
||||
|
||||
override ControlFlowNode getArg(int n) {
|
||||
n = 0 and result = this.getLeft()
|
||||
or
|
||||
n = 1 and result = this.getRight()
|
||||
}
|
||||
}
|
||||
|
||||
/** A subscript expression node that might correspond to a special method call. */
|
||||
abstract class SpecialSubscript extends Potential, SubscriptNode {
|
||||
override ControlFlowNode getArg(int n) {
|
||||
n = 0 and result = this.getObject()
|
||||
or
|
||||
n = 1 and result = this.getIndex()
|
||||
}
|
||||
}
|
||||
|
||||
/** A subscript expression node that might correspond to a call to __getitem__. */
|
||||
class SpecialGetItem extends SpecialSubscript {
|
||||
SpecialGetItem() { this.isLoad() }
|
||||
|
||||
override string getSpecialMethodName() { result = "__getitem__" }
|
||||
}
|
||||
|
||||
/** A subscript expression node that might correspond to a call to __setitem__. */
|
||||
class SpecialSetItem extends SpecialSubscript {
|
||||
SpecialSetItem() { this.isStore() }
|
||||
|
||||
override string getSpecialMethodName() { result = "__setitem__" }
|
||||
|
||||
override ControlFlowNode getArg(int n) {
|
||||
n = 0 and result = this.getObject()
|
||||
or
|
||||
n = 1 and result = this.getIndex()
|
||||
or
|
||||
n = 2 and result = this.getValueNode()
|
||||
}
|
||||
|
||||
private ControlFlowNode getValueNode() {
|
||||
exists(AssignStmt a |
|
||||
a.getATarget() = this.getNode() and
|
||||
result.getNode() = a.getValue()
|
||||
)
|
||||
or
|
||||
exists(AugAssign a |
|
||||
a.getTarget() = this.getNode() and
|
||||
result.getNode() = a.getValue()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/** A subscript expression node that might correspond to a call to __delitem__. */
|
||||
class SpecialDelItem extends SpecialSubscript {
|
||||
SpecialDelItem() { this.isDelete() }
|
||||
|
||||
override string getSpecialMethodName() { result = "__delitem__" }
|
||||
}
|
||||
}
|
||||
|
||||
/** A control flow node corresponding to a special method call. */
|
||||
class SpecialMethodCallNode extends PotentialSpecialMethodCallNode {
|
||||
Value resolvedSpecialMethod;
|
||||
|
||||
SpecialMethodCallNode() {
|
||||
exists(SpecialMethod::Potential pot |
|
||||
this.(SpecialMethod::Potential) = pot and
|
||||
pot.getSelf().pointsTo().getClass().lookup(pot.getSpecialMethodName()) = resolvedSpecialMethod
|
||||
)
|
||||
}
|
||||
|
||||
/** The method that is called. */
|
||||
Value getResolvedSpecialMethod() { result = resolvedSpecialMethod }
|
||||
}
|
||||
290
python/ql/test/TestUtilities/InlineExpectationsTest.qll
Normal file
290
python/ql/test/TestUtilities/InlineExpectationsTest.qll
Normal file
@@ -0,0 +1,290 @@
|
||||
/**
|
||||
* Provides a library for writing QL tests whose success or failure is based on expected results
|
||||
* embedded in the test source code as comments, rather than a `.expected` file.
|
||||
*
|
||||
* To add this framework to a new language:
|
||||
* - Add a file `InlineExpectationsTestPrivate.qll` that defines a `LineComment` class. This class
|
||||
* must support a `getContents` method that returns the contents of the given comment, _excluding_
|
||||
* the comment indicator itself. It should also define `toString` and `getLocation` as usual.
|
||||
*
|
||||
* To create a new inline expectations test:
|
||||
* - Declare a class that extends `InlineExpectationsTest`. In the characteristic predicate of the
|
||||
* new class, bind `this` to a unique string (usually the name of the test).
|
||||
* - Override the `hasActualResult()` predicate to produce the actual results of the query. For each
|
||||
* result, specify a `Location`, a text description of the element for which the result was
|
||||
* reported, a short string to serve as the tag to identify expected results for this test, and the
|
||||
* expected value of the result.
|
||||
* - Override `getARelevantTag()` to return the set of tags that can be produced by
|
||||
* `hasActualResult()`. Often this is just a single tag.
|
||||
*
|
||||
* Example:
|
||||
* ```ql
|
||||
* class ConstantValueTest extends InlineExpectationsTest {
|
||||
* ConstantValueTest() { this = "ConstantValueTest" }
|
||||
*
|
||||
* override string getARelevantTag() {
|
||||
* // We only use one tag for this test.
|
||||
* result = "const"
|
||||
* }
|
||||
*
|
||||
* override predicate hasActualResult(
|
||||
* Location location, string element, string tag, string value
|
||||
* ) {
|
||||
* exists(Expr e |
|
||||
* tag = "const" and // The tag for this test.
|
||||
* value = e.getValue() and // The expected value. Will only hold for constant expressions.
|
||||
* location = e.getLocation() and // The location of the result to be reported.
|
||||
* element = e.toString() // The display text for the result.
|
||||
* )
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* There is no need to write a `select` clause or query predicate. All of the differences between
|
||||
* expected results and actual results will be reported in the `failures()` query predicate.
|
||||
*
|
||||
* To annotate the test source code with an expected result, place a comment on the
|
||||
* same line as the expected result, with text of the following format as the body of the comment:
|
||||
*
|
||||
* `$tag=expected-value`
|
||||
*
|
||||
* Where `tag` is the value of the `tag` parameter from `hasActualResult()`, and `expected-value` is
|
||||
* the value of the `value` parameter from `hasActualResult()`. The `=expected-value` portion may be
|
||||
* omitted, in which case `expected-value` is treated as the empty string. Multiple expectations may
|
||||
* be placed in the same comment, as long as each is prefixed by a `$`. Any actual result that
|
||||
* appears on a line that does not contain a matching expected result comment will be reported with
|
||||
* a message of the form "Unexpected result: tag=value". Any expected result comment for which there
|
||||
* is no matching actual result will be reported with a message of the form
|
||||
* "Missing result: tag=expected-value".
|
||||
*
|
||||
* Example:
|
||||
* ```cpp
|
||||
* int i = x + 5; // $const=5
|
||||
* int j = y + (7 - 3) // $const=7 $const=3 $const=4 // The result of the subtraction is a constant.
|
||||
* ```
|
||||
*
|
||||
* For tests that contain known false positives and false negatives, it is possible to further
|
||||
* annotate that a particular expected result is known to be a false positive, or that a particular
|
||||
* missing result is known to be a false negative:
|
||||
*
|
||||
* `$f+:tag=expected-value` // False positive
|
||||
* `$f-:tag=expected-value` // False negative
|
||||
*
|
||||
* A false positive expectation is treated as any other expected result, except that if there is no
|
||||
* matching actual result, the message will be of the form "Fixed false positive: tag=value". A
|
||||
* false negative expectation is treated as if there were no expected result, except that if a
|
||||
* matching expected result is found, the message will be of the form
|
||||
* "Fixed false negative: tag=value".
|
||||
*
|
||||
* If the same result value is expected for two or more tags on the same line, there is a shorthand
|
||||
* notation available:
|
||||
*
|
||||
* `$tag1,tag2=expected-value`
|
||||
*
|
||||
* is equivalent to:
|
||||
*
|
||||
* `$tag1=expected-value $tag2=expected-value`
|
||||
*/
|
||||
|
||||
private import InlineExpectationsTestPrivate
|
||||
|
||||
/**
|
||||
* Base class for tests with inline expectations. The test extends this class to provide the actual
|
||||
* results of the query, which are then compared with the expected results in comments to produce a
|
||||
* list of failure messages that point out where the actual results differ from the expected
|
||||
* results.
|
||||
*/
|
||||
abstract class InlineExpectationsTest extends string {
|
||||
bindingset[this]
|
||||
InlineExpectationsTest() { any() }
|
||||
|
||||
/**
|
||||
* Returns all tags that can be generated by this test. Most tests will only ever produce a single
|
||||
* tag. Any expected result comments for a tag that is not returned by the `getARelevantTag()`
|
||||
* predicate for an active test will be ignored. This makes it possible to write multiple tests in
|
||||
* different `.ql` files that all query the same source code.
|
||||
*/
|
||||
abstract string getARelevantTag();
|
||||
|
||||
/**
|
||||
* Returns the actual results of the query that is being tested. Each result consist of the
|
||||
* following values:
|
||||
* - `location` - The source code location of the result. Any expected result comment must appear
|
||||
* on the start line of this location.
|
||||
* - `element` - Display text for the element on which the result is reported.
|
||||
* - `tag` - The tag that marks this result as coming from this test. This must be one of the tags
|
||||
* returned by `getARelevantTag()`.
|
||||
* - `value` - The value of the result, which will be matched against the value associated with
|
||||
* `tag` in any expected result comment on that line.
|
||||
*/
|
||||
abstract predicate hasActualResult(Location location, string element, string tag, string value);
|
||||
|
||||
final predicate hasFailureMessage(FailureLocatable element, string message) {
|
||||
exists(ActualResult actualResult |
|
||||
actualResult.getTest() = this and
|
||||
element = actualResult and
|
||||
(
|
||||
exists(FalseNegativeExpectation falseNegative |
|
||||
falseNegative.matchesActualResult(actualResult) and
|
||||
message = "Fixed false negative:" + falseNegative.getExpectationText()
|
||||
)
|
||||
or
|
||||
not exists(ValidExpectation expectation | expectation.matchesActualResult(actualResult)) and
|
||||
message = "Unexpected result: " + actualResult.getExpectationText()
|
||||
)
|
||||
)
|
||||
or
|
||||
exists(ValidExpectation expectation |
|
||||
not exists(ActualResult actualResult | expectation.matchesActualResult(actualResult)) and
|
||||
expectation.getTag() = getARelevantTag() and
|
||||
element = expectation and
|
||||
(
|
||||
expectation instanceof GoodExpectation and
|
||||
message = "Missing result:" + expectation.getExpectationText()
|
||||
or
|
||||
expectation instanceof FalsePositiveExpectation and
|
||||
message = "Fixed false positive:" + expectation.getExpectationText()
|
||||
)
|
||||
)
|
||||
or
|
||||
exists(InvalidExpectation expectation |
|
||||
element = expectation and
|
||||
message = "Invalid expectation syntax: " + expectation.getExpectation()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* RegEx pattern to match a comment containing one or more expected results. The comment must have
|
||||
* `$` as its first non-whitespace character. Any subsequent character
|
||||
* is treated as part of the expected results, except that the comment may contain a `//` sequence
|
||||
* to treat the remainder of the line as a regular (non-interpreted) comment.
|
||||
*/
|
||||
private string expectationCommentPattern() { result = "\\s*(\\$(?:[^/]|/[^/])*)(?://.*)?" }
|
||||
|
||||
/**
|
||||
* RegEx pattern to match a single expected result, not including the leading `$`. It starts with an
|
||||
* optional `f+:` or `f-:`, followed by one or more comma-separated tags containing only letters,
|
||||
* `-`, and `_`, optionally followed by `=` and the expected value.
|
||||
*/
|
||||
private string expectationPattern() {
|
||||
result = "(?:(f(?:\\+|-)):)?((?:[A-Za-z-_]+)(?:\\s*,\\s*[A-Za-z-_]+)*)(?:=(.*))?"
|
||||
}
|
||||
|
||||
private string getAnExpectation(LineComment comment) {
|
||||
result = comment.getContents().regexpCapture(expectationCommentPattern(), 1).splitAt("$").trim() and
|
||||
result != ""
|
||||
}
|
||||
|
||||
private newtype TFailureLocatable =
|
||||
TActualResult(
|
||||
InlineExpectationsTest test, Location location, string element, string tag, string value
|
||||
) {
|
||||
test.hasActualResult(location, element, tag, value)
|
||||
} or
|
||||
TValidExpectation(LineComment comment, string tag, string value, string knownFailure) {
|
||||
exists(string expectation |
|
||||
expectation = getAnExpectation(comment) and
|
||||
expectation.regexpMatch(expectationPattern()) and
|
||||
tag = expectation.regexpCapture(expectationPattern(), 2).splitAt(",").trim() and
|
||||
(
|
||||
if exists(expectation.regexpCapture(expectationPattern(), 3))
|
||||
then value = expectation.regexpCapture(expectationPattern(), 3)
|
||||
else value = ""
|
||||
) and
|
||||
(
|
||||
if exists(expectation.regexpCapture(expectationPattern(), 1))
|
||||
then knownFailure = expectation.regexpCapture(expectationPattern(), 1)
|
||||
else knownFailure = ""
|
||||
)
|
||||
)
|
||||
} or
|
||||
TInvalidExpectation(LineComment comment, string expectation) {
|
||||
expectation = getAnExpectation(comment) and
|
||||
not expectation.regexpMatch(expectationPattern())
|
||||
}
|
||||
|
||||
class FailureLocatable extends TFailureLocatable {
|
||||
string toString() { none() }
|
||||
|
||||
Location getLocation() { none() }
|
||||
|
||||
final string getExpectationText() { result = getTag() + "=" + getValue() }
|
||||
|
||||
string getTag() { none() }
|
||||
|
||||
string getValue() { none() }
|
||||
}
|
||||
|
||||
class ActualResult extends FailureLocatable, TActualResult {
|
||||
InlineExpectationsTest test;
|
||||
Location location;
|
||||
string element;
|
||||
string tag;
|
||||
string value;
|
||||
|
||||
ActualResult() { this = TActualResult(test, location, element, tag, value) }
|
||||
|
||||
override string toString() { result = element }
|
||||
|
||||
override Location getLocation() { result = location }
|
||||
|
||||
InlineExpectationsTest getTest() { result = test }
|
||||
|
||||
override string getTag() { result = tag }
|
||||
|
||||
override string getValue() { result = value }
|
||||
}
|
||||
|
||||
abstract private class Expectation extends FailureLocatable {
|
||||
LineComment comment;
|
||||
|
||||
override string toString() { result = comment.toString() }
|
||||
|
||||
override Location getLocation() { result = comment.getLocation() }
|
||||
}
|
||||
|
||||
private class ValidExpectation extends Expectation, TValidExpectation {
|
||||
string tag;
|
||||
string value;
|
||||
string knownFailure;
|
||||
|
||||
ValidExpectation() { this = TValidExpectation(comment, tag, value, knownFailure) }
|
||||
|
||||
override string getTag() { result = tag }
|
||||
|
||||
override string getValue() { result = value }
|
||||
|
||||
string getKnownFailure() { result = knownFailure }
|
||||
|
||||
predicate matchesActualResult(ActualResult actualResult) {
|
||||
getLocation().getStartLine() = actualResult.getLocation().getStartLine() and
|
||||
getLocation().getFile() = actualResult.getLocation().getFile() and
|
||||
getTag() = actualResult.getTag() and
|
||||
getValue() = actualResult.getValue()
|
||||
}
|
||||
}
|
||||
|
||||
class GoodExpectation extends ValidExpectation {
|
||||
GoodExpectation() { getKnownFailure() = "" }
|
||||
}
|
||||
|
||||
class FalsePositiveExpectation extends ValidExpectation {
|
||||
FalsePositiveExpectation() { getKnownFailure() = "f+" }
|
||||
}
|
||||
|
||||
class FalseNegativeExpectation extends ValidExpectation {
|
||||
FalseNegativeExpectation() { getKnownFailure() = "f-" }
|
||||
}
|
||||
|
||||
class InvalidExpectation extends Expectation, TInvalidExpectation {
|
||||
string expectation;
|
||||
|
||||
InvalidExpectation() { this = TInvalidExpectation(comment, expectation) }
|
||||
|
||||
string getExpectation() { result = expectation }
|
||||
}
|
||||
|
||||
query predicate failures(FailureLocatable element, string message) {
|
||||
exists(InlineExpectationsTest test | test.hasFailureMessage(element, message))
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
import python
|
||||
|
||||
/**
|
||||
* A class representing line comments in Python. As this is the only form of comment Python
|
||||
* permits, we simply reuse the `Comment` class.
|
||||
*/
|
||||
class LineComment = Comment;
|
||||
@@ -1,23 +1,16 @@
|
||||
| test.py:0:0:0:0 | GSSA Variable __name__ | test.py:0:0:0:0 | Exit node for Module test |
|
||||
| test.py:0:0:0:0 | GSSA Variable __name__ | test.py:7:1:7:1 | GSSA Variable b |
|
||||
| test.py:0:0:0:0 | GSSA Variable __name__ | test.py:7:5:7:20 | ControlFlowNode for obfuscated_id() |
|
||||
| test.py:0:0:0:0 | GSSA Variable __package__ | test.py:0:0:0:0 | Exit node for Module test |
|
||||
| test.py:0:0:0:0 | GSSA Variable __package__ | test.py:7:1:7:1 | GSSA Variable b |
|
||||
| test.py:0:0:0:0 | GSSA Variable __package__ | test.py:7:5:7:20 | ControlFlowNode for obfuscated_id() |
|
||||
| test.py:0:0:0:0 | GSSA Variable b | test.py:0:0:0:0 | Exit node for Module test |
|
||||
| test.py:0:0:0:0 | GSSA Variable b | test.py:7:1:7:1 | GSSA Variable b |
|
||||
| test.py:0:0:0:0 | GSSA Variable b | test.py:7:5:7:20 | ControlFlowNode for obfuscated_id() |
|
||||
| test.py:1:1:1:21 | ControlFlowNode for FunctionExpr | test.py:0:0:0:0 | Exit node for Module test |
|
||||
| test.py:1:1:1:21 | ControlFlowNode for FunctionExpr | test.py:1:5:1:17 | GSSA Variable obfuscated_id |
|
||||
| test.py:1:1:1:21 | ControlFlowNode for FunctionExpr | test.py:7:1:7:1 | GSSA Variable b |
|
||||
| test.py:1:1:1:21 | ControlFlowNode for FunctionExpr | test.py:7:5:7:17 | ControlFlowNode for obfuscated_id |
|
||||
| test.py:1:1:1:21 | ControlFlowNode for FunctionExpr | test.py:7:5:7:20 | ControlFlowNode for obfuscated_id() |
|
||||
| test.py:1:5:1:17 | GSSA Variable obfuscated_id | test.py:0:0:0:0 | Exit node for Module test |
|
||||
| test.py:1:5:1:17 | GSSA Variable obfuscated_id | test.py:7:1:7:1 | GSSA Variable b |
|
||||
| test.py:1:5:1:17 | GSSA Variable obfuscated_id | test.py:7:5:7:17 | ControlFlowNode for obfuscated_id |
|
||||
| test.py:1:5:1:17 | GSSA Variable obfuscated_id | test.py:7:5:7:20 | ControlFlowNode for obfuscated_id() |
|
||||
| test.py:1:19:1:19 | SSA variable x | test.py:0:0:0:0 | Exit node for Module test |
|
||||
| test.py:1:19:1:19 | SSA variable x | test.py:1:1:1:21 | Exit node for Function obfuscated_id |
|
||||
| test.py:1:19:1:19 | SSA variable x | test.py:2:3:2:3 | SSA variable y |
|
||||
| test.py:1:19:1:19 | SSA variable x | test.py:2:7:2:7 | ControlFlowNode for x |
|
||||
| test.py:1:19:1:19 | SSA variable x | test.py:3:3:3:3 | SSA variable z |
|
||||
@@ -25,37 +18,26 @@
|
||||
| test.py:1:19:1:19 | SSA variable x | test.py:4:10:4:10 | ControlFlowNode for z |
|
||||
| test.py:1:19:1:19 | SSA variable x | test.py:7:1:7:1 | GSSA Variable b |
|
||||
| test.py:1:19:1:19 | SSA variable x | test.py:7:5:7:20 | ControlFlowNode for obfuscated_id() |
|
||||
| test.py:2:3:2:3 | SSA variable y | test.py:0:0:0:0 | Exit node for Module test |
|
||||
| test.py:2:3:2:3 | SSA variable y | test.py:1:1:1:21 | Exit node for Function obfuscated_id |
|
||||
| test.py:2:3:2:3 | SSA variable y | test.py:3:3:3:3 | SSA variable z |
|
||||
| test.py:2:3:2:3 | SSA variable y | test.py:3:7:3:7 | ControlFlowNode for y |
|
||||
| test.py:2:3:2:3 | SSA variable y | test.py:4:10:4:10 | ControlFlowNode for z |
|
||||
| test.py:2:3:2:3 | SSA variable y | test.py:7:1:7:1 | GSSA Variable b |
|
||||
| test.py:2:3:2:3 | SSA variable y | test.py:7:5:7:20 | ControlFlowNode for obfuscated_id() |
|
||||
| test.py:2:7:2:7 | ControlFlowNode for x | test.py:0:0:0:0 | Exit node for Module test |
|
||||
| test.py:2:7:2:7 | ControlFlowNode for x | test.py:1:1:1:21 | Exit node for Function obfuscated_id |
|
||||
| test.py:2:7:2:7 | ControlFlowNode for x | test.py:2:3:2:3 | SSA variable y |
|
||||
| test.py:2:7:2:7 | ControlFlowNode for x | test.py:3:3:3:3 | SSA variable z |
|
||||
| test.py:2:7:2:7 | ControlFlowNode for x | test.py:3:7:3:7 | ControlFlowNode for y |
|
||||
| test.py:2:7:2:7 | ControlFlowNode for x | test.py:4:10:4:10 | ControlFlowNode for z |
|
||||
| test.py:2:7:2:7 | ControlFlowNode for x | test.py:7:1:7:1 | GSSA Variable b |
|
||||
| test.py:2:7:2:7 | ControlFlowNode for x | test.py:7:5:7:20 | ControlFlowNode for obfuscated_id() |
|
||||
| test.py:3:3:3:3 | SSA variable z | test.py:0:0:0:0 | Exit node for Module test |
|
||||
| test.py:3:3:3:3 | SSA variable z | test.py:1:1:1:21 | Exit node for Function obfuscated_id |
|
||||
| test.py:3:3:3:3 | SSA variable z | test.py:4:10:4:10 | ControlFlowNode for z |
|
||||
| test.py:3:3:3:3 | SSA variable z | test.py:7:1:7:1 | GSSA Variable b |
|
||||
| test.py:3:3:3:3 | SSA variable z | test.py:7:5:7:20 | ControlFlowNode for obfuscated_id() |
|
||||
| test.py:3:7:3:7 | ControlFlowNode for y | test.py:0:0:0:0 | Exit node for Module test |
|
||||
| test.py:3:7:3:7 | ControlFlowNode for y | test.py:1:1:1:21 | Exit node for Function obfuscated_id |
|
||||
| test.py:3:7:3:7 | ControlFlowNode for y | test.py:3:3:3:3 | SSA variable z |
|
||||
| test.py:3:7:3:7 | ControlFlowNode for y | test.py:4:10:4:10 | ControlFlowNode for z |
|
||||
| test.py:3:7:3:7 | ControlFlowNode for y | test.py:7:1:7:1 | GSSA Variable b |
|
||||
| test.py:3:7:3:7 | ControlFlowNode for y | test.py:7:5:7:20 | ControlFlowNode for obfuscated_id() |
|
||||
| test.py:4:10:4:10 | ControlFlowNode for z | test.py:0:0:0:0 | Exit node for Module test |
|
||||
| test.py:4:10:4:10 | ControlFlowNode for z | test.py:7:1:7:1 | GSSA Variable b |
|
||||
| test.py:4:10:4:10 | ControlFlowNode for z | test.py:7:5:7:20 | ControlFlowNode for obfuscated_id() |
|
||||
| test.py:6:1:6:1 | GSSA Variable a | test.py:0:0:0:0 | Exit node for Module test |
|
||||
| test.py:6:1:6:1 | GSSA Variable a | test.py:1:1:1:21 | Exit node for Function obfuscated_id |
|
||||
| test.py:6:1:6:1 | GSSA Variable a | test.py:1:19:1:19 | SSA variable x |
|
||||
| test.py:6:1:6:1 | GSSA Variable a | test.py:2:3:2:3 | SSA variable y |
|
||||
| test.py:6:1:6:1 | GSSA Variable a | test.py:2:7:2:7 | ControlFlowNode for x |
|
||||
@@ -66,8 +48,6 @@
|
||||
| test.py:6:1:6:1 | GSSA Variable a | test.py:7:5:7:20 | ControlFlowNode for obfuscated_id() |
|
||||
| test.py:6:1:6:1 | GSSA Variable a | test.py:7:5:7:20 | GSSA Variable a |
|
||||
| test.py:6:1:6:1 | GSSA Variable a | test.py:7:19:7:19 | ControlFlowNode for a |
|
||||
| test.py:6:5:6:6 | ControlFlowNode for IntegerLiteral | test.py:0:0:0:0 | Exit node for Module test |
|
||||
| test.py:6:5:6:6 | ControlFlowNode for IntegerLiteral | test.py:1:1:1:21 | Exit node for Function obfuscated_id |
|
||||
| test.py:6:5:6:6 | ControlFlowNode for IntegerLiteral | test.py:1:19:1:19 | SSA variable x |
|
||||
| test.py:6:5:6:6 | ControlFlowNode for IntegerLiteral | test.py:2:3:2:3 | SSA variable y |
|
||||
| test.py:6:5:6:6 | ControlFlowNode for IntegerLiteral | test.py:2:7:2:7 | ControlFlowNode for x |
|
||||
@@ -79,12 +59,7 @@
|
||||
| test.py:6:5:6:6 | ControlFlowNode for IntegerLiteral | test.py:7:5:7:20 | ControlFlowNode for obfuscated_id() |
|
||||
| test.py:6:5:6:6 | ControlFlowNode for IntegerLiteral | test.py:7:5:7:20 | GSSA Variable a |
|
||||
| test.py:6:5:6:6 | ControlFlowNode for IntegerLiteral | test.py:7:19:7:19 | ControlFlowNode for a |
|
||||
| test.py:7:1:7:1 | GSSA Variable b | test.py:0:0:0:0 | Exit node for Module test |
|
||||
| test.py:7:5:7:20 | ControlFlowNode for obfuscated_id() | test.py:0:0:0:0 | Exit node for Module test |
|
||||
| test.py:7:5:7:20 | ControlFlowNode for obfuscated_id() | test.py:7:1:7:1 | GSSA Variable b |
|
||||
| test.py:7:5:7:20 | GSSA Variable a | test.py:0:0:0:0 | Exit node for Module test |
|
||||
| test.py:7:19:7:19 | ControlFlowNode for a | test.py:0:0:0:0 | Exit node for Module test |
|
||||
| test.py:7:19:7:19 | ControlFlowNode for a | test.py:1:1:1:21 | Exit node for Function obfuscated_id |
|
||||
| test.py:7:19:7:19 | ControlFlowNode for a | test.py:1:19:1:19 | SSA variable x |
|
||||
| test.py:7:19:7:19 | ControlFlowNode for a | test.py:2:3:2:3 | SSA variable y |
|
||||
| test.py:7:19:7:19 | ControlFlowNode for a | test.py:2:7:2:7 | ControlFlowNode for x |
|
||||
|
||||
@@ -1,25 +1,15 @@
|
||||
| test.py:0:0:0:0 | GSSA Variable __name__ | test.py:0:0:0:0 | Exit node for Module test |
|
||||
| test.py:0:0:0:0 | GSSA Variable __name__ | test.py:0:0:0:0 | Exit node for Module test |
|
||||
| test.py:0:0:0:0 | GSSA Variable __name__ | test.py:7:5:7:20 | ControlFlowNode for obfuscated_id() |
|
||||
| test.py:0:0:0:0 | GSSA Variable __name__ | test.py:7:5:7:20 | ControlFlowNode for obfuscated_id() |
|
||||
| test.py:0:0:0:0 | GSSA Variable __package__ | test.py:0:0:0:0 | Exit node for Module test |
|
||||
| test.py:0:0:0:0 | GSSA Variable __package__ | test.py:0:0:0:0 | Exit node for Module test |
|
||||
| test.py:0:0:0:0 | GSSA Variable __package__ | test.py:7:5:7:20 | ControlFlowNode for obfuscated_id() |
|
||||
| test.py:0:0:0:0 | GSSA Variable __package__ | test.py:7:5:7:20 | ControlFlowNode for obfuscated_id() |
|
||||
| test.py:0:0:0:0 | GSSA Variable b | test.py:7:5:7:20 | ControlFlowNode for obfuscated_id() |
|
||||
| test.py:0:0:0:0 | GSSA Variable b | test.py:7:5:7:20 | ControlFlowNode for obfuscated_id() |
|
||||
| test.py:1:1:1:21 | ControlFlowNode for FunctionExpr | test.py:1:5:1:17 | GSSA Variable obfuscated_id |
|
||||
| test.py:1:1:1:21 | ControlFlowNode for FunctionExpr | test.py:1:5:1:17 | GSSA Variable obfuscated_id |
|
||||
| test.py:1:5:1:17 | GSSA Variable obfuscated_id | test.py:0:0:0:0 | Exit node for Module test |
|
||||
| test.py:1:5:1:17 | GSSA Variable obfuscated_id | test.py:0:0:0:0 | Exit node for Module test |
|
||||
| test.py:1:5:1:17 | GSSA Variable obfuscated_id | test.py:7:5:7:17 | ControlFlowNode for obfuscated_id |
|
||||
| test.py:1:5:1:17 | GSSA Variable obfuscated_id | test.py:7:5:7:17 | ControlFlowNode for obfuscated_id |
|
||||
| test.py:1:5:1:17 | GSSA Variable obfuscated_id | test.py:7:5:7:20 | ControlFlowNode for obfuscated_id() |
|
||||
| test.py:1:5:1:17 | GSSA Variable obfuscated_id | test.py:7:5:7:20 | ControlFlowNode for obfuscated_id() |
|
||||
| test.py:1:19:1:19 | SSA variable x | test.py:1:1:1:21 | Exit node for Function obfuscated_id |
|
||||
| test.py:1:19:1:19 | SSA variable x | test.py:1:1:1:21 | Exit node for Function obfuscated_id |
|
||||
| test.py:1:19:1:19 | SSA variable x | test.py:1:1:1:21 | Exit node for Function obfuscated_id |
|
||||
| test.py:1:19:1:19 | SSA variable x | test.py:1:1:1:21 | Exit node for Function obfuscated_id |
|
||||
| test.py:1:19:1:19 | SSA variable x | test.py:2:3:2:3 | SSA variable y |
|
||||
| test.py:1:19:1:19 | SSA variable x | test.py:2:3:2:3 | SSA variable y |
|
||||
| test.py:1:19:1:19 | SSA variable x | test.py:2:3:2:3 | SSA variable y |
|
||||
@@ -40,10 +30,6 @@
|
||||
| test.py:1:19:1:19 | SSA variable x | test.py:4:10:4:10 | ControlFlowNode for z |
|
||||
| test.py:1:19:1:19 | SSA variable x | test.py:4:10:4:10 | ControlFlowNode for z |
|
||||
| test.py:1:19:1:19 | SSA variable x | test.py:4:10:4:10 | ControlFlowNode for z |
|
||||
| test.py:2:3:2:3 | SSA variable y | test.py:1:1:1:21 | Exit node for Function obfuscated_id |
|
||||
| test.py:2:3:2:3 | SSA variable y | test.py:1:1:1:21 | Exit node for Function obfuscated_id |
|
||||
| test.py:2:3:2:3 | SSA variable y | test.py:1:1:1:21 | Exit node for Function obfuscated_id |
|
||||
| test.py:2:3:2:3 | SSA variable y | test.py:1:1:1:21 | Exit node for Function obfuscated_id |
|
||||
| test.py:2:3:2:3 | SSA variable y | test.py:3:3:3:3 | SSA variable z |
|
||||
| test.py:2:3:2:3 | SSA variable y | test.py:3:3:3:3 | SSA variable z |
|
||||
| test.py:2:3:2:3 | SSA variable y | test.py:3:3:3:3 | SSA variable z |
|
||||
@@ -56,10 +42,6 @@
|
||||
| test.py:2:3:2:3 | SSA variable y | test.py:4:10:4:10 | ControlFlowNode for z |
|
||||
| test.py:2:3:2:3 | SSA variable y | test.py:4:10:4:10 | ControlFlowNode for z |
|
||||
| test.py:2:3:2:3 | SSA variable y | test.py:4:10:4:10 | ControlFlowNode for z |
|
||||
| test.py:2:7:2:7 | ControlFlowNode for x | test.py:1:1:1:21 | Exit node for Function obfuscated_id |
|
||||
| test.py:2:7:2:7 | ControlFlowNode for x | test.py:1:1:1:21 | Exit node for Function obfuscated_id |
|
||||
| test.py:2:7:2:7 | ControlFlowNode for x | test.py:1:1:1:21 | Exit node for Function obfuscated_id |
|
||||
| test.py:2:7:2:7 | ControlFlowNode for x | test.py:1:1:1:21 | Exit node for Function obfuscated_id |
|
||||
| test.py:2:7:2:7 | ControlFlowNode for x | test.py:2:3:2:3 | SSA variable y |
|
||||
| test.py:2:7:2:7 | ControlFlowNode for x | test.py:2:3:2:3 | SSA variable y |
|
||||
| test.py:2:7:2:7 | ControlFlowNode for x | test.py:2:3:2:3 | SSA variable y |
|
||||
@@ -76,18 +58,10 @@
|
||||
| test.py:2:7:2:7 | ControlFlowNode for x | test.py:4:10:4:10 | ControlFlowNode for z |
|
||||
| test.py:2:7:2:7 | ControlFlowNode for x | test.py:4:10:4:10 | ControlFlowNode for z |
|
||||
| test.py:2:7:2:7 | ControlFlowNode for x | test.py:4:10:4:10 | ControlFlowNode for z |
|
||||
| test.py:3:3:3:3 | SSA variable z | test.py:1:1:1:21 | Exit node for Function obfuscated_id |
|
||||
| test.py:3:3:3:3 | SSA variable z | test.py:1:1:1:21 | Exit node for Function obfuscated_id |
|
||||
| test.py:3:3:3:3 | SSA variable z | test.py:1:1:1:21 | Exit node for Function obfuscated_id |
|
||||
| test.py:3:3:3:3 | SSA variable z | test.py:1:1:1:21 | Exit node for Function obfuscated_id |
|
||||
| test.py:3:3:3:3 | SSA variable z | test.py:4:10:4:10 | ControlFlowNode for z |
|
||||
| test.py:3:3:3:3 | SSA variable z | test.py:4:10:4:10 | ControlFlowNode for z |
|
||||
| test.py:3:3:3:3 | SSA variable z | test.py:4:10:4:10 | ControlFlowNode for z |
|
||||
| test.py:3:3:3:3 | SSA variable z | test.py:4:10:4:10 | ControlFlowNode for z |
|
||||
| test.py:3:7:3:7 | ControlFlowNode for y | test.py:1:1:1:21 | Exit node for Function obfuscated_id |
|
||||
| test.py:3:7:3:7 | ControlFlowNode for y | test.py:1:1:1:21 | Exit node for Function obfuscated_id |
|
||||
| test.py:3:7:3:7 | ControlFlowNode for y | test.py:1:1:1:21 | Exit node for Function obfuscated_id |
|
||||
| test.py:3:7:3:7 | ControlFlowNode for y | test.py:1:1:1:21 | Exit node for Function obfuscated_id |
|
||||
| test.py:3:7:3:7 | ControlFlowNode for y | test.py:3:3:3:3 | SSA variable z |
|
||||
| test.py:3:7:3:7 | ControlFlowNode for y | test.py:3:3:3:3 | SSA variable z |
|
||||
| test.py:3:7:3:7 | ControlFlowNode for y | test.py:3:3:3:3 | SSA variable z |
|
||||
@@ -106,12 +80,8 @@
|
||||
| test.py:6:1:6:1 | GSSA Variable a | test.py:7:19:7:19 | ControlFlowNode for a |
|
||||
| test.py:6:5:6:6 | ControlFlowNode for IntegerLiteral | test.py:6:1:6:1 | GSSA Variable a |
|
||||
| test.py:6:5:6:6 | ControlFlowNode for IntegerLiteral | test.py:6:1:6:1 | GSSA Variable a |
|
||||
| test.py:7:1:7:1 | GSSA Variable b | test.py:0:0:0:0 | Exit node for Module test |
|
||||
| test.py:7:1:7:1 | GSSA Variable b | test.py:0:0:0:0 | Exit node for Module test |
|
||||
| test.py:7:5:7:20 | ControlFlowNode for obfuscated_id() | test.py:7:1:7:1 | GSSA Variable b |
|
||||
| test.py:7:5:7:20 | ControlFlowNode for obfuscated_id() | test.py:7:1:7:1 | GSSA Variable b |
|
||||
| test.py:7:5:7:20 | GSSA Variable a | test.py:0:0:0:0 | Exit node for Module test |
|
||||
| test.py:7:5:7:20 | GSSA Variable a | test.py:0:0:0:0 | Exit node for Module test |
|
||||
| test.py:7:19:7:19 | ControlFlowNode for a | test.py:1:19:1:19 | SSA variable x |
|
||||
| test.py:7:19:7:19 | ControlFlowNode for a | test.py:1:19:1:19 | SSA variable x |
|
||||
| test.py:7:19:7:19 | ControlFlowNode for a | test.py:7:5:7:20 | ControlFlowNode for obfuscated_id() |
|
||||
|
||||
@@ -1,17 +1,11 @@
|
||||
| test.py:0:0:0:0 | Entry node for Module test | test.py:0:0:0:0 | Entry node for Module test |
|
||||
| test.py:0:0:0:0 | Exit node for Module test | test.py:0:0:0:0 | Exit node for Module test |
|
||||
| test.py:0:0:0:0 | GSSA Variable __name__ | test.py:0:0:0:0 | GSSA Variable __name__ |
|
||||
| test.py:0:0:0:0 | GSSA Variable __package__ | test.py:0:0:0:0 | GSSA Variable __package__ |
|
||||
| test.py:0:0:0:0 | GSSA Variable b | test.py:0:0:0:0 | GSSA Variable b |
|
||||
| test.py:0:0:0:0 | SSA variable $ | test.py:0:0:0:0 | Exit node for Module test |
|
||||
| test.py:0:0:0:0 | SSA variable $ | test.py:0:0:0:0 | SSA variable $ |
|
||||
| test.py:1:1:1:21 | ControlFlowNode for FunctionExpr | test.py:1:1:1:21 | ControlFlowNode for FunctionExpr |
|
||||
| test.py:1:1:1:21 | Entry node for Function obfuscated_id | test.py:1:1:1:21 | Entry node for Function obfuscated_id |
|
||||
| test.py:1:1:1:21 | Exit node for Function obfuscated_id | test.py:1:1:1:21 | Exit node for Function obfuscated_id |
|
||||
| test.py:1:5:1:17 | ControlFlowNode for obfuscated_id | test.py:1:5:1:17 | ControlFlowNode for obfuscated_id |
|
||||
| test.py:1:5:1:17 | GSSA Variable obfuscated_id | test.py:1:5:1:17 | GSSA Variable obfuscated_id |
|
||||
| test.py:1:19:1:19 | ControlFlowNode for x | test.py:1:19:1:19 | ControlFlowNode for x |
|
||||
| test.py:1:19:1:19 | SSA variable x | test.py:1:1:1:21 | Exit node for Function obfuscated_id |
|
||||
| test.py:1:19:1:19 | SSA variable x | test.py:1:19:1:19 | SSA variable x |
|
||||
| test.py:1:19:1:19 | SSA variable x | test.py:2:3:2:3 | SSA variable y |
|
||||
| test.py:1:19:1:19 | SSA variable x | test.py:2:7:2:7 | ControlFlowNode for x |
|
||||
@@ -19,26 +13,21 @@
|
||||
| test.py:1:19:1:19 | SSA variable x | test.py:3:7:3:7 | ControlFlowNode for y |
|
||||
| test.py:1:19:1:19 | SSA variable x | test.py:4:10:4:10 | ControlFlowNode for z |
|
||||
| test.py:2:3:2:3 | ControlFlowNode for y | test.py:2:3:2:3 | ControlFlowNode for y |
|
||||
| test.py:2:3:2:3 | SSA variable y | test.py:1:1:1:21 | Exit node for Function obfuscated_id |
|
||||
| test.py:2:3:2:3 | SSA variable y | test.py:2:3:2:3 | SSA variable y |
|
||||
| test.py:2:3:2:3 | SSA variable y | test.py:3:3:3:3 | SSA variable z |
|
||||
| test.py:2:3:2:3 | SSA variable y | test.py:3:7:3:7 | ControlFlowNode for y |
|
||||
| test.py:2:3:2:3 | SSA variable y | test.py:4:10:4:10 | ControlFlowNode for z |
|
||||
| test.py:2:7:2:7 | ControlFlowNode for x | test.py:1:1:1:21 | Exit node for Function obfuscated_id |
|
||||
| test.py:2:7:2:7 | ControlFlowNode for x | test.py:2:3:2:3 | SSA variable y |
|
||||
| test.py:2:7:2:7 | ControlFlowNode for x | test.py:2:7:2:7 | ControlFlowNode for x |
|
||||
| test.py:2:7:2:7 | ControlFlowNode for x | test.py:3:3:3:3 | SSA variable z |
|
||||
| test.py:2:7:2:7 | ControlFlowNode for x | test.py:3:7:3:7 | ControlFlowNode for y |
|
||||
| test.py:2:7:2:7 | ControlFlowNode for x | test.py:4:10:4:10 | ControlFlowNode for z |
|
||||
| test.py:3:3:3:3 | ControlFlowNode for z | test.py:3:3:3:3 | ControlFlowNode for z |
|
||||
| test.py:3:3:3:3 | SSA variable z | test.py:1:1:1:21 | Exit node for Function obfuscated_id |
|
||||
| test.py:3:3:3:3 | SSA variable z | test.py:3:3:3:3 | SSA variable z |
|
||||
| test.py:3:3:3:3 | SSA variable z | test.py:4:10:4:10 | ControlFlowNode for z |
|
||||
| test.py:3:7:3:7 | ControlFlowNode for y | test.py:1:1:1:21 | Exit node for Function obfuscated_id |
|
||||
| test.py:3:7:3:7 | ControlFlowNode for y | test.py:3:3:3:3 | SSA variable z |
|
||||
| test.py:3:7:3:7 | ControlFlowNode for y | test.py:3:7:3:7 | ControlFlowNode for y |
|
||||
| test.py:3:7:3:7 | ControlFlowNode for y | test.py:4:10:4:10 | ControlFlowNode for z |
|
||||
| test.py:4:3:4:10 | ControlFlowNode for Return | test.py:4:3:4:10 | ControlFlowNode for Return |
|
||||
| test.py:4:10:4:10 | ControlFlowNode for z | test.py:4:10:4:10 | ControlFlowNode for z |
|
||||
| test.py:6:1:6:1 | ControlFlowNode for a | test.py:6:1:6:1 | ControlFlowNode for a |
|
||||
| test.py:6:1:6:1 | GSSA Variable a | test.py:6:1:6:1 | GSSA Variable a |
|
||||
@@ -49,3 +38,4 @@
|
||||
| test.py:7:5:7:20 | ControlFlowNode for obfuscated_id() | test.py:7:5:7:20 | ControlFlowNode for obfuscated_id() |
|
||||
| test.py:7:5:7:20 | GSSA Variable a | test.py:7:5:7:20 | GSSA Variable a |
|
||||
| test.py:7:19:7:19 | ControlFlowNode for a | test.py:7:19:7:19 | ControlFlowNode for a |
|
||||
| test.py:7:19:7:19 | [post] ControlFlowNode for a | test.py:7:19:7:19 | [post] ControlFlowNode for a |
|
||||
|
||||
@@ -1,9 +1,5 @@
|
||||
| test.py:0:0:0:0 | SSA variable $ | test.py:0:0:0:0 | Exit node for Module test |
|
||||
| test.py:1:19:1:19 | SSA variable x | test.py:1:1:1:21 | Exit node for Function obfuscated_id |
|
||||
| test.py:1:19:1:19 | SSA variable x | test.py:2:7:2:7 | ControlFlowNode for x |
|
||||
| test.py:2:3:2:3 | SSA variable y | test.py:1:1:1:21 | Exit node for Function obfuscated_id |
|
||||
| test.py:2:3:2:3 | SSA variable y | test.py:3:7:3:7 | ControlFlowNode for y |
|
||||
| test.py:2:7:2:7 | ControlFlowNode for x | test.py:2:3:2:3 | SSA variable y |
|
||||
| test.py:3:3:3:3 | SSA variable z | test.py:1:1:1:21 | Exit node for Function obfuscated_id |
|
||||
| test.py:3:3:3:3 | SSA variable z | test.py:4:10:4:10 | ControlFlowNode for z |
|
||||
| test.py:3:7:3:7 | ControlFlowNode for y | test.py:3:3:3:3 | SSA variable z |
|
||||
|
||||
@@ -1,12 +1,8 @@
|
||||
| test.py:0:0:0:0 | Entry node for Module test |
|
||||
| test.py:0:0:0:0 | Exit node for Module test |
|
||||
| test.py:0:0:0:0 | GSSA Variable __name__ |
|
||||
| test.py:0:0:0:0 | GSSA Variable __package__ |
|
||||
| test.py:0:0:0:0 | GSSA Variable b |
|
||||
| test.py:0:0:0:0 | SSA variable $ |
|
||||
| test.py:1:1:1:21 | ControlFlowNode for FunctionExpr |
|
||||
| test.py:1:1:1:21 | Entry node for Function obfuscated_id |
|
||||
| test.py:1:1:1:21 | Exit node for Function obfuscated_id |
|
||||
| test.py:1:5:1:17 | ControlFlowNode for obfuscated_id |
|
||||
| test.py:1:5:1:17 | GSSA Variable obfuscated_id |
|
||||
| test.py:1:19:1:19 | ControlFlowNode for x |
|
||||
@@ -17,7 +13,6 @@
|
||||
| test.py:3:3:3:3 | ControlFlowNode for z |
|
||||
| test.py:3:3:3:3 | SSA variable z |
|
||||
| test.py:3:7:3:7 | ControlFlowNode for y |
|
||||
| test.py:4:3:4:10 | ControlFlowNode for Return |
|
||||
| test.py:4:10:4:10 | ControlFlowNode for z |
|
||||
| test.py:6:1:6:1 | ControlFlowNode for a |
|
||||
| test.py:6:1:6:1 | GSSA Variable a |
|
||||
@@ -28,3 +23,4 @@
|
||||
| test.py:7:5:7:20 | ControlFlowNode for obfuscated_id() |
|
||||
| test.py:7:5:7:20 | GSSA Variable a |
|
||||
| test.py:7:19:7:19 | ControlFlowNode for a |
|
||||
| test.py:7:19:7:19 | [post] ControlFlowNode for a |
|
||||
|
||||
@@ -1,12 +1,8 @@
|
||||
| test.py:0:0:0:0 | Entry node for Module test |
|
||||
| test.py:0:0:0:0 | Exit node for Module test |
|
||||
| test.py:0:0:0:0 | GSSA Variable __name__ |
|
||||
| test.py:0:0:0:0 | GSSA Variable __package__ |
|
||||
| test.py:0:0:0:0 | GSSA Variable b |
|
||||
| test.py:0:0:0:0 | SSA variable $ |
|
||||
| test.py:1:1:1:21 | ControlFlowNode for FunctionExpr |
|
||||
| test.py:1:1:1:21 | Entry node for Function obfuscated_id |
|
||||
| test.py:1:1:1:21 | Exit node for Function obfuscated_id |
|
||||
| test.py:1:5:1:17 | ControlFlowNode for obfuscated_id |
|
||||
| test.py:1:5:1:17 | GSSA Variable obfuscated_id |
|
||||
| test.py:1:19:1:19 | ControlFlowNode for x |
|
||||
@@ -17,7 +13,6 @@
|
||||
| test.py:3:3:3:3 | ControlFlowNode for z |
|
||||
| test.py:3:3:3:3 | SSA variable z |
|
||||
| test.py:3:7:3:7 | ControlFlowNode for y |
|
||||
| test.py:4:3:4:10 | ControlFlowNode for Return |
|
||||
| test.py:4:10:4:10 | ControlFlowNode for z |
|
||||
| test.py:6:1:6:1 | ControlFlowNode for a |
|
||||
| test.py:6:1:6:1 | GSSA Variable a |
|
||||
@@ -28,3 +23,4 @@
|
||||
| test.py:7:5:7:20 | ControlFlowNode for obfuscated_id() |
|
||||
| test.py:7:5:7:20 | GSSA Variable a |
|
||||
| test.py:7:19:7:19 | ControlFlowNode for a |
|
||||
| test.py:7:19:7:19 | [post] ControlFlowNode for a |
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
private import python
|
||||
import experimental.dataflow.DataFlow
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,12 +1,10 @@
|
||||
uniqueEnclosingCallable
|
||||
| test.py:0:0:0:0 | Exit node for Module test | Node should have one enclosing callable but has 0. |
|
||||
| test.py:0:0:0:0 | GSSA Variable __name__ | Node should have one enclosing callable but has 0. |
|
||||
| test.py:0:0:0:0 | GSSA Variable __package__ | Node should have one enclosing callable but has 0. |
|
||||
| test.py:0:0:0:0 | GSSA Variable test23 | Node should have one enclosing callable but has 0. |
|
||||
| test.py:0:0:0:0 | GSSA Variable test24 | Node should have one enclosing callable but has 0. |
|
||||
| test.py:0:0:0:0 | GSSA Variable test_truth | Node should have one enclosing callable but has 0. |
|
||||
| test.py:0:0:0:0 | GSSA Variable test_update_extend | Node should have one enclosing callable but has 0. |
|
||||
| test.py:0:0:0:0 | SSA variable $ | Node should have one enclosing callable but has 0. |
|
||||
| test.py:6:1:6:12 | ControlFlowNode for FunctionExpr | Node should have one enclosing callable but has 0. |
|
||||
| test.py:6:5:6:9 | GSSA Variable test1 | Node should have one enclosing callable but has 0. |
|
||||
| test.py:9:1:9:12 | ControlFlowNode for FunctionExpr | Node should have one enclosing callable but has 0. |
|
||||
@@ -87,21 +85,4 @@ postHasUniquePre
|
||||
uniquePostUpdate
|
||||
postIsInSameCallable
|
||||
reverseRead
|
||||
storeIsPostUpdate
|
||||
| test.py:152:9:152:16 | ControlFlowNode for List | Store targets should be PostUpdateNodes. |
|
||||
| test.py:153:9:153:24 | ControlFlowNode for Dict | Store targets should be PostUpdateNodes. |
|
||||
argHasPostUpdate
|
||||
| test.py:25:10:25:10 | ControlFlowNode for t | ArgumentNode is missing PostUpdateNode. |
|
||||
| test.py:29:10:29:10 | ControlFlowNode for t | ArgumentNode is missing PostUpdateNode. |
|
||||
| test.py:48:19:48:21 | ControlFlowNode for arg | ArgumentNode is missing PostUpdateNode. |
|
||||
| test.py:51:10:51:12 | ControlFlowNode for arg | ArgumentNode is missing PostUpdateNode. |
|
||||
| test.py:55:14:55:16 | ControlFlowNode for arg | ArgumentNode is missing PostUpdateNode. |
|
||||
| test.py:59:11:59:11 | ControlFlowNode for t | ArgumentNode is missing PostUpdateNode. |
|
||||
| test.py:67:11:67:14 | ControlFlowNode for cond | ArgumentNode is missing PostUpdateNode. |
|
||||
| test.py:67:17:67:17 | ControlFlowNode for t | ArgumentNode is missing PostUpdateNode. |
|
||||
| test.py:74:11:74:14 | ControlFlowNode for cond | ArgumentNode is missing PostUpdateNode. |
|
||||
| test.py:74:17:74:17 | ControlFlowNode for t | ArgumentNode is missing PostUpdateNode. |
|
||||
| test.py:81:13:81:13 | ControlFlowNode for t | ArgumentNode is missing PostUpdateNode. |
|
||||
| test.py:86:13:86:13 | ControlFlowNode for t | ArgumentNode is missing PostUpdateNode. |
|
||||
| test.py:158:15:158:15 | ControlFlowNode for l | ArgumentNode is missing PostUpdateNode. |
|
||||
| test.py:159:15:159:15 | ControlFlowNode for d | ArgumentNode is missing PostUpdateNode. |
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
| classes.py:620:5:620:16 | SSA variable with_getitem | classes.py:614:15:614:18 | ControlFlowNode for self |
|
||||
| classes.py:637:5:637:16 | SSA variable with_setitem | classes.py:632:15:632:18 | ControlFlowNode for self |
|
||||
| classes.py:654:5:654:16 | SSA variable with_delitem | classes.py:649:15:649:18 | ControlFlowNode for self |
|
||||
| classes.py:735:5:735:12 | SSA variable with_add | classes.py:729:15:729:18 | ControlFlowNode for self |
|
||||
| classes.py:752:5:752:12 | SSA variable with_sub | classes.py:746:15:746:18 | ControlFlowNode for self |
|
||||
| classes.py:769:5:769:12 | SSA variable with_mul | classes.py:763:15:763:18 | ControlFlowNode for self |
|
||||
| classes.py:786:5:786:15 | SSA variable with_matmul | classes.py:780:15:780:18 | ControlFlowNode for self |
|
||||
| classes.py:803:5:803:16 | SSA variable with_truediv | classes.py:797:15:797:18 | ControlFlowNode for self |
|
||||
| classes.py:820:5:820:17 | SSA variable with_floordiv | classes.py:814:15:814:18 | ControlFlowNode for self |
|
||||
| classes.py:837:5:837:12 | SSA variable with_mod | classes.py:831:15:831:18 | ControlFlowNode for self |
|
||||
| classes.py:877:5:877:12 | SSA variable with_pow | classes.py:865:15:865:18 | ControlFlowNode for self |
|
||||
| classes.py:894:5:894:15 | SSA variable with_lshift | classes.py:888:15:888:18 | ControlFlowNode for self |
|
||||
| classes.py:911:5:911:15 | SSA variable with_rshift | classes.py:905:15:905:18 | ControlFlowNode for self |
|
||||
| classes.py:928:5:928:12 | SSA variable with_and | classes.py:922:15:922:18 | ControlFlowNode for self |
|
||||
| classes.py:945:5:945:12 | SSA variable with_xor | classes.py:939:15:939:18 | ControlFlowNode for self |
|
||||
| classes.py:962:5:962:11 | SSA variable with_or | classes.py:956:15:956:18 | ControlFlowNode for self |
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import python
|
||||
import experimental.dataflow.DataFlow
|
||||
|
||||
/**
|
||||
@@ -7,9 +8,10 @@ class ArgumentRoutingConfig extends DataFlow::Configuration {
|
||||
ArgumentRoutingConfig() { this = "ArgumentRoutingConfig" }
|
||||
|
||||
override predicate isSource(DataFlow::Node node) {
|
||||
exists(AssignmentDefinition def |
|
||||
exists(AssignmentDefinition def, DataFlow::DataFlowCall call |
|
||||
def.getVariable() = node.(DataFlow::EssaNode).getVar() and
|
||||
def.getValue().(DataFlow::DataFlowCall).getCallable().getName().matches("With\\_%")
|
||||
def.getValue() = call.getNode() and
|
||||
call.getCallable().getName().matches("With\\_%")
|
||||
) and
|
||||
node.(DataFlow::EssaNode).getVar().getName().matches("with\\_%")
|
||||
}
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
| classes.py:622:18:622:21 | ControlFlowNode for arg2 | classes.py:613:15:613:17 | ControlFlowNode for key |
|
||||
| classes.py:640:18:640:21 | ControlFlowNode for arg2 | classes.py:631:15:631:17 | ControlFlowNode for key |
|
||||
| classes.py:656:22:656:25 | ControlFlowNode for arg2 | classes.py:648:15:648:17 | ControlFlowNode for key |
|
||||
| classes.py:737:16:737:19 | ControlFlowNode for arg2 | classes.py:728:15:728:19 | ControlFlowNode for other |
|
||||
| classes.py:754:16:754:19 | ControlFlowNode for arg2 | classes.py:745:15:745:19 | ControlFlowNode for other |
|
||||
| classes.py:771:16:771:19 | ControlFlowNode for arg2 | classes.py:762:15:762:19 | ControlFlowNode for other |
|
||||
| classes.py:788:19:788:22 | ControlFlowNode for arg2 | classes.py:779:15:779:19 | ControlFlowNode for other |
|
||||
| classes.py:805:20:805:23 | ControlFlowNode for arg2 | classes.py:796:15:796:19 | ControlFlowNode for other |
|
||||
| classes.py:822:22:822:25 | ControlFlowNode for arg2 | classes.py:813:15:813:19 | ControlFlowNode for other |
|
||||
| classes.py:839:16:839:19 | ControlFlowNode for arg2 | classes.py:830:15:830:19 | ControlFlowNode for other |
|
||||
| classes.py:879:17:879:20 | ControlFlowNode for arg2 | classes.py:864:15:864:19 | ControlFlowNode for other |
|
||||
| classes.py:896:20:896:23 | ControlFlowNode for arg2 | classes.py:887:15:887:19 | ControlFlowNode for other |
|
||||
| classes.py:913:20:913:23 | ControlFlowNode for arg2 | classes.py:904:15:904:19 | ControlFlowNode for other |
|
||||
| classes.py:930:16:930:19 | ControlFlowNode for arg2 | classes.py:921:15:921:19 | ControlFlowNode for other |
|
||||
| classes.py:947:16:947:19 | ControlFlowNode for arg2 | classes.py:938:15:938:19 | ControlFlowNode for other |
|
||||
| classes.py:964:15:964:18 | ControlFlowNode for arg2 | classes.py:955:15:955:19 | ControlFlowNode for other |
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import python
|
||||
import experimental.dataflow.DataFlow
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
| classes.py:640:26:640:29 | ControlFlowNode for arg3 | classes.py:630:15:630:19 | ControlFlowNode for value |
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import python
|
||||
import experimental.dataflow.DataFlow
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import python
|
||||
import experimental.dataflow.DataFlow
|
||||
|
||||
/**
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,39 @@
|
||||
| classes.py:32:12:32:31 | ControlFlowNode for Attribute() | classes.py:32:12:32:31 | ControlFlowNode for Attribute() |
|
||||
| classes.py:212:7:212:22 | ControlFlowNode for set() | classes.py:212:7:212:22 | ControlFlowNode for set() |
|
||||
| classes.py:216:7:216:28 | ControlFlowNode for frozenset() | classes.py:216:7:216:28 | ControlFlowNode for frozenset() |
|
||||
| classes.py:220:7:220:26 | ControlFlowNode for dict() | classes.py:220:7:220:26 | ControlFlowNode for dict() |
|
||||
| classes.py:369:27:369:50 | ControlFlowNode for dict() | classes.py:369:27:369:50 | ControlFlowNode for dict() |
|
||||
| classes.py:563:12:563:24 | ControlFlowNode for Attribute() | classes.py:563:12:563:24 | ControlFlowNode for Attribute() |
|
||||
| classes.py:41:16:41:35 | ControlFlowNode for Attribute() | classes.py:41:16:41:35 | ControlFlowNode for Attribute() |
|
||||
| classes.py:264:9:264:24 | ControlFlowNode for set() | classes.py:264:9:264:24 | ControlFlowNode for set() |
|
||||
| classes.py:269:9:269:30 | ControlFlowNode for frozenset() | classes.py:269:9:269:30 | ControlFlowNode for frozenset() |
|
||||
| classes.py:274:9:274:28 | ControlFlowNode for dict() | classes.py:274:9:274:28 | ControlFlowNode for dict() |
|
||||
| classes.py:454:29:454:52 | ControlFlowNode for dict() | classes.py:454:29:454:52 | ControlFlowNode for dict() |
|
||||
| classes.py:622:5:622:16 | ControlFlowNode for with_getitem | classes.py:612:21:612:24 | SSA variable self |
|
||||
| classes.py:622:18:622:21 | ControlFlowNode for arg2 | classes.py:612:27:612:29 | SSA variable key |
|
||||
| classes.py:640:5:640:16 | ControlFlowNode for with_setitem | classes.py:629:21:629:24 | SSA variable self |
|
||||
| classes.py:640:18:640:21 | ControlFlowNode for arg2 | classes.py:629:27:629:29 | SSA variable key |
|
||||
| classes.py:640:26:640:29 | ControlFlowNode for arg3 | classes.py:629:32:629:36 | SSA variable value |
|
||||
| classes.py:656:9:656:20 | ControlFlowNode for with_delitem | classes.py:647:21:647:24 | SSA variable self |
|
||||
| classes.py:656:22:656:25 | ControlFlowNode for arg2 | classes.py:647:27:647:29 | SSA variable key |
|
||||
| classes.py:683:16:683:28 | ControlFlowNode for Attribute() | classes.py:683:16:683:28 | ControlFlowNode for Attribute() |
|
||||
| classes.py:737:5:737:12 | ControlFlowNode for with_add | classes.py:727:17:727:20 | SSA variable self |
|
||||
| classes.py:737:16:737:19 | ControlFlowNode for arg2 | classes.py:727:23:727:27 | SSA variable other |
|
||||
| classes.py:754:5:754:12 | ControlFlowNode for with_sub | classes.py:744:17:744:20 | SSA variable self |
|
||||
| classes.py:754:16:754:19 | ControlFlowNode for arg2 | classes.py:744:23:744:27 | SSA variable other |
|
||||
| classes.py:771:5:771:12 | ControlFlowNode for with_mul | classes.py:761:17:761:20 | SSA variable self |
|
||||
| classes.py:771:16:771:19 | ControlFlowNode for arg2 | classes.py:761:23:761:27 | SSA variable other |
|
||||
| classes.py:788:5:788:15 | ControlFlowNode for with_matmul | classes.py:778:20:778:23 | SSA variable self |
|
||||
| classes.py:788:19:788:22 | ControlFlowNode for arg2 | classes.py:778:26:778:30 | SSA variable other |
|
||||
| classes.py:805:5:805:16 | ControlFlowNode for with_truediv | classes.py:795:21:795:24 | SSA variable self |
|
||||
| classes.py:805:20:805:23 | ControlFlowNode for arg2 | classes.py:795:27:795:31 | SSA variable other |
|
||||
| classes.py:822:5:822:17 | ControlFlowNode for with_floordiv | classes.py:812:22:812:25 | SSA variable self |
|
||||
| classes.py:822:22:822:25 | ControlFlowNode for arg2 | classes.py:812:28:812:32 | SSA variable other |
|
||||
| classes.py:839:5:839:12 | ControlFlowNode for with_mod | classes.py:829:17:829:20 | SSA variable self |
|
||||
| classes.py:839:16:839:19 | ControlFlowNode for arg2 | classes.py:829:23:829:27 | SSA variable other |
|
||||
| classes.py:879:5:879:12 | ControlFlowNode for with_pow | classes.py:863:17:863:20 | SSA variable self |
|
||||
| classes.py:879:17:879:20 | ControlFlowNode for arg2 | classes.py:863:23:863:27 | SSA variable other |
|
||||
| classes.py:896:5:896:15 | ControlFlowNode for with_lshift | classes.py:886:20:886:23 | SSA variable self |
|
||||
| classes.py:896:20:896:23 | ControlFlowNode for arg2 | classes.py:886:26:886:30 | SSA variable other |
|
||||
| classes.py:913:5:913:15 | ControlFlowNode for with_rshift | classes.py:903:20:903:23 | SSA variable self |
|
||||
| classes.py:913:20:913:23 | ControlFlowNode for arg2 | classes.py:903:26:903:30 | SSA variable other |
|
||||
| classes.py:930:5:930:12 | ControlFlowNode for with_and | classes.py:920:17:920:20 | SSA variable self |
|
||||
| classes.py:930:16:930:19 | ControlFlowNode for arg2 | classes.py:920:23:920:27 | SSA variable other |
|
||||
| classes.py:947:5:947:12 | ControlFlowNode for with_xor | classes.py:937:17:937:20 | SSA variable self |
|
||||
| classes.py:947:16:947:19 | ControlFlowNode for arg2 | classes.py:937:23:937:27 | SSA variable other |
|
||||
| classes.py:964:5:964:11 | ControlFlowNode for with_or | classes.py:954:16:954:19 | SSA variable self |
|
||||
| classes.py:964:15:964:18 | ControlFlowNode for arg2 | classes.py:954:22:954:26 | SSA variable other |
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
* @kind path-problem
|
||||
*/
|
||||
|
||||
import python
|
||||
import experimental.dataflow.testConfig
|
||||
import DataFlow::PathGraph
|
||||
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
| test.py:32:5:32:5 | SSA variable x | test.py:31:1:31:33 | Exit node for Function test_tuple_with_local_flow |
|
||||
| test.py:32:5:32:5 | SSA variable x | test.py:33:9:33:9 | ControlFlowNode for x |
|
||||
| test.py:32:10:32:26 | ControlFlowNode for Tuple | test.py:32:5:32:5 | SSA variable x |
|
||||
| test.py:33:5:33:5 | SSA variable y | test.py:34:5:34:11 | SSA variable y |
|
||||
| test.py:33:5:33:5 | SSA variable y | test.py:34:10:34:10 | ControlFlowNode for y |
|
||||
| test.py:33:9:33:12 | ControlFlowNode for Subscript | test.py:33:5:33:5 | SSA variable y |
|
||||
| test.py:34:5:34:11 | SSA variable y | test.py:31:1:31:33 | Exit node for Function test_tuple_with_local_flow |
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
* hope to remove the false positive.
|
||||
*/
|
||||
|
||||
import python
|
||||
import experimental.dataflow.testConfig
|
||||
|
||||
from DataFlow::Node source, DataFlow::Node sink
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
| test.py:0:0:0:0 | SSA variable $ | test.py:0:0:0:0 | Exit node for Module test |
|
||||
| test.py:7:5:7:16 | SSA variable also_tainted | test.py:8:5:8:22 | SSA variable also_tainted |
|
||||
| test.py:7:5:7:16 | SSA variable also_tainted | test.py:8:10:8:21 | ControlFlowNode for also_tainted |
|
||||
| test.py:7:20:7:25 | ControlFlowNode for SOURCE | test.py:7:5:7:16 | SSA variable also_tainted |
|
||||
| test.py:8:5:8:22 | SSA variable also_tainted | test.py:6:1:6:11 | Exit node for Function func |
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
* complex | `42j` (not supported yet)
|
||||
*/
|
||||
|
||||
private import python
|
||||
import experimental.dataflow.DataFlow
|
||||
|
||||
class TestConfiguration extends DataFlow::Configuration {
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
../CallGraph/CallGraphTest.qll
|
||||
@@ -1 +0,0 @@
|
||||
../CallGraph/PointsTo.ql
|
||||
@@ -0,0 +1 @@
|
||||
../CallGraph/PointsTo.ql
|
||||
Reference in New Issue
Block a user