mirror of
https://github.com/github/codeql.git
synced 2026-04-30 11:15:13 +02:00
Python: Test all expressions that incur dataflow
This commit is contained in:
@@ -1,6 +1,8 @@
|
||||
| test.py:20:9:20:14 | ControlFlowNode for SOURCE | test.py:21:10:21:10 | ControlFlowNode for x |
|
||||
| test.py:25:9:25:16 | ControlFlowNode for Str | test.py:26:10:26:10 | ControlFlowNode for x |
|
||||
| test.py:29:9:29:17 | ControlFlowNode for Str | test.py:30:10:30:10 | ControlFlowNode for x |
|
||||
| test.py:33:9:33:10 | ControlFlowNode for IntegerLiteral | test.py:34:10:34:10 | ControlFlowNode for x |
|
||||
| test.py:37:9:37:12 | ControlFlowNode for FloatLiteral | test.py:38:10:38:10 | ControlFlowNode for x |
|
||||
| test.py:46:10:46:15 | ControlFlowNode for SOURCE | test.py:47:10:47:10 | ControlFlowNode for x |
|
||||
| test.py:23:9:23:14 | ControlFlowNode for SOURCE | test.py:24:10:24:10 | ControlFlowNode for x |
|
||||
| test.py:28:9:28:16 | ControlFlowNode for Str | test.py:29:10:29:10 | ControlFlowNode for x |
|
||||
| test.py:32:9:32:17 | ControlFlowNode for Str | test.py:33:10:33:10 | ControlFlowNode for x |
|
||||
| test.py:36:9:36:10 | ControlFlowNode for IntegerLiteral | test.py:37:10:37:10 | ControlFlowNode for x |
|
||||
| test.py:40:9:40:12 | ControlFlowNode for FloatLiteral | test.py:41:10:41:10 | ControlFlowNode for x |
|
||||
| test.py:49:10:49:15 | ControlFlowNode for SOURCE | test.py:50:10:50:10 | ControlFlowNode for x |
|
||||
| test.py:226:15:226:20 | ControlFlowNode for SOURCE | test.py:226:10:226:21 | ControlFlowNode for f() |
|
||||
| test.py:280:12:280:17 | ControlFlowNode for SOURCE | test.py:280:10:280:18 | ControlFlowNode for f() |
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
| test.py:13:5:13:5 | SSA variable x | test.py:12:1:12:33 | Exit node for Function test_tuple_with_local_flow |
|
||||
| test.py:13:5:13:5 | SSA variable x | test.py:14:9:14:9 | ControlFlowNode for x |
|
||||
| test.py:13:10:13:18 | ControlFlowNode for Tuple | test.py:13:5:13:5 | SSA variable x |
|
||||
| test.py:14:5:14:5 | SSA variable y | test.py:15:5:15:11 | SSA variable y |
|
||||
| test.py:14:5:14:5 | SSA variable y | test.py:15:10:15:10 | ControlFlowNode for y |
|
||||
| test.py:14:9:14:12 | ControlFlowNode for Subscript | test.py:14:5:14:5 | SSA variable y |
|
||||
| test.py:15:5:15:11 | SSA variable y | test.py:12:1:12:33 | Exit node for Function test_tuple_with_local_flow |
|
||||
| test.py:17:5:17:5 | SSA variable x | test.py:16:1:16:33 | Exit node for Function test_tuple_with_local_flow |
|
||||
| test.py:17:5:17:5 | SSA variable x | test.py:18:9:18:9 | ControlFlowNode for x |
|
||||
| test.py:17:10:17:18 | ControlFlowNode for Tuple | test.py:17:5:17:5 | SSA variable x |
|
||||
| test.py:18:5:18:5 | SSA variable y | test.py:19:5:19:11 | SSA variable y |
|
||||
| test.py:18:5:18:5 | SSA variable y | test.py:19:10:19:10 | ControlFlowNode for y |
|
||||
| test.py:18:9:18:12 | ControlFlowNode for Subscript | test.py:18:5:18:5 | SSA variable y |
|
||||
| test.py:19:5:19:11 | SSA variable y | test.py:16:1:16:33 | Exit node for Function test_tuple_with_local_flow |
|
||||
|
||||
@@ -1,10 +1,14 @@
|
||||
# This should cover all the syntactical constructs that we hope to support
|
||||
# This should cover all the syntactical constructs that we hope to support.
|
||||
# Headings refer to https://docs.python.org/3/reference/expressions.html,
|
||||
# and are selected whenever they incur dataflow.
|
||||
# Intended sources should be the variable `SOURCE` and intended sinks should be
|
||||
# arguments to the function `SINK` (see python/ql/test/experimental/dataflow/testConfig.qll).
|
||||
#
|
||||
# Functions whose name ends with "_with_local_flow" will also be tested for local flow.
|
||||
#
|
||||
# All functions starting with "test_" should run and print a source (sources are defined in testConfig.qll).
|
||||
|
||||
# These are included so that we can easily evaluate the test code
|
||||
# These are defined so that we can evaluate the test code.
|
||||
SOURCE = "source"
|
||||
def SINK(x):
|
||||
print(x)
|
||||
@@ -14,7 +18,6 @@ def test_tuple_with_local_flow():
|
||||
y = x[1]
|
||||
SINK(y)
|
||||
|
||||
# List taken from https://docs.python.org/3/reference/expressions.html
|
||||
# 6.2.1. Identifiers (Names)
|
||||
def test_names():
|
||||
x = SOURCE
|
||||
@@ -90,42 +93,188 @@ def test_generator():
|
||||
x = (SOURCE for y in [3])
|
||||
SINK([*x][0])
|
||||
|
||||
# List taken from https://docs.python.org/3/reference/expressions.html
|
||||
# 6. Expressions
|
||||
# 6.1. Arithmetic conversions
|
||||
# 6.2. Atoms
|
||||
# 6.2.1. Identifiers (Names)
|
||||
# 6.2.2. Literals
|
||||
# 6.2.3. Parenthesized forms
|
||||
# 6.2.4. Displays for lists, sets and dictionaries
|
||||
# 6.2.5. List displays
|
||||
# 6.2.6. Set displays
|
||||
# 6.2.7. Dictionary displays
|
||||
# 6.2.8. Generator expressions
|
||||
# 6.2.9. Yield expressions
|
||||
def gen(x):
|
||||
yield x
|
||||
|
||||
def test_yield():
|
||||
g = gen(SOURCE)
|
||||
SINK(next(g))
|
||||
|
||||
def gen_from(x):
|
||||
yield from gen(x)
|
||||
|
||||
def test_yield_from():
|
||||
g = gen_from(SOURCE)
|
||||
SINK(next(g))
|
||||
|
||||
# a statement rather than an expression, but related to generators
|
||||
def test_for():
|
||||
for x in gen(SOURCE):
|
||||
SINK(x)
|
||||
|
||||
# 6.2.9.1. Generator-iterator methods
|
||||
# 6.2.9.2. Examples
|
||||
def test___next__():
|
||||
g = gen(SOURCE)
|
||||
SINK(g.__next__())
|
||||
|
||||
def gen2(x):
|
||||
m = yield x # argument of `send` has to flow to value of `yield x` (and so to `m`)
|
||||
yield m
|
||||
|
||||
def test_send():
|
||||
g = gen2(3)
|
||||
n = next(g)
|
||||
SINK(g.send(SOURCE))
|
||||
|
||||
def gen_ex(x):
|
||||
try:
|
||||
yield 3
|
||||
except:
|
||||
yield x # `x` has to flow to call to `throw`
|
||||
|
||||
def test_throw():
|
||||
g = gen_ex(SOURCE)
|
||||
n = next(g)
|
||||
SINK(g.throw(TypeError))
|
||||
|
||||
# no `test_close` as `close` involves no data flow
|
||||
|
||||
# 6.2.9.3. Asynchronous generator functions
|
||||
async def agen(x):
|
||||
yield x
|
||||
|
||||
# 6.2.9.4. Asynchronous generator-iterator methods
|
||||
# 6.3. Primaries
|
||||
|
||||
# helper to run async test functions
|
||||
def runa(a):
|
||||
import asyncio
|
||||
asyncio.run(a)
|
||||
|
||||
async def atest___anext__():
|
||||
g = agen(SOURCE)
|
||||
SINK(await g.__anext__())
|
||||
|
||||
def test___anext__():
|
||||
runa(atest___anext__())
|
||||
|
||||
async def agen2(x):
|
||||
m = yield x # argument of `send` has to flow to value of `yield x` (and so to `m`)
|
||||
yield m
|
||||
|
||||
async def atest_asend():
|
||||
g = agen2(3)
|
||||
n = await g.__anext__()
|
||||
SINK(await g.asend(SOURCE))
|
||||
|
||||
def test_asend():
|
||||
runa(atest_asend())
|
||||
|
||||
async def agen_ex(x):
|
||||
try:
|
||||
yield 3
|
||||
except:
|
||||
yield x # `x` has to flow to call to `athrow`
|
||||
|
||||
async def atest_athrow():
|
||||
g = agen_ex(SOURCE)
|
||||
n = await g.__anext__()
|
||||
SINK(await g.athrow(TypeError))
|
||||
|
||||
def test_athrow():
|
||||
runa(atest_athrow())
|
||||
|
||||
# 6.3.1. Attribute references
|
||||
class C:
|
||||
a = SOURCE
|
||||
|
||||
def test_attribute_reference():
|
||||
SINK(C.a)
|
||||
|
||||
# overriding __getattr__ should be tested by the class coverage tests
|
||||
|
||||
# 6.3.2. Subscriptions
|
||||
# This does not constitute dataflow (but could be taint flow)
|
||||
def example_subscription_string():
|
||||
SINK("source"[0])
|
||||
|
||||
def test_subscription_tuple():
|
||||
SINK((SOURCE,)[0])
|
||||
|
||||
def test_subscription_list():
|
||||
SINK([SOURCE][0])
|
||||
|
||||
def test_subscription_mapping():
|
||||
SINK({"s":SOURCE}["s"])
|
||||
|
||||
# overriding __getitem__ should be tested by the class coverage tests
|
||||
|
||||
# 6.3.3. Slicings
|
||||
l = [SOURCE]
|
||||
|
||||
def test_slicing():
|
||||
s = l[0:1:1]
|
||||
SINK(s[0])
|
||||
|
||||
# The grammar seems to allow `l[0:1:1, 0:1]`, but the interpreter does not like it
|
||||
|
||||
# 6.3.4. Calls
|
||||
# 6.4. Await expression
|
||||
# 6.5. The power operator
|
||||
# 6.6. Unary arithmetic and bitwise operations
|
||||
# 6.7. Binary arithmetic operations
|
||||
# 6.8. Shifting operations
|
||||
# 6.9. Binary bitwise operations
|
||||
# 6.10. Comparisons
|
||||
# 6.10.1. Value comparisons
|
||||
# 6.10.2. Membership test operations
|
||||
# 6.10.3. Identity comparisons
|
||||
# 6.11. Boolean operations
|
||||
def f(a, b):
|
||||
return b
|
||||
|
||||
def test_call_positional():
|
||||
SINK(f(3, SOURCE))
|
||||
|
||||
def test_call_keyword():
|
||||
SINK(f(3, b=SOURCE))
|
||||
|
||||
def test_call_unpack_iterable():
|
||||
SINK(f(3, *[SOURCE]))
|
||||
|
||||
def test_call_unpack_mapping():
|
||||
SINK(f(3, **{"b": SOURCE}))
|
||||
|
||||
def f_extra_pos(a, *b):
|
||||
return b[0]
|
||||
|
||||
def test_call_extra_pos():
|
||||
SINK(f_extra_pos(3, SOURCE))
|
||||
|
||||
def f_extra_keyword(a, **b):
|
||||
return b["b"]
|
||||
|
||||
def test_call_extra_keyword():
|
||||
SINK(f_extra_keyword(3, b=SOURCE))
|
||||
|
||||
# return the name of the first extra keyword argument
|
||||
def f_extra_keyword_flow(**a):
|
||||
return [*a][0]
|
||||
|
||||
# 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}))
|
||||
|
||||
# 6.12. Assignment expressions
|
||||
def test_assignment_expression():
|
||||
x = 3
|
||||
SINK(x := SOURCE)
|
||||
|
||||
# 6.13. Conditional expressions
|
||||
def test_conditional_true():
|
||||
SINK(SOURCE if True else 3)
|
||||
|
||||
def test_conditional_false():
|
||||
SINK(3 if False else SOURCE)
|
||||
|
||||
def test_conditional_evaluation_true():
|
||||
x = 3
|
||||
SINK(x if (SOURCE == (x := SOURCE)) else 3) # Condition is evaluated first, so x is SOURCE once chosen
|
||||
|
||||
def test_conditional_evaluation_false():
|
||||
x = 3
|
||||
SINK(3 if (3 == (x := SOURCE)) else x) # Condition is evaluated first, so x is SOURCE once chosen
|
||||
|
||||
# 6.14. Lambdas
|
||||
# 6.15. Expression lists
|
||||
# 6.16. Evaluation order
|
||||
# 6.17. Operator precedence
|
||||
def test_lambda():
|
||||
f = lambda x : x
|
||||
SINK(f(SOURCE))
|
||||
|
||||
Reference in New Issue
Block a user