Skip to content

Commit 58faa2d

Browse files
committed
JS: Add: dataflow step for static method of groupBy from Map.
1 parent 6344f83 commit 58faa2d

File tree

4 files changed

+27
-5
lines changed

4 files changed

+27
-5
lines changed

javascript/ql/lib/semmle/javascript/Collections.qll

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,22 @@ private module CollectionDataFlow {
160160
exists(DataFlow::MethodCallNode call |
161161
call = DataFlow::globalVarRef(["Map", "Object"]).getAMemberCall("groupBy") and
162162
pred = call.getArgument(0) and
163-
succ = call
163+
(succ = call.getCallback(1).getParameter(0) or succ = call.getALocalUse())
164+
)
165+
}
166+
}
167+
168+
/**
169+
* A step for handling data flow and taint tracking for the groupBy method on iterable objects.
170+
* Ensures propagation of taint and data flow through the groupBy operation.
171+
*/
172+
private class GroupByDataFlowStep extends PreCallGraphStep {
173+
override predicate storeStep(DataFlow::Node pred, DataFlow::SourceNode succ, string prop) {
174+
exists(DataFlow::MethodCallNode call |
175+
call = DataFlow::globalVarRef("Map").getAMemberCall("groupBy") and
176+
pred = call.getArgument(0) and
177+
succ = call and
178+
prop = mapValueUnknownKey()
164179
)
165180
}
166181
}

javascript/ql/test/library-tests/TaintTracking/BasicTaintTracking.expected

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -246,10 +246,15 @@ typeInferenceMismatch
246246
| tst.js:2:13:2:20 | source() | tst.js:70:10:70:18 | xReversed |
247247
| tst.js:2:13:2:20 | source() | tst.js:72:10:72:31 | Map.gro ... z => z) |
248248
| tst.js:2:13:2:20 | source() | tst.js:74:10:74:34 | Object. ... z => z) |
249+
| tst.js:2:13:2:20 | source() | tst.js:78:55:78:58 | item |
249250
| tst.js:2:13:2:20 | source() | tst.js:79:14:79:20 | grouped |
250251
| tst.js:75:22:75:29 | source() | tst.js:75:10:75:52 | Map.gro ... (item)) |
252+
| tst.js:75:22:75:29 | source() | tst.js:75:47:75:50 | item |
253+
| tst.js:82:23:82:30 | source() | tst.js:83:58:83:61 | item |
251254
| tst.js:82:23:82:30 | source() | tst.js:84:14:84:20 | grouped |
252255
| tst.js:87:22:87:29 | source() | tst.js:90:14:90:25 | taintedValue |
256+
| tst.js:93:22:93:29 | source() | tst.js:96:14:96:25 | taintedValue |
257+
| tst.js:93:22:93:29 | source() | tst.js:97:14:97:26 | map.get(true) |
253258
| xml.js:5:18:5:25 | source() | xml.js:8:14:8:17 | text |
254259
| xml.js:12:17:12:24 | source() | xml.js:13:14:13:19 | result |
255260
| xml.js:23:18:23:25 | source() | xml.js:20:14:20:17 | attr |

javascript/ql/test/library-tests/TaintTracking/DataFlowTracking.expected

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,3 +112,5 @@
112112
| thisAssignments.js:7:19:7:26 | source() | thisAssignments.js:8:10:8:20 | this.field2 |
113113
| tst.js:2:13:2:20 | source() | tst.js:4:10:4:10 | x |
114114
| tst.js:2:13:2:20 | source() | tst.js:54:14:54:19 | unsafe |
115+
| tst.js:93:22:93:29 | source() | tst.js:96:14:96:25 | taintedValue |
116+
| tst.js:93:22:93:29 | source() | tst.js:97:14:97:26 | map.get(true) |

javascript/ql/test/library-tests/TaintTracking/tst.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -75,12 +75,12 @@ function test() {
7575
sink(Map.groupBy(source(), (item) => sink(item))); // NOT OK
7676

7777
{
78-
const grouped = Map.groupBy(x, (item) => sink(item)); // NOT OK -- Should be tainted, but it is not
78+
const grouped = Map.groupBy(x, (item) => sink(item)); // NOT OK
7979
sink(grouped); // NOT OK
8080
}
8181
{
8282
const list = [source()];
83-
const grouped = Map.groupBy(list, (item) => sink(item)); // NOT OK -- Should be tainted, but it is not
83+
const grouped = Map.groupBy(list, (item) => sink(item)); // NOT OK
8484
sink(grouped); // NOT OK
8585
}
8686
{
@@ -93,7 +93,7 @@ function test() {
9393
const data = source();
9494
const map = Map.groupBy(data, item => item);
9595
const taintedValue = map.get(true);
96-
sink(taintedValue); // NOT OK -- Should be tainted, but it is not
97-
sink(map.get(true)); // NOT OK -- Should be tainted, but it is not
96+
sink(taintedValue); // NOT OK
97+
sink(map.get(true)); // NOT OK
9898
}
9999
}

0 commit comments

Comments
 (0)