@@ -77,8 +77,12 @@ module ArrayTaintTracking {
7777 succ = call .getReceiver ( ) .getALocalSource ( ) and
7878 call .getCalleeName ( ) = [ "push" , "unshift" ]
7979 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
8286 succ .( DataFlow:: SourceNode ) .getAMethodCall ( "splice" ) = call
8387 or
8488 // `e = array.pop()`, `e = array.shift()`, or similar: if `array` is tainted, then so is `e`.
@@ -115,9 +119,9 @@ private module ArrayDataFlow {
115119 * A step modeling the creation of an Array using the `Array.from(x)` method.
116120 * The step copies the elements of the argument (set, array, or iterator elements) into the resulting array.
117121 */
118- private class ArrayFrom extends DataFlow :: SharedFlowStep {
122+ private class ArrayFrom extends PreCallGraphStep {
119123 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
121125 ) {
122126 exists ( DataFlow:: CallNode call |
123127 call = arrayFromCall ( ) and
@@ -135,9 +139,9 @@ private module ArrayDataFlow {
135139 *
136140 * Such a step can occur both with the `push` and `unshift` methods, or when creating a new array.
137141 */
138- private class ArrayCopySpread extends DataFlow :: SharedFlowStep {
142+ private class ArrayCopySpread extends PreCallGraphStep {
139143 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
141145 ) {
142146 fromProp = arrayLikeElement ( ) and
143147 toProp = arrayElement ( ) and
@@ -156,7 +160,7 @@ private module ArrayDataFlow {
156160 /**
157161 * A step for storing an element on an array using `arr.push(e)` or `arr.unshift(e)`.
158162 */
159- private class ArrayAppendStep extends DataFlow :: SharedFlowStep {
163+ private class ArrayAppendStep extends PreCallGraphStep {
160164 override predicate storeStep ( DataFlow:: Node element , DataFlow:: SourceNode obj , string prop ) {
161165 prop = arrayElement ( ) and
162166 exists ( DataFlow:: MethodCallNode call |
@@ -187,7 +191,7 @@ private module ArrayDataFlow {
187191 * A step for reading/writing an element from an array inside a for-loop.
188192 * E.g. a read from `foo[i]` to `bar` in `for(var i = 0; i < arr.length; i++) {bar = foo[i]}`.
189193 */
190- private class ArrayIndexingStep extends DataFlow :: SharedFlowStep {
194+ private class ArrayIndexingStep extends PreCallGraphStep {
191195 override predicate loadStep ( DataFlow:: Node obj , DataFlow:: Node element , string prop ) {
192196 exists ( ArrayIndexingAccess access |
193197 prop = arrayElement ( ) and
@@ -209,7 +213,7 @@ private module ArrayDataFlow {
209213 * A step for retrieving an element from an array using `.pop()`, `.shift()`, or `.at()`.
210214 * E.g. `array.pop()`.
211215 */
212- private class ArrayPopStep extends DataFlow :: SharedFlowStep {
216+ private class ArrayPopStep extends PreCallGraphStep {
213217 override predicate loadStep ( DataFlow:: Node obj , DataFlow:: Node element , string prop ) {
214218 exists ( DataFlow:: MethodCallNode call |
215219 call .getMethodName ( ) = [ "pop" , "shift" , "at" ] and
@@ -274,25 +278,38 @@ private module ArrayDataFlow {
274278
275279 /**
276280 * 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`
278282 */
279- private class ArraySpliceStep extends DataFlow :: SharedFlowStep {
283+ private class ArraySpliceStep extends PreCallGraphStep {
280284 override predicate storeStep ( DataFlow:: Node element , DataFlow:: SourceNode obj , string prop ) {
281285 exists ( DataFlow:: MethodCallNode call |
282286 call .getMethodName ( ) = "splice" and
283287 prop = arrayElement ( ) and
284- element = call .getArgument ( 2 ) and
288+ element = call .getArgument ( any ( int i | i >= 2 ) ) and
285289 call = obj .getAMethodCall ( )
286290 )
287291 }
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+ }
288305 }
289306
290307 /**
291308 * A step for modeling `concat`.
292309 * For example in `e = arr1.concat(arr2, arr3)`: if any of the `arr` is tainted, then so is `e`.
293310 */
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 ) {
296313 exists ( DataFlow:: MethodCallNode call |
297314 call .getMethodName ( ) = "concat" and
298315 prop = arrayElement ( ) and
@@ -305,8 +322,8 @@ private module ArrayDataFlow {
305322 /**
306323 * A step for modeling that elements from an array `arr` also appear in the result from calling `slice`/`splice`/`filter`.
307324 */
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 ) {
310327 exists ( DataFlow:: MethodCallNode call |
311328 call .getMethodName ( ) = [ "slice" , "splice" , "filter" ] and
312329 prop = arrayElement ( ) and
@@ -319,7 +336,7 @@ private module ArrayDataFlow {
319336 /**
320337 * A step modeling that elements from an array `arr` are received by calling `find`.
321338 */
322- private class ArrayFindStep extends DataFlow :: SharedFlowStep {
339+ private class ArrayFindStep extends PreCallGraphStep {
323340 override predicate loadStep ( DataFlow:: Node pred , DataFlow:: Node succ , string prop ) {
324341 exists ( DataFlow:: CallNode call |
325342 call = arrayFindCall ( pred ) and
@@ -382,7 +399,7 @@ private module ArrayLibraries {
382399 * E.g. `array-union` that creates a union of multiple arrays, or `array-uniq` that creates an array with unique elements.
383400 */
384401 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
386403 array = result .getAnArgument ( )
387404 }
388405
@@ -401,8 +418,8 @@ private module ArrayLibraries {
401418 /**
402419 * A loadStoreStep for a library that copies the elements of an array into another array.
403420 */
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 ) {
406423 exists ( DataFlow:: CallNode call |
407424 call = arrayCopyCall ( pred ) and
408425 succ = call and
0 commit comments