Skip to content

Commit a9c4094

Browse files
committed
Python: more tests and comments
1 parent 9b198c6 commit a9c4094

File tree

5 files changed

+112
-0
lines changed

5 files changed

+112
-0
lines changed

python/ql/lib/semmle/python/dataflow/new/internal/DataFlowPrivate.qll

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,9 @@ predicate simpleLocalFlowStep(Node nodeFrom, Node nodeTo) {
245245
/**
246246
* Holds if there is an Essa flow step from `nodeFrom` to `nodeTo` that does not switch between
247247
* local and global SSA variables.
248+
*
249+
* This predicate is currently empty, since `EssaFlow::essaFlowStep` never goes between `EssaNode`s.
250+
* (It only starts in an `EssaNode` in a single case, namely `defToFirstUse` which ends in a `CfgNode`.)
248251
*/
249252
private predicate localEssaStep(EssaNode nodeFrom, EssaNode nodeTo) {
250253
EssaFlow::essaFlowStep(nodeFrom, nodeTo) and
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
| base.py:1:7:1:7 | ControlFlowNode for IntegerLiteral | base.py:1:1:1:3 | GSSA Variable foo |
2+
| m1.py:2:7:2:8 | ControlFlowNode for IntegerLiteral | m1.py:2:1:2:3 | GSSA Variable foo |
3+
| m1.py:4:8:4:11 | ControlFlowNode for ImportExpr | m1.py:4:8:4:11 | GSSA Variable base |
4+
| m1.py:4:8:4:11 | GSSA Variable base | m1.py:10:14:10:17 | ControlFlowNode for base |
5+
| m1.py:6:1:6:14 | ControlFlowNode for FunctionExpr | m1.py:6:5:6:10 | GSSA Variable passOn |
6+
| m1.py:6:5:6:10 | GSSA Variable passOn | m1.py:10:7:10:12 | ControlFlowNode for passOn |
7+
| m1.py:10:7:10:22 | ControlFlowNode for passOn() | m1.py:10:1:10:3 | GSSA Variable bar |
8+
| multiphase.py:0:0:0:0 | GSSA Variable __file__ | multiphase.py:4:50:4:57 | ControlFlowNode for __file__ |
9+
| multiphase.py:0:0:0:0 | GSSA Variable expects | multiphase.py:37:2:37:8 | ControlFlowNode for expects |
10+
| multiphase.py:1:8:1:10 | ControlFlowNode for ImportExpr | multiphase.py:1:8:1:10 | GSSA Variable sys |
11+
| multiphase.py:1:8:1:10 | GSSA Variable sys | multiphase.py:4:1:4:3 | ControlFlowNode for sys |
12+
| multiphase.py:2:8:2:9 | ControlFlowNode for ImportExpr | multiphase.py:2:8:2:9 | GSSA Variable os |
13+
| multiphase.py:2:8:2:9 | GSSA Variable os | multiphase.py:4:17:4:18 | ControlFlowNode for os |
14+
| multiphase.py:4:17:4:18 | ControlFlowNode for os | multiphase.py:4:33:4:34 | ControlFlowNode for os |
15+
| multiphase.py:4:17:4:18 | [post read] ControlFlowNode for os | multiphase.py:4:33:4:34 | ControlFlowNode for os |
16+
| multiphase.py:8:1:8:9 | GSSA Variable NONSOURCE | multiphase.py:34:7:34:15 | ControlFlowNode for NONSOURCE |
17+
| multiphase.py:8:13:8:26 | ControlFlowNode for Str | multiphase.py:8:1:8:9 | GSSA Variable NONSOURCE |
18+
| multiphase.py:9:10:9:17 | ControlFlowNode for Str | multiphase.py:9:1:9:6 | GSSA Variable SOURCE |
19+
| multiphase.py:12:1:12:17 | ControlFlowNode for FunctionExpr | multiphase.py:12:5:12:13 | GSSA Variable is_source |
20+
| multiphase.py:16:1:16:12 | ControlFlowNode for FunctionExpr | multiphase.py:16:5:16:8 | GSSA Variable SINK |
21+
| multiphase.py:23:1:23:14 | ControlFlowNode for FunctionExpr | multiphase.py:23:5:23:10 | GSSA Variable SINK_F |
22+
| multiphase.py:29:1:29:14 | ControlFlowNode for FunctionExpr | multiphase.py:29:5:29:11 | GSSA Variable set_foo |
23+
| multiphase.py:29:5:29:11 | GSSA Variable set_foo | multiphase.py:35:1:35:7 | ControlFlowNode for set_foo |
24+
| multiphase.py:34:7:34:15 | ControlFlowNode for NONSOURCE | multiphase.py:34:1:34:3 | GSSA Variable foo |
25+
| multiphase.py:37:2:37:11 | ControlFlowNode for expects()() | multiphase.py:38:5:38:15 | GSSA Variable test_phases |
26+
| test.py:2:13:2:26 | ControlFlowNode for Str | test.py:2:1:2:9 | GSSA Variable NONSOURCE |
27+
| test.py:3:10:3:17 | ControlFlowNode for Str | test.py:3:1:3:6 | GSSA Variable SOURCE |
28+
| test.py:6:1:6:17 | ControlFlowNode for FunctionExpr | test.py:6:5:6:13 | GSSA Variable is_source |
29+
| test.py:10:1:10:12 | ControlFlowNode for FunctionExpr | test.py:10:5:10:8 | GSSA Variable SINK |
30+
| test.py:17:1:17:14 | ControlFlowNode for FunctionExpr | test.py:17:5:17:10 | GSSA Variable SINK_F |
31+
| test.py:23:8:23:11 | ControlFlowNode for ImportExpr | test.py:23:8:23:11 | GSSA Variable base |
32+
| test.py:23:8:23:11 | GSSA Variable base | test.py:25:1:25:4 | ControlFlowNode for base |
33+
| test.py:27:8:27:9 | ControlFlowNode for ImportExpr | test.py:27:8:27:9 | GSSA Variable m1 |
34+
| test.py:29:1:29:17 | ControlFlowNode for FunctionExpr | test.py:29:5:29:14 | GSSA Variable test_const |
35+
| test.py:32:1:32:23 | ControlFlowNode for FunctionExpr | test.py:32:5:32:20 | GSSA Variable test_overwritten |
36+
| testOnce.py:2:13:2:26 | ControlFlowNode for Str | testOnce.py:2:1:2:9 | GSSA Variable NONSOURCE |
37+
| testOnce.py:3:10:3:17 | ControlFlowNode for Str | testOnce.py:3:1:3:6 | GSSA Variable SOURCE |
38+
| testOnce.py:6:1:6:17 | ControlFlowNode for FunctionExpr | testOnce.py:6:5:6:13 | GSSA Variable is_source |
39+
| testOnce.py:10:1:10:12 | ControlFlowNode for FunctionExpr | testOnce.py:10:5:10:8 | GSSA Variable SINK |
40+
| testOnce.py:17:1:17:14 | ControlFlowNode for FunctionExpr | testOnce.py:17:5:17:10 | GSSA Variable SINK_F |
41+
| testOnce.py:23:8:23:9 | ControlFlowNode for ImportExpr | testOnce.py:23:8:23:9 | GSSA Variable m1 |
42+
| testOnce.py:25:8:25:11 | ControlFlowNode for ImportExpr | testOnce.py:25:8:25:11 | GSSA Variable base |
43+
| testOnce.py:25:8:25:11 | GSSA Variable base | testOnce.py:27:1:27:4 | ControlFlowNode for base |
44+
| testOnce.py:29:1:29:17 | ControlFlowNode for FunctionExpr | testOnce.py:29:5:29:14 | GSSA Variable test_const |
45+
| testOnce.py:32:1:32:25 | ControlFlowNode for FunctionExpr | testOnce.py:32:5:32:22 | GSSA Variable test_unoverwritten |
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// This query should be more focused yet.
2+
import python
3+
import semmle.python.dataflow.new.DataFlow
4+
5+
pragma[inline]
6+
predicate inCodebase(DataFlow::Node node) { exists(node.getLocation().getFile().getRelativePath()) }
7+
8+
predicate isTopLevel(DataFlow::Node node) { node.getScope() instanceof Module }
9+
10+
predicate inFocus(DataFlow::Node node) {
11+
isTopLevel(node) and
12+
inCodebase(node)
13+
}
14+
15+
from DataFlow::Node nodeFrom, DataFlow::Node nodeTo
16+
where
17+
inFocus(nodeFrom) and
18+
inFocus(nodeTo) and
19+
DataFlow::localFlowStep(nodeFrom, nodeTo)
20+
select nodeFrom, nodeTo
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import sys
2+
import os
3+
4+
sys.path.append(os.path.dirname(os.path.dirname((__file__))))
5+
from testlib import *
6+
7+
# These are defined so that we can evaluate the test code.
8+
NONSOURCE = "not a source"
9+
SOURCE = "source"
10+
11+
12+
def is_source(x):
13+
return x == "source" or x == b"source" or x == 42 or x == 42.0 or x == 42j
14+
15+
16+
def SINK(x):
17+
if is_source(x):
18+
print("OK")
19+
else:
20+
print("Unexpected flow", x)
21+
22+
23+
def SINK_F(x):
24+
if is_source(x):
25+
print("Unexpected flow", x)
26+
else:
27+
print("OK")
28+
29+
def set_foo():
30+
global foo
31+
print(foo)
32+
foo = SOURCE
33+
34+
foo = NONSOURCE
35+
set_foo()
36+
37+
@expects(2)
38+
def test_phases():
39+
global foo
40+
SINK(foo)
41+
foo = NONSOURCE
42+
set_foo()
43+
SINK(foo)

python/ql/test/experimental/dataflow/validTest.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ def check_tests_valid(testFile):
5656
check_tests_valid("variable-capture.in")
5757
check_tests_valid("variable-capture.nonlocal")
5858
check_tests_valid("variable-capture.dict")
59+
check_tests_valid("module-initialization.multiphase")
5960
# The below fails when trying to import modules
6061
# check_tests_valid("module-initialization.test")
6162
# check_tests_valid("module-initialization.testOnce")

0 commit comments

Comments
 (0)