JS: Update TaintTracking test

This commit is contained in:
Asger F
2023-10-06 15:12:18 +02:00
parent b5ad36686e
commit 2eff07f476
20 changed files with 598 additions and 157 deletions

View File

@@ -1,17 +1,29 @@
typeInferenceMismatch
| call-apply.js:27:14:27:21 | source() | call-apply.js:3:1:5:1 | 'arguments' object of function foo1 |
| call-apply.js:27:14:27:21 | source() | call-apply.js:7:1:9:1 | 'arguments' object of function foo2 |
| call-apply.js:27:14:27:21 | source() | call-apply.js:12:10:12:30 | reflective call |
| call-apply.js:27:14:27:21 | source() | call-apply.js:16:10:16:40 | reflective call |
| call-apply.js:27:14:27:21 | source() | call-apply.js:23:1:25:1 | 'arguments' object of function foo1_sink |
| call-apply.js:27:14:27:21 | source() | call-apply.js:29:6:29:32 | reflective call |
| call-apply.js:27:14:27:21 | source() | call-apply.js:32:6:32:35 | reflective call |
| call-apply.js:27:14:27:21 | source() | call-apply.js:33:6:33:35 | reflective call |
| call-apply.js:27:14:27:21 | source() | call-apply.js:64:3:66:3 | 'arguments' object of function sinkArguments1 |
| call-apply.js:27:14:27:21 | source() | call-apply.js:67:3:69:3 | 'arguments' object of function sinkArguments0 |
| call-apply.js:27:14:27:21 | source() | call-apply.js:71:3:74:3 | 'arguments' object of function fowardArguments |
| destruct.js:20:7:20:14 | source() | destruct.js:13:14:13:19 | [a, b] |
#select
legacyDataFlowDifference
| bound-function.js:27:8:27:15 | source() | bound-function.js:30:10:30:10 | y | only flow with OLD data flow library |
| call-apply.js:45:8:45:15 | source() | call-apply.js:55:6:55:13 | foo(obj) | only flow with NEW data flow library |
| callbacks.js:37:17:37:24 | source() | callbacks.js:38:35:38:35 | x | only flow with NEW data flow library |
| callbacks.js:37:17:37:24 | source() | callbacks.js:41:10:41:10 | x | only flow with NEW data flow library |
| callbacks.js:44:17:44:24 | source() | callbacks.js:37:37:37:37 | x | only flow with NEW data flow library |
| callbacks.js:44:17:44:24 | source() | callbacks.js:38:35:38:35 | x | only flow with NEW data flow library |
| capture-flow.js:89:13:89:20 | source() | capture-flow.js:89:6:89:21 | test3c(source()) | only flow with NEW data flow library |
| capture-flow.js:101:12:101:19 | source() | capture-flow.js:102:6:102:20 | test5("safe")() | only flow with OLD data flow library |
| constructor-calls.js:4:18:4:25 | source() | constructor-calls.js:40:8:40:14 | e.taint | only flow with NEW data flow library |
| constructor-calls.js:4:18:4:25 | source() | constructor-calls.js:44:8:44:19 | f_safe.taint | only flow with NEW data flow library |
| constructor-calls.js:20:15:20:22 | source() | constructor-calls.js:39:8:39:14 | e.param | only flow with NEW data flow library |
| exceptions.js:53:14:53:21 | source() | exceptions.js:54:10:54:10 | e | only flow with NEW data flow library |
| getters-and-setters.js:53:21:53:28 | source() | getters-and-setters.js:53:10:53:30 | getX(ne ... rce())) | only flow with NEW data flow library |
| nested-props.js:14:15:14:22 | source() | nested-props.js:15:10:15:16 | obj.x.y | only flow with NEW data flow library |
| nested-props.js:19:17:19:24 | source() | nested-props.js:20:10:20:18 | obj.x.y.z | only flow with NEW data flow library |
| nested-props.js:27:18:27:25 | source() | nested-props.js:28:10:28:14 | obj.x | only flow with NEW data flow library |
| nested-props.js:51:22:51:29 | source() | nested-props.js:52:10:52:16 | obj.x.y | only flow with NEW data flow library |
| object-bypass-sanitizer.js:35:29:35:36 | source() | object-bypass-sanitizer.js:23:14:23:20 | obj.foo | only flow with OLD data flow library |
| object-bypass-sanitizer.js:35:29:35:36 | source() | object-bypass-sanitizer.js:28:10:28:30 | sanitiz ... bj).foo | only flow with OLD data flow library |
| promise.js:12:20:12:27 | source() | promise.js:13:8:13:23 | resolver.promise | only flow with OLD data flow library |
| sanitizer-guards.js:57:11:57:18 | source() | sanitizer-guards.js:64:8:64:8 | x | only flow with NEW data flow library |
| stringification-read-steps.js:7:22:7:29 | source() | stringification-read-steps.js:17:10:17:31 | JSON.st ... object) | only flow with NEW data flow library |
| stringification-read-steps.js:7:22:7:29 | source() | stringification-read-steps.js:25:10:25:31 | JSON.st ... object) | only flow with NEW data flow library |
consistencyIssue
flow
| access-path-sanitizer.js:2:18:2:25 | source() | access-path-sanitizer.js:4:8:4:12 | obj.x |
| addexpr.js:4:10:4:17 | source() | addexpr.js:7:8:7:8 | x |
| addexpr.js:11:15:11:22 | source() | addexpr.js:21:8:21:12 | value |
@@ -46,22 +58,22 @@ typeInferenceMismatch
| booleanOps.js:2:11:2:18 | source() | booleanOps.js:13:10:13:10 | x |
| booleanOps.js:2:11:2:18 | source() | booleanOps.js:19:10:19:10 | x |
| booleanOps.js:2:11:2:18 | source() | booleanOps.js:22:10:22:10 | x |
| bound-function.js:12:12:12:19 | source() | bound-function.js:4:10:4:10 | y |
| bound-function.js:14:6:14:13 | source() | bound-function.js:4:10:4:10 | y |
| bound-function.js:22:8:22:15 | source() | bound-function.js:25:10:25:10 | y |
| bound-function.js:45:10:45:17 | source() | bound-function.js:45:6:45:18 | id3(source()) |
| bound-function.js:49:12:49:19 | source() | bound-function.js:54:6:54:14 | source0() |
| bound-function.js:49:12:49:19 | source() | bound-function.js:55:6:55:14 | source1() |
| bound-function.js:17:21:17:28 | source() | bound-function.js:5:10:5:16 | y.test2 |
| bound-function.js:19:15:19:22 | source() | bound-function.js:6:10:6:16 | y.test3 |
| bound-function.js:50:10:50:17 | source() | bound-function.js:50:6:50:18 | id3(source()) |
| bound-function.js:54:12:54:19 | source() | bound-function.js:59:6:59:14 | source0() |
| bound-function.js:54:12:54:19 | source() | bound-function.js:60:6:60:14 | source1() |
| call-apply.js:27:14:27:21 | source() | call-apply.js:24:8:24:11 | arg1 |
| call-apply.js:27:14:27:21 | source() | call-apply.js:29:6:29:32 | foo1.ca ... ce, "") |
| call-apply.js:27:14:27:21 | source() | call-apply.js:32:6:32:35 | foo1.ap ... e, ""]) |
| call-apply.js:27:14:27:21 | source() | call-apply.js:33:6:33:35 | foo2.ap ... e, ""]) |
| call-apply.js:27:14:27:21 | source() | call-apply.js:40:6:40:29 | foo1_ap ... e, ""]) |
| call-apply.js:27:14:27:21 | source() | call-apply.js:46:6:46:28 | foo1_ca ... e, ""]) |
| call-apply.js:27:14:27:21 | source() | call-apply.js:47:6:47:28 | foo1_ca ... ource]) |
| call-apply.js:27:14:27:21 | source() | call-apply.js:65:10:65:21 | arguments[1] |
| call-apply.js:27:14:27:21 | source() | call-apply.js:68:10:68:21 | arguments[0] |
| call-apply.js:87:17:87:24 | source() | call-apply.js:84:8:84:11 | this |
| call-apply.js:27:14:27:21 | source() | call-apply.js:34:6:34:29 | foo1_ap ... e, ""]) |
| call-apply.js:27:14:27:21 | source() | call-apply.js:40:6:40:28 | foo1_ca ... e, ""]) |
| call-apply.js:27:14:27:21 | source() | call-apply.js:41:6:41:28 | foo1_ca ... ource]) |
| call-apply.js:27:14:27:21 | source() | call-apply.js:59:10:59:21 | arguments[1] |
| call-apply.js:27:14:27:21 | source() | call-apply.js:62:10:62:21 | arguments[0] |
| call-apply.js:45:8:45:15 | source() | call-apply.js:55:6:55:13 | foo(obj) |
| call-apply.js:81:17:81:24 | source() | call-apply.js:78:8:78:11 | this |
| callbacks.js:4:6:4:13 | source() | callbacks.js:34:27:34:27 | x |
| callbacks.js:4:6:4:13 | source() | callbacks.js:35:27:35:27 | x |
| callbacks.js:5:6:5:13 | source() | callbacks.js:34:27:34:27 | x |
@@ -69,6 +81,10 @@ typeInferenceMismatch
| callbacks.js:25:16:25:23 | source() | callbacks.js:47:26:47:26 | x |
| callbacks.js:25:16:25:23 | source() | callbacks.js:48:26:48:26 | x |
| callbacks.js:37:17:37:24 | source() | callbacks.js:37:37:37:37 | x |
| callbacks.js:37:17:37:24 | source() | callbacks.js:38:35:38:35 | x |
| callbacks.js:37:17:37:24 | source() | callbacks.js:41:10:41:10 | x |
| callbacks.js:44:17:44:24 | source() | callbacks.js:37:37:37:37 | x |
| callbacks.js:44:17:44:24 | source() | callbacks.js:38:35:38:35 | x |
| callbacks.js:44:17:44:24 | source() | callbacks.js:41:10:41:10 | x |
| callbacks.js:50:18:50:25 | source() | callbacks.js:30:29:30:29 | y |
| callbacks.js:51:18:51:25 | source() | callbacks.js:30:29:30:29 | y |
@@ -76,6 +92,27 @@ typeInferenceMismatch
| capture-flow.js:9:11:9:18 | source() | capture-flow.js:14:10:14:16 | outer() |
| capture-flow.js:9:11:9:18 | source() | capture-flow.js:19:6:19:16 | outerMost() |
| capture-flow.js:31:14:31:21 | source() | capture-flow.js:31:6:31:22 | confuse(source()) |
| capture-flow.js:45:12:45:19 | source() | capture-flow.js:45:6:45:20 | test3(source()) |
| capture-flow.js:60:13:60:20 | source() | capture-flow.js:60:6:60:21 | test3a(source()) |
| capture-flow.js:76:13:76:20 | source() | capture-flow.js:76:6:76:21 | test3b(source()) |
| capture-flow.js:89:13:89:20 | source() | capture-flow.js:89:6:89:21 | test3c(source()) |
| capture-flow.js:93:13:93:20 | source() | capture-flow.js:96:6:96:14 | test4()() |
| capture-flow.js:101:12:101:19 | source() | capture-flow.js:101:6:101:22 | test5(source())() |
| capture-flow.js:110:12:110:19 | source() | capture-flow.js:106:14:106:14 | x |
| capture-flow.js:118:37:118:44 | source() | capture-flow.js:114:14:114:14 | x |
| capture-flow.js:126:25:126:32 | source() | capture-flow.js:123:14:123:26 | orderingTaint |
| capture-flow.js:126:25:126:32 | source() | capture-flow.js:129:14:129:26 | orderingTaint |
| capture-flow.js:177:26:177:33 | source() | capture-flow.js:173:14:173:14 | x |
| capture-flow.js:187:34:187:41 | source() | capture-flow.js:183:14:183:14 | x |
| capture-flow.js:195:24:195:31 | source() | capture-flow.js:191:14:191:14 | x |
| capture-flow.js:205:24:205:31 | source() | capture-flow.js:200:18:200:18 | x |
| capture-flow.js:225:13:225:20 | source() | capture-flow.js:220:51:220:59 | fileOrDir |
| capture-flow.js:230:9:230:16 | source() | capture-flow.js:233:14:233:14 | x |
| capture-flow.js:259:23:259:30 | source() | capture-flow.js:243:18:243:40 | objectW ... s.field |
| capture-flow.js:259:23:259:30 | source() | capture-flow.js:247:18:247:40 | objectW ... s.field |
| capture-flow.js:259:23:259:30 | source() | capture-flow.js:248:18:248:27 | this.field |
| capture-flow.js:259:23:259:30 | source() | capture-flow.js:252:14:252:36 | objectW ... s.field |
| capture-flow.js:259:23:259:30 | source() | capture-flow.js:253:14:253:23 | this.field |
| captured-sanitizer.js:25:3:25:10 | source() | captured-sanitizer.js:15:10:15:10 | x |
| case.js:2:16:2:23 | source() | case.js:5:8:5:35 | changeC ... source) |
| case.js:2:16:2:23 | source() | case.js:8:8:8:24 | camelCase(source) |
@@ -88,12 +125,15 @@ typeInferenceMismatch
| closure.js:6:15:6:22 | source() | closure.js:8:8:8:31 | string. ... (taint) |
| closure.js:6:15:6:22 | source() | closure.js:9:8:9:25 | string.trim(taint) |
| closure.js:6:15:6:22 | source() | closure.js:10:8:10:33 | string. ... nt, 50) |
| constructor-calls.js:4:18:4:25 | source() | constructor-calls.js:18:8:18:14 | c.taint |
| constructor-calls.js:4:18:4:25 | source() | constructor-calls.js:22:8:22:19 | c_safe.taint |
| constructor-calls.js:10:16:10:23 | source() | constructor-calls.js:26:8:26:14 | d.taint |
| constructor-calls.js:10:16:10:23 | source() | constructor-calls.js:30:8:30:19 | d_safe.taint |
| constructor-calls.js:14:15:14:22 | source() | constructor-calls.js:17:8:17:14 | c.param |
| constructor-calls.js:14:15:14:22 | source() | constructor-calls.js:25:8:25:14 | d.param |
| constructor-calls.js:4:18:4:25 | source() | constructor-calls.js:24:8:24:14 | c.taint |
| constructor-calls.js:4:18:4:25 | source() | constructor-calls.js:28:8:28:19 | c_safe.taint |
| constructor-calls.js:4:18:4:25 | source() | constructor-calls.js:40:8:40:14 | e.taint |
| constructor-calls.js:4:18:4:25 | source() | constructor-calls.js:44:8:44:19 | f_safe.taint |
| constructor-calls.js:10:16:10:23 | source() | constructor-calls.js:32:8:32:14 | d.taint |
| constructor-calls.js:10:16:10:23 | source() | constructor-calls.js:36:8:36:19 | d_safe.taint |
| constructor-calls.js:20:15:20:22 | source() | constructor-calls.js:23:8:23:14 | c.param |
| constructor-calls.js:20:15:20:22 | source() | constructor-calls.js:31:8:31:14 | d.param |
| constructor-calls.js:20:15:20:22 | source() | constructor-calls.js:39:8:39:14 | e.param |
| destruct.js:20:7:20:14 | source() | destruct.js:5:10:5:10 | z |
| destruct.js:20:7:20:14 | source() | destruct.js:8:10:8:10 | w |
| destruct.js:20:7:20:14 | source() | destruct.js:11:10:11:10 | q |
@@ -104,6 +144,7 @@ typeInferenceMismatch
| exceptions.js:21:17:21:24 | source() | exceptions.js:24:10:24:21 | e.toString() |
| exceptions.js:21:17:21:24 | source() | exceptions.js:25:10:25:18 | e.message |
| exceptions.js:21:17:21:24 | source() | exceptions.js:26:10:26:19 | e.fileName |
| exceptions.js:53:14:53:21 | source() | exceptions.js:54:10:54:10 | e |
| exceptions.js:59:24:59:31 | source() | exceptions.js:61:12:61:12 | e |
| exceptions.js:88:6:88:13 | source() | exceptions.js:11:10:11:10 | e |
| exceptions.js:88:6:88:13 | source() | exceptions.js:32:10:32:10 | e |
@@ -125,12 +166,14 @@ typeInferenceMismatch
| getters-and-setters.js:6:20:6:27 | source() | getters-and-setters.js:13:18:13:20 | c.x |
| getters-and-setters.js:27:15:27:22 | source() | getters-and-setters.js:23:18:23:18 | v |
| getters-and-setters.js:47:23:47:30 | source() | getters-and-setters.js:45:14:45:16 | c.x |
| getters-and-setters.js:53:21:53:28 | source() | getters-and-setters.js:53:10:53:30 | getX(ne ... rce())) |
| getters-and-setters.js:60:20:60:27 | source() | getters-and-setters.js:66:10:66:14 | obj.x |
| getters-and-setters.js:67:13:67:20 | source() | getters-and-setters.js:63:18:63:22 | value |
| getters-and-setters.js:79:20:79:27 | source() | getters-and-setters.js:88:10:88:18 | new C().x |
| getters-and-setters.js:79:20:79:27 | source() | getters-and-setters.js:92:14:92:16 | c.x |
| getters-and-setters.js:79:20:79:27 | source() | getters-and-setters.js:100:10:100:22 | getX(new C()) |
| getters-and-setters.js:89:17:89:24 | source() | getters-and-setters.js:82:18:82:22 | value |
| implied-receiver.js:4:16:4:23 | source() | implied-receiver.js:7:18:7:25 | this.foo |
| importedReactComponent.jsx:4:40:4:47 | source() | exportedReactComponent.jsx:2:10:2:19 | props.text |
| indexOf.js:4:11:4:18 | source() | indexOf.js:9:10:9:10 | x |
| json-stringify.js:2:16:2:23 | source() | json-stringify.js:5:8:5:29 | JSON.st ... source) |
@@ -156,12 +199,14 @@ typeInferenceMismatch
| json-stringify.js:3:15:3:22 | source() | json-stringify.js:8:8:8:31 | jsonStr ... (taint) |
| nested-props.js:4:13:4:20 | source() | nested-props.js:5:10:5:14 | obj.x |
| nested-props.js:9:18:9:25 | source() | nested-props.js:10:10:10:16 | obj.x.y |
| nested-props.js:14:15:14:22 | source() | nested-props.js:15:10:15:16 | obj.x.y |
| nested-props.js:19:17:19:24 | source() | nested-props.js:20:10:20:18 | obj.x.y.z |
| nested-props.js:27:18:27:25 | source() | nested-props.js:28:10:28:14 | obj.x |
| nested-props.js:35:13:35:20 | source() | nested-props.js:36:10:36:20 | doLoad(obj) |
| nested-props.js:43:13:43:20 | source() | nested-props.js:44:10:44:18 | id(obj).x |
| nested-props.js:51:22:51:29 | source() | nested-props.js:52:10:52:16 | obj.x.y |
| nested-props.js:67:31:67:38 | source() | nested-props.js:68:10:68:10 | x |
| nested-props.js:77:36:77:43 | source() | nested-props.js:78:10:78:10 | x |
| object-bypass-sanitizer.js:35:29:35:36 | source() | object-bypass-sanitizer.js:23:14:23:20 | obj.foo |
| object-bypass-sanitizer.js:35:29:35:36 | source() | object-bypass-sanitizer.js:28:10:28:30 | sanitiz ... bj).foo |
| partialCalls.js:4:17:4:24 | source() | partialCalls.js:17:14:17:14 | x |
| partialCalls.js:4:17:4:24 | source() | partialCalls.js:20:14:20:14 | y |
| partialCalls.js:4:17:4:24 | source() | partialCalls.js:30:14:30:20 | x.value |
@@ -170,7 +215,8 @@ typeInferenceMismatch
| promise.js:4:24:4:31 | source() | promise.js:4:8:4:32 | Promise ... urce()) |
| promise.js:5:25:5:32 | source() | promise.js:5:8:5:33 | bluebir ... urce()) |
| promise.js:10:24:10:31 | source() | promise.js:10:8:10:32 | Promise ... urce()) |
| promise.js:12:20:12:27 | source() | promise.js:13:8:13:23 | resolver.promise |
| promise.js:18:22:18:29 | source() | promise.js:24:10:24:10 | e |
| promise.js:33:21:33:28 | source() | promise.js:38:10:38:10 | e |
| rxjs.js:3:1:3:8 | source() | rxjs.js:10:14:10:17 | data |
| rxjs.js:13:1:13:8 | source() | rxjs.js:17:23:17:23 | x |
| rxjs.js:13:1:13:8 | source() | rxjs.js:18:23:18:23 | x |
@@ -185,6 +231,7 @@ typeInferenceMismatch
| sanitizer-guards.js:13:14:13:21 | source() | sanitizer-guards.js:26:9:26:14 | this.x |
| sanitizer-guards.js:43:11:43:18 | source() | sanitizer-guards.js:45:8:45:8 | x |
| sanitizer-guards.js:43:11:43:18 | source() | sanitizer-guards.js:48:10:48:10 | x |
| sanitizer-guards.js:57:11:57:18 | source() | sanitizer-guards.js:64:8:64:8 | x |
| sanitizer-guards.js:68:11:68:18 | source() | sanitizer-guards.js:75:8:75:8 | x |
| sanitizer-guards.js:79:11:79:18 | source() | sanitizer-guards.js:81:8:81:8 | x |
| sanitizer-guards.js:79:11:79:18 | source() | sanitizer-guards.js:84:10:84:10 | x |
@@ -208,6 +255,8 @@ typeInferenceMismatch
| string-replace.js:3:13:3:20 | source() | string-replace.js:21:6:21:41 | safe(). ... taint) |
| string-replace.js:3:13:3:20 | source() | string-replace.js:22:6:22:48 | safe(). ... taint) |
| string-replace.js:3:13:3:20 | source() | string-replace.js:24:6:24:45 | taint.r ... + '!') |
| stringification-read-steps.js:7:22:7:29 | source() | stringification-read-steps.js:17:10:17:31 | JSON.st ... object) |
| stringification-read-steps.js:7:22:7:29 | source() | stringification-read-steps.js:25:10:25:31 | JSON.st ... object) |
| summarize-store-load-in-call.js:9:15:9:22 | source() | summarize-store-load-in-call.js:9:10:9:23 | blah(source()) |
| thisAssignments.js:4:17:4:24 | source() | thisAssignments.js:5:10:5:18 | obj.field |
| thisAssignments.js:7:19:7:26 | source() | thisAssignments.js:8:10:8:20 | this.field2 |

View File

@@ -1,5 +1,6 @@
import javascript
import semmle.javascript.dataflow.InferredTypes
import testUtilities.ConsistencyChecking
DataFlow::CallNode getACall(string name) {
result.getCalleeName() = name
@@ -7,53 +8,53 @@ DataFlow::CallNode getACall(string name) {
result.getCalleeNode().getALocalSource() = DataFlow::globalVarRef(name)
}
class Sink extends DataFlow::Node {
Sink() { this = getACall("sink").getAnArgument() }
}
module TestConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node node) { node = getACall("source") }
/**
* A node that shouldn't be taintable according to the type inference,
* as it claims to be neither an object nor a string.
*/
class UntaintableNode extends DataFlow::Node {
UntaintableNode() {
not this.analyze().getAType() = TTObject() and
not this.analyze().getAType() = TTString()
predicate isSink(DataFlow::Node node) { node = getACall("sink").getAnArgument() }
predicate isBarrier(DataFlow::Node node) {
node.(DataFlow::InvokeNode).getCalleeName().matches("sanitizer_%") or
node = DataFlow::MakeBarrierGuard<BasicSanitizerGuard>::getABarrierNode() or
node = TaintTracking::AdHocWhitelistCheckSanitizer::getABarrierNode()
}
}
class BasicConfig extends TaintTracking::Configuration {
BasicConfig() { this = "BasicConfig" }
module TestFlow = TaintTracking::Global<TestConfig>;
override predicate isSource(DataFlow::Node node) { node = getACall("source") }
class LegacyConfig extends TaintTracking::Configuration {
LegacyConfig() { this = "LegacyConfig" }
override predicate isSink(DataFlow::Node node) {
node instanceof Sink
or
node instanceof UntaintableNode
}
override predicate isSource(DataFlow::Node node) { TestConfig::isSource(node) }
override predicate isSink(DataFlow::Node node) { TestConfig::isSink(node) }
override predicate isSanitizer(DataFlow::Node node) {
node.(DataFlow::InvokeNode).getCalleeName().matches("sanitizer_%")
}
override predicate isSanitizerGuard(TaintTracking::SanitizerGuardNode node) {
node instanceof BasicSanitizerGuard
node instanceof BasicSanitizerGuard or
node instanceof TaintTracking::AdHocWhitelistCheckSanitizer
}
}
import testUtilities.LegacyDataFlowDiff::DataFlowDiff<TestFlow, LegacyConfig>
class BasicSanitizerGuard extends TaintTracking::SanitizerGuardNode, DataFlow::CallNode {
BasicSanitizerGuard() { this = getACall("isSafe") }
override predicate sanitizes(boolean outcome, Expr e) {
override predicate sanitizes(boolean outcome, Expr e) { this.blocksExpr(outcome, e) }
predicate blocksExpr(boolean outcome, Expr e) {
outcome = true and e = this.getArgument(0).asExpr()
}
}
query predicate typeInferenceMismatch(DataFlow::Node source, UntaintableNode sink) {
any(BasicConfig cfg).hasFlow(source, sink)
}
query predicate flow = TestFlow::flow/2;
from BasicConfig cfg, DataFlow::Node src, Sink sink
where cfg.hasFlow(src, sink)
select src, sink
class Consistency extends ConsistencyConfiguration {
Consistency() { this = "Consistency" }
override DataFlow::Node getAnAlert() { TestFlow::flowTo(result) }
}

View File

@@ -1,9 +1,34 @@
legacyDataFlowDifference
| arrays-init.js:2:16:2:23 | source() | arrays-init.js:38:8:38:13 | arr[5] | only flow with NEW data flow library |
| bound-function.js:27:8:27:15 | source() | bound-function.js:30:10:30:10 | y | only flow with OLD data flow library |
| call-apply.js:27:14:27:21 | source() | call-apply.js:34:6:34:29 | foo1_ap ... e, ""]) | only flow with NEW data flow library |
| call-apply.js:45:8:45:15 | source() | call-apply.js:55:6:55:13 | foo(obj) | only flow with NEW data flow library |
| callbacks.js:37:17:37:24 | source() | callbacks.js:38:35:38:35 | x | only flow with NEW data flow library |
| callbacks.js:37:17:37:24 | source() | callbacks.js:41:10:41:10 | x | only flow with NEW data flow library |
| callbacks.js:44:17:44:24 | source() | callbacks.js:37:37:37:37 | x | only flow with NEW data flow library |
| callbacks.js:44:17:44:24 | source() | callbacks.js:38:35:38:35 | x | only flow with NEW data flow library |
| capture-flow.js:89:13:89:20 | source() | capture-flow.js:89:6:89:21 | test3c(source()) | only flow with NEW data flow library |
| capture-flow.js:101:12:101:19 | source() | capture-flow.js:102:6:102:20 | test5("safe")() | only flow with OLD data flow library |
| constructor-calls.js:4:18:4:25 | source() | constructor-calls.js:40:8:40:14 | e.taint | only flow with NEW data flow library |
| constructor-calls.js:4:18:4:25 | source() | constructor-calls.js:44:8:44:19 | f_safe.taint | only flow with NEW data flow library |
| constructor-calls.js:20:15:20:22 | source() | constructor-calls.js:39:8:39:14 | e.param | only flow with NEW data flow library |
| exceptions.js:53:14:53:21 | source() | exceptions.js:54:10:54:10 | e | only flow with NEW data flow library |
| getters-and-setters.js:53:21:53:28 | source() | getters-and-setters.js:53:10:53:30 | getX(ne ... rce())) | only flow with NEW data flow library |
| nested-props.js:14:15:14:22 | source() | nested-props.js:15:10:15:16 | obj.x.y | only flow with NEW data flow library |
| nested-props.js:19:17:19:24 | source() | nested-props.js:20:10:20:18 | obj.x.y.z | only flow with NEW data flow library |
| nested-props.js:27:18:27:25 | source() | nested-props.js:28:10:28:14 | obj.x | only flow with NEW data flow library |
| nested-props.js:51:22:51:29 | source() | nested-props.js:52:10:52:16 | obj.x.y | only flow with NEW data flow library |
| sanitizer-guards.js:57:11:57:18 | source() | sanitizer-guards.js:64:8:64:8 | x | only flow with NEW data flow library |
| tst.js:2:13:2:20 | source() | tst.js:35:14:35:16 | ary | only flow with NEW data flow library |
| tst.js:2:13:2:20 | source() | tst.js:41:14:41:16 | ary | only flow with NEW data flow library |
flow
| access-path-sanitizer.js:2:18:2:25 | source() | access-path-sanitizer.js:4:8:4:12 | obj.x |
| advanced-callgraph.js:2:13:2:20 | source() | advanced-callgraph.js:6:22:6:22 | v |
| arrays-init.js:2:16:2:23 | source() | arrays-init.js:17:8:17:13 | arr[1] |
| arrays-init.js:2:16:2:23 | source() | arrays-init.js:22:8:22:13 | arr[6] |
| arrays-init.js:2:16:2:23 | source() | arrays-init.js:28:8:28:13 | arr[1] |
| arrays-init.js:2:16:2:23 | source() | arrays-init.js:34:8:34:13 | arr[1] |
| arrays-init.js:2:16:2:23 | source() | arrays-init.js:38:8:38:13 | arr[5] |
| arrays-init.js:2:16:2:23 | source() | arrays-init.js:43:10:43:15 | arr[i] |
| arrays-init.js:2:16:2:23 | source() | arrays-init.js:55:10:55:15 | arr[i] |
| arrays-init.js:2:16:2:23 | source() | arrays-init.js:61:10:61:13 | item |
@@ -13,18 +38,19 @@
| booleanOps.js:2:11:2:18 | source() | booleanOps.js:13:10:13:10 | x |
| booleanOps.js:2:11:2:18 | source() | booleanOps.js:19:10:19:10 | x |
| booleanOps.js:2:11:2:18 | source() | booleanOps.js:22:10:22:10 | x |
| bound-function.js:12:12:12:19 | source() | bound-function.js:4:10:4:10 | y |
| bound-function.js:14:6:14:13 | source() | bound-function.js:4:10:4:10 | y |
| bound-function.js:22:8:22:15 | source() | bound-function.js:25:10:25:10 | y |
| bound-function.js:45:10:45:17 | source() | bound-function.js:45:6:45:18 | id3(source()) |
| bound-function.js:49:12:49:19 | source() | bound-function.js:54:6:54:14 | source0() |
| bound-function.js:49:12:49:19 | source() | bound-function.js:55:6:55:14 | source1() |
| bound-function.js:17:21:17:28 | source() | bound-function.js:5:10:5:16 | y.test2 |
| bound-function.js:19:15:19:22 | source() | bound-function.js:6:10:6:16 | y.test3 |
| bound-function.js:50:10:50:17 | source() | bound-function.js:50:6:50:18 | id3(source()) |
| bound-function.js:54:12:54:19 | source() | bound-function.js:59:6:59:14 | source0() |
| bound-function.js:54:12:54:19 | source() | bound-function.js:60:6:60:14 | source1() |
| call-apply.js:27:14:27:21 | source() | call-apply.js:24:8:24:11 | arg1 |
| call-apply.js:27:14:27:21 | source() | call-apply.js:29:6:29:32 | foo1.ca ... ce, "") |
| call-apply.js:27:14:27:21 | source() | call-apply.js:32:6:32:35 | foo1.ap ... e, ""]) |
| call-apply.js:27:14:27:21 | source() | call-apply.js:46:6:46:28 | foo1_ca ... e, ""]) |
| call-apply.js:27:14:27:21 | source() | call-apply.js:68:10:68:21 | arguments[0] |
| call-apply.js:87:17:87:24 | source() | call-apply.js:84:8:84:11 | this |
| call-apply.js:27:14:27:21 | source() | call-apply.js:34:6:34:29 | foo1_ap ... e, ""]) |
| call-apply.js:27:14:27:21 | source() | call-apply.js:40:6:40:28 | foo1_ca ... e, ""]) |
| call-apply.js:27:14:27:21 | source() | call-apply.js:62:10:62:21 | arguments[0] |
| call-apply.js:45:8:45:15 | source() | call-apply.js:55:6:55:13 | foo(obj) |
| call-apply.js:81:17:81:24 | source() | call-apply.js:78:8:78:11 | this |
| callbacks.js:4:6:4:13 | source() | callbacks.js:34:27:34:27 | x |
| callbacks.js:4:6:4:13 | source() | callbacks.js:35:27:35:27 | x |
| callbacks.js:5:6:5:13 | source() | callbacks.js:34:27:34:27 | x |
@@ -32,6 +58,10 @@
| callbacks.js:25:16:25:23 | source() | callbacks.js:47:26:47:26 | x |
| callbacks.js:25:16:25:23 | source() | callbacks.js:48:26:48:26 | x |
| callbacks.js:37:17:37:24 | source() | callbacks.js:37:37:37:37 | x |
| callbacks.js:37:17:37:24 | source() | callbacks.js:38:35:38:35 | x |
| callbacks.js:37:17:37:24 | source() | callbacks.js:41:10:41:10 | x |
| callbacks.js:44:17:44:24 | source() | callbacks.js:37:37:37:37 | x |
| callbacks.js:44:17:44:24 | source() | callbacks.js:38:35:38:35 | x |
| callbacks.js:44:17:44:24 | source() | callbacks.js:41:10:41:10 | x |
| callbacks.js:50:18:50:25 | source() | callbacks.js:30:29:30:29 | y |
| callbacks.js:51:18:51:25 | source() | callbacks.js:30:29:30:29 | y |
@@ -39,14 +69,39 @@
| capture-flow.js:9:11:9:18 | source() | capture-flow.js:14:10:14:16 | outer() |
| capture-flow.js:9:11:9:18 | source() | capture-flow.js:19:6:19:16 | outerMost() |
| capture-flow.js:31:14:31:21 | source() | capture-flow.js:31:6:31:22 | confuse(source()) |
| capture-flow.js:45:12:45:19 | source() | capture-flow.js:45:6:45:20 | test3(source()) |
| capture-flow.js:60:13:60:20 | source() | capture-flow.js:60:6:60:21 | test3a(source()) |
| capture-flow.js:76:13:76:20 | source() | capture-flow.js:76:6:76:21 | test3b(source()) |
| capture-flow.js:89:13:89:20 | source() | capture-flow.js:89:6:89:21 | test3c(source()) |
| capture-flow.js:93:13:93:20 | source() | capture-flow.js:96:6:96:14 | test4()() |
| capture-flow.js:101:12:101:19 | source() | capture-flow.js:101:6:101:22 | test5(source())() |
| capture-flow.js:110:12:110:19 | source() | capture-flow.js:106:14:106:14 | x |
| capture-flow.js:118:37:118:44 | source() | capture-flow.js:114:14:114:14 | x |
| capture-flow.js:126:25:126:32 | source() | capture-flow.js:123:14:123:26 | orderingTaint |
| capture-flow.js:126:25:126:32 | source() | capture-flow.js:129:14:129:26 | orderingTaint |
| capture-flow.js:177:26:177:33 | source() | capture-flow.js:173:14:173:14 | x |
| capture-flow.js:187:34:187:41 | source() | capture-flow.js:183:14:183:14 | x |
| capture-flow.js:195:24:195:31 | source() | capture-flow.js:191:14:191:14 | x |
| capture-flow.js:205:24:205:31 | source() | capture-flow.js:200:18:200:18 | x |
| capture-flow.js:225:13:225:20 | source() | capture-flow.js:220:51:220:59 | fileOrDir |
| capture-flow.js:230:9:230:16 | source() | capture-flow.js:233:14:233:14 | x |
| capture-flow.js:259:23:259:30 | source() | capture-flow.js:243:18:243:40 | objectW ... s.field |
| capture-flow.js:259:23:259:30 | source() | capture-flow.js:247:18:247:40 | objectW ... s.field |
| capture-flow.js:259:23:259:30 | source() | capture-flow.js:248:18:248:27 | this.field |
| capture-flow.js:259:23:259:30 | source() | capture-flow.js:252:14:252:36 | objectW ... s.field |
| capture-flow.js:259:23:259:30 | source() | capture-flow.js:253:14:253:23 | this.field |
| captured-sanitizer.js:25:3:25:10 | source() | captured-sanitizer.js:15:10:15:10 | x |
| constructor-calls.js:4:18:4:25 | source() | constructor-calls.js:18:8:18:14 | c.taint |
| constructor-calls.js:4:18:4:25 | source() | constructor-calls.js:22:8:22:19 | c_safe.taint |
| constructor-calls.js:10:16:10:23 | source() | constructor-calls.js:26:8:26:14 | d.taint |
| constructor-calls.js:10:16:10:23 | source() | constructor-calls.js:30:8:30:19 | d_safe.taint |
| constructor-calls.js:14:15:14:22 | source() | constructor-calls.js:17:8:17:14 | c.param |
| constructor-calls.js:14:15:14:22 | source() | constructor-calls.js:25:8:25:14 | d.param |
| constructor-calls.js:4:18:4:25 | source() | constructor-calls.js:24:8:24:14 | c.taint |
| constructor-calls.js:4:18:4:25 | source() | constructor-calls.js:28:8:28:19 | c_safe.taint |
| constructor-calls.js:4:18:4:25 | source() | constructor-calls.js:40:8:40:14 | e.taint |
| constructor-calls.js:4:18:4:25 | source() | constructor-calls.js:44:8:44:19 | f_safe.taint |
| constructor-calls.js:10:16:10:23 | source() | constructor-calls.js:32:8:32:14 | d.taint |
| constructor-calls.js:10:16:10:23 | source() | constructor-calls.js:36:8:36:19 | d_safe.taint |
| constructor-calls.js:20:15:20:22 | source() | constructor-calls.js:23:8:23:14 | c.param |
| constructor-calls.js:20:15:20:22 | source() | constructor-calls.js:31:8:31:14 | d.param |
| constructor-calls.js:20:15:20:22 | source() | constructor-calls.js:39:8:39:14 | e.param |
| exceptions.js:3:15:3:22 | source() | exceptions.js:5:10:5:10 | e |
| exceptions.js:53:14:53:21 | source() | exceptions.js:54:10:54:10 | e |
| exceptions.js:59:24:59:31 | source() | exceptions.js:61:12:61:12 | e |
| exceptions.js:88:6:88:13 | source() | exceptions.js:11:10:11:10 | e |
| exceptions.js:93:11:93:18 | source() | exceptions.js:95:10:95:10 | e |
@@ -64,18 +119,24 @@
| getters-and-setters.js:6:20:6:27 | source() | getters-and-setters.js:13:18:13:20 | c.x |
| getters-and-setters.js:27:15:27:22 | source() | getters-and-setters.js:23:18:23:18 | v |
| getters-and-setters.js:47:23:47:30 | source() | getters-and-setters.js:45:14:45:16 | c.x |
| getters-and-setters.js:53:21:53:28 | source() | getters-and-setters.js:53:10:53:30 | getX(ne ... rce())) |
| getters-and-setters.js:60:20:60:27 | source() | getters-and-setters.js:66:10:66:14 | obj.x |
| getters-and-setters.js:67:13:67:20 | source() | getters-and-setters.js:63:18:63:22 | value |
| getters-and-setters.js:79:20:79:27 | source() | getters-and-setters.js:88:10:88:18 | new C().x |
| getters-and-setters.js:79:20:79:27 | source() | getters-and-setters.js:92:14:92:16 | c.x |
| getters-and-setters.js:79:20:79:27 | source() | getters-and-setters.js:100:10:100:22 | getX(new C()) |
| getters-and-setters.js:89:17:89:24 | source() | getters-and-setters.js:82:18:82:22 | value |
| implied-receiver.js:4:16:4:23 | source() | implied-receiver.js:7:18:7:25 | this.foo |
| indexOf.js:4:11:4:18 | source() | indexOf.js:9:10:9:10 | x |
| indexOf.js:4:11:4:18 | source() | indexOf.js:13:10:13:10 | x |
| nested-props.js:4:13:4:20 | source() | nested-props.js:5:10:5:14 | obj.x |
| nested-props.js:9:18:9:25 | source() | nested-props.js:10:10:10:16 | obj.x.y |
| nested-props.js:14:15:14:22 | source() | nested-props.js:15:10:15:16 | obj.x.y |
| nested-props.js:19:17:19:24 | source() | nested-props.js:20:10:20:18 | obj.x.y.z |
| nested-props.js:27:18:27:25 | source() | nested-props.js:28:10:28:14 | obj.x |
| nested-props.js:35:13:35:20 | source() | nested-props.js:36:10:36:20 | doLoad(obj) |
| nested-props.js:43:13:43:20 | source() | nested-props.js:44:10:44:18 | id(obj).x |
| nested-props.js:51:22:51:29 | source() | nested-props.js:52:10:52:16 | obj.x.y |
| nested-props.js:67:31:67:38 | source() | nested-props.js:68:10:68:10 | x |
| object-bypass-sanitizer.js:32:21:32:28 | source() | object-bypass-sanitizer.js:15:10:15:24 | sanitizer_id(x) |
| object-bypass-sanitizer.js:35:29:35:36 | source() | object-bypass-sanitizer.js:27:10:27:30 | sanitiz ... bj.foo) |
@@ -97,10 +158,11 @@
| sanitizer-guards.js:43:11:43:18 | source() | sanitizer-guards.js:45:8:45:8 | x |
| sanitizer-guards.js:43:11:43:18 | source() | sanitizer-guards.js:48:10:48:10 | x |
| sanitizer-guards.js:43:11:43:18 | source() | sanitizer-guards.js:52:10:52:10 | x |
| sanitizer-guards.js:57:11:57:18 | source() | sanitizer-guards.js:64:8:64:8 | x |
| sanitizer-guards.js:68:11:68:18 | source() | sanitizer-guards.js:75:8:75:8 | x |
| sanitizer-guards.js:79:11:79:18 | source() | sanitizer-guards.js:81:8:81:8 | x |
| sanitizer-guards.js:79:11:79:18 | source() | sanitizer-guards.js:84:10:84:10 | x |
| sanitizer-guards.js:79:11:79:18 | source() | sanitizer-guards.js:86:7:86:7 | x |
| sanitizer-guards.js:79:11:79:18 | source() | sanitizer-guards.js:86:9:86:9 | x |
| sanitizer-guards.js:91:11:91:18 | source() | sanitizer-guards.js:93:8:93:8 | x |
| sanitizer-guards.js:91:11:91:18 | source() | sanitizer-guards.js:96:10:96:10 | x |
| sanitizer-guards.js:91:11:91:18 | source() | sanitizer-guards.js:98:7:98:7 | x |
@@ -109,4 +171,6 @@
| thisAssignments.js:4:17:4:24 | source() | thisAssignments.js:5:10:5:18 | obj.field |
| thisAssignments.js:7:19:7:26 | source() | thisAssignments.js:8:10:8:20 | this.field2 |
| tst.js:2:13:2:20 | source() | tst.js:4:10:4:10 | x |
| tst.js:2:13:2:20 | source() | tst.js:35:14:35:16 | ary |
| tst.js:2:13:2:20 | source() | tst.js:41:14:41:16 | ary |
| tst.js:2:13:2:20 | source() | tst.js:54:14:54:19 | unsafe |

View File

@@ -2,26 +2,44 @@ import javascript
DataFlow::CallNode getACall(string name) { result.getCalleeName() = name }
class BasicConfig extends DataFlow::Configuration {
BasicConfig() { this = "BasicConfig" }
module TestConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node node) { node = getACall("source") }
override predicate isSource(DataFlow::Node node) { node = getACall("source") }
predicate isSink(DataFlow::Node node) { node = getACall("sink").getAnArgument() }
override predicate isSink(DataFlow::Node node) { node = getACall("sink").getAnArgument() }
override predicate isBarrierGuard(DataFlow::BarrierGuardNode node) {
additional predicate isBarrierGuard(DataFlow::BarrierGuardNode node) {
node instanceof BasicBarrierGuard
}
predicate isBarrier(DataFlow::Node node) {
node = DataFlow::MakeLegacyBarrierGuard<isBarrierGuard/1>::getABarrierNode()
}
}
module TestFlow = DataFlow::Global<TestConfig>;
class BasicBarrierGuard extends DataFlow::BarrierGuardNode, DataFlow::CallNode {
BasicBarrierGuard() { this = getACall("isSafe") }
override predicate blocks(boolean outcome, Expr e) {
override predicate blocks(boolean outcome, Expr e) { this.blocksExpr(outcome, e) }
predicate blocksExpr(boolean outcome, Expr e) {
outcome = true and e = this.getArgument(0).asExpr()
}
}
from BasicConfig cfg, DataFlow::Node src, DataFlow::Node sink
where cfg.hasFlow(src, sink)
select src, sink
class LegacyConfig extends DataFlow::Configuration {
LegacyConfig() { this = "LegacyConfig" }
override predicate isSource(DataFlow::Node source) { TestConfig::isSource(source) }
override predicate isSink(DataFlow::Node sink) { TestConfig::isSink(sink) }
override predicate isBarrierGuard(DataFlow::BarrierGuardNode node) {
TestConfig::isBarrierGuard(node)
}
}
import testUtilities.LegacyDataFlowDiff::DataFlowDiff<TestFlow, LegacyConfig>
query predicate flow = TestFlow::flow/2;

View File

@@ -1,7 +1,7 @@
(function () {
let source = source();
var str = "FALSE";
var str = "FALSE";
console.log("=== access by index (init by ctor) ===");
var arr = new Array(2);
@@ -24,18 +24,18 @@
console.log("=== access by index (init by [...]) ===");
var arr = [str, source];
sink(arr[0]); // OK
sink(arr[0]); // OK [INCONSISTENCY]
sink(arr[1]); // NOT OK
sink(str); // OK
console.log("=== access by index (init by [...], array.lenght > 5) ===");
var arr = [str, source, 'b', 'c', 'd', source];
sink(arr[0]); // OK
sink(arr[0]); // OK [INCONSISTENCY]
sink(arr[1]); // NOT OK
sink(arr[2]); // OK
sink(arr[3]); // OK
sink(arr[4]); // OK
sink(arr[5]); // NOT OK - but not flagged [INCONSISTENCY]
sink(arr[2]); // OK [INCONSISTENCY]
sink(arr[3]); // OK [INCONSISTENCY]
sink(arr[4]); // OK [INCONSISTENCY]
sink(arr[5]); // NOT OK
console.log("=== access in for (init by [...]) ===");
var arr = [str, source];
@@ -58,6 +58,6 @@
console.log("=== access in forof (init by [...]) ===");
var arr = [str, source];
for (const item of arr) {
sink(item); // NOT OK
sink(item); // NOT OK
}
}());
}());

View File

@@ -1,23 +1,23 @@
function test() {
let x = source();
sink(x); // NOT OK
if (x === 'a')
sink(x); // OK
if (x === 'a' || x === 'b')
sink(x); // OK
if (x === 'a' || 1 === 1)
sink(x); // NOT OK
if (isSafe(x))
sink(x); // OK
if (isSafe(x, y) || isSafe(x, z))
sink(x); // OK
sink(x); // OK [INCONSISTENCY]
if (isSafe(x) || 1 === 1)
sink(x); // NOT OK
}

View File

@@ -1,28 +1,33 @@
import * as dummy from 'dummy';
function foo(x, y) {
sink(y);
sink(y.test1); // OK
sink(y.test2); // NOT OK
sink(y.test3); // NOT OK
sink(y.test4); // OK
sink(y.test5); // OK
sink(y.test6); // OK
}
let foo0 = foo.bind(null);
let foo1 = foo.bind(null, null);
let foo2 = foo.bind(null, null, null);
foo0(source(), null); // OK
foo0(null, source()); // NOT OK
foo0({ test1: source() }, null);
foo0(null, { test2: source() });
foo1(source()); // NOT OK
foo1(null, source()); // OK
foo1({ test3: source() });
foo1(null, { test4: source() });
foo2(source()); // OK
foo2(null, source()); // OK
foo2({ test5: source() });
foo2(null, { test6: source() });
function takesCallback(cb) {
cb(source()); // NOT OK
cb(source());
}
function callback(x, y) {
sink(y);
sink(y); // NOT OK [INCONSISTENCY] - lambda flow in dataflow2 does not handle partial invocations yet
}
takesCallback(callback.bind(null, null));
@@ -33,7 +38,7 @@ function id(x) {
let sourceGetter = id.bind(null, source());
let constGetter = id.bind(null, 'safe');
sink(sourceGetter()); // NOT OK - but not flagged
sink(sourceGetter()); // NOT OK [INCONSISTENCY]
sink(constGetter()); // OK
function id2(x, y) {

View File

@@ -30,21 +30,15 @@ sink(foo1.call(null, source, "")); // NOT OK
sink(foo2.call(null, source, "")); // OK
sink(foo1.apply(null, [source, ""])); // NOT OK
sink(foo2.apply(null, [source, ""])); // OK
// doesn't work due to fundamental limitations of our dataflow analysis.
// exactly (and I mean exactly) the same thing happens in the below `obj.foo` example.
// in general we don't track flow that first goes through a call, and then a return, unless we can summarize it.
// in the other examples we can summarize the flow, because it's quite simple, but here we can't.
// (try to read the QLDoc in the top of `Configuration.qll`, that might help).
sink(foo1_apply([source, ""])); // NOT OK - but not flagged [INCONSISTENCY]
sink(foo2.apply(null, [source, ""])); // OK [INCONSISTENCY]
sink(foo1_apply([source, ""])); // NOT OK
foo1_apply_sink([source, ""]); // This works, because we don't need a return after a call (the sink is inside the called function).
sink(foo1_apply.apply(["", source])); // OK
sink(foo1_call([source, ""])); // NOT OK
sink(foo1_call(["", source])); // OK
sink(foo1_call(["", source])); // OK [INCONSISTENCY]
var obj = {
@@ -58,21 +52,21 @@ function foo(x) {
function bar(x) {
return x.foo;
}
sink(foo(obj)); // NOT OK - but not flagged [INCONSISTENCY]
sink(foo(obj)); // NOT OK
function argumentsObject() {
function sinkArguments1() {
sink(arguments[1]); // OK
sink(arguments[1]); // OK [INCONSISTENCY]
}
function sinkArguments0() {
sink(arguments[0]); // NOT OK
}
function fowardArguments() {
sinkArguments1.apply(this, arguments);
sinkArguments0.apply(this, arguments);
}
fowardArguments.apply(this, [source, ""]);
}
@@ -84,4 +78,4 @@ function sinksThis2() {
sink(this); // NOT OK
}
sinksThis.apply(source(), []);
sinksThis.apply(source(), []);

View File

@@ -35,8 +35,8 @@ function test() {
provideTaint2(x => sink(x)); // NOT OK
forwardTaint2(source(), x => sink(x)); // NOT OK
forwardTaint2("safe", x => sink(x)); // OK
forwardTaint2("safe", x => sink(x)); // OK [INCONSISTENCY]
function helper1(x) {
sink(x); // NOT OK
return x;

View File

@@ -29,3 +29,231 @@ function confuse(x) {
sink(confuse('safe')); // OK
sink(confuse(source())); // NOT OK
function test3(param) {
var x;
function one() {
x = param;
}
function two() {
one();
return x;
}
return two();
}
sink(test3(source())); // NOT OK
sink(test3("safe")); // OK
function test3a(param) {
var x;
function one() {
x = param;
}
one();
function two() {
return x;
}
return two();
}
sink(test3a(source())); // NOT OK
sink(test3a("safe")); // OK
function test3b(param) {
var x;
function one() {
x = param;
}
one();
function two() {
one();
return x;
}
return two();
}
sink(test3b(source())); // NOT OK
sink(test3b("safe")); // OK
function test3c(param) {
function one() {
return param;
}
function two() {
return one();
}
return two();
}
sink(test3c(source())); // NOT OK
sink(test3c("safe")); // OK
function test4() {
var x = source();
return () => x;
}
sink(test4()()); // NOT OK
function test5(x) {
return () => x;
}
sink(test5(source())()); // NOT OK
sink(test5("safe")()); // OK
function testEscape(x) {
function escapingFunction() {
sink(x); // NOT OK
}
global.doEscape(escapingFunction);
}
testEscape(source());
function testEscapeViaReturn(x) {
function escapingFunction() {
sink(x); // NOT OK
}
return escapingFunction;
}
global.doEscape(testEscapeViaReturn(source()));
function ordering() {
var orderingTaint;
global.addEventListener('click', () => {
sink(orderingTaint); // NOT OK
});
global.addEventListener('load', () => {
orderingTaint = source();
});
global.addEventListener('click', () => {
sink(orderingTaint); // NOT OK
});
}
ordering();
function makeSafe(x) {
console.log(x);
return "safe";
}
function flowSensitiveParamUpdate(x) {
x = makeSafe(x);
function captureX() {
console.log(x);
}
captureX();
sink(x); // OK
}
flowSensitiveParamUpdate(source());
function flowSensitiveLocalUpdate() {
let x = source();
x = makeSafe(x);
function captureX() {
console.log(x);
}
captureX();
sink(x); // OK
}
flowSensitiveLocalUpdate();
function flowSensitiveLocalIncrement() {
let x = source();
++x;
function captureX() {
console.log(x);
}
captureX();
sink(x); // OK
}
flowSensitiveLocalIncrement();
function destructuredVarDecl(param) {
let { x } = param;
function inner() {
sink(x); // NOT OK
}
inner();
}
destructuredVarDecl({ x: source() });
function destructuredLocalAssignment(param) {
let x;
({ x } = param);
function inner() {
sink(x); // NOT OK
}
inner();
}
destructuredLocalAssignment({ x: source() });
function destructuredParam({ x }) {
function inner() {
sink(x); // NOT OK
}
inner();
}
destructuredParam({ x: source() });
function destructuredLoop(data) {
for (let { x } of data) {
function inner() {
sink(x); // NOT OK
}
inner();
}
}
destructuredLoop([{ x: source() }]);
function testPromise(arg) {
function transform(x) {
return { prop: x };
}
class Foo {
updatePrVisibility(y) {
const { prop: variable } = transform(y);
this.exists(variable).then(() => {
transform(variable);
});
}
exists(fileOrDir) {
return new Promise(resolve => fs.sink(fileOrDir, err => resolve(!err))); // NOT OK
}
}
new Foo().updatePrVisibility(arg);
}
testPromise(source());
function sinkInner() {
var x = "safe";
console.log(x);
x = source();
console.log(x);
function inner() {
sink(x); // NOT OK
}
inner();
}
sinkInner();
function testObjectWithMethods(taint) {
const objectWithMethods = {
field: taint,
arrowFunction: () => {
sink(objectWithMethods.field); // NOT OK
sink(this.field); // OK - refers to outer 'this'
},
regularFunction() {
sink(objectWithMethods.field); // NOT OK
sink(this.field); // NOT OK
},
};
objectWithMethods.functionAddedLater = function() {
sink(objectWithMethods.field); // NOT OK
sink(this.field); // NOT OK
};
objectWithMethods.arrowFunction();
objectWithMethods.regularFunction();
objectWithMethods.functionAddedLater();
}
testObjectWithMethods(source());

View File

@@ -10,22 +10,36 @@ function JsClass(param) {
this.taint = source();
}
class SubClass extends EcmaClass {
constructor(param) {
super(param);
}
}
function test() {
let taint = source();
let c = new EcmaClass(taint);
sink(c.param); // NOT OK
sink(c.taint); // NOT OK
let c_safe = new EcmaClass("safe");
sink(c_safe.param); // OK
sink(c_safe.taint); // NOT OK
let d = new JsClass(taint);
sink(d.param); // NOT OK
sink(d.taint); // NOT OK
let d_safe = new JsClass("safe");
sink(d_safe.param); // OK
sink(d_safe.taint); // NOT OK
let e = new SubClass(taint);
sink(e.param); // NOT OK
sink(e.taint); // NOT OK
let f_safe = new SubClass("safe");
sink(f_safe.param); // OK
sink(f_safe.taint); // NOT OK
}

View File

@@ -23,7 +23,7 @@ function test(unsafe, safe) {
sink(e); // NOT OK
sink(e.toString()); // NOT OK
sink(e.message); // NOT OK
sink(e.fileName); // OK - but flagged anyway
sink(e.fileName); // OK - but flagged anyway [INCONSISTENCY]
}
try {
@@ -32,16 +32,16 @@ function test(unsafe, safe) {
sink(e); // NOT OK
sink(e.toString()); // NOT OK
sink(e.message); // NOT OK
sink(e.fileName); // OK - but flagged anyway
sink(e.fileName); // OK - but flagged anyway [INCONSISTENCY]
}
try {
throwError2(safe);
} catch (e) {
sink(e); // NOT OK
sink(e.toString()); // NOT OK
sink(e.message); // NOT OK
sink(e.fileName); // OK - but flagged anyway
sink(e); // OK
sink(e.toString()); // OK
sink(e.message); // OK
sink(e.fileName); // OK
}
try {
@@ -51,14 +51,14 @@ function test(unsafe, safe) {
}
throwAsync(source()).catch(e => {
sink(e); // NOT OK - but not flagged
sink(e); // NOT OK
});
async function asyncTester() {
try {
await throwAsync(source());
} catch (e) {
sink(e); // NOT OK - but not flagged
sink(e); // NOT OK
}
}
}

View File

@@ -50,7 +50,7 @@ function testFlowThroughGetter() {
function getX(c) {
return c.x;
}
sink(getX(new C(source()))); // NOT OK - but not flagged
sink(getX(new C(source()))); // NOT OK
getX(null);
}
@@ -67,7 +67,7 @@ function testFlowThroughObjectLiteralAccessors() {
obj.y = source();
function indirection(c) {
sink(c.x); // NOT OK - but not currently flagged
sink(c.x); // NOT OK - but not currently flagged [INCONSISTENCY]
}
indirection(obj);
indirection(null);

View File

@@ -0,0 +1,11 @@
import 'dummy';
function Foo() {
this.foo = source();
var obj = {
bar: function() {
sink(this.foo); // NOT OK
}
};
Object.assign(this, obj);
}

View File

@@ -57,7 +57,7 @@ function doLoadLoad(obj) {
}
function storeBackloadCallLoadLoadReturn(obj) {
obj.x.y = source();
sink(doLoadStore(obj)); // NOT OK - but not found
sink(doLoadStore(obj)); // NOT OK - but not found [INCONSISTENCY]
}
function doStoreReturn(val) {

View File

@@ -20,12 +20,12 @@ function useTaintedValue(x) {
function useTaintedObject(obj) {
if (isSafe(obj)) {
sink(obj); // OK
sink(obj.foo); // NOT OK
sink(obj.foo); // NOT OK [INCONSISTENCY] - FN caused by barriers blocking content flow
}
sink(sanitizer_id(obj)); // OK
sink(sanitizer_id(obj.foo)); // OK
sink(sanitizer_id(obj).foo); // NOT OK
sink(sanitizer_id(obj).foo); // NOT OK [INCONSISTENCY] - FN caused by barriers blocking content flow
}
function test() {

View File

@@ -42,7 +42,7 @@ function test() {
let taintGetter = id.bind(null, taint);
sink(taintGetter); // OK - this is a function object
sink(taintGetter()); // NOT OK - but not currently detected
sink(taintGetter()); // NOT OK - but not currently detected [INCONSISTENCY]
function safearray(x) {
sink(x); // OK

View File

@@ -10,5 +10,31 @@ function closure() {
sink(Promise.resolve(source())); // NOT OK
let resolver = Promise.withResolver();
resolver.resolve(source());
sink(resolver.promise); // NOT OK
}
sink(resolver.promise); // NOT OK [INCONSISTENCY] - flow summary for withResolver() currently not working
}
function exceptionThroughThen() {
return new Promise((resolve, reject) => {
reject(new Error(source()));
})
.then(x => "safe")
.then(x => "safe")
.then(x => "safe")
.catch(e => {
sink(e); // NOT OK
})
}
function exceptionThroughThen2() {
return new Promise((resolve, reject) => {
resolve("safe")
})
.then(x => {
throw new Error(source())
})
.then(x => "safe")
.then(x => "safe")
.catch(e => {
sink(e); // NOT OK
})
}

View File

@@ -1,8 +1,8 @@
function test() {
let x = source();
sink(x); // NOT OK
if (isSafe(x)) {
sink(x); // OK
}
@@ -18,7 +18,7 @@ class C {
sink(this.x); // OK
addEventListener('hey', () => {
sink(this.x); // OK - but still flagged
sink(this.x); // OK - but still flagged [INCONSISTENCY]
});
}
@@ -61,7 +61,7 @@ function phi() {
} else {
x = null;
}
sink(x); // OK
sink(x); // OK [INCONSISTENCY] - dataflow2 cannot block the phi edge
}
function phi2() {
@@ -77,13 +77,13 @@ function phi2() {
function falsy() {
let x = source();
sink(x); // NOT OK
if (x) {
sink(x); // OK (for taint-tracking)
sink(x); // NOT OK (for taint-tracking)
} else {
sink(x); // NOT OK
sink(x); // OK
}
}

View File

@@ -0,0 +1,31 @@
import 'dummy';
function makeObject() {
return {
foo: {
bar: {
baz: source()
}
}
};
}
function test() {
const object = makeObject();
sink(object); // OK
sink(JSON.stringify(object)); // NOT OK
sink(object); // OK
}
function testCapture() {
const object = makeObject();
sink(object); // OK
sink(JSON.stringify(object)); // NOT OK
sink(object); // OK - use-use flow should not see the effects of the implicit read in JSON.stringify
function capture() {
object;
}
}