diff --git a/python/ql/src/experimental/dataflow/internal/TaintTrackingPrivate.qll b/python/ql/src/experimental/dataflow/internal/TaintTrackingPrivate.qll index d1866cf420b..21af765ca7d 100644 --- a/python/ql/src/experimental/dataflow/internal/TaintTrackingPrivate.qll +++ b/python/ql/src/experimental/dataflow/internal/TaintTrackingPrivate.qll @@ -67,11 +67,7 @@ predicate subscriptStep(DataFlow::CfgNode nodeFrom, DataFlow::CfgNode nodeTo) { predicate stringMethods(DataFlow::CfgNode nodeFrom, DataFlow::CfgNode nodeTo) { // transforming something tainted into a string will make the string tainted exists(CallNode call | call = nodeTo.getNode() | - ( - call.getFunction().(NameNode).getId() = "str" - or - call.getFunction().(NameNode).getId() = "bytes" - ) and + call.getFunction().(NameNode).getId() in ["str", "bytes", "unicode"] and ( nodeFrom.getNode() = call.getArg(0) or diff --git a/python/ql/test/experimental/dataflow/tainttracking/string/TestTaint.expected b/python/ql/test/experimental/dataflow/tainttracking/string/TestTaint.expected index af462f60271..56bbd2924f7 100644 --- a/python/ql/test/experimental/dataflow/tainttracking/string/TestTaint.expected +++ b/python/ql/test/experimental/dataflow/tainttracking/string/TestTaint.expected @@ -1,64 +1,65 @@ -| test.py:24 | ok | str_operations | ts | -| test.py:25 | ok | str_operations | BinaryExpr | -| test.py:26 | ok | str_operations | BinaryExpr | -| test.py:27 | ok | str_operations | BinaryExpr | -| test.py:28 | ok | str_operations | ts[Slice] | -| test.py:29 | ok | str_operations | ts[Slice] | -| test.py:30 | ok | str_operations | ts[Slice] | -| test.py:31 | ok | str_operations | ts[0] | -| test.py:32 | ok | str_operations | str(..) | -| test.py:33 | ok | str_operations | bytes(..) | -| test.py:42 | ok | str_methods | ts.capitalize() | -| test.py:43 | ok | str_methods | ts.casefold() | -| test.py:44 | ok | str_methods | ts.center(..) | -| test.py:45 | ok | str_methods | ts.expandtabs() | -| test.py:47 | ok | str_methods | ts.format() | -| test.py:48 | ok | str_methods | "{}".format(..) | -| test.py:49 | ok | str_methods | "{unsafe}".format(..) | -| test.py:51 | ok | str_methods | ts.format_map(..) | -| test.py:52 | fail | str_methods | "{unsafe}".format_map(..) | -| test.py:54 | ok | str_methods | ts.join(..) | -| test.py:55 | fail | str_methods | "".join(..) | -| test.py:57 | ok | str_methods | ts.ljust(..) | -| test.py:58 | ok | str_methods | ts.lstrip() | -| test.py:59 | ok | str_methods | ts.lower() | -| test.py:61 | ok | str_methods | ts.replace(..) | -| test.py:62 | ok | str_methods | "safe".replace(..) | -| test.py:64 | ok | str_methods | ts.rjust(..) | -| test.py:65 | ok | str_methods | ts.rstrip() | -| test.py:66 | ok | str_methods | ts.strip() | -| test.py:67 | ok | str_methods | ts.swapcase() | -| test.py:68 | ok | str_methods | ts.title() | -| test.py:69 | ok | str_methods | ts.upper() | -| test.py:70 | ok | str_methods | ts.zfill(..) | -| test.py:72 | ok | str_methods | ts.encode(..) | -| test.py:73 | ok | str_methods | ts.encode(..).decode(..) | -| test.py:75 | ok | str_methods | tb.decode(..) | -| test.py:76 | ok | str_methods | tb.decode(..).encode(..) | -| test.py:79 | ok | str_methods | ts.partition(..) | -| test.py:80 | ok | str_methods | ts.rpartition(..) | -| test.py:81 | ok | str_methods | ts.rsplit(..) | -| test.py:82 | ok | str_methods | ts.split(..) | -| test.py:83 | ok | str_methods | ts.splitlines() | -| test.py:88 | ok | str_methods | "safe".replace(..) | -| test.py:90 | fail | str_methods | ts.join(..) | -| test.py:91 | fail | str_methods | ts.join(..) | -| test.py:101 | fail | non_syntactic | meth() | -| test.py:102 | fail | non_syntactic | _str(..) | -| test.py:111 | ok | percent_fmt | BinaryExpr | -| test.py:112 | ok | percent_fmt | BinaryExpr | -| test.py:113 | fail | percent_fmt | BinaryExpr | -| test.py:123 | fail | binary_decode_encode | base64.b64encode(..) | -| test.py:124 | fail | binary_decode_encode | base64.b64decode(..) | -| test.py:126 | fail | binary_decode_encode | base64.standard_b64encode(..) | -| test.py:127 | fail | binary_decode_encode | base64.standard_b64decode(..) | -| test.py:129 | fail | binary_decode_encode | base64.urlsafe_b64encode(..) | -| test.py:130 | fail | binary_decode_encode | base64.urlsafe_b64decode(..) | -| test.py:132 | fail | binary_decode_encode | base64.b32encode(..) | -| test.py:133 | fail | binary_decode_encode | base64.b32decode(..) | -| test.py:135 | fail | binary_decode_encode | base64.b16encode(..) | -| test.py:136 | fail | binary_decode_encode | base64.b16decode(..) | -| test.py:151 | fail | binary_decode_encode | base64.encodestring(..) | -| test.py:152 | fail | binary_decode_encode | base64.decodestring(..) | -| test.py:157 | fail | binary_decode_encode | quopri.encodestring(..) | -| test.py:158 | fail | binary_decode_encode | quopri.decodestring(..) | +| test.py:32 | ok | str_operations | ts | +| test.py:33 | ok | str_operations | BinaryExpr | +| test.py:34 | ok | str_operations | BinaryExpr | +| test.py:35 | ok | str_operations | BinaryExpr | +| test.py:36 | ok | str_operations | ts[Slice] | +| test.py:37 | ok | str_operations | ts[Slice] | +| test.py:38 | ok | str_operations | ts[Slice] | +| test.py:39 | ok | str_operations | ts[0] | +| test.py:40 | ok | str_operations | str(..) | +| test.py:41 | ok | str_operations | bytes(..) | +| test.py:42 | ok | str_operations | unicode(..) | +| test.py:51 | ok | str_methods | ts.capitalize() | +| test.py:52 | ok | str_methods | ts.casefold() | +| test.py:53 | ok | str_methods | ts.center(..) | +| test.py:54 | ok | str_methods | ts.expandtabs() | +| test.py:56 | ok | str_methods | ts.format() | +| test.py:57 | ok | str_methods | "{}".format(..) | +| test.py:58 | ok | str_methods | "{unsafe}".format(..) | +| test.py:60 | ok | str_methods | ts.format_map(..) | +| test.py:61 | fail | str_methods | "{unsafe}".format_map(..) | +| test.py:63 | ok | str_methods | ts.join(..) | +| test.py:64 | fail | str_methods | "".join(..) | +| test.py:66 | ok | str_methods | ts.ljust(..) | +| test.py:67 | ok | str_methods | ts.lstrip() | +| test.py:68 | ok | str_methods | ts.lower() | +| test.py:70 | ok | str_methods | ts.replace(..) | +| test.py:71 | ok | str_methods | "safe".replace(..) | +| test.py:73 | ok | str_methods | ts.rjust(..) | +| test.py:74 | ok | str_methods | ts.rstrip() | +| test.py:75 | ok | str_methods | ts.strip() | +| test.py:76 | ok | str_methods | ts.swapcase() | +| test.py:77 | ok | str_methods | ts.title() | +| test.py:78 | ok | str_methods | ts.upper() | +| test.py:79 | ok | str_methods | ts.zfill(..) | +| test.py:81 | ok | str_methods | ts.encode(..) | +| test.py:82 | ok | str_methods | ts.encode(..).decode(..) | +| test.py:84 | ok | str_methods | tb.decode(..) | +| test.py:85 | ok | str_methods | tb.decode(..).encode(..) | +| test.py:88 | ok | str_methods | ts.partition(..) | +| test.py:89 | ok | str_methods | ts.rpartition(..) | +| test.py:90 | ok | str_methods | ts.rsplit(..) | +| test.py:91 | ok | str_methods | ts.split(..) | +| test.py:92 | ok | str_methods | ts.splitlines() | +| test.py:97 | ok | str_methods | "safe".replace(..) | +| test.py:99 | fail | str_methods | ts.join(..) | +| test.py:100 | fail | str_methods | ts.join(..) | +| test.py:110 | fail | non_syntactic | meth() | +| test.py:111 | fail | non_syntactic | _str(..) | +| test.py:120 | ok | percent_fmt | BinaryExpr | +| test.py:121 | ok | percent_fmt | BinaryExpr | +| test.py:122 | fail | percent_fmt | BinaryExpr | +| test.py:132 | fail | binary_decode_encode | base64.b64encode(..) | +| test.py:133 | fail | binary_decode_encode | base64.b64decode(..) | +| test.py:135 | fail | binary_decode_encode | base64.standard_b64encode(..) | +| test.py:136 | fail | binary_decode_encode | base64.standard_b64decode(..) | +| test.py:138 | fail | binary_decode_encode | base64.urlsafe_b64encode(..) | +| test.py:139 | fail | binary_decode_encode | base64.urlsafe_b64decode(..) | +| test.py:141 | fail | binary_decode_encode | base64.b32encode(..) | +| test.py:142 | fail | binary_decode_encode | base64.b32decode(..) | +| test.py:144 | fail | binary_decode_encode | base64.b16encode(..) | +| test.py:145 | fail | binary_decode_encode | base64.b16decode(..) | +| test.py:160 | fail | binary_decode_encode | base64.encodestring(..) | +| test.py:161 | fail | binary_decode_encode | base64.decodestring(..) | +| test.py:166 | fail | binary_decode_encode | quopri.encodestring(..) | +| test.py:167 | fail | binary_decode_encode | quopri.decodestring(..) | diff --git a/python/ql/test/experimental/dataflow/tainttracking/string/test.py b/python/ql/test/experimental/dataflow/tainttracking/string/test.py index 8b4e972ff63..807b06ad19e 100644 --- a/python/ql/test/experimental/dataflow/tainttracking/string/test.py +++ b/python/ql/test/experimental/dataflow/tainttracking/string/test.py @@ -1,3 +1,9 @@ +import sys + +if sys.version_info[0] == 3: + unicode = str + + TAINTED_STRING = "TAINTED_STRING" TAINTED_BYTES = b"TAINTED_BYTES" @@ -20,6 +26,8 @@ def ensure_not_tainted(*args): def str_operations(): print("\n# str_operations") ts = TAINTED_STRING + tb = TAINTED_BYTES + ensure_tainted( ts, ts + "foo", @@ -30,7 +38,8 @@ def str_operations(): ts[0:1000], ts[0], str(ts), - bytes(ts), + bytes(tb), + unicode(ts), )