JavaScript: Fix data flow out of reflective calls.

We were previously missing a data-flow edge from reflected calls to the corresponding reflective call, that is, for `f.call(...)` we didn't have a flow edge from the implicit call to `f` to the result of `f.call(...)`.
This commit is contained in:
Max Schaefer
2019-07-01 20:40:46 +01:00
parent 7f95c20345
commit 91a718cfe5
9 changed files with 23 additions and 0 deletions

View File

@@ -1163,6 +1163,9 @@ module DataFlow {
pred = TThisNode(thiz.getBindingContainer()) and
succ = valueNode(thiz)
)
or
// `f.call(...)` and `f.apply(...)` evaluate to the result of the reflective call they perform
pred = TReflectiveCallNode(succ.asExpr(), _)
}
/**

View File

@@ -140,6 +140,7 @@
| tst.js:111:23:111:25 | v2c | tst.js:111:6:111:38 | v2c |
| tst.js:111:29:111:31 | o2c | tst.js:111:6:111:38 | v2c |
| tst.js:111:36:111:38 | o2d | tst.js:111:6:111:32 | [v2a, v ... = o2c] |
| tst.js:115:1:115:12 | reflective call | tst.js:115:1:115:12 | Array.call() |
| tst.ts:1:1:1:1 | A | tst.ts:1:11:1:11 | A |
| tst.ts:1:1:1:1 | A | tst.ts:7:1:7:0 | A |
| tst.ts:1:1:5:1 | A | tst.ts:7:1:7:0 | A |

View File

@@ -82,6 +82,11 @@
| tst.js:111:23:111:25 | v2c | heap |
| tst.js:111:29:111:31 | o2c | global |
| tst.js:111:36:111:38 | o2d | global |
| tst.js:115:1:115:5 | Array | global |
| tst.js:115:1:115:10 | Array.call | global |
| tst.js:115:1:115:10 | Array.call | heap |
| tst.js:115:1:115:12 | Array.call() | call |
| tst.js:115:1:115:12 | exceptional return of Array.call() | call |
| tst.ts:2:14:2:19 | x | namespace |
| tst.ts:3:3:3:8 | exceptional return of setX() | call |
| tst.ts:3:3:3:8 | setX() | call |

View File

@@ -85,6 +85,10 @@
| tst.js:111:23:111:25 | v2c |
| tst.js:111:29:111:31 | o2c |
| tst.js:111:36:111:38 | o2d |
| tst.js:115:1:115:5 | Array |
| tst.js:115:1:115:10 | Array.call |
| tst.js:115:1:115:12 | Array.call() |
| tst.js:115:1:115:12 | reflective call |
| tst.ts:1:1:1:0 | this |
| tst.ts:3:3:3:8 | setX() |
| tst.ts:7:1:7:0 | this |

View File

@@ -111,4 +111,7 @@ x ?? y; // flow through short-circuiting operator
var [v2a, v2b = o2b, v2c = o2c] = o2d;
v2a + v2b + v2c;
});
Array.call() // flow from implicit call to `Array` to `Array.call`
// semmle-extractor-options: --experimental

View File

@@ -39,6 +39,7 @@
| tst2.js:6:24:6:37 | "also tainted" | tst2.js:10:15:10:24 | g(source1) |
| tst2.js:6:24:6:37 | "also tainted" | tst2.js:11:15:11:24 | g(source2) |
| tst6.mjs:12:14:12:21 | "source" | tst6.mjs:14:12:14:16 | a.m() |
| tst6.mjs:16:15:16:23 | "source2" | tst6.mjs:18:13:18:24 | a.m.call(a2) |
| tst.js:2:17:2:22 | "src1" | tst.js:39:17:39:17 | x |
| tst.js:2:17:2:22 | "src1" | tst.js:41:19:41:19 | x |
| tst.js:2:17:2:22 | "src1" | tst.js:45:17:45:17 | x |

View File

@@ -40,6 +40,7 @@
| tst2.js:6:24:6:37 | "also tainted" | tst2.js:10:15:10:24 | g(source1) |
| tst2.js:6:24:6:37 | "also tainted" | tst2.js:11:15:11:24 | g(source2) |
| tst6.mjs:12:14:12:21 | "source" | tst6.mjs:14:12:14:16 | a.m() |
| tst6.mjs:16:15:16:23 | "source2" | tst6.mjs:18:13:18:24 | a.m.call(a2) |
| tst.js:2:17:2:22 | "src1" | tst.js:39:17:39:17 | x |
| tst.js:2:17:2:22 | "src1" | tst.js:41:19:41:19 | x |
| tst.js:2:17:2:22 | "src1" | tst.js:45:17:45:17 | x |

View File

@@ -49,6 +49,7 @@
| tst4.js:2:16:2:24 | "tainted" | tst4.js:16:15:16:28 | p.also_tainted |
| tst4.js:2:16:2:24 | "tainted" | tst4.js:17:15:17:28 | substr(source) |
| tst6.mjs:12:14:12:21 | "source" | tst6.mjs:14:12:14:16 | a.m() |
| tst6.mjs:16:15:16:23 | "source2" | tst6.mjs:18:13:18:24 | a.m.call(a2) |
| tst.js:2:17:2:22 | "src1" | tst.js:3:15:3:29 | String(source1) |
| tst.js:2:17:2:22 | "src1" | tst.js:4:15:4:29 | RegExp(source1) |
| tst.js:2:17:2:22 | "src1" | tst.js:5:15:5:33 | new String(source1) |

View File

@@ -12,3 +12,7 @@ class A {
var source = "source";
var a = new A(source);
var sink = a.m();
var source2 = "source2";
var a2 = new A(source2);
var sink2 = a.m.call(a2);