@@ -84,16 +84,17 @@ private module ArrayDataFlow {
8484 * A step modelling the creation of an Array using the `Array.from(x)` method.
8585 * The step copies the elements of the argument (set, array, or iterator elements) into the resulting array.
8686 */
87- private class ArrayFrom extends DataFlow:: AdditionalFlowStep , DataFlow:: CallNode {
88- ArrayFrom ( ) { this = DataFlow:: globalVarRef ( "Array" ) .getAMemberCall ( "from" ) }
89-
87+ private class ArrayFrom extends DataFlow:: SharedFlowStep {
9088 override predicate loadStoreStep (
9189 DataFlow:: Node pred , DataFlow:: Node succ , string fromProp , string toProp
9290 ) {
93- pred = this .getArgument ( 0 ) and
94- succ = this and
95- fromProp = arrayLikeElement ( ) and
96- toProp = arrayElement ( )
91+ exists ( DataFlow:: CallNode call |
92+ call = DataFlow:: globalVarRef ( "Array" ) .getAMemberCall ( "from" ) and
93+ pred = call .getArgument ( 0 ) and
94+ succ = call and
95+ fromProp = arrayLikeElement ( ) and
96+ toProp = arrayElement ( )
97+ )
9798 }
9899 }
99100
@@ -103,55 +104,45 @@ private module ArrayDataFlow {
103104 *
104105 * Such a step can occur both with the `push` and `unshift` methods, or when creating a new array.
105106 */
106- private class ArrayCopySpread extends DataFlow:: AdditionalFlowStep {
107- DataFlow:: Node spreadArgument ; // the spread argument containing the elements to be copied.
108- DataFlow:: Node base ; // the object where the elements should be copied to.
109-
110- ArrayCopySpread ( ) {
111- exists ( DataFlow:: MethodCallNode mcn | mcn = this |
112- mcn .getMethodName ( ) = [ "push" , "unshift" ] and
113- spreadArgument = mcn .getASpreadArgument ( ) and
114- base = mcn .getReceiver ( ) .getALocalSource ( )
115- )
116- or
117- spreadArgument = this .( DataFlow:: ArrayCreationNode ) .getASpreadArgument ( ) and
118- base = this
119- }
120-
107+ private class ArrayCopySpread extends DataFlow:: SharedFlowStep {
121108 override predicate loadStoreStep (
122109 DataFlow:: Node pred , DataFlow:: Node succ , string fromProp , string toProp
123110 ) {
124- pred = spreadArgument and
125- succ = base and
126111 fromProp = arrayLikeElement ( ) and
127- toProp = arrayElement ( )
112+ toProp = arrayElement ( ) and
113+ (
114+ exists ( DataFlow:: MethodCallNode mcn |
115+ mcn .getMethodName ( ) = [ "push" , "unshift" ] and
116+ pred = mcn .getASpreadArgument ( ) and
117+ succ = mcn .getReceiver ( ) .getALocalSource ( )
118+ )
119+ or
120+ pred = succ .( DataFlow:: ArrayCreationNode ) .getASpreadArgument ( )
121+ )
128122 }
129123 }
130124
131125 /**
132126 * A step for storing an element on an array using `arr.push(e)` or `arr.unshift(e)`.
133127 */
134- private class ArrayAppendStep extends DataFlow:: AdditionalFlowStep , DataFlow:: MethodCallNode {
135- ArrayAppendStep ( ) {
136- this .getMethodName ( ) = "push" or
137- this .getMethodName ( ) = "unshift"
138- }
139-
128+ private class ArrayAppendStep extends DataFlow:: SharedFlowStep {
140129 override predicate storeStep ( DataFlow:: Node element , DataFlow:: SourceNode obj , string prop ) {
141130 prop = arrayElement ( ) and
142- element = this .getAnArgument ( ) and
143- obj .getAMethodCall ( ) = this
131+ exists ( DataFlow:: MethodCallNode call |
132+ call .getMethodName ( ) = [ "push" , "unshift" ] and
133+ element = call .getAnArgument ( ) and
134+ obj .getAMethodCall ( ) = call
135+ )
144136 }
145137 }
146138
147139 /**
148- * A step for reading/writing an element from an array inside a for-loop.
149- * E.g. a read from `foo[i]` to `bar` in `for(var i = 0; i < arr.length; i++) {bar = foo[i]}`.
140+ * A node that reads or writes an element from an array inside a for-loop.
150141 */
151- private class ArrayIndexingStep extends DataFlow :: AdditionalFlowStep , DataFlow:: Node {
142+ private class ArrayIndexingAccess extends DataFlow:: Node {
152143 DataFlow:: PropRef read ;
153144
154- ArrayIndexingStep ( ) {
145+ ArrayIndexingAccess ( ) {
155146 read = this and
156147 TTNumber ( ) =
157148 unique( InferredType type | type = read .getPropertyNameExpr ( ) .flow ( ) .analyze ( ) .getAType ( ) ) and
@@ -162,34 +153,42 @@ private module ArrayDataFlow {
162153 i .getVariable ( ) .getADefinition ( ) .( VariableDeclarator ) .getDeclStmt ( ) = init
163154 )
164155 }
156+ }
165157
158+ /**
159+ * A step for reading/writing an element from an array inside a for-loop.
160+ * E.g. a read from `foo[i]` to `bar` in `for(var i = 0; i < arr.length; i++) {bar = foo[i]}`.
161+ */
162+ private class ArrayIndexingStep extends DataFlow:: SharedFlowStep {
166163 override predicate loadStep ( DataFlow:: Node obj , DataFlow:: Node element , string prop ) {
167- prop = arrayElement ( ) and
168- obj = this .( DataFlow:: PropRead ) .getBase ( ) and
169- element = this
164+ exists ( ArrayIndexingAccess access |
165+ prop = arrayElement ( ) and
166+ obj = access .( DataFlow:: PropRead ) .getBase ( ) and
167+ element = access
168+ )
170169 }
171170
172171 override predicate storeStep ( DataFlow:: Node element , DataFlow:: SourceNode obj , string prop ) {
173- prop = arrayElement ( ) and
174- element = this .( DataFlow:: PropWrite ) .getRhs ( ) and
175- this = obj .getAPropertyWrite ( )
172+ exists ( ArrayIndexingAccess access |
173+ prop = arrayElement ( ) and
174+ element = access .( DataFlow:: PropWrite ) .getRhs ( ) and
175+ access = obj .getAPropertyWrite ( )
176+ )
176177 }
177178 }
178179
179180 /**
180181 * A step for retrieving an element from an array using `.pop()` or `.shift()`.
181182 * E.g. `array.pop()`.
182183 */
183- private class ArrayPopStep extends DataFlow:: AdditionalFlowStep , DataFlow:: MethodCallNode {
184- ArrayPopStep ( ) {
185- getMethodName ( ) = "pop" or
186- getMethodName ( ) = "shift"
187- }
188-
184+ private class ArrayPopStep extends DataFlow:: SharedFlowStep {
189185 override predicate loadStep ( DataFlow:: Node obj , DataFlow:: Node element , string prop ) {
190- prop = arrayElement ( ) and
191- obj = this .getReceiver ( ) and
192- element = this
186+ exists ( DataFlow:: MethodCallNode call |
187+ call .getMethodName ( ) = [ "pop" , "shift" ] and
188+ prop = arrayElement ( ) and
189+ obj = call .getReceiver ( ) and
190+ element = call
191+ )
193192 }
194193 }
195194
@@ -235,12 +234,12 @@ private module ArrayDataFlow {
235234 /**
236235 * A step for creating an array and storing the elements in the array.
237236 */
238- private class ArrayCreationStep extends DataFlow:: AdditionalFlowStep , DataFlow :: ArrayCreationNode {
237+ private class ArrayCreationStep extends DataFlow:: SharedFlowStep {
239238 override predicate storeStep ( DataFlow:: Node element , DataFlow:: SourceNode obj , string prop ) {
240- exists ( int i |
241- element = this .getElement ( i ) and
242- obj = this and
243- if this = any ( PromiseAllCreation c ) .getArrayNode ( )
239+ exists ( DataFlow :: ArrayCreationNode array , int i |
240+ element = array .getElement ( i ) and
241+ obj = array and
242+ if array = any ( PromiseAllCreation c ) .getArrayNode ( )
244243 then prop = arrayElement ( i )
245244 else prop = arrayElement ( )
246245 )
@@ -251,56 +250,42 @@ private module ArrayDataFlow {
251250 * A step modelling that `splice` can insert elements into an array.
252251 * For example in `array.splice(i, del, e)`: if `e` is tainted, then so is `array
253252 */
254- private class ArraySpliceStep extends DataFlow:: AdditionalFlowStep , DataFlow:: MethodCallNode {
255- ArraySpliceStep ( ) { this .getMethodName ( ) = "splice" }
256-
253+ private class ArraySpliceStep extends DataFlow:: SharedFlowStep {
257254 override predicate storeStep ( DataFlow:: Node element , DataFlow:: SourceNode obj , string prop ) {
258- prop = arrayElement ( ) and
259- element = getArgument ( 2 ) and
260- this = obj .getAMethodCall ( )
255+ exists ( DataFlow:: MethodCallNode call |
256+ call .getMethodName ( ) = "splice" and
257+ prop = arrayElement ( ) and
258+ element = call .getArgument ( 2 ) and
259+ call = obj .getAMethodCall ( )
260+ )
261261 }
262262 }
263263
264264 /**
265265 * A step for modelling `concat`.
266266 * For example in `e = arr1.concat(arr2, arr3)`: if any of the `arr` is tainted, then so is `e`.
267267 */
268- private class ArrayConcatStep extends DataFlow:: AdditionalFlowStep , DataFlow:: MethodCallNode {
269- ArrayConcatStep ( ) { this .getMethodName ( ) = "concat" }
270-
268+ private class ArrayConcatStep extends DataFlow:: SharedFlowStep {
271269 override predicate loadStoreStep ( DataFlow:: Node pred , DataFlow:: Node succ , string prop ) {
272- prop = arrayElement ( ) and
273- ( pred = this .getReceiver ( ) or pred = this .getAnArgument ( ) ) and
274- succ = this
270+ exists ( DataFlow:: MethodCallNode call |
271+ call .getMethodName ( ) = "concat" and
272+ prop = arrayElement ( ) and
273+ ( pred = call .getReceiver ( ) or pred = call .getAnArgument ( ) ) and
274+ succ = call
275+ )
275276 }
276277 }
277278
278279 /**
279280 * A step for modelling that elements from an array `arr` also appear in the result from calling `slice`/`splice`/`filter`.
280281 */
281- private class ArraySliceStep extends DataFlow:: AdditionalFlowStep , DataFlow:: MethodCallNode {
282- ArraySliceStep ( ) {
283- this .getMethodName ( ) = "slice" or
284- this .getMethodName ( ) = "splice" or
285- this .getMethodName ( ) = "filter"
286- }
287-
282+ private class ArraySliceStep extends DataFlow:: SharedFlowStep {
288283 override predicate loadStoreStep ( DataFlow:: Node pred , DataFlow:: Node succ , string prop ) {
289- prop = arrayElement ( ) and
290- pred = this .getReceiver ( ) and
291- succ = this
292- }
293- }
294-
295- /**
296- * A step for modelling `for of` iteration on arrays.
297- */
298- private class ForOfStep extends PreCallGraphStep {
299- override predicate loadStep ( DataFlow:: Node obj , DataFlow:: Node e , string prop ) {
300- exists ( ForOfStmt forOf |
301- obj = forOf .getIterationDomain ( ) .flow ( ) and
302- e = DataFlow:: lvalueNode ( forOf .getLValue ( ) ) and
303- prop = arrayElement ( )
284+ exists ( DataFlow:: MethodCallNode call |
285+ call .getMethodName ( ) = [ "slice" , "splice" , "filter" ] and
286+ prop = arrayElement ( ) and
287+ pred = call .getReceiver ( ) and
288+ succ = call
304289 )
305290 }
306291 }
0 commit comments