|
1 | 1 | import javascript
|
2 | 2 | private import semmle.javascript.dataflow.InferredTypes
|
| 3 | +private import semmle.javascript.dataflow.internal.PreCallGraphStep |
3 | 4 |
|
4 | 5 | /**
|
5 | 6 | * Classes and predicates for modelling TaintTracking steps for arrays.
|
@@ -222,29 +223,32 @@ private module ArrayDataFlow {
|
222 | 223 | *
|
223 | 224 | * And the second parameter in the callback is the array ifself, so there is a `loadStoreStep` from the array to that second parameter.
|
224 | 225 | */
|
225 |
| - private class ArrayIteration extends DataFlow::AdditionalFlowStep, DataFlow::MethodCallNode { |
226 |
| - ArrayIteration() { |
227 |
| - this.getMethodName() = "map" or |
228 |
| - this.getMethodName() = "forEach" |
229 |
| - } |
230 |
| - |
| 226 | + private class ArrayIteration extends PreCallGraphStep { |
231 | 227 | override predicate loadStep(DataFlow::Node obj, DataFlow::Node element, string prop) {
|
232 |
| - prop = arrayElement() and |
233 |
| - obj = this.getReceiver() and |
234 |
| - element = getCallback(0).getParameter(0) |
| 228 | + exists(DataFlow::MethodCallNode call | |
| 229 | + call.getMethodName() = ["map", "forEach"] and |
| 230 | + prop = arrayElement() and |
| 231 | + obj = call.getReceiver() and |
| 232 | + element = call.getCallback(0).getParameter(0) |
| 233 | + ) |
235 | 234 | }
|
236 | 235 |
|
237 | 236 | override predicate storeStep(DataFlow::Node element, DataFlow::SourceNode obj, string prop) {
|
238 |
| - this.getMethodName() = "map" and |
239 |
| - prop = arrayElement() and |
240 |
| - element = this.getCallback(0).getAReturn() and |
241 |
| - obj = this |
| 237 | + exists(DataFlow::MethodCallNode call | |
| 238 | + call.getMethodName() = "map" and |
| 239 | + prop = arrayElement() and |
| 240 | + element = call.getCallback(0).getAReturn() and |
| 241 | + obj = call |
| 242 | + ) |
242 | 243 | }
|
243 | 244 |
|
244 |
| - override predicate loadStoreStep(DataFlow::Node pred, DataFlow::Node succ, string prop) { |
245 |
| - prop = arrayElement() and |
246 |
| - pred = this.getReceiver() and |
247 |
| - succ = getCallback(0).getParameter(2) |
| 245 | + override predicate loadStoreStep(DataFlow::Node pred, DataFlow::SourceNode succ, string prop) { |
| 246 | + exists(DataFlow::MethodCallNode call | |
| 247 | + call.getMethodName() = ["map", "forEach"] and |
| 248 | + prop = arrayElement() and |
| 249 | + pred = call.getReceiver() and |
| 250 | + succ = call.getCallback(0).getParameter(2) |
| 251 | + ) |
248 | 252 | }
|
249 | 253 | }
|
250 | 254 |
|
@@ -311,16 +315,13 @@ private module ArrayDataFlow {
|
311 | 315 | /**
|
312 | 316 | * A step for modelling `for of` iteration on arrays.
|
313 | 317 | */
|
314 |
| - private class ForOfStep extends DataFlow::AdditionalFlowStep, DataFlow::ValueNode { |
315 |
| - ForOfStmt forOf; |
316 |
| - DataFlow::Node element; |
317 |
| - |
318 |
| - ForOfStep() { this.asExpr() = forOf.getIterationDomain() } |
319 |
| - |
| 318 | + private class ForOfStep extends PreCallGraphStep { |
320 | 319 | override predicate loadStep(DataFlow::Node obj, DataFlow::Node e, string prop) {
|
321 |
| - obj = this and |
322 |
| - e = DataFlow::lvalueNode(forOf.getLValue()) and |
323 |
| - prop = arrayElement() |
| 320 | + exists(ForOfStmt forOf | |
| 321 | + obj = forOf.getIterationDomain().flow() and |
| 322 | + e = DataFlow::lvalueNode(forOf.getLValue()) and |
| 323 | + prop = arrayElement() |
| 324 | + ) |
324 | 325 | }
|
325 | 326 | }
|
326 | 327 | }
|
0 commit comments