Merge pull request #8886 from kaeluka/add-rest-parameter-flowstep

JS: Add flow step to `...rest` parameters
This commit is contained in:
Stephan Brandauer
2022-04-28 08:39:50 +01:00
committed by GitHub
4 changed files with 139 additions and 0 deletions

View File

@@ -41,6 +41,11 @@ class Function extends @function, Parameterized, TypeParameterized, StmtContaine
/** Gets the `i`th parameter of this function. */
Parameter getParameter(int i) { result = this.getChildExpr(i) }
/** Gets the `...rest` parameter, if any. */
Parameter getRestParameter() {
result = this.getParameter(this.getNumParameter() - 1) and result.isRestParameter()
}
/** Gets a parameter of this function. */
override Parameter getAParameter() { exists(int idx | result = this.getParameter(idx)) }

View File

@@ -212,6 +212,8 @@ private module CachedSteps {
)
or
parm = reflectiveParameterAccess(f, i)
or
parm = restParameterAccess(f, i)
)
or
arg = invk.(DataFlow::CallNode).getReceiver() and
@@ -264,6 +266,21 @@ private module CachedSteps {
result.(DataFlow::PropRead).accesses(argumentsAccess(f), any(string p | i = p.toInt()))
}
/**
* Gets a data-flow node that refers to the `i`th parameter of `f` through its `...rest` argument.
*
* If there is normal arguments before `...rest`, we have to account for them.
* For example, a function `function f(a, ...rest) { console.log(rest[1]); }`:
* Here, `restParameterAccess(_, 2)` will return `rest[1]`, because there is the leading
* `a` parameter.
*/
private DataFlow::SourceNode restParameterAccess(Function f, int i) {
result
.(DataFlow::PropRead)
.accesses(f.getRestParameter().flow().(DataFlow::ParameterNode).getALocalUse(),
any(string idx | i = idx.toInt() + f.getNumParameter() - 1))
}
/**
* Holds if there is a flow step from `pred` to `succ` through parameter passing
* to a function call.

View File

@@ -1362,6 +1362,50 @@ nodes
| tests.js:517:40:517:42 | key |
| tests.js:517:40:517:42 | key |
| tests.js:517:40:517:42 | key |
| tests.js:523:11:523:23 | dst |
| tests.js:523:11:523:23 | dst |
| tests.js:523:17:523:23 | args[0] |
| tests.js:523:17:523:23 | args[0] |
| tests.js:524:11:524:23 | src |
| tests.js:524:11:524:23 | src |
| tests.js:524:17:524:23 | args[1] |
| tests.js:524:17:524:23 | args[1] |
| tests.js:525:14:525:16 | key |
| tests.js:525:14:525:16 | key |
| tests.js:525:14:525:16 | key |
| tests.js:527:35:527:37 | dst |
| tests.js:527:35:527:37 | dst |
| tests.js:527:35:527:42 | dst[key] |
| tests.js:527:35:527:42 | dst[key] |
| tests.js:527:35:527:42 | dst[key] |
| tests.js:527:35:527:42 | dst[key] |
| tests.js:527:39:527:41 | key |
| tests.js:527:39:527:41 | key |
| tests.js:527:45:527:47 | src |
| tests.js:527:45:527:47 | src |
| tests.js:527:45:527:52 | src[key] |
| tests.js:527:45:527:52 | src[key] |
| tests.js:527:45:527:52 | src[key] |
| tests.js:527:45:527:52 | src[key] |
| tests.js:527:45:527:52 | src[key] |
| tests.js:527:49:527:51 | key |
| tests.js:527:49:527:51 | key |
| tests.js:529:13:529:15 | dst |
| tests.js:529:13:529:15 | dst |
| tests.js:529:13:529:15 | dst |
| tests.js:529:17:529:19 | key |
| tests.js:529:17:529:19 | key |
| tests.js:529:17:529:19 | key |
| tests.js:529:24:529:26 | src |
| tests.js:529:24:529:26 | src |
| tests.js:529:24:529:31 | src[key] |
| tests.js:529:24:529:31 | src[key] |
| tests.js:529:24:529:31 | src[key] |
| tests.js:529:24:529:31 | src[key] |
| tests.js:529:24:529:31 | src[key] |
| tests.js:529:24:529:31 | src[key] |
| tests.js:529:28:529:30 | key |
| tests.js:529:28:529:30 | key |
edges
| examples/PrototypePollutingFunction.js:1:16:1:18 | dst | examples/PrototypePollutingFunction.js:5:19:5:21 | dst |
| examples/PrototypePollutingFunction.js:1:16:1:18 | dst | examples/PrototypePollutingFunction.js:5:19:5:21 | dst |
@@ -3075,6 +3119,66 @@ edges
| tests.js:516:36:516:38 | key | tests.js:516:32:516:39 | src[key] |
| tests.js:516:36:516:38 | key | tests.js:516:32:516:39 | src[key] |
| tests.js:516:36:516:38 | key | tests.js:516:32:516:39 | src[key] |
| tests.js:523:11:523:23 | dst | tests.js:527:35:527:37 | dst |
| tests.js:523:11:523:23 | dst | tests.js:527:35:527:37 | dst |
| tests.js:523:11:523:23 | dst | tests.js:529:13:529:15 | dst |
| tests.js:523:11:523:23 | dst | tests.js:529:13:529:15 | dst |
| tests.js:523:11:523:23 | dst | tests.js:529:13:529:15 | dst |
| tests.js:523:11:523:23 | dst | tests.js:529:13:529:15 | dst |
| tests.js:523:17:523:23 | args[0] | tests.js:523:11:523:23 | dst |
| tests.js:523:17:523:23 | args[0] | tests.js:523:11:523:23 | dst |
| tests.js:524:11:524:23 | src | tests.js:527:45:527:47 | src |
| tests.js:524:11:524:23 | src | tests.js:527:45:527:47 | src |
| tests.js:524:11:524:23 | src | tests.js:529:24:529:26 | src |
| tests.js:524:11:524:23 | src | tests.js:529:24:529:26 | src |
| tests.js:524:17:524:23 | args[1] | tests.js:524:11:524:23 | src |
| tests.js:524:17:524:23 | args[1] | tests.js:524:11:524:23 | src |
| tests.js:525:14:525:16 | key | tests.js:527:39:527:41 | key |
| tests.js:525:14:525:16 | key | tests.js:527:39:527:41 | key |
| tests.js:525:14:525:16 | key | tests.js:527:39:527:41 | key |
| tests.js:525:14:525:16 | key | tests.js:527:39:527:41 | key |
| tests.js:525:14:525:16 | key | tests.js:527:49:527:51 | key |
| tests.js:525:14:525:16 | key | tests.js:527:49:527:51 | key |
| tests.js:525:14:525:16 | key | tests.js:527:49:527:51 | key |
| tests.js:525:14:525:16 | key | tests.js:527:49:527:51 | key |
| tests.js:525:14:525:16 | key | tests.js:529:17:529:19 | key |
| tests.js:525:14:525:16 | key | tests.js:529:17:529:19 | key |
| tests.js:525:14:525:16 | key | tests.js:529:17:529:19 | key |
| tests.js:525:14:525:16 | key | tests.js:529:17:529:19 | key |
| tests.js:525:14:525:16 | key | tests.js:529:17:529:19 | key |
| tests.js:525:14:525:16 | key | tests.js:529:17:529:19 | key |
| tests.js:525:14:525:16 | key | tests.js:529:17:529:19 | key |
| tests.js:525:14:525:16 | key | tests.js:529:28:529:30 | key |
| tests.js:525:14:525:16 | key | tests.js:529:28:529:30 | key |
| tests.js:525:14:525:16 | key | tests.js:529:28:529:30 | key |
| tests.js:525:14:525:16 | key | tests.js:529:28:529:30 | key |
| tests.js:527:35:527:37 | dst | tests.js:527:35:527:42 | dst[key] |
| tests.js:527:35:527:37 | dst | tests.js:527:35:527:42 | dst[key] |
| tests.js:527:35:527:42 | dst[key] | tests.js:523:17:523:23 | args[0] |
| tests.js:527:35:527:42 | dst[key] | tests.js:523:17:523:23 | args[0] |
| tests.js:527:35:527:42 | dst[key] | tests.js:523:17:523:23 | args[0] |
| tests.js:527:35:527:42 | dst[key] | tests.js:523:17:523:23 | args[0] |
| tests.js:527:39:527:41 | key | tests.js:527:35:527:42 | dst[key] |
| tests.js:527:39:527:41 | key | tests.js:527:35:527:42 | dst[key] |
| tests.js:527:45:527:47 | src | tests.js:527:45:527:52 | src[key] |
| tests.js:527:45:527:47 | src | tests.js:527:45:527:52 | src[key] |
| tests.js:527:45:527:52 | src[key] | tests.js:524:17:524:23 | args[1] |
| tests.js:527:45:527:52 | src[key] | tests.js:524:17:524:23 | args[1] |
| tests.js:527:45:527:52 | src[key] | tests.js:524:17:524:23 | args[1] |
| tests.js:527:45:527:52 | src[key] | tests.js:524:17:524:23 | args[1] |
| tests.js:527:45:527:52 | src[key] | tests.js:524:17:524:23 | args[1] |
| tests.js:527:45:527:52 | src[key] | tests.js:524:17:524:23 | args[1] |
| tests.js:527:49:527:51 | key | tests.js:527:45:527:52 | src[key] |
| tests.js:527:49:527:51 | key | tests.js:527:45:527:52 | src[key] |
| tests.js:529:24:529:26 | src | tests.js:529:24:529:31 | src[key] |
| tests.js:529:24:529:26 | src | tests.js:529:24:529:31 | src[key] |
| tests.js:529:24:529:26 | src | tests.js:529:24:529:31 | src[key] |
| tests.js:529:24:529:26 | src | tests.js:529:24:529:31 | src[key] |
| tests.js:529:24:529:31 | src[key] | tests.js:529:24:529:31 | src[key] |
| tests.js:529:28:529:30 | key | tests.js:529:24:529:31 | src[key] |
| tests.js:529:28:529:30 | key | tests.js:529:24:529:31 | src[key] |
| tests.js:529:28:529:30 | key | tests.js:529:24:529:31 | src[key] |
| tests.js:529:28:529:30 | key | tests.js:529:24:529:31 | src[key] |
#select
| examples/PrototypePollutingFunction.js:7:13:7:15 | dst | examples/PrototypePollutingFunction.js:2:14:2:16 | key | examples/PrototypePollutingFunction.js:7:13:7:15 | dst | Properties are copied from $@ to $@ without guarding against prototype pollution. | examples/PrototypePollutingFunction.js:2:21:2:23 | src | src | examples/PrototypePollutingFunction.js:7:13:7:15 | dst | dst |
| path-assignment.js:15:13:15:18 | target | path-assignment.js:8:19:8:25 | keys[i] | path-assignment.js:15:13:15:18 | target | The property chain $@ is recursively assigned to $@ without guarding against prototype pollution. | path-assignment.js:8:19:8:25 | keys[i] | here | path-assignment.js:15:13:15:18 | target | target |
@@ -3104,3 +3208,4 @@ edges
| tests.js:477:13:477:15 | dst | tests.js:473:25:473:27 | key | tests.js:477:13:477:15 | dst | Properties are copied from $@ to $@ without guarding against prototype pollution. | tests.js:473:12:473:14 | src | src | tests.js:477:13:477:15 | dst | dst |
| tests.js:489:13:489:15 | dst | tests.js:484:14:484:16 | key | tests.js:489:13:489:15 | dst | Properties are copied from $@ to $@ without guarding against prototype pollution. | tests.js:484:21:484:23 | src | src | tests.js:489:13:489:15 | dst | dst |
| tests.js:517:35:517:37 | dst | tests.js:511:19:511:25 | keys[i] | tests.js:517:35:517:37 | dst | Properties are copied from $@ to $@ without guarding against prototype pollution. | tests.js:509:28:509:30 | src | src | tests.js:517:35:517:37 | dst | dst |
| tests.js:529:13:529:15 | dst | tests.js:525:14:525:16 | key | tests.js:529:13:529:15 | dst | Properties are copied from $@ to $@ without guarding against prototype pollution. | tests.js:525:21:525:23 | src | src | tests.js:529:13:529:15 | dst | dst |

View File

@@ -518,3 +518,15 @@ function usingDefineProperty(dst, src) {
}
}
}
function copyUsingForInAndRest(...args) {
const dst = args[0];
const src = args[1];
for (let key in src) {
if (dst[key]) {
copyUsingForInAndRest(dst[key], src[key]);
} else {
dst[key] = src[key]; // NOT OK
}
}
}