Skip to content

Commit 5ee755d

Browse files
committed
Python: Require MISSING: flow annotations for normal data-flow tests
I had to rewrite the SINK1-SINK7 definitions, since this new requirement complained that we had to add this `MISSING: flow` annotation :D Doing this implementation also revealed that there was a bug, since I did not compare files when checking for these `MISSING:` annotations. So fixed that up in the implementation for inline taint tests as well. (extra whitespace in argumentPassing.py to avoid changing line numbers for other tests)
1 parent 2bc4a60 commit 5ee755d

File tree

8 files changed

+50
-23
lines changed

8 files changed

+50
-23
lines changed

python/ql/test/experimental/dataflow/TestUtil/NormalDataflowTest.qll

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,3 +16,22 @@ class DataFlowTest extends FlowTest {
1616
super.hasActualResult(location, element, tag, value)
1717
}
1818
}
19+
20+
query predicate missingAnnotationOnSINK(Location location, string error, string element) {
21+
error = "ERROR, you should add `# $ MISSING: flow` annotation" and
22+
exists(DataFlow::Node sink |
23+
exists(DataFlow::CallCfgNode call |
24+
// note: we only care about `SINK` and not `SINK_F`, so we have to reconstruct manually.
25+
call.getFunction().asCfgNode().(NameNode).getId() = "SINK" and
26+
(sink = call.getArg(_) or sink = call.getArgByName(_))
27+
) and
28+
location = sink.getLocation() and
29+
element = prettyExpr(sink.asExpr()) and
30+
not any(TestConfiguration config).hasFlow(_, sink) and
31+
not exists(FalseNegativeExpectation missingResult |
32+
missingResult.getTag() = "flow" and
33+
missingResult.getLocation().getFile() = location.getFile() and
34+
missingResult.getLocation().getStartLine() = location.getStartLine()
35+
)
36+
)
37+
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
missingAnnotationOnSINK
2+
failures

python/ql/test/experimental/dataflow/coverage/argumentPassing.py

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import sys
22
import os
3+
import functools
34

45
sys.path.append(os.path.dirname(os.path.dirname((__file__))))
56
from testlib import *
@@ -29,36 +30,35 @@ def SINK_F(x, unexpected=arg):
2930
SINK_TEST(x, test=lambda x: x != unexpected)
3031

3132

32-
def SINK1(x):
33-
SINK(x, expected=arg1)
33+
SINK1 = functools.partial(SINK, expected=arg1)
34+
SINK2 = functools.partial(SINK, expected=arg2)
35+
SINK3 = functools.partial(SINK, expected=arg3)
36+
SINK4 = functools.partial(SINK, expected=arg4)
37+
SINK5 = functools.partial(SINK, expected=arg5)
38+
SINK6 = functools.partial(SINK, expected=arg6)
39+
SINK7 = functools.partial(SINK, expected=arg7)
40+
41+
42+
43+
44+
45+
46+
47+
3448

3549

36-
def SINK2(x):
37-
SINK(x, expected=arg2)
3850

3951

40-
def SINK2_F(x):
41-
SINK_F(x, unexpected=arg2)
4252

4353

44-
def SINK3(x):
45-
SINK(x, expected=arg3)
4654

4755

48-
def SINK4(x):
49-
SINK(x, expected=arg4)
5056

5157

52-
def SINK5(x):
53-
SINK(x, expected=arg5)
5458

5559

56-
def SINK6(x):
57-
SINK(x, expected=arg6)
5860

5961

60-
def SINK7(x):
61-
SINK(x, expected=arg7)
6262

6363

6464
def argument_passing(

python/ql/test/experimental/dataflow/coverage/datamodel.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -90,11 +90,11 @@ def gen(x, count):
9090
n -= 1
9191

9292
iter = gen(SOURCE, 1)
93-
SINK(iter.__next__())
93+
SINK(iter.__next__()) # $ MISSING: flow
9494
# SINK_F(iter.__next__()) # throws StopIteration, FP
9595

9696
oiter = c.gen(SOURCE, 1)
97-
SINK(oiter.__next__())
97+
SINK(oiter.__next__()) # $ MISSING: flow
9898
# SINK_F(oiter.__next__()) # throws StopIteration, FP
9999

100100
# Coroutine functions
@@ -103,8 +103,8 @@ async def coro(x):
103103
return x
104104

105105
import asyncio
106-
SINK(asyncio.run(coro(SOURCE)))
107-
SINK(asyncio.run(c.coro(SOURCE)))
106+
SINK(asyncio.run(coro(SOURCE))) # $ MISSING: flow
107+
SINK(asyncio.run(c.coro(SOURCE))) # $ MISSING: flow
108108

109109
class A:
110110

@@ -116,7 +116,7 @@ async def agen(x):
116116
a = A()
117117
return await a
118118

119-
SINK(asyncio.run(agen(SOURCE)))
119+
SINK(asyncio.run(agen(SOURCE))) # $ MISSING: flow
120120

121121
# Asynchronous generator functions
122122
# A function or method which is defined using async def and which uses the yield statement is called a asynchronous generator function. Such a function, when called, returns an asynchronous iterator object which can be used in an async for statement to execute the body of the function.
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
missingAnnotationOnSINK
2+
failures

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ def test_example1_method():
6161
myobj = MyObj("OK")
6262

6363
myobj.setFoo(SOURCE)
64-
SINK(myobj.foo)
64+
SINK(myobj.foo) # $ MISSING: flow
6565

6666

6767
def test_example2():
@@ -81,7 +81,7 @@ def test_example2_method():
8181

8282
a.getObj().foo = x
8383

84-
SINK(a.obj.foo)
84+
SINK(a.obj.foo) # $ MISSING: flow
8585

8686

8787
def test_example3():
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
missingAnnotationOnSINK
2+
failures

python/ql/test/experimental/meta/InlineTaintTest.qll

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,8 @@ query predicate untaintedArgumentToEnsureTaintedNotMarkedAsMissing(
100100
not any(TestTaintTrackingConfiguration config).hasFlow(_, sink) and
101101
location = sink.getLocation() and
102102
not exists(FalseNegativeExpectation missingResult |
103+
missingResult.getTag() = "tainted" and
104+
missingResult.getLocation().getFile() = location.getFile() and
103105
missingResult.getLocation().getStartLine() = location.getStartLine()
104106
)
105107
)

0 commit comments

Comments
 (0)