Merge pull request #3564 from max-schaefer/js/reflective-argument-access

Approved by asgerf
This commit is contained in:
semmle-qlci
2020-05-26 12:09:13 +01:00
committed by GitHub
11 changed files with 160 additions and 28 deletions

View File

@@ -151,11 +151,14 @@ private module CachedSteps {
) {
calls(invk, f) and
(
exists(int i, Parameter p |
f.getParameter(i) = p and
not p.isRestParameter() and
arg = invk.getArgument(i) and
parm = DataFlow::parameterNode(p)
exists(int i | arg = invk.getArgument(i) |
exists(Parameter p |
f.getParameter(i) = p and
not p.isRestParameter() and
parm = DataFlow::parameterNode(p)
)
or
parm = reflectiveParameterAccess(f, i)
)
or
arg = invk.(DataFlow::CallNode).getReceiver() and
@@ -185,6 +188,22 @@ private module CachedSteps {
)
}
/**
* Gets a data-flow node inside `f` that refers to the `arguments` object of `f`.
*/
private DataFlow::Node argumentsAccess(Function f) {
result.getContainer().getEnclosingContainer*() = f and
result.analyze().getAValue().(AbstractArguments).getFunction() = f
}
/**
* Gets a data-flow node that refers to the `i`th parameter of `f` through its `arguments`
* object.
*/
private DataFlow::SourceNode reflectiveParameterAccess(Function f, int i) {
result.(DataFlow::PropRead).accesses(argumentsAccess(f), any(string p | i = p.toInt()))
}
/**
* Holds if there is a flow step from `pred` to `succ` through parameter passing
* to a function call.

View File

@@ -0,0 +1,10 @@
| arguments.js:11:5:11:14 | f(1, 2, 3) | arguments.js:11:7:11:7 | 1 | arguments.js:2:5:10:5 | functio ... ;\\n } | arguments.js:2:16:2:16 | x |
| arguments.js:11:5:11:14 | f(1, 2, 3) | arguments.js:11:7:11:7 | 1 | arguments.js:2:5:10:5 | functio ... ;\\n } | arguments.js:4:28:4:39 | arguments[0] |
| arguments.js:11:5:11:14 | f(1, 2, 3) | arguments.js:11:10:11:10 | 2 | arguments.js:2:5:10:5 | functio ... ;\\n } | arguments.js:5:25:5:36 | arguments[1] |
| arguments.js:11:5:11:14 | f(1, 2, 3) | arguments.js:11:13:11:13 | 3 | arguments.js:2:5:10:5 | functio ... ;\\n } | arguments.js:7:24:7:30 | args[2] |
| sources.js:3:1:5:6 | (functi ... \\n})(23) | sources.js:5:4:5:5 | 23 | sources.js:3:2:5:1 | functio ... x+19;\\n} | sources.js:3:11:3:11 | x |
| tst.js:16:1:20:9 | (functi ... ("arg") | tst.js:20:4:20:8 | "arg" | tst.js:16:2:20:1 | functio ... n "";\\n} | tst.js:16:13:16:13 | a |
| tst.js:35:1:35:7 | g(true) | tst.js:35:3:35:6 | true | tst.js:32:1:34:1 | functio ... ables\\n} | tst.js:32:12:32:12 | b |
| tst.js:44:1:44:5 | o.m() | tst.js:44:1:44:1 | o | tst.js:39:4:41:3 | () {\\n this;\\n } | tst.js:39:4:39:3 | this |
| tst.js:87:1:96:2 | (functi ... r: 0\\n}) | tst.js:92:4:96:1 | {\\n p: ... r: 0\\n} | tst.js:87:2:92:1 | functio ... + z;\\n} | tst.js:87:11:87:24 | { p: x, ...o } |
| tst.js:98:1:103:17 | (functi ... 3, 0 ]) | tst.js:103:4:103:16 | [ 19, 23, 0 ] | tst.js:98:2:103:1 | functio ... + z;\\n} | tst.js:98:11:98:24 | [ x, ...rest ] |

View File

@@ -0,0 +1,6 @@
import javascript
import semmle.javascript.dataflow.internal.FlowSteps as FlowSteps
from DataFlow::Node invk, DataFlow::Node arg, Function f, DataFlow::SourceNode parm
where FlowSteps::argumentPassing(invk, arg, f, parm)
select invk, arg, f, parm

View File

@@ -0,0 +1,12 @@
(function() {
function f(x) {
let firstArg = x;
let alsoFirstArg = arguments[0];
let secondArg = arguments[1];
let args = arguments;
let thirdArg = args[2];
arguments = {};
let notFirstArg = arguments[0];
}
f(1, 2, 3);
})();

View File

@@ -1,3 +1,42 @@
| arguments.js:1:1:12:2 | (functi ... 3);\\n}) | arguments.js:1:1:12:2 | (functi ... 3);\\n}) |
| arguments.js:1:1:12:4 | (functi ... );\\n})() | arguments.js:1:1:12:4 | (functi ... );\\n})() |
| arguments.js:1:2:12:1 | functio ... , 3);\\n} | arguments.js:1:2:12:1 | functio ... , 3);\\n} |
| arguments.js:2:14:2:14 | f | arguments.js:2:14:2:14 | f |
| arguments.js:2:16:2:16 | x | arguments.js:2:16:2:16 | x |
| arguments.js:3:13:3:20 | firstArg | arguments.js:3:13:3:20 | firstArg |
| arguments.js:3:13:3:24 | firstArg = x | arguments.js:3:13:3:24 | firstArg = x |
| arguments.js:3:24:3:24 | x | arguments.js:3:24:3:24 | x |
| arguments.js:4:13:4:24 | alsoFirstArg | arguments.js:4:13:4:24 | alsoFirstArg |
| arguments.js:4:13:4:39 | alsoFir ... ents[0] | arguments.js:4:13:4:39 | alsoFir ... ents[0] |
| arguments.js:4:28:4:36 | arguments | arguments.js:4:28:4:36 | arguments |
| arguments.js:4:28:4:39 | arguments[0] | arguments.js:4:28:4:39 | arguments[0] |
| arguments.js:4:38:4:38 | 0 | arguments.js:4:38:4:38 | 0 |
| arguments.js:5:13:5:21 | secondArg | arguments.js:5:13:5:21 | secondArg |
| arguments.js:5:13:5:36 | secondA ... ents[1] | arguments.js:5:13:5:36 | secondA ... ents[1] |
| arguments.js:5:25:5:33 | arguments | arguments.js:5:25:5:33 | arguments |
| arguments.js:5:25:5:36 | arguments[1] | arguments.js:5:25:5:36 | arguments[1] |
| arguments.js:5:35:5:35 | 1 | arguments.js:5:35:5:35 | 1 |
| arguments.js:6:13:6:16 | args | arguments.js:6:13:6:16 | args |
| arguments.js:6:13:6:28 | args = arguments | arguments.js:6:13:6:28 | args = arguments |
| arguments.js:6:20:6:28 | arguments | arguments.js:6:20:6:28 | arguments |
| arguments.js:7:13:7:20 | thirdArg | arguments.js:7:13:7:20 | thirdArg |
| arguments.js:7:13:7:30 | thirdArg = args[2] | arguments.js:7:13:7:30 | thirdArg = args[2] |
| arguments.js:7:24:7:27 | args | arguments.js:7:24:7:27 | args |
| arguments.js:7:24:7:30 | args[2] | arguments.js:7:24:7:30 | args[2] |
| arguments.js:7:29:7:29 | 2 | arguments.js:7:29:7:29 | 2 |
| arguments.js:8:9:8:17 | arguments | arguments.js:8:9:8:17 | arguments |
| arguments.js:8:9:8:22 | arguments = {} | arguments.js:8:9:8:22 | arguments = {} |
| arguments.js:8:21:8:22 | {} | arguments.js:8:21:8:22 | {} |
| arguments.js:9:13:9:23 | notFirstArg | arguments.js:9:13:9:23 | notFirstArg |
| arguments.js:9:13:9:38 | notFirs ... ents[0] | arguments.js:9:13:9:38 | notFirs ... ents[0] |
| arguments.js:9:27:9:35 | arguments | arguments.js:9:27:9:35 | arguments |
| arguments.js:9:27:9:38 | arguments[0] | arguments.js:9:27:9:38 | arguments[0] |
| arguments.js:9:37:9:37 | 0 | arguments.js:9:37:9:37 | 0 |
| arguments.js:11:5:11:5 | f | arguments.js:11:5:11:5 | f |
| arguments.js:11:5:11:14 | f(1, 2, 3) | arguments.js:11:5:11:14 | f(1, 2, 3) |
| arguments.js:11:7:11:7 | 1 | arguments.js:11:7:11:7 | 1 |
| arguments.js:11:10:11:10 | 2 | arguments.js:11:10:11:10 | 2 |
| arguments.js:11:13:11:13 | 3 | arguments.js:11:13:11:13 | 3 |
| eval.js:1:10:1:10 | k | eval.js:1:10:1:10 | k |
| eval.js:2:7:2:7 | x | eval.js:2:7:2:7 | x |
| eval.js:2:7:2:12 | x = 42 | eval.js:2:7:2:12 | x = 42 |

View File

@@ -1,3 +1,16 @@
| arguments.js:1:2:12:1 | functio ... , 3);\\n} | arguments.js:1:1:12:2 | (functi ... 3);\\n}) |
| arguments.js:2:5:2:5 | arguments | arguments.js:4:28:4:36 | arguments |
| arguments.js:2:5:2:5 | arguments | arguments.js:5:25:5:33 | arguments |
| arguments.js:2:5:2:5 | arguments | arguments.js:6:20:6:28 | arguments |
| arguments.js:2:5:10:5 | functio ... ;\\n } | arguments.js:2:14:2:14 | f |
| arguments.js:2:14:2:14 | f | arguments.js:11:5:11:5 | f |
| arguments.js:2:16:2:16 | x | arguments.js:2:16:2:16 | x |
| arguments.js:2:16:2:16 | x | arguments.js:3:24:3:24 | x |
| arguments.js:6:13:6:28 | args | arguments.js:7:24:7:27 | args |
| arguments.js:6:20:6:28 | arguments | arguments.js:6:13:6:28 | args |
| arguments.js:8:9:8:22 | arguments | arguments.js:9:27:9:35 | arguments |
| arguments.js:8:21:8:22 | {} | arguments.js:8:9:8:22 | arguments |
| arguments.js:8:21:8:22 | {} | arguments.js:8:9:8:22 | arguments = {} |
| eval.js:2:7:2:12 | x | eval.js:4:3:4:3 | x |
| eval.js:2:11:2:12 | 42 | eval.js:2:7:2:12 | x |
| sources.js:1:6:1:6 | x | sources.js:1:6:1:6 | x |

View File

@@ -1,3 +1,10 @@
| arguments.js:4:38:4:38 | 0 | 0 |
| arguments.js:5:35:5:35 | 1 | 1 |
| arguments.js:7:29:7:29 | 2 | 2 |
| arguments.js:9:37:9:37 | 0 | 0 |
| arguments.js:11:7:11:7 | 1 | 1 |
| arguments.js:11:10:11:10 | 2 | 2 |
| arguments.js:11:13:11:13 | 3 | 3 |
| eval.js:2:11:2:12 | 42 | 42 |
| sources.js:4:12:4:13 | 19 | 19 |
| sources.js:5:4:5:5 | 23 | 23 |

View File

@@ -1,3 +1,13 @@
| arguments.js:1:1:12:4 | exceptional return of (functi ... );\\n})() | call |
| arguments.js:1:2:12:1 | exceptional return of anonymous function | call |
| arguments.js:2:5:10:5 | exceptional return of function f | call |
| arguments.js:2:16:2:16 | x | call |
| arguments.js:4:28:4:39 | arguments[0] | heap |
| arguments.js:5:25:5:36 | arguments[1] | heap |
| arguments.js:7:24:7:30 | args[2] | heap |
| arguments.js:9:27:9:38 | arguments[0] | heap |
| arguments.js:11:5:11:14 | exceptional return of f(1, 2, 3) | call |
| arguments.js:11:5:11:14 | f(1, 2, 3) | call |
| eval.js:1:1:5:1 | exceptional return of function k | call |
| eval.js:2:7:2:12 | x | eval |
| eval.js:3:3:3:6 | eval | global |

View File

@@ -1,3 +1,4 @@
| arguments.js:2:16:2:16 | x |
| sources.js:1:6:1:6 | x |
| sources.js:3:11:3:11 | x |
| sources.js:9:14:9:18 | array |

View File

@@ -1,3 +1,16 @@
| arguments.js:1:1:1:0 | this |
| arguments.js:1:1:12:4 | (functi ... );\\n})() |
| arguments.js:1:2:1:1 | this |
| arguments.js:1:2:12:1 | functio ... , 3);\\n} |
| arguments.js:2:5:2:4 | this |
| arguments.js:2:5:10:5 | functio ... ;\\n } |
| arguments.js:2:16:2:16 | x |
| arguments.js:4:28:4:39 | arguments[0] |
| arguments.js:5:25:5:36 | arguments[1] |
| arguments.js:7:24:7:30 | args[2] |
| arguments.js:8:21:8:22 | {} |
| arguments.js:9:27:9:38 | arguments[0] |
| arguments.js:11:5:11:14 | f(1, 2, 3) |
| eval.js:1:1:1:0 | this |
| eval.js:1:1:1:0 | this |
| eval.js:1:1:5:1 | functio ... eval`\\n} |