mirror of
https://github.com/github/codeql.git
synced 2025-12-20 10:46:30 +01:00
Python: Factor out prettyPrinter and update tests
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
import python
|
||||
import semmle.python.dataflow.new.DataFlow
|
||||
import TestUtilities.InlineExpectationsTest
|
||||
import experimental.dataflow.TestUtil.PrintNode
|
||||
|
||||
abstract class FlowTest extends InlineExpectationsTest {
|
||||
bindingset[this]
|
||||
@@ -17,7 +18,8 @@ abstract class FlowTest extends InlineExpectationsTest {
|
||||
location = toNode.getLocation() and
|
||||
tag = this.flowTag() and
|
||||
value =
|
||||
"\"" + fromNode.toString() + lineStr(fromNode, toNode) + " -> " + toNode.toString() + "\"" and
|
||||
"\"" + prettyNode(fromNode).replaceAll("\"", "'") + lineStr(fromNode, toNode) + " -> " +
|
||||
prettyNode(toNode).replaceAll("\"", "'") + "\"" and
|
||||
element = toNode.toString()
|
||||
)
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
import python
|
||||
import semmle.python.dataflow.new.DataFlow
|
||||
private import semmle.python.dataflow.new.internal.DataFlowPrivate
|
||||
import FlowTest
|
||||
|
||||
class MaximalFlowTest extends FlowTest {
|
||||
@@ -21,14 +22,21 @@ 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 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()
|
||||
}
|
||||
@@ -1 +1 @@
|
||||
import experimental.dataflow.FlowTestUtil.LocalFlowStepTest
|
||||
import experimental.dataflow.TestUtil.LocalFlowStepTest
|
||||
|
||||
@@ -1 +1 @@
|
||||
import experimental.dataflow.FlowTestUtil.MaximalFlowTest
|
||||
import experimental.dataflow.TestUtil.MaximalFlowTest
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
def obfuscated_id(x): #$ step="ControlFlowNode for FunctionExpr -> GSSA Variable obfuscated_id"
|
||||
y = x #$ step="ControlFlowNode for x -> SSA variable y" step="SSA variable x, l:1 -> ControlFlowNode for x"
|
||||
z = y #$ step="ControlFlowNode for y -> SSA variable z" step="SSA variable y, l:2 -> ControlFlowNode for y"
|
||||
return z #$ flow="ControlFlowNode for IntegerLiteral, l:6 -> ControlFlowNode for z" step="SSA variable z, l:3 -> ControlFlowNode for z"
|
||||
def obfuscated_id(x): #$ step="FunctionExpr -> GSSA Variable obfuscated_id"
|
||||
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:2 -> y"
|
||||
return z #$ flow="42, l:6 -> z" step="SSA variable z, l:3 -> z"
|
||||
|
||||
a = 42 #$ step="ControlFlowNode for IntegerLiteral -> GSSA Variable a"
|
||||
b = obfuscated_id(a) #$ flow="ControlFlowNode for IntegerLiteral, l:6 -> GSSA Variable b" flow="ControlFlowNode for FunctionExpr, l:1 -> ControlFlowNode for obfuscated_id" step="ControlFlowNode for obfuscated_id() -> GSSA Variable b" step="GSSA Variable obfuscated_id, l:1 -> ControlFlowNode for obfuscated_id" step="GSSA Variable a, l:6 -> ControlFlowNode for a"
|
||||
a = 42 #$ step="42 -> GSSA Variable a"
|
||||
b = obfuscated_id(a) #$ flow="42, l:6 -> GSSA Variable b" flow="FunctionExpr, l:1 -> obfuscated_id" step="obfuscated_id(..) -> GSSA Variable b" step="GSSA Variable obfuscated_id, l:1 -> obfuscated_id" step="GSSA Variable a, l:6 -> a"
|
||||
|
||||
@@ -72,14 +72,14 @@ def argument_passing(
|
||||
f,
|
||||
**g,
|
||||
):
|
||||
SINK1(a) #$ arg1="ControlFlowNode for arg1, l:89 -> ControlFlowNode for a" arg1="ControlFlowNode for arg1, l:94 -> ControlFlowNode for a"
|
||||
SINK2(b) #$ arg2="ControlFlowNode for arg2, l:94 -> ControlFlowNode for b" MISSING:arg2="ControlFlowNode for arg2, l:89 -> ControlFlowNode for b"
|
||||
SINK3(c) #$ arg3="ControlFlowNode for arg3, l:94 -> ControlFlowNode for c" MISSING: arg3="ControlFlowNode for arg3, l:89 -> ControlFlowNode for c"
|
||||
SINK4(d) #$ MISSING: arg4="ControlFlowNode for arg4, l:89 -> ControlFlowNode for d"
|
||||
SINK5(e) #$ MISSING: arg5="ControlFlowNode for arg5, l:89 -> ControlFlowNode for e"
|
||||
SINK6(f) #$ MISSING: arg6="ControlFlowNode for arg6, l:89 -> ControlFlowNode for f"
|
||||
SINK1(a) #$ arg1="arg1, l:89 -> a" arg1="arg1, l:94 -> a"
|
||||
SINK2(b) #$ arg2="arg2, l:94 -> b" MISSING:arg2="arg2, l:89 -> b"
|
||||
SINK3(c) #$ arg3="arg3, l:94 -> c" MISSING: arg3="arg3, l:89 -> c"
|
||||
SINK4(d) #$ MISSING: arg4="arg4, l:89 -> d"
|
||||
SINK5(e) #$ MISSING: arg5="arg5, l:89 -> e"
|
||||
SINK6(f) #$ MISSING: arg6="arg6, l:89 -> f"
|
||||
try:
|
||||
SINK7(g["g"]) #$ arg7="ControlFlowNode for arg7, l:89 -> ControlFlowNode for Subscript"
|
||||
SINK7(g["g"]) #$ arg7="arg7, l:89 -> g['g']"
|
||||
except:
|
||||
print("OK")
|
||||
|
||||
@@ -95,8 +95,8 @@ def test_argument_passing2():
|
||||
|
||||
|
||||
def with_pos_only(a, /, b):
|
||||
SINK1(a) #$ arg1="ControlFlowNode for arg1, l:104 -> ControlFlowNode for a" arg1="ControlFlowNode for arg1, l:105 -> ControlFlowNode for a" arg1="ControlFlowNode for arg1, l:106 -> ControlFlowNode for a"
|
||||
SINK2(b) #$ arg2="ControlFlowNode for arg2, l:104 -> ControlFlowNode for b" arg2="ControlFlowNode for arg2, l:105 -> ControlFlowNode for b" MISSING: arg2="ControlFlowNode for arg2, l:106 -> ControlFlowNode for b"
|
||||
SINK1(a) #$ arg1="arg1, l:104 -> a" arg1="arg1, l:105 -> a" arg1="arg1, l:106 -> a"
|
||||
SINK2(b) #$ arg2="arg2, l:104 -> b" arg2="arg2, l:105 -> b" MISSING: arg2="arg2, l:106 -> b"
|
||||
|
||||
|
||||
@expects(6)
|
||||
@@ -107,9 +107,9 @@ def test_pos_only():
|
||||
|
||||
|
||||
def with_multiple_kw_args(a, b, c):
|
||||
SINK1(a) #$ arg1="ControlFlowNode for arg1, l:117 -> ControlFlowNode for a" arg1="ControlFlowNode for arg1, l:118 -> ControlFlowNode for a" arg1="ControlFlowNode for arg1, l:119 -> ControlFlowNode for a" arg1="ControlFlowNode for arg1, l:120 -> ControlFlowNode for a"
|
||||
SINK2(b) #$ arg2="ControlFlowNode for arg2, l:117 -> ControlFlowNode for b" arg2="ControlFlowNode for arg2, l:120 -> ControlFlowNode for b" MISSING: arg2="ControlFlowNode for arg2, l:118 -> ControlFlowNode for b" arg2="ControlFlowNode for arg2, l:119 -> ControlFlowNode for b"
|
||||
SINK3(c) #$ arg3="ControlFlowNode for arg3, l:117 -> ControlFlowNode for c" arg3="ControlFlowNode for arg3, l:119 -> ControlFlowNode for c" arg3="ControlFlowNode for arg3, l:120 -> ControlFlowNode for c" MISSING: arg3="ControlFlowNode for arg3, l:118 -> ControlFlowNode for c"
|
||||
SINK1(a) #$ arg1="arg1, l:117 -> a" arg1="arg1, l:118 -> a" arg1="arg1, l:119 -> a" arg1="arg1, l:120 -> a"
|
||||
SINK2(b) #$ arg2="arg2, l:117 -> b" arg2="arg2, l:120 -> b" MISSING: arg2="arg2, l:118 -> b" arg2="arg2, l:119 -> b"
|
||||
SINK3(c) #$ arg3="arg3, l:117 -> c" arg3="arg3, l:119 -> c" arg3="arg3, l:120 -> c" MISSING: arg3="arg3, l:118 -> c"
|
||||
|
||||
|
||||
@expects(9)
|
||||
@@ -121,9 +121,9 @@ def test_multiple_kw_args():
|
||||
|
||||
|
||||
def with_default_arguments(a=arg1, b=arg2, c=arg3):
|
||||
SINK1(a) #$ arg1="ControlFlowNode for arg1, l:132 -> ControlFlowNode for a" MISSING:arg1="ControlFlowNode for arg1, l:123 -> ControlFlowNode for a"
|
||||
SINK2(b) #$ arg2="ControlFlowNode for arg2, l:133 -> ControlFlowNode for b" MISSING: arg2="ControlFlowNode for arg2, l:123 -> ControlFlowNode for b"
|
||||
SINK3(c) #$ arg3="ControlFlowNode for arg3, l:134 -> ControlFlowNode for c" MISSING: arg3="ControlFlowNode for arg3, l:123 -> ControlFlowNode for c"
|
||||
SINK1(a) #$ arg1="arg1, l:132 -> a" MISSING:arg1="arg1, l:123 -> a"
|
||||
SINK2(b) #$ arg2="arg2, l:133 -> b" MISSING: arg2="arg2, l:123 -> b"
|
||||
SINK3(c) #$ arg3="arg3, l:134 -> c" MISSING: arg3="arg3, l:123 -> c"
|
||||
|
||||
|
||||
@expects(12)
|
||||
@@ -136,14 +136,14 @@ def test_default_arguments():
|
||||
|
||||
# Nested constructor pattern
|
||||
def grab_foo_bar_baz(foo, **kwargs):
|
||||
SINK1(foo) #$ arg1="ControlFlowNode for arg1, l:160 -> ControlFlowNode for foo"
|
||||
SINK1(foo) #$ arg1="arg1, l:160 -> foo"
|
||||
grab_bar_baz(**kwargs)
|
||||
|
||||
|
||||
# It is not possible to pass `bar` into `kwargs`,
|
||||
# since `bar` is a valid keyword argument.
|
||||
def grab_bar_baz(bar, **kwargs):
|
||||
SINK2(bar) #$ arg2="ControlFlowNode for arg2, l:160 -> ControlFlowNode for bar"
|
||||
SINK2(bar) #$ arg2="arg2, l:160 -> bar"
|
||||
try:
|
||||
SINK2_F(kwargs["bar"])
|
||||
except:
|
||||
@@ -152,7 +152,7 @@ def grab_bar_baz(bar, **kwargs):
|
||||
|
||||
|
||||
def grab_baz(baz):
|
||||
SINK3(baz) #$ arg3="ControlFlowNode for arg3, l:160 -> ControlFlowNode for baz"
|
||||
SINK3(baz) #$ arg3="arg3, l:160 -> baz"
|
||||
|
||||
|
||||
@expects(4)
|
||||
@@ -163,14 +163,14 @@ def test_grab():
|
||||
# All combinations
|
||||
def test_pos_pos():
|
||||
def with_pos(a):
|
||||
SINK1(a) #$ arg1="ControlFlowNode for arg1, l:168 -> ControlFlowNode for a"
|
||||
SINK1(a) #$ arg1="arg1, l:168 -> a"
|
||||
|
||||
with_pos(arg1)
|
||||
|
||||
|
||||
def test_pos_pos_only():
|
||||
def with_pos_only(a, /):
|
||||
SINK1(a) #$ arg1="ControlFlowNode for arg1, l:175 -> ControlFlowNode for a"
|
||||
SINK1(a) #$ arg1="arg1, l:175 -> a"
|
||||
|
||||
with_pos_only(arg1)
|
||||
|
||||
@@ -178,34 +178,34 @@ def test_pos_pos_only():
|
||||
def test_pos_star():
|
||||
def with_star(*a):
|
||||
if len(a) > 0:
|
||||
SINK1(a[0]) #$ arg1="ControlFlowNode for arg1, l:183 -> ControlFlowNode for Subscript"
|
||||
SINK1(a[0]) #$ arg1="arg1, l:183 -> a[0]"
|
||||
|
||||
with_star(arg1)
|
||||
|
||||
|
||||
def test_pos_kw():
|
||||
def with_kw(a=""):
|
||||
SINK1(a) #$ arg1="ControlFlowNode for arg1, l:190 -> ControlFlowNode for a"
|
||||
SINK1(a) #$ arg1="arg1, l:190 -> a"
|
||||
|
||||
with_kw(arg1)
|
||||
|
||||
|
||||
def test_kw_pos():
|
||||
def with_pos(a):
|
||||
SINK1(a) #$ arg1="ControlFlowNode for arg1, l:197 -> ControlFlowNode for a"
|
||||
SINK1(a) #$ arg1="arg1, l:197 -> a"
|
||||
|
||||
with_pos(a=arg1)
|
||||
|
||||
|
||||
def test_kw_kw():
|
||||
def with_kw(a=""):
|
||||
SINK1(a) #$ arg1="ControlFlowNode for arg1, l:204 -> ControlFlowNode for a"
|
||||
SINK1(a) #$ arg1="arg1, l:204 -> a"
|
||||
|
||||
with_kw(a=arg1)
|
||||
|
||||
|
||||
def test_kw_doublestar():
|
||||
def with_doublestar(**a):
|
||||
SINK1(a["a"]) #$ arg1="ControlFlowNode for arg1, l:211 -> ControlFlowNode for Subscript"
|
||||
SINK1(a["a"]) #$ arg1="arg1, l:211 -> a['a']"
|
||||
|
||||
with_doublestar(a=arg1)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import python
|
||||
import semmle.python.dataflow.new.DataFlow
|
||||
private import semmle.python.dataflow.new.internal.DataFlowPrivate as DataFlowPrivate
|
||||
import experimental.dataflow.FlowTestUtil.FlowTest
|
||||
import experimental.dataflow.TestUtil.FlowTest
|
||||
|
||||
class Argument1RoutingTest extends FlowTest {
|
||||
Argument1RoutingTest() { this = "Argument1RoutingTest" }
|
||||
|
||||
@@ -553,8 +553,8 @@ def test_length_hint():
|
||||
# object.__getitem__(self, key)
|
||||
class With_getitem:
|
||||
def __getitem__(self, key):
|
||||
SINK2(key) #$ arg2="ControlFlowNode for arg2, l:565 -> ControlFlowNode for key"
|
||||
SINK1(self) #$ arg1="SSA variable with_getitem, l:563 -> ControlFlowNode for self"
|
||||
SINK2(key) #$ arg2="arg2, l:565 -> key"
|
||||
SINK1(self) #$ arg1="SSA variable with_getitem, l:563 -> self"
|
||||
OK()
|
||||
return ""
|
||||
|
||||
@@ -568,9 +568,9 @@ def test_getitem():
|
||||
# object.__setitem__(self, key, value)
|
||||
class With_setitem:
|
||||
def __setitem__(self, key, value):
|
||||
SINK3(value) #$ arg3="ControlFlowNode for arg3, l:581 -> ControlFlowNode for value"
|
||||
SINK2(key) #$ arg2="ControlFlowNode for arg2, l:581 -> ControlFlowNode for key"
|
||||
SINK1(self) #$ arg1="SSA variable with_setitem, l:578 -> ControlFlowNode for self"
|
||||
SINK3(value) #$ arg3="arg3, l:581 -> value"
|
||||
SINK2(key) #$ arg2="arg2, l:581 -> key"
|
||||
SINK1(self) #$ arg1="SSA variable with_setitem, l:578 -> self"
|
||||
OK()
|
||||
|
||||
|
||||
@@ -584,8 +584,8 @@ def test_setitem():
|
||||
# object.__delitem__(self, key)
|
||||
class With_delitem:
|
||||
def __delitem__(self, key):
|
||||
SINK2(key) #$ arg2="ControlFlowNode for arg2, l:595 -> ControlFlowNode for key"
|
||||
SINK1(self) #$ arg1="SSA variable with_delitem, l:593 -> ControlFlowNode for self"
|
||||
SINK2(key) #$ arg2="arg2, l:595 -> key"
|
||||
SINK1(self) #$ arg1="SSA variable with_delitem, l:593 -> self"
|
||||
OK()
|
||||
|
||||
|
||||
@@ -655,8 +655,8 @@ def test_contains():
|
||||
# object.__add__(self, other)
|
||||
class With_add:
|
||||
def __add__(self, other):
|
||||
SINK2(other) #$ arg2="ControlFlowNode for arg2, l:667 -> ControlFlowNode for other"
|
||||
SINK1(self) #$ arg1="SSA variable with_add, l:665 -> ControlFlowNode for self"
|
||||
SINK2(other) #$ arg2="arg2, l:667 -> other"
|
||||
SINK1(self) #$ arg1="SSA variable with_add, l:665 -> self"
|
||||
OK()
|
||||
return self
|
||||
|
||||
@@ -670,8 +670,8 @@ def test_add():
|
||||
# object.__sub__(self, other)
|
||||
class With_sub:
|
||||
def __sub__(self, other):
|
||||
SINK2(other) #$ arg2="ControlFlowNode for arg2, l:682 -> ControlFlowNode for other"
|
||||
SINK1(self) #$ arg1="SSA variable with_sub, l:680 -> ControlFlowNode for self"
|
||||
SINK2(other) #$ arg2="arg2, l:682 -> other"
|
||||
SINK1(self) #$ arg1="SSA variable with_sub, l:680 -> self"
|
||||
OK()
|
||||
return self
|
||||
|
||||
@@ -685,8 +685,8 @@ def test_sub():
|
||||
# object.__mul__(self, other)
|
||||
class With_mul:
|
||||
def __mul__(self, other):
|
||||
SINK2(other) #$ arg2="ControlFlowNode for arg2, l:697 -> ControlFlowNode for other"
|
||||
SINK1(self) #$ arg1="SSA variable with_mul, l:695 -> ControlFlowNode for self"
|
||||
SINK2(other) #$ arg2="arg2, l:697 -> other"
|
||||
SINK1(self) #$ arg1="SSA variable with_mul, l:695 -> self"
|
||||
OK()
|
||||
return self
|
||||
|
||||
@@ -700,8 +700,8 @@ def test_mul():
|
||||
# object.__matmul__(self, other)
|
||||
class With_matmul:
|
||||
def __matmul__(self, other):
|
||||
SINK2(other) #$ arg2="ControlFlowNode for arg2, l:712 -> ControlFlowNode for other"
|
||||
SINK1(self) #$ arg1="SSA variable with_matmul, l:710 -> ControlFlowNode for self"
|
||||
SINK2(other) #$ arg2="arg2, l:712 -> other"
|
||||
SINK1(self) #$ arg1="SSA variable with_matmul, l:710 -> self"
|
||||
OK()
|
||||
return self
|
||||
|
||||
@@ -715,8 +715,8 @@ def test_matmul():
|
||||
# object.__truediv__(self, other)
|
||||
class With_truediv:
|
||||
def __truediv__(self, other):
|
||||
SINK2(other) #$ arg2="ControlFlowNode for arg2, l:727 -> ControlFlowNode for other"
|
||||
SINK1(self) #$ arg1="SSA variable with_truediv, l:725 -> ControlFlowNode for self"
|
||||
SINK2(other) #$ arg2="arg2, l:727 -> other"
|
||||
SINK1(self) #$ arg1="SSA variable with_truediv, l:725 -> self"
|
||||
OK()
|
||||
return self
|
||||
|
||||
@@ -730,8 +730,8 @@ def test_truediv():
|
||||
# object.__floordiv__(self, other)
|
||||
class With_floordiv:
|
||||
def __floordiv__(self, other):
|
||||
SINK2(other) #$ arg2="ControlFlowNode for arg2, l:742 -> ControlFlowNode for other"
|
||||
SINK1(self) #$ arg1="SSA variable with_floordiv, l:740 -> ControlFlowNode for self"
|
||||
SINK2(other) #$ arg2="arg2, l:742 -> other"
|
||||
SINK1(self) #$ arg1="SSA variable with_floordiv, l:740 -> self"
|
||||
OK()
|
||||
return self
|
||||
|
||||
@@ -745,8 +745,8 @@ def test_floordiv():
|
||||
# object.__mod__(self, other)
|
||||
class With_mod:
|
||||
def __mod__(self, other):
|
||||
SINK2(other) #$ arg2="ControlFlowNode for arg2, l:757 -> ControlFlowNode for other"
|
||||
SINK1(self) #$ arg1="SSA variable with_mod, l:755 -> ControlFlowNode for self"
|
||||
SINK2(other) #$ arg2="arg2, l:757 -> other"
|
||||
SINK1(self) #$ arg1="SSA variable with_mod, l:755 -> self"
|
||||
OK()
|
||||
return self
|
||||
|
||||
@@ -775,8 +775,8 @@ def test_divmod():
|
||||
# object.__pow__(self, other[, modulo])
|
||||
class With_pow:
|
||||
def __pow__(self, other):
|
||||
SINK2(other) #$ arg2="ControlFlowNode for arg2, l:793 -> ControlFlowNode for other"
|
||||
SINK1(self) #$ arg1="SSA variable with_pow, l:791 -> ControlFlowNode for self"
|
||||
SINK2(other) #$ arg2="arg2, l:793 -> other"
|
||||
SINK1(self) #$ arg1="SSA variable with_pow, l:791 -> self"
|
||||
OK()
|
||||
return self
|
||||
|
||||
@@ -796,8 +796,8 @@ def test_pow_op():
|
||||
# object.__lshift__(self, other)
|
||||
class With_lshift:
|
||||
def __lshift__(self, other):
|
||||
SINK2(other) #$ arg2="ControlFlowNode for arg2, l:808 -> ControlFlowNode for other"
|
||||
SINK1(self) #$ arg1="SSA variable with_lshift, l:806 -> ControlFlowNode for self"
|
||||
SINK2(other) #$ arg2="arg2, l:808 -> other"
|
||||
SINK1(self) #$ arg1="SSA variable with_lshift, l:806 -> self"
|
||||
OK()
|
||||
return self
|
||||
|
||||
@@ -811,8 +811,8 @@ def test_lshift():
|
||||
# object.__rshift__(self, other)
|
||||
class With_rshift:
|
||||
def __rshift__(self, other):
|
||||
SINK2(other) #$ arg2="ControlFlowNode for arg2, l:823 -> ControlFlowNode for other"
|
||||
SINK1(self) #$ arg1="SSA variable with_rshift, l:821 -> ControlFlowNode for self"
|
||||
SINK2(other) #$ arg2="arg2, l:823 -> other"
|
||||
SINK1(self) #$ arg1="SSA variable with_rshift, l:821 -> self"
|
||||
OK()
|
||||
return self
|
||||
|
||||
@@ -826,8 +826,8 @@ def test_rshift():
|
||||
# object.__and__(self, other)
|
||||
class With_and:
|
||||
def __and__(self, other):
|
||||
SINK2(other) #$ arg2="ControlFlowNode for arg2, l:838 -> ControlFlowNode for other"
|
||||
SINK1(self) #$ arg1="SSA variable with_and, l:836 -> ControlFlowNode for self"
|
||||
SINK2(other) #$ arg2="arg2, l:838 -> other"
|
||||
SINK1(self) #$ arg1="SSA variable with_and, l:836 -> self"
|
||||
OK()
|
||||
return self
|
||||
|
||||
@@ -841,8 +841,8 @@ def test_and():
|
||||
# object.__xor__(self, other)
|
||||
class With_xor:
|
||||
def __xor__(self, other):
|
||||
SINK2(other) #$ arg2="ControlFlowNode for arg2, l:853 -> ControlFlowNode for other"
|
||||
SINK1(self) #$ arg1="SSA variable with_xor, l:851 -> ControlFlowNode for self"
|
||||
SINK2(other) #$ arg2="arg2, l:853 -> other"
|
||||
SINK1(self) #$ arg1="SSA variable with_xor, l:851 -> self"
|
||||
OK()
|
||||
return self
|
||||
|
||||
@@ -856,8 +856,8 @@ def test_xor():
|
||||
# object.__or__(self, other)
|
||||
class With_or:
|
||||
def __or__(self, other):
|
||||
SINK2(other) #$ arg2="ControlFlowNode for arg2, l:868 -> ControlFlowNode for other"
|
||||
SINK1(self) #$ arg1="SSA variable with_or, l:866 -> ControlFlowNode for self"
|
||||
SINK2(other) #$ arg2="arg2, l:868 -> other"
|
||||
SINK1(self) #$ arg1="SSA variable with_or, l:866 -> self"
|
||||
OK()
|
||||
return self
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import python
|
||||
import experimental.dataflow.FlowTestUtil.FlowTest
|
||||
import experimental.dataflow.TestUtil.FlowTest
|
||||
import experimental.dataflow.testConfig
|
||||
|
||||
class DataFlowTest extends FlowTest {
|
||||
|
||||
@@ -35,7 +35,7 @@ def SINK_F(x):
|
||||
def f(a, b):
|
||||
return a
|
||||
|
||||
SINK(f(SOURCE, 3)) #$ flow="ControlFlowNode for SOURCE -> ControlFlowNode for f()" flow="ControlFlowNode for Str, l:13 -> ControlFlowNode for f()"
|
||||
SINK(f(SOURCE, 3)) #$ flow="SOURCE -> f(..)" flow="'source', l:13 -> 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)) #$ flow="ControlFlowNode for SOURCE -> ControlFlowNode for Attribute()" flow="ControlFlowNode for SOURCE, l:38 -> ControlFlowNode for Attribute()" flow="ControlFlowNode for Str, l:13 -> ControlFlowNode for Attribute()"
|
||||
SINK(C.method(c, SOURCE, C)) #$ flow="ControlFlowNode for SOURCE -> ControlFlowNode for Attribute()" flow="ControlFlowNode for SOURCE, l:38 -> ControlFlowNode for Attribute()" flow="ControlFlowNode for SOURCE, l:71 -> ControlFlowNode for Attribute()" flow="ControlFlowNode for Str, l:13 -> ControlFlowNode for Attribute()"
|
||||
SINK(func_obj(c, SOURCE, C))
|
||||
SINK(c.method(SOURCE, C)) #$ flow="SOURCE -> c.method(..)" flow="SOURCE, l:38 -> c.method(..)" flow="'source', l:13 -> c.method(..)"
|
||||
SINK(C.method(c, SOURCE, C)) #$ flow="SOURCE -> C.method(..)" flow="SOURCE, l:38 -> C.method(..)" flow="SOURCE, l:71 -> C.method(..)" flow="'source', l:13 -> C.method(..)"
|
||||
SINK(func_obj(c, SOURCE, C)) #$ MISSING: flow="SOURCE -> func_obj(..)" flow="SOURCE, l:38 -> func_obj(..)" flow="SOURCE, l:71 -> func_obj(..)" flow="SOURCE, l:72 -> func_obj(..)" flow="'source', l:13 -> 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)) #$ flow="ControlFlowNode for SOURCE -> ControlFlowNode for Attribute()" flow="ControlFlowNode for SOURCE, l:38 -> ControlFlowNode for Attribute()" flow="ControlFlowNode for SOURCE, l:71 -> ControlFlowNode for Attribute()" flow="ControlFlowNode for SOURCE, l:72 -> ControlFlowNode for Attribute()" flow="ControlFlowNode for SOURCE, l:73 -> ControlFlowNode for Attribute()" flow="ControlFlowNode for Str, l:13 -> ControlFlowNode for Attribute()"
|
||||
SINK(C.classmethod(SOURCE)) #$ flow="ControlFlowNode for SOURCE -> ControlFlowNode for Attribute()" flow="ControlFlowNode for SOURCE, l:38 -> ControlFlowNode for Attribute()" flow="ControlFlowNode for SOURCE, l:71 -> ControlFlowNode for Attribute()" flow="ControlFlowNode for SOURCE, l:72 -> ControlFlowNode for Attribute()" flow="ControlFlowNode for SOURCE, l:73 -> ControlFlowNode for Attribute()" flow="ControlFlowNode for SOURCE, l:80 -> ControlFlowNode for Attribute()" flow="ControlFlowNode for Str, l:13 -> ControlFlowNode for Attribute()"
|
||||
SINK(c_func_obj(C, SOURCE))
|
||||
SINK(c.classmethod(SOURCE)) #$ flow="SOURCE -> c.classmethod(..)" flow="SOURCE, l:38 -> c.classmethod(..)" flow="SOURCE, l:71 -> c.classmethod(..)" flow="SOURCE, l:72 -> c.classmethod(..)" flow="SOURCE, l:73 -> c.classmethod(..)" flow="'source', l:13 -> c.classmethod(..)"
|
||||
SINK(C.classmethod(SOURCE)) #$ flow="SOURCE -> C.classmethod(..)" flow="SOURCE, l:38 -> C.classmethod(..)" flow="SOURCE, l:71 -> C.classmethod(..)" flow="SOURCE, l:72 -> C.classmethod(..)" flow="SOURCE, l:73 -> C.classmethod(..)" flow="SOURCE, l:80 -> C.classmethod(..)" flow="'source', l:13 -> C.classmethod(..)"
|
||||
SINK(c_func_obj(C, SOURCE)) #$ MISSING: flow="SOURCE -> c_func_obj(..)" flow="SOURCE, l:38 -> c_func_obj(..)" flow="SOURCE, l:71 -> c_func_obj(..)" flow="SOURCE, l:72 -> c_func_obj(..)" flow="SOURCE, l:73 -> c_func_obj(..)" flow="SOURCE, l:80 -> c_func_obj(..)" flow="SOURCE, l:81 -> c_func_obj(..)" flow="'source', l:13 -> 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.
|
||||
@@ -156,4 +156,4 @@ customized = Customized()
|
||||
SINK(Customized.a)
|
||||
SINK_F(Customized.b)
|
||||
SINK(customized.a)
|
||||
SINK(customized.b) #$ flow="ControlFlowNode for SOURCE, l:152 -> ControlFlowNode for Attribute" flow="ControlFlowNode for Str, l:13 -> ControlFlowNode for Attribute"
|
||||
SINK(customized.b) #$ flow="SOURCE, l:152 -> customized.b" flow="'source', l:13 -> customized.b"
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
import experimental.dataflow.FlowTestUtil.MaximalFlowTest
|
||||
@@ -41,7 +41,7 @@ def SINK_F(x):
|
||||
def test_tuple_with_local_flow():
|
||||
x = (NONSOURCE, SOURCE)
|
||||
y = x[1]
|
||||
SINK(y) #$ flow="ControlFlowNode for SOURCE, l:42 -> ControlFlowNode for y" flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for y"
|
||||
SINK(y) #$ flow="SOURCE, l:42 -> y" flow="'source', l:20 -> 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) #$ flow="ControlFlowNode for SOURCE, l:55 -> ControlFlowNode for x" flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for x"
|
||||
SINK(x) #$ flow="SOURCE, l:55 -> x" flow="'source', l:20 -> x"
|
||||
|
||||
|
||||
# 6.2.2. Literals
|
||||
def test_string_literal():
|
||||
x = "source"
|
||||
SINK(x) #$ flow="ControlFlowNode for Str, l:61 -> ControlFlowNode for x"
|
||||
SINK(x) #$ flow="'source', l:61 -> x"
|
||||
|
||||
|
||||
def test_bytes_literal():
|
||||
x = b"source"
|
||||
SINK(x) #$ flow="ControlFlowNode for Str, l:66 -> ControlFlowNode for x"
|
||||
SINK(x) #$ flow="b'source', l:66 -> x"
|
||||
|
||||
|
||||
def test_integer_literal():
|
||||
x = 42
|
||||
SINK(x) #$ flow="ControlFlowNode for IntegerLiteral, l:71 -> ControlFlowNode for x"
|
||||
SINK(x) #$ flow="42, l:71 -> x"
|
||||
|
||||
|
||||
def test_floatnumber_literal():
|
||||
x = 42.0
|
||||
SINK(x) #$ flow="ControlFlowNode for FloatLiteral, l:76 -> ControlFlowNode for x"
|
||||
SINK(x) #$ flow="42.0, l:76 -> x"
|
||||
|
||||
|
||||
def test_imagnumber_literal():
|
||||
x = 42j
|
||||
SINK(x) #$ MISSING:flow="ControlFlowNode for FloatLiteral, l:81 -> ControlFlowNode for x"
|
||||
SINK(x) #$ MISSING:flow="42j, l:81 -> x"
|
||||
|
||||
|
||||
# 6.2.3. Parenthesized forms
|
||||
def test_parenthesized_form():
|
||||
x = (SOURCE)
|
||||
SINK(x) #$ flow="ControlFlowNode for SOURCE, l:87 -> ControlFlowNode for x" flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for x"
|
||||
SINK(x) #$ flow="SOURCE, l:87 -> x" flow="'source', l:20 -> x"
|
||||
|
||||
|
||||
# 6.2.5. List displays
|
||||
def test_list_display():
|
||||
x = [SOURCE]
|
||||
SINK(x[0]) #$ flow="ControlFlowNode for SOURCE, l:93 -> ControlFlowNode for Subscript" flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for Subscript"
|
||||
SINK(x[0]) #$ flow="SOURCE, l:93 -> x[0]" flow="'source', l:20 -> x[0]"
|
||||
|
||||
|
||||
def test_list_display_negative():
|
||||
@@ -101,109 +101,109 @@ def test_list_display_negative():
|
||||
|
||||
def test_list_comprehension():
|
||||
x = [SOURCE for y in [NONSOURCE]]
|
||||
SINK(x[0]) #$ flow="ControlFlowNode for SOURCE, l:103 -> ControlFlowNode for Subscript" flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for Subscript"
|
||||
SINK(x[0]) #$ flow="SOURCE, l:103 -> x[0]" flow="'source', l:20 -> x[0]"
|
||||
|
||||
|
||||
def test_list_comprehension_flow():
|
||||
x = [y for y in [SOURCE]]
|
||||
SINK(x[0]) #$ flow="ControlFlowNode for SOURCE, l:108 -> ControlFlowNode for Subscript" flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for Subscript"
|
||||
SINK(x[0]) #$ flow="SOURCE, l:108 -> x[0]" flow="'source', l:20 -> x[0]"
|
||||
|
||||
|
||||
def test_list_comprehension_inflow():
|
||||
l = [SOURCE]
|
||||
x = [y for y in l]
|
||||
SINK(x[0]) #$ flow="ControlFlowNode for SOURCE, l:113 -> ControlFlowNode for Subscript" flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for Subscript"
|
||||
SINK(x[0]) #$ flow="SOURCE, l:113 -> x[0]" flow="'source', l:20 -> x[0]"
|
||||
|
||||
|
||||
def test_nested_list_display():
|
||||
x = [*[SOURCE]]
|
||||
SINK(x[0]) #$ MISSING:flow="ControlFlowNode for SOURCE, l:119 -> ControlFlowNode for Subscript" MISSING:flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for Subscript"
|
||||
SINK(x[0]) #$ MISSING:flow="SOURCE, l:119 -> x[0]" MISSING:flow="'source', l:20 -> x[0]"
|
||||
|
||||
|
||||
# 6.2.6. Set displays
|
||||
def test_set_display():
|
||||
x = {SOURCE}
|
||||
SINK(x.pop()) #$ flow="ControlFlowNode for SOURCE, l:125 -> ControlFlowNode for Attribute()" flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for Attribute()"
|
||||
SINK(x.pop()) #$ flow="SOURCE, l:125 -> x.pop()" flow="'source', l:20 -> x.pop()"
|
||||
|
||||
|
||||
def test_set_comprehension():
|
||||
x = {SOURCE for y in [NONSOURCE]}
|
||||
SINK(x.pop()) #$ flow="ControlFlowNode for SOURCE, l:130 -> ControlFlowNode for Attribute()" flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for Attribute()"
|
||||
SINK(x.pop()) #$ flow="SOURCE, l:130 -> x.pop()" flow="'source', l:20 -> x.pop()"
|
||||
|
||||
|
||||
def test_set_comprehension_flow():
|
||||
x = {y for y in [SOURCE]}
|
||||
SINK(x.pop()) #$ flow="ControlFlowNode for SOURCE, l:135 -> ControlFlowNode for Attribute()" flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for Attribute()"
|
||||
SINK(x.pop()) #$ flow="SOURCE, l:135 -> x.pop()" flow="'source', l:20 -> x.pop()"
|
||||
|
||||
|
||||
def test_set_comprehension_inflow():
|
||||
l = {SOURCE}
|
||||
x = {y for y in l}
|
||||
SINK(x.pop()) #$ flow="ControlFlowNode for SOURCE, l:140 -> ControlFlowNode for Attribute()" flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for Attribute()"
|
||||
SINK(x.pop()) #$ flow="SOURCE, l:140 -> x.pop()" flow="'source', l:20 -> x.pop()"
|
||||
|
||||
|
||||
def test_nested_set_display():
|
||||
x = {*{SOURCE}}
|
||||
SINK(x.pop()) #$ MISSING:flow="ControlFlowNode for SOURCE, l:146 -> ControlFlowNode for Attribute()" MISSING:flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for Attribute()"
|
||||
SINK(x.pop()) #$ MISSING:flow="SOURCE, l:146 -> x.pop()" MISSING:flow="'source', l:20 -> x.pop()"
|
||||
|
||||
|
||||
# 6.2.7. Dictionary displays
|
||||
def test_dict_display():
|
||||
x = {"s": SOURCE}
|
||||
SINK(x["s"]) #$ flow="ControlFlowNode for SOURCE, l:152 -> ControlFlowNode for Subscript" flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for Subscript"
|
||||
SINK(x["s"]) #$ flow="SOURCE, l:152 -> x['s']" flow="'source', l:20 -> x['s']"
|
||||
|
||||
|
||||
def test_dict_display_pop():
|
||||
x = {"s": SOURCE}
|
||||
SINK(x.pop("s")) #$ flow="ControlFlowNode for SOURCE, l:157 -> ControlFlowNode for Attribute()" flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for Attribute()"
|
||||
SINK(x.pop("s")) #$ flow="SOURCE, l:157 -> x.pop(..)" flow="'source', l:20 -> x.pop(..)"
|
||||
|
||||
|
||||
def test_dict_comprehension():
|
||||
x = {y: SOURCE for y in ["s"]}
|
||||
SINK(x["s"]) #$ MISSING:flow="ControlFlowNode for SOURCE, l:152 -> ControlFlowNode for Subscript" MISING:flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for Subscript"
|
||||
SINK(x["s"]) #$ MISSING:flow="SOURCE, l:152 -> x['s']" MISING:flow="'source', l:20 -> x['s']"
|
||||
|
||||
|
||||
def test_dict_comprehension_pop():
|
||||
x = {y: SOURCE for y in ["s"]}
|
||||
SINK(x.pop("s")) #$ MISSING:flow="ControlFlowNode for SOURCE, l:167 -> ControlFlowNode for Attribute()" MISSING:flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for Attribute()"
|
||||
SINK(x.pop("s")) #$ MISSING:flow="SOURCE, l:167 -> x.pop()" MISSING:flow="'source', l:20 -> x.pop()"
|
||||
|
||||
|
||||
def test_nested_dict_display():
|
||||
x = {**{"s": SOURCE}}
|
||||
SINK(x["s"]) #$ MISSING:flow="ControlFlowNode for SOURCE, l:172 -> ControlFlowNode for Subscript" MISING:flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for Subscript"
|
||||
SINK(x["s"]) #$ MISSING:flow="SOURCE, l:172 -> x['s']" MISING:flow="'source', l:20 -> x['s']"
|
||||
|
||||
|
||||
def test_nested_dict_display_pop():
|
||||
x = {**{"s": SOURCE}}
|
||||
SINK(x.pop("s")) #$ MISSING:flow="ControlFlowNode for SOURCE, l:177 -> ControlFlowNode for Attribute()" MISSING:flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for Attribute()"
|
||||
SINK(x.pop("s")) #$ MISSING:flow="SOURCE, l:177 -> x.pop()" MISSING:flow="'source', l:20 -> x.pop()"
|
||||
|
||||
|
||||
# Nested comprehensions
|
||||
def test_nested_comprehension():
|
||||
x = [y for z in [[SOURCE]] for y in z]
|
||||
SINK(x[0]) #$ flow="ControlFlowNode for SOURCE, l:183 -> ControlFlowNode for Subscript" flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for Subscript"
|
||||
SINK(x[0]) #$ flow="SOURCE, l:183 -> x[0]" flow="'source', l:20 -> 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]) #$ flow="ControlFlowNode for SOURCE, l:188 -> ControlFlowNode for Subscript" flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for Subscript"
|
||||
SINK(x[0]) #$ flow="SOURCE, l:188 -> x[0]" flow="'source', l:20 -> 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]) #$ MISSING:flow="ControlFlowNode for SOURCE, l:193 -> ControlFlowNode for Subscript" MISING:flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for Subscript"
|
||||
SINK(x[0]) #$ MISSING:flow="SOURCE, l:193 -> x[0]" MISING:flow="'source', l:20 -> x[0]"
|
||||
|
||||
|
||||
def test_nested_comprehension_paren():
|
||||
x = [y for y in (z for z in [SOURCE])]
|
||||
SINK(x[0]) #$ flow="ControlFlowNode for SOURCE, l:199 -> ControlFlowNode for Subscript" flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for Subscript"
|
||||
SINK(x[0]) #$ flow="SOURCE, l:199 -> x[0]" flow="'source', l:20 -> x[0]"
|
||||
|
||||
|
||||
# 6.2.8. Generator expressions
|
||||
def test_generator():
|
||||
x = (SOURCE for y in [NONSOURCE])
|
||||
SINK([*x][0]) #$ MISSING:flow="ControlFlowNode for SOURCE, l:205 -> ControlFlowNode for Subscript" MISING:flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for Subscript"
|
||||
SINK([*x][0]) #$ MISSING:flow="SOURCE, l:205 -> List[0]" MISING:flow="'source', l:20 -> List[0]"
|
||||
|
||||
|
||||
# 6.2.9. Yield expressions
|
||||
@@ -213,7 +213,7 @@ def gen(x):
|
||||
|
||||
def test_yield():
|
||||
g = gen(SOURCE)
|
||||
SINK(next(g)) #$ MISSING:flow="ControlFlowNode for SOURCE, l:215 -> ControlFlowNode for next()" MISING:flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for next()"
|
||||
SINK(next(g)) #$ MISSING:flow="SOURCE, l:215 -> next()" MISING:flow="'source', l:20 -> next()"
|
||||
|
||||
|
||||
def gen_from(x):
|
||||
@@ -222,19 +222,19 @@ def gen_from(x):
|
||||
|
||||
def test_yield_from():
|
||||
g = gen_from(SOURCE)
|
||||
SINK(next(g)) #$ MISSING:flow="ControlFlowNode for SOURCE, l:224 -> ControlFlowNode for next()" MISING:flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for next()"
|
||||
SINK(next(g)) #$ MISSING:flow="SOURCE, l:224 -> next()" MISING:flow="'source', l:20 -> next()"
|
||||
|
||||
|
||||
# a statement rather than an expression, but related to generators
|
||||
def test_for():
|
||||
for x in gen(SOURCE):
|
||||
SINK(x) #$ MISSING:flow="ControlFlowNode for SOURCE, l:230 -> ControlFlowNode for x" MISING:flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for x"
|
||||
SINK(x) #$ MISSING:flow="SOURCE, l:230 -> x" MISING:flow="'source', l:20 -> x"
|
||||
|
||||
|
||||
# 6.2.9.1. Generator-iterator methods
|
||||
def test___next__():
|
||||
g = gen(SOURCE)
|
||||
SINK(g.__next__()) #$ MISSING:flow="ControlFlowNode for SOURCE, l:236 -> ControlFlowNode for Attribute()" MISSING:flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for Attribute()"
|
||||
SINK(g.__next__()) #$ MISSING:flow="SOURCE, l:236 -> g.__next__()" MISSING:flow="'source', l:20 -> g.__next__()"
|
||||
|
||||
|
||||
def gen2(x):
|
||||
@@ -246,7 +246,7 @@ def gen2(x):
|
||||
def test_send():
|
||||
g = gen2(NONSOURCE)
|
||||
n = next(g)
|
||||
SINK(g.send(SOURCE)) #$ MISSING:flow="ControlFlowNode for SOURCE -> ControlFlowNode for Attribute()" MISSING:flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for Attribute()"
|
||||
SINK(g.send(SOURCE)) #$ MISSING:flow="SOURCE -> g.send()" MISSING:flow="'source', l:20 -> g.send()"
|
||||
|
||||
|
||||
def gen_ex(x):
|
||||
@@ -259,7 +259,7 @@ def gen_ex(x):
|
||||
def test_throw():
|
||||
g = gen_ex(SOURCE)
|
||||
n = next(g)
|
||||
SINK(g.throw(TypeError)) #$ MISSING:flow="ControlFlowNode for SOURCE, l:260 -> ControlFlowNode for Attribute()" MISSING:flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for Attribute()"
|
||||
SINK(g.throw(TypeError)) #$ MISSING:flow="SOURCE, l:260 -> g.throw()" MISSING:flow="'source', l:20 -> g.throw()"
|
||||
|
||||
|
||||
# no `test_close` as `close` involves no data flow
|
||||
@@ -280,7 +280,7 @@ def runa(a):
|
||||
|
||||
async def atest___anext__():
|
||||
g = agen(SOURCE)
|
||||
SINK(await g.__anext__()) #$ MISSING:flow="ControlFlowNode for SOURCE, l:282 -> ControlFlowNode for Attribute()" MISSING:flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for Attribute()"
|
||||
SINK(await g.__anext__()) #$ MISSING:flow="SOURCE, l:282 -> g.__anext__()" MISSING:flow="'source', l:20 -> g.__anext__()"
|
||||
|
||||
|
||||
def test___anext__():
|
||||
@@ -296,7 +296,7 @@ async def agen2(x):
|
||||
async def atest_asend():
|
||||
g = agen2(NONSOURCE)
|
||||
n = await g.__anext__()
|
||||
SINK(await g.asend(SOURCE)) #$ MISSING:flow="ControlFlowNode for SOURCE -> ControlFlowNode for Attribute()" MISSING:flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for Attribute()"
|
||||
SINK(await g.asend(SOURCE)) #$ MISSING:flow="SOURCE -> g.asend()" MISSING:flow="'source', l:20 -> g.asend()"
|
||||
|
||||
|
||||
def test_asend():
|
||||
@@ -313,7 +313,7 @@ async def agen_ex(x):
|
||||
async def atest_athrow():
|
||||
g = agen_ex(SOURCE)
|
||||
n = await g.__anext__()
|
||||
SINK(await g.athrow(TypeError)) #$ MISSING:flow="ControlFlowNode for SOURCE, l:314 -> ControlFlowNode for Attribute()" MISSING:flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for Attribute()"
|
||||
SINK(await g.athrow(TypeError)) #$ MISSING:flow="SOURCE, l:314 -> g.athrow()" MISSING:flow="'source', l:20 -> g.athrow()"
|
||||
|
||||
|
||||
def test_athrow():
|
||||
@@ -326,22 +326,22 @@ class C:
|
||||
|
||||
|
||||
def test_attribute_reference():
|
||||
SINK(C.a) #$ MISSING:flow="ControlFlowNode for SOURCE, l:325 -> ControlFlowNode for Attribute" MISSING:flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for Attribute"
|
||||
SINK(C.a) #$ MISSING:flow="SOURCE, l:325 -> C.a" MISSING:flow="'source', l:20 -> C.a"
|
||||
|
||||
|
||||
# overriding __getattr__ should be tested by the class coverage tests
|
||||
|
||||
# 6.3.2. Subscriptions
|
||||
def test_subscription_tuple():
|
||||
SINK((SOURCE,)[0]) #$ flow="ControlFlowNode for SOURCE -> ControlFlowNode for Subscript" flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for Subscript"
|
||||
SINK((SOURCE,)[0]) #$ flow="SOURCE -> Tuple[0]" flow="'source', l:20 -> Tuple[0]"
|
||||
|
||||
|
||||
def test_subscription_list():
|
||||
SINK([SOURCE][0]) #$ flow="ControlFlowNode for SOURCE -> ControlFlowNode for Subscript" flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for Subscript"
|
||||
SINK([SOURCE][0]) #$ flow="SOURCE -> List[0]" flow="'source', l:20 -> List[0]"
|
||||
|
||||
|
||||
def test_subscription_mapping():
|
||||
SINK({"s": SOURCE}["s"]) #$ flow="ControlFlowNode for SOURCE -> ControlFlowNode for Subscript" flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for Subscript"
|
||||
SINK({"s": SOURCE}["s"]) #$ flow="SOURCE -> Dict['s']" flow="'source', l:20 -> Dict['s']"
|
||||
|
||||
|
||||
# overriding __getitem__ should be tested by the class coverage tests
|
||||
@@ -353,7 +353,7 @@ l = [SOURCE]
|
||||
|
||||
def test_slicing():
|
||||
s = l[0:1:1]
|
||||
SINK(s[0]) #$ MISSING:flow="ControlFlowNode for SOURCE -> ControlFlowNode for Subscript" MISSING:flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for Subscript"
|
||||
SINK(s[0]) #$ MISSING:flow="SOURCE -> s[0]" MISSING:flow="'source', l:20 -> s[0]"
|
||||
|
||||
|
||||
# The grammar seems to allow `l[0:1:1, 0:1]`, but the interpreter does not like it
|
||||
@@ -364,7 +364,7 @@ def second(a, b):
|
||||
|
||||
|
||||
def test_call_positional():
|
||||
SINK(second(NONSOURCE, SOURCE)) #$ flow="ControlFlowNode for SOURCE -> ControlFlowNode for second()" flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for second()"
|
||||
SINK(second(NONSOURCE, SOURCE)) #$ flow="SOURCE -> second(..)" flow="'source', l:20 -> second(..)"
|
||||
|
||||
|
||||
def test_call_positional_negative():
|
||||
@@ -372,15 +372,15 @@ def test_call_positional_negative():
|
||||
|
||||
|
||||
def test_call_keyword():
|
||||
SINK(second(NONSOURCE, b=SOURCE)) #$ flow="ControlFlowNode for SOURCE -> ControlFlowNode for second()" flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for second()"
|
||||
SINK(second(NONSOURCE, b=SOURCE)) #$ flow="SOURCE -> second(..)" flow="'source', l:20 -> second(..)"
|
||||
|
||||
|
||||
def test_call_unpack_iterable():
|
||||
SINK(second(NONSOURCE, *[SOURCE])) #$ MISSING:flow="ControlFlowNode for SOURCE -> ControlFlowNode for second()" MISING:flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for second()"
|
||||
SINK(second(NONSOURCE, *[SOURCE])) #$ MISSING:flow="SOURCE -> second(..)" MISING:flow="'source', l:20 -> second(..)"
|
||||
|
||||
|
||||
def test_call_unpack_mapping():
|
||||
SINK(second(NONSOURCE, **{"b": SOURCE})) #$ flow="ControlFlowNode for SOURCE -> ControlFlowNode for second()" flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for second()"
|
||||
SINK(second(NONSOURCE, **{"b": SOURCE})) #$ flow="SOURCE -> second(..)" flow="'source', l:20 -> second(..)"
|
||||
|
||||
|
||||
def f_extra_pos(a, *b):
|
||||
@@ -388,7 +388,7 @@ def f_extra_pos(a, *b):
|
||||
|
||||
|
||||
def test_call_extra_pos():
|
||||
SINK(f_extra_pos(NONSOURCE, SOURCE)) #$ flow="ControlFlowNode for SOURCE -> ControlFlowNode for f_extra_pos()" flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for f_extra_pos()"
|
||||
SINK(f_extra_pos(NONSOURCE, SOURCE)) #$ flow="SOURCE -> f_extra_pos(..)" flow="'source', l:20 -> f_extra_pos(..)"
|
||||
|
||||
|
||||
def f_extra_keyword(a, **b):
|
||||
@@ -396,7 +396,7 @@ def f_extra_keyword(a, **b):
|
||||
|
||||
|
||||
def test_call_extra_keyword():
|
||||
SINK(f_extra_keyword(NONSOURCE, b=SOURCE)) #$ flow="ControlFlowNode for SOURCE -> ControlFlowNode for f_extra_keyword()" flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for f_extra_keyword()"
|
||||
SINK(f_extra_keyword(NONSOURCE, b=SOURCE)) #$ flow="SOURCE -> f_extra_keyword(..)" flow="'source', l:20 -> f_extra_keyword(..)"
|
||||
|
||||
|
||||
# return the name of the first extra keyword argument
|
||||
@@ -406,18 +406,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})) #$ MISSING:flow="ControlFlowNode for SOURCE -> ControlFlowNode for f_extra_keyword()" MISSING:flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for f_extra_keyword()"
|
||||
SINK(f_extra_keyword_flow(**{SOURCE: None})) #$ MISSING:flow="SOURCE -> f_extra_keyword(..)" MISSING:flow="'source', l:20 -> f_extra_keyword(..)"
|
||||
|
||||
|
||||
# 6.12. Assignment expressions
|
||||
def test_assignment_expression():
|
||||
x = NONSOURCE
|
||||
SINK(x := SOURCE) #$ MISSING:flow="ControlFlowNode for SOURCE -> ControlFlowNode for x" MISSING:flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for x"
|
||||
SINK(x := SOURCE) #$ MISSING:flow="SOURCE -> x" MISSING:flow="'source', l:20 -> x"
|
||||
|
||||
|
||||
# 6.13. Conditional expressions
|
||||
def test_conditional_true():
|
||||
SINK(SOURCE if True else NONSOURCE) #$ flow="ControlFlowNode for SOURCE -> ControlFlowNode for IfExp" flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for IfExp"
|
||||
SINK(SOURCE if True else NONSOURCE) #$ flow="SOURCE -> IfExp" flow="'source', l:20 -> IfExp"
|
||||
|
||||
|
||||
def test_conditional_true_guards():
|
||||
@@ -425,7 +425,7 @@ def test_conditional_true_guards():
|
||||
|
||||
|
||||
def test_conditional_false():
|
||||
SINK(NONSOURCE if False else SOURCE) #$ flow="ControlFlowNode for SOURCE -> ControlFlowNode for IfExp" flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for IfExp"
|
||||
SINK(NONSOURCE if False else SOURCE) #$ flow="SOURCE -> IfExp" flow="'source', l:20 -> IfExp"
|
||||
|
||||
|
||||
def test_conditional_false_guards():
|
||||
@@ -435,13 +435,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) #$ MISSING:flow="ControlFlowNode for SOURCE -> ControlFlowNode for IfExp" MISSING:flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for IfExp"
|
||||
SINK(x if (SOURCE == (x := SOURCE)) else NONSOURCE) #$ MISSING:flow="SOURCE -> IfExp" MISSING:flow="'source', l:20 -> 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) #$ MISSING:flow="ControlFlowNode for SOURCE -> ControlFlowNode for IfExp" MISSING:flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for IfExp"
|
||||
SINK(NONSOURCE if (NONSOURCE == (x := SOURCE)) else x) #$ MISSING:flow="SOURCE -> IfExp" MISSING:flow="'source', l:20 -> IfExp"
|
||||
|
||||
|
||||
# 6.14. Lambdas
|
||||
@@ -449,14 +449,14 @@ def test_lambda():
|
||||
def f(x):
|
||||
return x
|
||||
|
||||
SINK(f(SOURCE)) #$ flow="ControlFlowNode for SOURCE -> ControlFlowNode for f()" flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for f()"
|
||||
SINK(f(SOURCE)) #$ flow="SOURCE -> f(..)" flow="'source', l:20 -> f(..)"
|
||||
|
||||
|
||||
def test_lambda_positional():
|
||||
def second(a, b):
|
||||
return b
|
||||
|
||||
SINK(second(NONSOURCE, SOURCE)) #$ flow="ControlFlowNode for SOURCE -> ControlFlowNode for second()" flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for second()"
|
||||
SINK(second(NONSOURCE, SOURCE)) #$ flow="SOURCE -> second(..)" flow="'source', l:20 -> second(..)"
|
||||
|
||||
|
||||
def test_lambda_positional_negative():
|
||||
@@ -470,50 +470,50 @@ def test_lambda_keyword():
|
||||
def second(a, b):
|
||||
return b
|
||||
|
||||
SINK(second(NONSOURCE, b=SOURCE)) #$ flow="ControlFlowNode for SOURCE -> ControlFlowNode for second()" flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for second()"
|
||||
SINK(second(NONSOURCE, b=SOURCE)) #$ flow="SOURCE -> second(..)" flow="'source', l:20 -> second(..)"
|
||||
|
||||
|
||||
def test_lambda_unpack_iterable():
|
||||
def second(a, b):
|
||||
return b
|
||||
|
||||
SINK(second(NONSOURCE, *[SOURCE])) #$ MISSING:flow="ControlFlowNode for SOURCE -> ControlFlowNode for second()" MISSING:flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for second()" # Flow missing
|
||||
SINK(second(NONSOURCE, *[SOURCE])) #$ MISSING:flow="SOURCE -> second(..)" MISSING:flow="'source', l:20 -> second(..)" # Flow missing
|
||||
|
||||
|
||||
def test_lambda_unpack_mapping():
|
||||
def second(a, b):
|
||||
return b
|
||||
|
||||
SINK(second(NONSOURCE, **{"b": SOURCE})) #$ flow="ControlFlowNode for SOURCE -> ControlFlowNode for second()" flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for second()"
|
||||
SINK(second(NONSOURCE, **{"b": SOURCE})) #$ flow="SOURCE -> second(..)" flow="'source', l:20 -> second(..)"
|
||||
|
||||
|
||||
def test_lambda_extra_pos():
|
||||
f_extra_pos = lambda a, *b: b[0]
|
||||
SINK(f_extra_pos(NONSOURCE, SOURCE)) #$ flow="ControlFlowNode for SOURCE -> ControlFlowNode for f_extra_pos()" flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for f_extra_pos()"
|
||||
SINK(f_extra_pos(NONSOURCE, SOURCE)) #$ flow="SOURCE -> f_extra_pos(..)" flow="'source', l:20 -> f_extra_pos(..)"
|
||||
|
||||
|
||||
def test_lambda_extra_keyword():
|
||||
f_extra_keyword = lambda a, **b: b["b"]
|
||||
SINK(f_extra_keyword(NONSOURCE, b=SOURCE)) #$ flow="ControlFlowNode for SOURCE -> ControlFlowNode for f_extra_keyword()" flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for f_extra_keyword()"
|
||||
SINK(f_extra_keyword(NONSOURCE, b=SOURCE)) #$ flow="SOURCE -> f_extra_keyword(..)" flow="'source', l:20 -> 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})) #$ MISSING:flow="ControlFlowNode for SOURCE -> ControlFlowNode for f_extra_keyword()" MISSING:flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for f_extra_keyword()"
|
||||
SINK(f_extra_keyword_flow(**{SOURCE: None})) #$ MISSING:flow="SOURCE -> f_extra_keyword(..)" MISSING:flow="'source', l:20 -> f_extra_keyword(..)"
|
||||
|
||||
|
||||
@expects(4)
|
||||
def test_swap():
|
||||
a = SOURCE
|
||||
b = NONSOURCE
|
||||
SINK(a) #$ flow="ControlFlowNode for SOURCE, l:509 -> ControlFlowNode for a" flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for a"
|
||||
SINK(a) #$ flow="SOURCE, l:509 -> a" flow="'source', l:20 -> a"
|
||||
SINK_F(b)
|
||||
|
||||
a, b = b, a
|
||||
SINK_F(a)
|
||||
SINK(b) #$ flow="ControlFlowNode for SOURCE, l:509 -> ControlFlowNode for b" flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for b"
|
||||
SINK(b) #$ flow="SOURCE, l:509 -> b" flow="'source', l:20 -> b"
|
||||
|
||||
|
||||
def test_deep_callgraph():
|
||||
@@ -538,7 +538,7 @@ def test_deep_callgraph():
|
||||
return f5(arg)
|
||||
|
||||
x = f6(SOURCE)
|
||||
SINK(x) #$ MISSING:flow="ControlFlowNode for SOURCE, l:540 -> ControlFlowNode for x" MISING:flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for x"
|
||||
SINK(x) #$ MISSING:flow="SOURCE, l:540 -> x" MISING:flow="'source', l:20 -> x"
|
||||
|
||||
|
||||
@expects(2)
|
||||
@@ -547,7 +547,7 @@ def test_dynamic_tuple_creation_1():
|
||||
tup += (SOURCE,)
|
||||
tup += (NONSOURCE,)
|
||||
|
||||
SINK(tup[0]) #$ MISSING:flow="ControlFlowNode for SOURCE, l:547 -> ControlFlowNode for Subscript" MISING:flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for Subscript"
|
||||
SINK(tup[0]) #$ MISSING:flow="SOURCE, l:547 -> tup[0]" MISING:flow="'source', l:20 -> tup[0]"
|
||||
SINK_F(tup[1])
|
||||
|
||||
|
||||
@@ -557,7 +557,7 @@ def test_dynamic_tuple_creation_2():
|
||||
tup += (SOURCE,)
|
||||
tup += (NONSOURCE,)
|
||||
|
||||
SINK(tup[0]) #$ MISSING:flow="ControlFlowNode for SOURCE, l:557 -> ControlFlowNode for Subscript" MISING:flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for Subscript"
|
||||
SINK(tup[0]) #$ MISSING:flow="SOURCE, l:557 -> tup[0]" MISING:flow="'source', l:20 -> tup[0]"
|
||||
SINK_F(tup[1])
|
||||
|
||||
|
||||
@@ -567,7 +567,7 @@ def test_dynamic_tuple_creation_3():
|
||||
tup2 = (NONSOURCE,)
|
||||
tup = tup1 + tup2
|
||||
|
||||
SINK(tup[0]) #$ MISSING:flow="ControlFlowNode for SOURCE, l:566 -> ControlFlowNode for Subscript" MISING:flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for Subscript"
|
||||
SINK(tup[0]) #$ MISSING:flow="SOURCE, l:566 -> tup[0]" MISING:flow="'source', l:20 -> tup[0]"
|
||||
SINK_F(tup[1])
|
||||
|
||||
|
||||
@@ -578,5 +578,5 @@ def test_dynamic_tuple_creation_4():
|
||||
for item in [SOURCE, NONSOURCE]:
|
||||
tup += (item,)
|
||||
|
||||
SINK(tup[0]) #$ MISSING:flow="ControlFlowNode for SOURCE, l:578 -> ControlFlowNode for Subscript" MISING:flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for Subscript"
|
||||
SINK(tup[0]) #$ MISSING:flow="SOURCE, l:578 -> tup[0]" MISING:flow="'source', l:20 -> tup[0]"
|
||||
SINK_F(tup[1])
|
||||
|
||||
@@ -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" }
|
||||
@@ -18,31 +19,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
|
||||
@@ -69,6 +45,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)
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user