|
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