Skip to content

Commit e64f29f

Browse files
committed
add support for Array.prototype.find and polyfills
1 parent f6f63e2 commit e64f29f

File tree

4 files changed

+39
-1
lines changed

4 files changed

+39
-1
lines changed
Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
lgtm,codescanning
22
* The dataflow libraries now model dataflow through more array libraries.
33
Affected packages are
4-
[array-from](https://npmjs.com/package/array-from)
4+
[array-from](https://npmjs.com/package/array-from),
5+
[array.prototype.find](https://npmjs.com/package/array.prototype.find),
6+
[array-find](https://npmjs.com/package/array-find)

javascript/ql/src/semmle/javascript/Arrays.qll

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,11 @@ module ArrayTaintTracking {
7979
call.(DataFlow::MethodCallNode).getMethodName() = "concat" and
8080
succ = call and
8181
pred = call.getAnArgument()
82+
or
83+
// find
84+
// `e = arr.find(callback)`
85+
call = arrayFindCall(pred) and
86+
succ = call
8287
}
8388
}
8489

@@ -297,6 +302,19 @@ private module ArrayDataFlow {
297302
)
298303
}
299304
}
305+
306+
/**
307+
* A step modelling that elements from an array `arr` are received by calling `find`.
308+
*/
309+
private class ArrayFindStep extends DataFlow::SharedFlowStep {
310+
override predicate loadStep(DataFlow::Node pred, DataFlow::Node succ, string prop) {
311+
exists(DataFlow::CallNode call |
312+
call = arrayFindCall(pred) and
313+
succ = call and
314+
prop = arrayElement()
315+
)
316+
}
317+
}
300318
}
301319

302320
private import ArrayLibraries
@@ -313,4 +331,15 @@ private module ArrayLibraries {
313331
or
314332
result = DataFlow::moduleImport("array-from").getACall()
315333
}
334+
335+
/**
336+
* Gets a call to `Array.prototype.find` or a polyfill implementing the same functionality.
337+
*/
338+
DataFlow::CallNode arrayFindCall(DataFlow::Node array) {
339+
result.(DataFlow::MethodCallNode).getMethodName() = "find" and
340+
array = result.getReceiver()
341+
or
342+
result = DataFlow::moduleImport(["array.prototype.find", "array-find"]).getACall() and
343+
array = result.getArgument(0)
344+
}
316345
}

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
| arrays.js:2:16:2:23 | "source" | arrays.js:60:10:60:10 | x |
99
| arrays.js:2:16:2:23 | "source" | arrays.js:66:10:66:10 | x |
1010
| arrays.js:2:16:2:23 | "source" | arrays.js:71:10:71:10 | x |
11+
| arrays.js:2:16:2:23 | "source" | arrays.js:74:8:74:29 | arr.fin ... llback) |
12+
| arrays.js:2:16:2:23 | "source" | arrays.js:77:8:77:35 | arrayFi ... llback) |
1113
| arrays.js:18:22:18:29 | "source" | arrays.js:18:50:18:50 | e |
1214
| arrays.js:22:15:22:22 | "source" | arrays.js:23:8:23:17 | arr2.pop() |
1315
| arrays.js:25:15:25:22 | "source" | arrays.js:26:8:26:17 | arr3.pop() |

javascript/ql/test/library-tests/Arrays/arrays.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,4 +70,9 @@
7070
for (const x of arrayFrom(arr)) {
7171
sink(x); // NOT OK
7272
}
73+
74+
sink(arr.find(someCallback)); // NOT OK
75+
76+
const arrayFind = require("array-find");
77+
sink(arrayFind(arr, someCallback)); // NOT OK
7378
});

0 commit comments

Comments
 (0)