mirror of
https://github.com/github/codeql.git
synced 2026-05-02 04:05:14 +02:00
Python: Move dataflow tests out of experimental
This commit is contained in:
@@ -0,0 +1 @@
|
||||
| test.py:126:13:126:25 | ControlFlowNode for CUSTOM_SOURCE | test.py:130:21:130:21 | ControlFlowNode for t |
|
||||
@@ -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
|
||||
@@ -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 |
|
||||
13
python/ql/test/library-tests/dataflow/regression/dataflow.ql
Normal file
13
python/ql/test/library-tests/dataflow/regression/dataflow.ql
Normal 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
|
||||
10
python/ql/test/library-tests/dataflow/regression/module.py
Normal file
10
python/ql/test/library-tests/dataflow/regression/module.py
Normal file
@@ -0,0 +1,10 @@
|
||||
dangerous = SOURCE
|
||||
safe = "safe"
|
||||
|
||||
|
||||
def dangerous_func():
|
||||
return SOURCE
|
||||
|
||||
|
||||
safe2 = SOURCE
|
||||
safe2 = "safe"
|
||||
214
python/ql/test/library-tests/dataflow/regression/test.py
Normal file
214
python/ql/test/library-tests/dataflow/regression/test.py
Normal 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
|
||||
Reference in New Issue
Block a user