Python: Move dataflow tests out of experimental

This commit is contained in:
Rasmus Wriedt Larsen
2024-04-23 09:40:44 +02:00
parent 19974f04c9
commit ce711f7d2f
260 changed files with 0 additions and 0 deletions

View File

@@ -0,0 +1 @@
| test.py:126:13:126:25 | ControlFlowNode for CUSTOM_SOURCE | test.py:130:21:130:21 | ControlFlowNode for t |

View File

@@ -0,0 +1,28 @@
/**
* This query is meant to catch the flows from `CUSTOM_SOURCE` to `CUSTOM_SINK`.
*
* This should be compared to
* python/ql/test/library-tests/taint/dataflow/Dataflow.ql
* A first goal is to have identical results; after that we
* hope to remove the false positive.
*/
import python
import semmle.python.dataflow.new.DataFlow
module CustomTestConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node node) { node.asCfgNode().(NameNode).getId() = "CUSTOM_SOURCE" }
predicate isSink(DataFlow::Node node) {
exists(CallNode call |
call.getFunction().(NameNode).getId() in ["CUSTOM_SINK", "CUSTOM_SINK_F"] and
node.asCfgNode() = call.getAnArg()
)
}
}
module CustomTestFlow = DataFlow::Global<CustomTestConfig>;
from DataFlow::Node source, DataFlow::Node sink
where CustomTestFlow::flow(source, sink)
select source, sink

View File

@@ -0,0 +1,25 @@
| module.py:1:13:1:18 | ControlFlowNode for SOURCE | test.py:89:10:89:10 | ControlFlowNode for t |
| module.py:1:13:1:18 | ControlFlowNode for SOURCE | test.py:106:10:106:14 | ControlFlowNode for Attribute |
| module.py:1:13:1:18 | ControlFlowNode for SOURCE | test.py:111:10:111:12 | ControlFlowNode for Attribute |
| module.py:1:13:1:18 | ControlFlowNode for SOURCE | test.py:156:6:156:11 | ControlFlowNode for unsafe |
| module.py:6:12:6:17 | ControlFlowNode for SOURCE | test.py:101:10:101:10 | ControlFlowNode for t |
| test.py:3:10:3:15 | ControlFlowNode for SOURCE | test.py:3:10:3:15 | ControlFlowNode for SOURCE |
| test.py:6:9:6:14 | ControlFlowNode for SOURCE | test.py:7:10:7:10 | ControlFlowNode for s |
| test.py:10:12:10:17 | ControlFlowNode for SOURCE | test.py:13:10:13:12 | ControlFlowNode for arg |
| test.py:10:12:10:17 | ControlFlowNode for SOURCE | test.py:17:10:17:10 | ControlFlowNode for t |
| test.py:20:9:20:14 | ControlFlowNode for SOURCE | test.py:13:10:13:12 | ControlFlowNode for arg |
| test.py:37:13:37:18 | ControlFlowNode for SOURCE | test.py:41:14:41:14 | ControlFlowNode for t |
| test.py:62:13:62:18 | ControlFlowNode for SOURCE | test.py:13:10:13:12 | ControlFlowNode for arg |
| test.py:67:13:67:18 | ControlFlowNode for SOURCE | test.py:13:10:13:12 | ControlFlowNode for arg |
| test.py:76:9:76:14 | ControlFlowNode for SOURCE | test.py:78:10:78:10 | ControlFlowNode for t |
| test.py:128:13:128:18 | ControlFlowNode for SOURCE | test.py:132:14:132:14 | ControlFlowNode for t |
| test.py:159:10:159:15 | ControlFlowNode for SOURCE | test.py:160:14:160:14 | ControlFlowNode for t |
| test.py:163:9:163:14 | ControlFlowNode for SOURCE | test.py:165:12:165:12 | ControlFlowNode for s |
| test.py:178:9:178:14 | ControlFlowNode for SOURCE | test.py:180:14:180:14 | ControlFlowNode for t |
| test.py:178:9:178:14 | ControlFlowNode for SOURCE | test.py:182:16:182:16 | ControlFlowNode for t |
| test.py:178:9:178:14 | ControlFlowNode for SOURCE | test.py:184:16:184:16 | ControlFlowNode for t |
| test.py:178:9:178:14 | ControlFlowNode for SOURCE | test.py:186:14:186:14 | ControlFlowNode for t |
| test.py:195:9:195:14 | ControlFlowNode for SOURCE | test.py:197:14:197:14 | ControlFlowNode for t |
| test.py:195:9:195:14 | ControlFlowNode for SOURCE | test.py:199:14:199:14 | ControlFlowNode for t |
| test.py:202:10:202:15 | ControlFlowNode for SOURCE | test.py:204:14:204:14 | ControlFlowNode for i |
| test.py:202:10:202:15 | ControlFlowNode for SOURCE | test.py:205:10:205:10 | ControlFlowNode for i |

View File

@@ -0,0 +1,13 @@
/**
* This should be compared to
* python/ql/test/library-tests/taint/dataflow/Dataflow.ql
* A first goal is to have identical results; after that we
* hope to remove the false positive.
*/
import python
import experimental.dataflow.testConfig
from DataFlow::Node source, DataFlow::Node sink
where TestFlow::flow(source, sink)
select source, sink

View File

@@ -0,0 +1,10 @@
dangerous = SOURCE
safe = "safe"
def dangerous_func():
return SOURCE
safe2 = SOURCE
safe2 = "safe"

View File

@@ -0,0 +1,214 @@
def test1():
SINK(SOURCE)
def test2():
s = SOURCE
SINK(s)
def source():
return SOURCE
def sink(arg):
SINK(arg)
def test3():
t = source()
SINK(t)
def test4():
t = SOURCE
sink(t)
def test5():
t = source()
sink(t)
def test6(cond):
if cond:
t = "Safe"
else:
t = SOURCE
if cond:
SINK_F(t)
def test7(cond):
if cond:
t = SOURCE
else:
t = "Safe"
if cond:
SINK(t)
def source2():
return source()
def sink2(arg):
sink(arg)
def sink3(cond, arg):
if cond:
sink(arg)
def test8(cond): # This test currently adds nothing, as we only track SOURCE -> SINK, and previous tests already add flow from line 10 to line 13
t = source2()
sink2(t)
#False positive
def test9(cond):
if cond:
t = "Safe"
else:
t = SOURCE
sink3(cond, t)
def test10(cond):
if cond:
t = SOURCE
else:
t = "Safe"
sink3(cond, t)
def hub(arg):
return arg
def test11():
t = SOURCE
t = hub(t)
SINK(t)
def test12():
t = "safe"
t = hub(t)
SINK_F(t)
import module
def test13():
t = module.dangerous
SINK(t)
def test14():
t = module.safe
SINK_F(t)
def test15():
t = module.safe2
SINK_F(t)
def test16():
t = module.dangerous_func()
SINK(t)
class C(object): pass
def x_sink(arg):
SINK(arg.x)
def test17():
t = C()
t.x = module.dangerous
SINK(t.x)
def test18():
t = C()
t.x = module.dangerous
t = hub(t)
x_sink(t)
def test19():
t = CUSTOM_SOURCE
t = hub(TAINT_FROM_ARG(t))
CUSTOM_SINK(t)
def test20(cond):
if cond:
t = CUSTOM_SOURCE
else:
t = SOURCE
if cond:
CUSTOM_SINK(t)
else:
SINK(t)
def test21(cond):
if cond:
t = CUSTOM_SOURCE
else:
t = SOURCE
if not cond:
CUSTOM_SINK_F(t)
else:
SINK_F(t)
def test22(cond):
if cond:
t = CUSTOM_SOURCE
else:
t = SOURCE
t = TAINT_FROM_ARG(t) # Blocks data flow
if cond:
CUSTOM_SINK(t)
else:
SINK(t)
from module import dangerous as unsafe
SINK(unsafe)
def test23():
with SOURCE as t:
SINK(t)
def test24():
s = SOURCE
SANITIZE(s) # Does not block data flow
SINK_F(s)
def test_update_extend(x, y):
l = [SOURCE]
d = {"key" : SOURCE}
x.extend(l)
y.update(d)
SINK(x[0]) # Flow not found
SINK(y["key"]) # Flow not found
l2 = list(l)
d2 = dict(d)
def test_truth():
t = SOURCE
if t:
SINK(t)
else:
SINK_F(t) # False positive
if not t:
SINK_F(t) # False positive
else:
SINK(t)
def test_early_exit():
t = FALSEY
if not t:
return
t
def flow_through_type_test_if_no_class():
t = SOURCE
if isinstance(t, str):
SINK(t) # Flows's both here..
else:
SINK(t) # ..and here
def flow_in_iteration():
t = [SOURCE]
for i in t:
SINK(i)
SINK(i)
def flow_in_generator():
seq = [SOURCE]
for i in seq:
yield i
def flow_from_generator():
for x in flow_in_generator():
SINK(x) # Flow not found