From 7703b1fab5211538d70ae2e4c994cab3c00a49a0 Mon Sep 17 00:00:00 2001 From: Asger F Date: Fri, 11 Apr 2025 08:26:04 +0200 Subject: [PATCH 1/3] JS: Add test for missing getALocalSource flow for rest pattern --- .../GetALocalSource/rest-pattern.js | 15 ++++++++++ .../GetALocalSource/test.expected | 1 + .../library-tests/GetALocalSource/test.ql | 30 +++++++++++++++++++ .../library-tests/GetALocalSource/test.qlref | 2 ++ 4 files changed, 48 insertions(+) create mode 100644 javascript/ql/test/library-tests/GetALocalSource/rest-pattern.js create mode 100644 javascript/ql/test/library-tests/GetALocalSource/test.expected create mode 100644 javascript/ql/test/library-tests/GetALocalSource/test.ql create mode 100644 javascript/ql/test/library-tests/GetALocalSource/test.qlref diff --git a/javascript/ql/test/library-tests/GetALocalSource/rest-pattern.js b/javascript/ql/test/library-tests/GetALocalSource/rest-pattern.js new file mode 100644 index 000000000000..8eb0c808853c --- /dev/null +++ b/javascript/ql/test/library-tests/GetALocalSource/rest-pattern.js @@ -0,0 +1,15 @@ +function t1() { + const { ...rest } = source('t1.1'); + rest; // $ MISSING: getALocalSource=rest +} + +function t2() { + const [ ...rest ] = source('t2.1'); + rest; // $ MISSING: getALocalSource=rest +} + +function t3() { + const { p1, ...rest } = source('t3.1'); + p1; // $ getALocalSource=p1 + rest; // $ MISSING: getALocalSource=rest +} diff --git a/javascript/ql/test/library-tests/GetALocalSource/test.expected b/javascript/ql/test/library-tests/GetALocalSource/test.expected new file mode 100644 index 000000000000..6efee9a8f1e2 --- /dev/null +++ b/javascript/ql/test/library-tests/GetALocalSource/test.expected @@ -0,0 +1 @@ +| rest-pattern.js:13:5:13:6 | p1 | p1 | diff --git a/javascript/ql/test/library-tests/GetALocalSource/test.ql b/javascript/ql/test/library-tests/GetALocalSource/test.ql new file mode 100644 index 000000000000..7803f6fd4959 --- /dev/null +++ b/javascript/ql/test/library-tests/GetALocalSource/test.ql @@ -0,0 +1,30 @@ +import javascript + +string nodeName(DataFlow::SourceNode node) { + result = node.getAstNode().(VarRef).getName() + or + result = node.getAstNode().(PropertyPattern).getName() + or + result = node.getAstNode().(PropAccess).getPropertyName() + or + exists(DataFlow::InvokeNode invoke | + node = invoke and + invoke.getCalleeName() = "source" and + result = invoke.getArgument(0).getStringValue() + ) +} + +bindingset[node1, node2] +pragma[inline_late] +predicate sameLine(DataFlow::Node node1, DataFlow::Node node2) { + node1.getLocation().getFile() = node2.getLocation().getFile() and + node1.getLocation().getStartLine() = node2.getLocation().getStartLine() +} + +query predicate getALocalSource(DataFlow::Node node, string name) { + exists(DataFlow::SourceNode sn | + sn = node.getALocalSource() and + name = nodeName(sn) and + not sameLine(node, sn) + ) +} diff --git a/javascript/ql/test/library-tests/GetALocalSource/test.qlref b/javascript/ql/test/library-tests/GetALocalSource/test.qlref new file mode 100644 index 000000000000..ab6773f15f90 --- /dev/null +++ b/javascript/ql/test/library-tests/GetALocalSource/test.qlref @@ -0,0 +1,2 @@ +query: test.ql +postprocess: utils/test/InlineExpectationsTestQuery.ql From 719456e27d7d3f8efcd442848c5fef1df2f21a24 Mon Sep 17 00:00:00 2001 From: Asger F Date: Fri, 11 Apr 2025 08:33:29 +0200 Subject: [PATCH 2/3] JS: Fix missing flow into rest pattern lvalue --- javascript/ql/lib/semmle/javascript/dataflow/DataFlow.qll | 5 +++++ .../ql/test/library-tests/GetALocalSource/rest-pattern.js | 6 +++--- .../ql/test/library-tests/GetALocalSource/test.expected | 3 +++ 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/javascript/ql/lib/semmle/javascript/dataflow/DataFlow.qll b/javascript/ql/lib/semmle/javascript/dataflow/DataFlow.qll index f86d8806304d..46801bd1ad7e 100644 --- a/javascript/ql/lib/semmle/javascript/dataflow/DataFlow.qll +++ b/javascript/ql/lib/semmle/javascript/dataflow/DataFlow.qll @@ -1610,6 +1610,11 @@ module DataFlow { pred = TElementPatternNode(_, element) and succ = lvalueNodeInternal(element) ) + or + exists(Expr rest | + pred = TRestPatternNode(_, rest) and + succ = lvalueNodeInternal(rest) + ) } /** diff --git a/javascript/ql/test/library-tests/GetALocalSource/rest-pattern.js b/javascript/ql/test/library-tests/GetALocalSource/rest-pattern.js index 8eb0c808853c..3e0a62755f04 100644 --- a/javascript/ql/test/library-tests/GetALocalSource/rest-pattern.js +++ b/javascript/ql/test/library-tests/GetALocalSource/rest-pattern.js @@ -1,15 +1,15 @@ function t1() { const { ...rest } = source('t1.1'); - rest; // $ MISSING: getALocalSource=rest + rest; // $ getALocalSource=rest } function t2() { const [ ...rest ] = source('t2.1'); - rest; // $ MISSING: getALocalSource=rest + rest; // $ getALocalSource=rest } function t3() { const { p1, ...rest } = source('t3.1'); p1; // $ getALocalSource=p1 - rest; // $ MISSING: getALocalSource=rest + rest; // $ getALocalSource=rest } diff --git a/javascript/ql/test/library-tests/GetALocalSource/test.expected b/javascript/ql/test/library-tests/GetALocalSource/test.expected index 6efee9a8f1e2..5770e50b8a62 100644 --- a/javascript/ql/test/library-tests/GetALocalSource/test.expected +++ b/javascript/ql/test/library-tests/GetALocalSource/test.expected @@ -1 +1,4 @@ +| rest-pattern.js:3:5:3:8 | rest | rest | +| rest-pattern.js:8:5:8:8 | rest | rest | | rest-pattern.js:13:5:13:6 | p1 | p1 | +| rest-pattern.js:14:5:14:8 | rest | rest | From 6c01709048a97c36727c6a7538efb478c53f12a9 Mon Sep 17 00:00:00 2001 From: Asger F Date: Fri, 11 Apr 2025 15:15:22 +0200 Subject: [PATCH 3/3] JS: Update more test output --- javascript/ql/test/library-tests/DataFlow/tests.expected | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/javascript/ql/test/library-tests/DataFlow/tests.expected b/javascript/ql/test/library-tests/DataFlow/tests.expected index 3637927d0e25..55c6771eef02 100644 --- a/javascript/ql/test/library-tests/DataFlow/tests.expected +++ b/javascript/ql/test/library-tests/DataFlow/tests.expected @@ -1094,6 +1094,7 @@ flowStep | tst.js:87:11:87:24 | o | tst.js:90:15:90:15 | o | | tst.js:87:11:87:24 | x | tst.js:91:10:91:10 | x | | tst.js:87:13:87:16 | p: x | tst.js:87:11:87:24 | x | +| tst.js:87:22:87:22 | ...o | tst.js:87:11:87:24 | o | | tst.js:88:7:88:18 | y | tst.js:91:14:91:14 | y | | tst.js:88:9:88:12 | q: y | tst.js:88:7:88:18 | y | | tst.js:88:18:88:18 | o | tst.js:88:7:88:14 | { q: y } | @@ -1110,6 +1111,7 @@ flowStep | tst.js:98:11:98:24 | rest | tst.js:101:13:101:16 | rest | | tst.js:98:11:98:24 | x | tst.js:102:10:102:10 | x | | tst.js:98:13:98:13 | x | tst.js:98:11:98:24 | x | +| tst.js:98:19:98:22 | ...rest | tst.js:98:11:98:24 | rest | | tst.js:99:7:99:18 | y | tst.js:102:14:102:14 | y | | tst.js:99:9:99:9 | y | tst.js:99:7:99:18 | y | | tst.js:99:15:99:18 | rest | tst.js:99:7:99:11 | [ y ] | @@ -1264,6 +1266,7 @@ getImmediatePredecessor | tst.js:87:11:87:24 | o | tst.js:90:15:90:15 | o | | tst.js:87:11:87:24 | x | tst.js:91:10:91:10 | x | | tst.js:87:13:87:16 | p: x | tst.js:87:11:87:24 | x | +| tst.js:87:22:87:22 | ...o | tst.js:87:11:87:24 | o | | tst.js:88:7:88:18 | y | tst.js:91:14:91:14 | y | | tst.js:88:9:88:12 | q: y | tst.js:88:7:88:18 | y | | tst.js:88:18:88:18 | o | tst.js:88:7:88:14 | { q: y } | @@ -1279,6 +1282,7 @@ getImmediatePredecessor | tst.js:98:11:98:24 | rest | tst.js:101:13:101:16 | rest | | tst.js:98:11:98:24 | x | tst.js:102:10:102:10 | x | | tst.js:98:13:98:13 | x | tst.js:98:11:98:24 | x | +| tst.js:98:19:98:22 | ...rest | tst.js:98:11:98:24 | rest | | tst.js:99:7:99:18 | y | tst.js:102:14:102:14 | y | | tst.js:99:9:99:9 | y | tst.js:99:7:99:18 | y | | tst.js:99:15:99:18 | rest | tst.js:99:7:99:11 | [ y ] |