@@ -77,8 +77,12 @@ module ArrayTaintTracking {
77
77
succ = call .getReceiver ( ) .getALocalSource ( ) and
78
78
call .getCalleeName ( ) = [ "push" , "unshift" ]
79
79
or
80
- // `array.splice(i, del, e)`: if `e` is tainted, then so is `array`.
81
- pred = call .getArgument ( 2 ) and
80
+ // `array.splice(i, del, e1, e2, ...)`: if any item is tainted, then so is `array`.
81
+ pred = call .getArgument ( any ( int i | i >= 2 ) ) and
82
+ succ .( DataFlow:: SourceNode ) .getAMethodCall ( "splice" ) = call
83
+ or
84
+ // `array.splice(i, del, ...e)`: if `e` is tainted, then so is `array`.
85
+ pred = call .getASpreadArgument ( ) and
82
86
succ .( DataFlow:: SourceNode ) .getAMethodCall ( "splice" ) = call
83
87
or
84
88
// `e = array.pop()`, `e = array.shift()`, or similar: if `array` is tainted, then so is `e`.
@@ -115,9 +119,9 @@ private module ArrayDataFlow {
115
119
* A step modeling the creation of an Array using the `Array.from(x)` method.
116
120
* The step copies the elements of the argument (set, array, or iterator elements) into the resulting array.
117
121
*/
118
- private class ArrayFrom extends DataFlow :: SharedFlowStep {
122
+ private class ArrayFrom extends PreCallGraphStep {
119
123
override predicate loadStoreStep (
120
- DataFlow:: Node pred , DataFlow:: Node succ , string fromProp , string toProp
124
+ DataFlow:: Node pred , DataFlow:: SourceNode succ , string fromProp , string toProp
121
125
) {
122
126
exists ( DataFlow:: CallNode call |
123
127
call = arrayFromCall ( ) and
@@ -135,9 +139,9 @@ private module ArrayDataFlow {
135
139
*
136
140
* Such a step can occur both with the `push` and `unshift` methods, or when creating a new array.
137
141
*/
138
- private class ArrayCopySpread extends DataFlow :: SharedFlowStep {
142
+ private class ArrayCopySpread extends PreCallGraphStep {
139
143
override predicate loadStoreStep (
140
- DataFlow:: Node pred , DataFlow:: Node succ , string fromProp , string toProp
144
+ DataFlow:: Node pred , DataFlow:: SourceNode succ , string fromProp , string toProp
141
145
) {
142
146
fromProp = arrayLikeElement ( ) and
143
147
toProp = arrayElement ( ) and
@@ -156,7 +160,7 @@ private module ArrayDataFlow {
156
160
/**
157
161
* A step for storing an element on an array using `arr.push(e)` or `arr.unshift(e)`.
158
162
*/
159
- private class ArrayAppendStep extends DataFlow :: SharedFlowStep {
163
+ private class ArrayAppendStep extends PreCallGraphStep {
160
164
override predicate storeStep ( DataFlow:: Node element , DataFlow:: SourceNode obj , string prop ) {
161
165
prop = arrayElement ( ) and
162
166
exists ( DataFlow:: MethodCallNode call |
@@ -187,7 +191,7 @@ private module ArrayDataFlow {
187
191
* A step for reading/writing an element from an array inside a for-loop.
188
192
* E.g. a read from `foo[i]` to `bar` in `for(var i = 0; i < arr.length; i++) {bar = foo[i]}`.
189
193
*/
190
- private class ArrayIndexingStep extends DataFlow :: SharedFlowStep {
194
+ private class ArrayIndexingStep extends PreCallGraphStep {
191
195
override predicate loadStep ( DataFlow:: Node obj , DataFlow:: Node element , string prop ) {
192
196
exists ( ArrayIndexingAccess access |
193
197
prop = arrayElement ( ) and
@@ -209,7 +213,7 @@ private module ArrayDataFlow {
209
213
* A step for retrieving an element from an array using `.pop()`, `.shift()`, or `.at()`.
210
214
* E.g. `array.pop()`.
211
215
*/
212
- private class ArrayPopStep extends DataFlow :: SharedFlowStep {
216
+ private class ArrayPopStep extends PreCallGraphStep {
213
217
override predicate loadStep ( DataFlow:: Node obj , DataFlow:: Node element , string prop ) {
214
218
exists ( DataFlow:: MethodCallNode call |
215
219
call .getMethodName ( ) = [ "pop" , "shift" , "at" ] and
@@ -274,25 +278,38 @@ private module ArrayDataFlow {
274
278
275
279
/**
276
280
* A step modeling that `splice` can insert elements into an array.
277
- * For example in `array.splice(i, del, e )`: if `e` is tainted, then so is `array
281
+ * For example in `array.splice(i, del, e1, e2, ... )`: if any item is tainted, then so is `array`
278
282
*/
279
- private class ArraySpliceStep extends DataFlow :: SharedFlowStep {
283
+ private class ArraySpliceStep extends PreCallGraphStep {
280
284
override predicate storeStep ( DataFlow:: Node element , DataFlow:: SourceNode obj , string prop ) {
281
285
exists ( DataFlow:: MethodCallNode call |
282
286
call .getMethodName ( ) = "splice" and
283
287
prop = arrayElement ( ) and
284
- element = call .getArgument ( 2 ) and
288
+ element = call .getArgument ( any ( int i | i >= 2 ) ) and
285
289
call = obj .getAMethodCall ( )
286
290
)
287
291
}
292
+
293
+ override predicate loadStoreStep (
294
+ DataFlow:: Node pred , DataFlow:: SourceNode succ , string fromProp , string toProp
295
+ ) {
296
+ fromProp = arrayLikeElement ( ) and
297
+ toProp = arrayElement ( ) and
298
+ // `array.splice(i, del, ...arr)` variant
299
+ exists ( DataFlow:: MethodCallNode mcn |
300
+ mcn .getMethodName ( ) = "splice" and
301
+ pred = mcn .getASpreadArgument ( ) and
302
+ succ = mcn .getReceiver ( ) .getALocalSource ( )
303
+ )
304
+ }
288
305
}
289
306
290
307
/**
291
308
* A step for modeling `concat`.
292
309
* For example in `e = arr1.concat(arr2, arr3)`: if any of the `arr` is tainted, then so is `e`.
293
310
*/
294
- private class ArrayConcatStep extends DataFlow :: SharedFlowStep {
295
- override predicate loadStoreStep ( DataFlow:: Node pred , DataFlow:: Node succ , string prop ) {
311
+ private class ArrayConcatStep extends PreCallGraphStep {
312
+ override predicate loadStoreStep ( DataFlow:: Node pred , DataFlow:: SourceNode succ , string prop ) {
296
313
exists ( DataFlow:: MethodCallNode call |
297
314
call .getMethodName ( ) = "concat" and
298
315
prop = arrayElement ( ) and
@@ -305,8 +322,8 @@ private module ArrayDataFlow {
305
322
/**
306
323
* A step for modeling that elements from an array `arr` also appear in the result from calling `slice`/`splice`/`filter`.
307
324
*/
308
- private class ArraySliceStep extends DataFlow :: SharedFlowStep {
309
- override predicate loadStoreStep ( DataFlow:: Node pred , DataFlow:: Node succ , string prop ) {
325
+ private class ArraySliceStep extends PreCallGraphStep {
326
+ override predicate loadStoreStep ( DataFlow:: Node pred , DataFlow:: SourceNode succ , string prop ) {
310
327
exists ( DataFlow:: MethodCallNode call |
311
328
call .getMethodName ( ) = [ "slice" , "splice" , "filter" ] and
312
329
prop = arrayElement ( ) and
@@ -319,7 +336,7 @@ private module ArrayDataFlow {
319
336
/**
320
337
* A step modeling that elements from an array `arr` are received by calling `find`.
321
338
*/
322
- private class ArrayFindStep extends DataFlow :: SharedFlowStep {
339
+ private class ArrayFindStep extends PreCallGraphStep {
323
340
override predicate loadStep ( DataFlow:: Node pred , DataFlow:: Node succ , string prop ) {
324
341
exists ( DataFlow:: CallNode call |
325
342
call = arrayFindCall ( pred ) and
@@ -382,7 +399,7 @@ private module ArrayLibraries {
382
399
* E.g. `array-union` that creates a union of multiple arrays, or `array-uniq` that creates an array with unique elements.
383
400
*/
384
401
DataFlow:: CallNode arrayCopyCall ( DataFlow:: Node array ) {
385
- result = API :: moduleImport ( [ "array-union" , "array-uniq" , "uniq" ] ) .getACall ( ) and
402
+ result = DataFlow :: moduleImport ( [ "array-union" , "array-uniq" , "uniq" ] ) .getACall ( ) and
386
403
array = result .getAnArgument ( )
387
404
}
388
405
@@ -401,8 +418,8 @@ private module ArrayLibraries {
401
418
/**
402
419
* A loadStoreStep for a library that copies the elements of an array into another array.
403
420
*/
404
- private class ArrayCopyLoadStore extends DataFlow :: SharedFlowStep {
405
- override predicate loadStoreStep ( DataFlow:: Node pred , DataFlow:: Node succ , string prop ) {
421
+ private class ArrayCopyLoadStore extends PreCallGraphStep {
422
+ override predicate loadStoreStep ( DataFlow:: Node pred , DataFlow:: SourceNode succ , string prop ) {
406
423
exists ( DataFlow:: CallNode call |
407
424
call = arrayCopyCall ( pred ) and
408
425
succ = call and
0 commit comments