Skip to content

Commit a3f1f4c

Browse files
committed
Python: Add iterable unpacking tests
1 parent fa48fb0 commit a3f1f4c

File tree

6 files changed

+161
-0
lines changed

6 files changed

+161
-0
lines changed
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import python
2+
import semmle.python.security.TaintTracking
3+
import semmle.python.security.strings.Untrusted
4+
5+
class SimpleSource extends TaintSource {
6+
SimpleSource() { this.(NameNode).getId() = "TAINTED_STRING" }
7+
8+
override predicate isSourceOf(TaintKind kind) { kind instanceof ExternalStringKind }
9+
10+
override string toString() { result = "taint source" }
11+
}
12+
13+
class ListSource extends TaintSource {
14+
ListSource() { this.(NameNode).getId() = "TAINTED_LIST" }
15+
16+
override predicate isSourceOf(TaintKind kind) { kind instanceof ExternalStringSequenceKind }
17+
18+
override string toString() { result = "list taint source" }
19+
}
20+
21+
class DictSource extends TaintSource {
22+
DictSource() { this.(NameNode).getId() = "TAINTED_DICT" }
23+
24+
override predicate isSourceOf(TaintKind kind) { kind instanceof ExternalStringDictKind }
25+
26+
override string toString() { result = "dict taint source" }
27+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
| Taint [[externally controlled string]] | test.py:19 | test.py:19:10:19:18 | List | | --> | Taint [[externally controlled string]] | test.py:22 | test.py:22:28:22:29 | ll | |
2+
| Taint [[externally controlled string]] | test.py:19 | test.py:19:10:19:18 | List | | --> | Taint [[externally controlled string]] | test.py:26 | test.py:26:28:26:29 | ll | |
3+
| Taint [[externally controlled string]] | test.py:19 | test.py:19:10:19:18 | List | | --> | Taint [[externally controlled string]] | test.py:30 | test.py:30:28:30:29 | ll | |
4+
| Taint [externally controlled string] | test.py:6 | test.py:6:9:6:20 | TAINTED_LIST | | --> | Taint [externally controlled string] | test.py:7 | test.py:7:15:7:15 | l | |
5+
| Taint [externally controlled string] | test.py:12 | test.py:12:9:12:20 | TAINTED_LIST | | --> | Taint [externally controlled string] | test.py:13 | test.py:13:17:13:17 | l | |
6+
| Taint [externally controlled string] | test.py:18 | test.py:18:9:18:20 | TAINTED_LIST | | --> | Taint [externally controlled string] | test.py:19 | test.py:19:11:19:11 | l | |
7+
| Taint [externally controlled string] | test.py:18 | test.py:18:9:18:20 | TAINTED_LIST | | --> | Taint [externally controlled string] | test.py:19 | test.py:19:14:19:14 | l | |
8+
| Taint [externally controlled string] | test.py:18 | test.py:18:9:18:20 | TAINTED_LIST | | --> | Taint [externally controlled string] | test.py:19 | test.py:19:17:19:17 | l | |
9+
| Taint [externally controlled string] | test.py:19 | test.py:19:11:19:11 | l | | --> | Taint [[externally controlled string]] | test.py:19 | test.py:19:10:19:18 | List | |
10+
| Taint [externally controlled string] | test.py:19 | test.py:19:14:19:14 | l | | --> | Taint [[externally controlled string]] | test.py:19 | test.py:19:10:19:18 | List | |
11+
| Taint [externally controlled string] | test.py:19 | test.py:19:17:19:17 | l | | --> | Taint [[externally controlled string]] | test.py:19 | test.py:19:10:19:18 | List | |
12+
| Taint [externally controlled string] | test.py:43 | test.py:43:20:43:31 | TAINTED_LIST | | --> | Taint [externally controlled string] | test.py:47 | test.py:47:28:47:39 | tainted_list | |
13+
| Taint [externally controlled string] | test.py:47 | test.py:47:28:47:39 | tainted_list | | --> | Taint [[externally controlled string]] | test.py:47 | test.py:47:28:47:54 | Tuple | |
14+
| Taint [externally controlled string] | test.py:55 | test.py:55:27:55:38 | TAINTED_LIST | | --> | Taint [[externally controlled string]] | test.py:55 | test.py:55:25:55:40 | List | |
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import python
2+
import semmle.python.security.TaintTracking
3+
import Taint
4+
5+
from TaintedNode n, TaintedNode s
6+
where
7+
n.getLocation().getFile().getShortName() = "test.py" and
8+
s.getLocation().getFile().getShortName() = "test.py" and
9+
s = n.getASuccessor()
10+
select "Taint " + n.getTaintKind(), n.getLocation().toString(), n.getAstNode(), n.getContext(),
11+
" --> ", "Taint " + s.getTaintKind(), s.getLocation().toString(), s.getAstNode(), s.getContext()
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
| test.py:8 | unpacking | a | NO TAINT |
2+
| test.py:8 | unpacking | b | NO TAINT |
3+
| test.py:8 | unpacking | c | NO TAINT |
4+
| test.py:14 | unpacking_to_list | a | NO TAINT |
5+
| test.py:14 | unpacking_to_list | b | NO TAINT |
6+
| test.py:14 | unpacking_to_list | c | NO TAINT |
7+
| test.py:23 | nested | a1 | NO TAINT |
8+
| test.py:23 | nested | a2 | NO TAINT |
9+
| test.py:23 | nested | a3 | NO TAINT |
10+
| test.py:23 | nested | b | NO TAINT |
11+
| test.py:23 | nested | c | NO TAINT |
12+
| test.py:27 | nested | a1 | NO TAINT |
13+
| test.py:27 | nested | a2 | NO TAINT |
14+
| test.py:27 | nested | a3 | NO TAINT |
15+
| test.py:27 | nested | b | NO TAINT |
16+
| test.py:27 | nested | c | NO TAINT |
17+
| test.py:31 | nested | a1 | NO TAINT |
18+
| test.py:31 | nested | a2 | NO TAINT |
19+
| test.py:31 | nested | a3 | NO TAINT |
20+
| test.py:31 | nested | b | NO TAINT |
21+
| test.py:31 | nested | c | NO TAINT |
22+
| test.py:38 | unpack_from_set | a | NO TAINT |
23+
| test.py:38 | unpack_from_set | b | NO TAINT |
24+
| test.py:38 | unpack_from_set | c | NO TAINT |
25+
| test.py:48 | contrived_1 | a | NO TAINT |
26+
| test.py:48 | contrived_1 | b | NO TAINT |
27+
| test.py:48 | contrived_1 | c | NO TAINT |
28+
| test.py:48 | contrived_1 | d | NO TAINT |
29+
| test.py:48 | contrived_1 | e | NO TAINT |
30+
| test.py:48 | contrived_1 | f | NO TAINT |
31+
| test.py:56 | contrived_2 | a | NO TAINT |
32+
| test.py:56 | contrived_2 | b | NO TAINT |
33+
| test.py:56 | contrived_2 | c | NO TAINT |
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import python
2+
import semmle.python.security.TaintTracking
3+
import Taint
4+
5+
from Call call, Expr arg, string taint_string
6+
where
7+
call.getLocation().getFile().getShortName() = "test.py" and
8+
call.getFunc().(Name).getId() = "test" and
9+
arg = call.getAnArg() and
10+
(
11+
not exists(TaintedNode tainted | tainted.getAstNode() = arg) and
12+
taint_string = "NO TAINT"
13+
or
14+
exists(TaintedNode tainted | tainted.getAstNode() = arg |
15+
taint_string = tainted.getTaintKind().toString()
16+
)
17+
)
18+
select arg.getLocation().toString(), call.getScope().(Function).getName(), arg.toString(), taint_string
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
def test(*args):
2+
pass
3+
4+
5+
def unpacking():
6+
l = TAINTED_LIST
7+
a, b, c = l
8+
test(a, b, c)
9+
10+
11+
def unpacking_to_list():
12+
l = TAINTED_LIST
13+
[a, b, c] = l
14+
test(a, b, c)
15+
16+
17+
def nested():
18+
l = TAINTED_LIST
19+
ll = [l, l, l]
20+
21+
# list
22+
[[a1, a2, a3], b, c] = ll
23+
test(a1, a2, a3, b, c)
24+
25+
# tuple
26+
((a1, a2, a3), b, c) = ll
27+
test(a1, a2, a3, b, c)
28+
29+
# mixed
30+
[(a1, a2, a3), b, c] = ll
31+
test(a1, a2, a3, b, c)
32+
33+
34+
def unpack_from_set():
35+
# no guarantee on ordering ... don't know why you would ever do this
36+
a, b, c = {"foo", "bar", TAINTED_STRING}
37+
# either all should be tainted, or none of them
38+
test(a, b, c)
39+
40+
41+
def contrived_1():
42+
# A contrived example. Don't know why anyone would ever actually do this.
43+
tainted_list = TAINTED_LIST
44+
no_taint_list = [1,2,3]
45+
46+
# We don't handle this case currently, since we mark `d`, `e` and `f` as tainted.
47+
(a, b, c), (d, e, f) = tainted_list, no_taint_list
48+
test(a, b, c, d, e, f)
49+
50+
51+
def contrived_2():
52+
# A contrived example. Don't know why anyone would ever actually do this.
53+
54+
# We currently only handle taint nested 2 levels.
55+
[[[ (a,b,c) ]]] = [[[ TAINTED_LIST ]]]
56+
test(a, b, c)
57+
58+
# For Python 3, see https://www.python.org/dev/peps/pep-3132/

0 commit comments

Comments
 (0)