Skip to content

Commit c2cab18

Browse files
authored
Merge pull request #19283 from asgerf/js/rest-pattern-fix
JS: Fix missing flow into rest pattern lvalue
2 parents 254789c + 6c01709 commit c2cab18

File tree

6 files changed

+60
-0
lines changed

6 files changed

+60
-0
lines changed

javascript/ql/lib/semmle/javascript/dataflow/DataFlow.qll

+5
Original file line numberDiff line numberDiff line change
@@ -1610,6 +1610,11 @@ module DataFlow {
16101610
pred = TElementPatternNode(_, element) and
16111611
succ = lvalueNodeInternal(element)
16121612
)
1613+
or
1614+
exists(Expr rest |
1615+
pred = TRestPatternNode(_, rest) and
1616+
succ = lvalueNodeInternal(rest)
1617+
)
16131618
}
16141619

16151620
/**

javascript/ql/test/library-tests/DataFlow/tests.expected

+4
Original file line numberDiff line numberDiff line change
@@ -1094,6 +1094,7 @@ flowStep
10941094
| tst.js:87:11:87:24 | o | tst.js:90:15:90:15 | o |
10951095
| tst.js:87:11:87:24 | x | tst.js:91:10:91:10 | x |
10961096
| tst.js:87:13:87:16 | p: x | tst.js:87:11:87:24 | x |
1097+
| tst.js:87:22:87:22 | ...o | tst.js:87:11:87:24 | o |
10971098
| tst.js:88:7:88:18 | y | tst.js:91:14:91:14 | y |
10981099
| tst.js:88:9:88:12 | q: y | tst.js:88:7:88:18 | y |
10991100
| tst.js:88:18:88:18 | o | tst.js:88:7:88:14 | { q: y } |
@@ -1110,6 +1111,7 @@ flowStep
11101111
| tst.js:98:11:98:24 | rest | tst.js:101:13:101:16 | rest |
11111112
| tst.js:98:11:98:24 | x | tst.js:102:10:102:10 | x |
11121113
| tst.js:98:13:98:13 | x | tst.js:98:11:98:24 | x |
1114+
| tst.js:98:19:98:22 | ...rest | tst.js:98:11:98:24 | rest |
11131115
| tst.js:99:7:99:18 | y | tst.js:102:14:102:14 | y |
11141116
| tst.js:99:9:99:9 | y | tst.js:99:7:99:18 | y |
11151117
| tst.js:99:15:99:18 | rest | tst.js:99:7:99:11 | [ y ] |
@@ -1264,6 +1266,7 @@ getImmediatePredecessor
12641266
| tst.js:87:11:87:24 | o | tst.js:90:15:90:15 | o |
12651267
| tst.js:87:11:87:24 | x | tst.js:91:10:91:10 | x |
12661268
| tst.js:87:13:87:16 | p: x | tst.js:87:11:87:24 | x |
1269+
| tst.js:87:22:87:22 | ...o | tst.js:87:11:87:24 | o |
12671270
| tst.js:88:7:88:18 | y | tst.js:91:14:91:14 | y |
12681271
| tst.js:88:9:88:12 | q: y | tst.js:88:7:88:18 | y |
12691272
| tst.js:88:18:88:18 | o | tst.js:88:7:88:14 | { q: y } |
@@ -1279,6 +1282,7 @@ getImmediatePredecessor
12791282
| tst.js:98:11:98:24 | rest | tst.js:101:13:101:16 | rest |
12801283
| tst.js:98:11:98:24 | x | tst.js:102:10:102:10 | x |
12811284
| tst.js:98:13:98:13 | x | tst.js:98:11:98:24 | x |
1285+
| tst.js:98:19:98:22 | ...rest | tst.js:98:11:98:24 | rest |
12821286
| tst.js:99:7:99:18 | y | tst.js:102:14:102:14 | y |
12831287
| tst.js:99:9:99:9 | y | tst.js:99:7:99:18 | y |
12841288
| tst.js:99:15:99:18 | rest | tst.js:99:7:99:11 | [ y ] |
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
function t1() {
2+
const { ...rest } = source('t1.1');
3+
rest; // $ getALocalSource=rest
4+
}
5+
6+
function t2() {
7+
const [ ...rest ] = source('t2.1');
8+
rest; // $ getALocalSource=rest
9+
}
10+
11+
function t3() {
12+
const { p1, ...rest } = source('t3.1');
13+
p1; // $ getALocalSource=p1
14+
rest; // $ getALocalSource=rest
15+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
| rest-pattern.js:3:5:3:8 | rest | rest |
2+
| rest-pattern.js:8:5:8:8 | rest | rest |
3+
| rest-pattern.js:13:5:13:6 | p1 | p1 |
4+
| rest-pattern.js:14:5:14:8 | rest | rest |
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import javascript
2+
3+
string nodeName(DataFlow::SourceNode node) {
4+
result = node.getAstNode().(VarRef).getName()
5+
or
6+
result = node.getAstNode().(PropertyPattern).getName()
7+
or
8+
result = node.getAstNode().(PropAccess).getPropertyName()
9+
or
10+
exists(DataFlow::InvokeNode invoke |
11+
node = invoke and
12+
invoke.getCalleeName() = "source" and
13+
result = invoke.getArgument(0).getStringValue()
14+
)
15+
}
16+
17+
bindingset[node1, node2]
18+
pragma[inline_late]
19+
predicate sameLine(DataFlow::Node node1, DataFlow::Node node2) {
20+
node1.getLocation().getFile() = node2.getLocation().getFile() and
21+
node1.getLocation().getStartLine() = node2.getLocation().getStartLine()
22+
}
23+
24+
query predicate getALocalSource(DataFlow::Node node, string name) {
25+
exists(DataFlow::SourceNode sn |
26+
sn = node.getALocalSource() and
27+
name = nodeName(sn) and
28+
not sameLine(node, sn)
29+
)
30+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
query: test.ql
2+
postprocess: utils/test/InlineExpectationsTestQuery.ql

0 commit comments

Comments
 (0)