Skip to content

Commit cb4b4e9

Browse files
committed
Python: Taint for string multiplication
1 parent b688fe6 commit cb4b4e9

File tree

3 files changed

+64
-56
lines changed

3 files changed

+64
-56
lines changed

python/ql/src/experimental/dataflow/internal/TaintTrackingPrivate.qll

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,12 @@ predicate stringMethods(DataFlow::CfgNode nodeFrom, DataFlow::CfgNode nodeTo) {
119119
fmt.getRight() = nodeFrom.getNode()
120120
)
121121
)
122+
or
123+
// string multiplication -- `"foo" * 10`
124+
exists(BinaryExprNode mult | mult = nodeTo.getNode() |
125+
mult.getOp() instanceof Mult and
126+
mult.getLeft() = nodeFrom.getNode()
127+
)
122128
// TODO: Handle encode/decode from base64/quopri
123129
// TODO: Handle os.path.join
124130
// TODO: Handle functions in https://docs.python.org/3/library/binascii.html
Lines changed: 57 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -1,63 +1,64 @@
11
| test.py:24 | ok | str_operations | ts |
22
| test.py:25 | ok | str_operations | BinaryExpr |
33
| test.py:26 | ok | str_operations | BinaryExpr |
4-
| test.py:27 | ok | str_operations | ts[Slice] |
4+
| test.py:27 | ok | str_operations | BinaryExpr |
55
| test.py:28 | ok | str_operations | ts[Slice] |
66
| test.py:29 | ok | str_operations | ts[Slice] |
7-
| test.py:30 | ok | str_operations | ts[0] |
8-
| test.py:31 | ok | str_operations | str(..) |
9-
| test.py:32 | ok | str_operations | bytes(..) |
10-
| test.py:41 | ok | str_methods | ts.capitalize() |
11-
| test.py:42 | ok | str_methods | ts.casefold() |
12-
| test.py:43 | ok | str_methods | ts.center(..) |
13-
| test.py:44 | ok | str_methods | ts.expandtabs() |
14-
| test.py:46 | ok | str_methods | ts.format() |
15-
| test.py:47 | ok | str_methods | "{}".format(..) |
16-
| test.py:48 | ok | str_methods | "{unsafe}".format(..) |
17-
| test.py:50 | ok | str_methods | ts.format_map(..) |
18-
| test.py:51 | fail | str_methods | "{unsafe}".format_map(..) |
19-
| test.py:53 | ok | str_methods | ts.join(..) |
20-
| test.py:54 | fail | str_methods | "".join(..) |
21-
| test.py:56 | ok | str_methods | ts.ljust(..) |
22-
| test.py:57 | ok | str_methods | ts.lstrip() |
23-
| test.py:58 | ok | str_methods | ts.lower() |
24-
| test.py:60 | ok | str_methods | ts.replace(..) |
25-
| test.py:61 | ok | str_methods | "safe".replace(..) |
26-
| test.py:63 | ok | str_methods | ts.rjust(..) |
27-
| test.py:64 | ok | str_methods | ts.rstrip() |
28-
| test.py:65 | ok | str_methods | ts.strip() |
29-
| test.py:66 | ok | str_methods | ts.swapcase() |
30-
| test.py:67 | ok | str_methods | ts.title() |
31-
| test.py:68 | ok | str_methods | ts.upper() |
32-
| test.py:69 | ok | str_methods | ts.zfill(..) |
33-
| test.py:71 | ok | str_methods | ts.encode(..) |
34-
| test.py:72 | ok | str_methods | ts.encode(..).decode(..) |
35-
| test.py:74 | ok | str_methods | tb.decode(..) |
36-
| test.py:75 | ok | str_methods | tb.decode(..).encode(..) |
37-
| test.py:78 | ok | str_methods | ts.partition(..) |
38-
| test.py:79 | ok | str_methods | ts.rpartition(..) |
39-
| test.py:80 | ok | str_methods | ts.rsplit(..) |
40-
| test.py:81 | ok | str_methods | ts.split(..) |
41-
| test.py:82 | ok | str_methods | ts.splitlines() |
42-
| test.py:87 | ok | str_methods | "safe".replace(..) |
43-
| test.py:89 | fail | str_methods | ts.join(..) |
7+
| test.py:30 | ok | str_operations | ts[Slice] |
8+
| test.py:31 | ok | str_operations | ts[0] |
9+
| test.py:32 | ok | str_operations | str(..) |
10+
| test.py:33 | ok | str_operations | bytes(..) |
11+
| test.py:42 | ok | str_methods | ts.capitalize() |
12+
| test.py:43 | ok | str_methods | ts.casefold() |
13+
| test.py:44 | ok | str_methods | ts.center(..) |
14+
| test.py:45 | ok | str_methods | ts.expandtabs() |
15+
| test.py:47 | ok | str_methods | ts.format() |
16+
| test.py:48 | ok | str_methods | "{}".format(..) |
17+
| test.py:49 | ok | str_methods | "{unsafe}".format(..) |
18+
| test.py:51 | ok | str_methods | ts.format_map(..) |
19+
| test.py:52 | fail | str_methods | "{unsafe}".format_map(..) |
20+
| test.py:54 | ok | str_methods | ts.join(..) |
21+
| test.py:55 | fail | str_methods | "".join(..) |
22+
| test.py:57 | ok | str_methods | ts.ljust(..) |
23+
| test.py:58 | ok | str_methods | ts.lstrip() |
24+
| test.py:59 | ok | str_methods | ts.lower() |
25+
| test.py:61 | ok | str_methods | ts.replace(..) |
26+
| test.py:62 | ok | str_methods | "safe".replace(..) |
27+
| test.py:64 | ok | str_methods | ts.rjust(..) |
28+
| test.py:65 | ok | str_methods | ts.rstrip() |
29+
| test.py:66 | ok | str_methods | ts.strip() |
30+
| test.py:67 | ok | str_methods | ts.swapcase() |
31+
| test.py:68 | ok | str_methods | ts.title() |
32+
| test.py:69 | ok | str_methods | ts.upper() |
33+
| test.py:70 | ok | str_methods | ts.zfill(..) |
34+
| test.py:72 | ok | str_methods | ts.encode(..) |
35+
| test.py:73 | ok | str_methods | ts.encode(..).decode(..) |
36+
| test.py:75 | ok | str_methods | tb.decode(..) |
37+
| test.py:76 | ok | str_methods | tb.decode(..).encode(..) |
38+
| test.py:79 | ok | str_methods | ts.partition(..) |
39+
| test.py:80 | ok | str_methods | ts.rpartition(..) |
40+
| test.py:81 | ok | str_methods | ts.rsplit(..) |
41+
| test.py:82 | ok | str_methods | ts.split(..) |
42+
| test.py:83 | ok | str_methods | ts.splitlines() |
43+
| test.py:88 | ok | str_methods | "safe".replace(..) |
4444
| test.py:90 | fail | str_methods | ts.join(..) |
45-
| test.py:100 | fail | non_syntactic | meth() |
46-
| test.py:101 | fail | non_syntactic | _str(..) |
47-
| test.py:110 | ok | percent_fmt | BinaryExpr |
45+
| test.py:91 | fail | str_methods | ts.join(..) |
46+
| test.py:101 | fail | non_syntactic | meth() |
47+
| test.py:102 | fail | non_syntactic | _str(..) |
4848
| test.py:111 | ok | percent_fmt | BinaryExpr |
49-
| test.py:112 | fail | percent_fmt | BinaryExpr |
50-
| test.py:122 | fail | binary_decode_encode | base64.b64encode(..) |
51-
| test.py:123 | fail | binary_decode_encode | base64.b64decode(..) |
52-
| test.py:125 | fail | binary_decode_encode | base64.standard_b64encode(..) |
53-
| test.py:126 | fail | binary_decode_encode | base64.standard_b64decode(..) |
54-
| test.py:128 | fail | binary_decode_encode | base64.urlsafe_b64encode(..) |
55-
| test.py:129 | fail | binary_decode_encode | base64.urlsafe_b64decode(..) |
56-
| test.py:131 | fail | binary_decode_encode | base64.b32encode(..) |
57-
| test.py:132 | fail | binary_decode_encode | base64.b32decode(..) |
58-
| test.py:134 | fail | binary_decode_encode | base64.b16encode(..) |
59-
| test.py:135 | fail | binary_decode_encode | base64.b16decode(..) |
60-
| test.py:150 | fail | binary_decode_encode | base64.encodestring(..) |
61-
| test.py:151 | fail | binary_decode_encode | base64.decodestring(..) |
62-
| test.py:156 | fail | binary_decode_encode | quopri.encodestring(..) |
63-
| test.py:157 | fail | binary_decode_encode | quopri.decodestring(..) |
49+
| test.py:112 | ok | percent_fmt | BinaryExpr |
50+
| test.py:113 | fail | percent_fmt | BinaryExpr |
51+
| test.py:123 | fail | binary_decode_encode | base64.b64encode(..) |
52+
| test.py:124 | fail | binary_decode_encode | base64.b64decode(..) |
53+
| test.py:126 | fail | binary_decode_encode | base64.standard_b64encode(..) |
54+
| test.py:127 | fail | binary_decode_encode | base64.standard_b64decode(..) |
55+
| test.py:129 | fail | binary_decode_encode | base64.urlsafe_b64encode(..) |
56+
| test.py:130 | fail | binary_decode_encode | base64.urlsafe_b64decode(..) |
57+
| test.py:132 | fail | binary_decode_encode | base64.b32encode(..) |
58+
| test.py:133 | fail | binary_decode_encode | base64.b32decode(..) |
59+
| test.py:135 | fail | binary_decode_encode | base64.b16encode(..) |
60+
| test.py:136 | fail | binary_decode_encode | base64.b16decode(..) |
61+
| test.py:151 | fail | binary_decode_encode | base64.encodestring(..) |
62+
| test.py:152 | fail | binary_decode_encode | base64.decodestring(..) |
63+
| test.py:157 | fail | binary_decode_encode | quopri.encodestring(..) |
64+
| test.py:158 | fail | binary_decode_encode | quopri.decodestring(..) |

python/ql/test/experimental/dataflow/tainttracking/string/test.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ def str_operations():
2424
ts,
2525
ts + "foo",
2626
"foo" + ts,
27+
ts * 5,
2728
ts[0 : len(ts)],
2829
ts[:],
2930
ts[0:1000],

0 commit comments

Comments
 (0)