Skip to content

Commit ea37665

Browse files
author
Esben Sparre Andreasen
committed
JS: move array-specific taint steps to separate class
1 parent 9e0ba51 commit ea37665

File tree

1 file changed

+37
-22
lines changed

1 file changed

+37
-22
lines changed

javascript/ql/src/semmle/javascript/dataflow/TaintTracking.qll

Lines changed: 37 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -185,18 +185,44 @@ module TaintTracking {
185185

186186
override predicate step(DataFlow::Node pred, DataFlow::Node succ) {
187187
succ = this and
188-
(
189-
exists (Expr e, Expr f | e = this.asExpr() and f = pred.asExpr() |
190-
// arrays with tainted elements and objects with tainted property names are tainted
191-
e.(ArrayExpr).getAnElement() = f or
192-
exists (Property prop | e.(ObjectExpr).getAProperty() = prop |
193-
prop.isComputed() and f = prop.getNameExpr()
194-
)
195-
or
196-
// awaiting a tainted expression gives a tainted result
197-
e.(AwaitExpr).getOperand() = f
188+
exists (Expr e, Expr f | e = this.asExpr() and f = pred.asExpr() |
189+
// arrays with tainted elements and objects with tainted property names are tainted
190+
e.(ArrayExpr).getAnElement() = f or
191+
exists (Property prop | e.(ObjectExpr).getAProperty() = prop |
192+
prop.isComputed() and f = prop.getNameExpr()
198193
)
199194
or
195+
// awaiting a tainted expression gives a tainted result
196+
e.(AwaitExpr).getOperand() = f
197+
)
198+
or
199+
// reading from a tainted object yields a tainted result
200+
this = succ and
201+
succ.(DataFlow::PropRead).getBase() = pred
202+
or
203+
// iterating over a tainted iterator taints the loop variable
204+
exists (EnhancedForLoop efl, SsaExplicitDefinition ssa |
205+
this = DataFlow::valueNode(efl.getIterationDomain()) and
206+
pred = this and
207+
ssa.getDef() = efl.getIteratorExpr() and
208+
succ = DataFlow::ssaDefinitionNode(ssa)
209+
)
210+
}
211+
}
212+
213+
/**
214+
* A taint propagating data flow edge caused by the builtin array functions.
215+
*/
216+
private class ArrayFunctionTaintStep extends AdditionalTaintStep {
217+
218+
ArrayFunctionTaintStep() {
219+
this = DataFlow::valueNode(_) or
220+
this = DataFlow::parameterNode(_) or
221+
this instanceof DataFlow::PropRead
222+
}
223+
224+
override predicate step(DataFlow::Node pred, DataFlow::Node succ) {
225+
succ = this and (
200226
// `array.map(function (elt, i, ary) { ... })`: if `array` is tainted, then so are
201227
// `elt` and `ary`; similar for `forEach`
202228
exists (MethodCallExpr m, Function f, int i, SimpleParameter p |
@@ -218,19 +244,8 @@ module TaintTracking {
218244
// `array.push(e)`: if `e` is tainted, then so is `array`
219245
succ.(DataFlow::SourceNode).getAMethodCall("push").getAnArgument() = pred
220246
)
221-
or
222-
// reading from a tainted object yields a tainted result
223-
this = succ and
224-
succ.(DataFlow::PropRead).getBase() = pred
225-
or
226-
// iterating over a tainted iterator taints the loop variable
227-
exists (EnhancedForLoop efl, SsaExplicitDefinition ssa |
228-
this = DataFlow::valueNode(efl.getIterationDomain()) and
229-
pred = this and
230-
ssa.getDef() = efl.getIteratorExpr() and
231-
succ = DataFlow::ssaDefinitionNode(ssa)
232-
)
233247
}
248+
234249
}
235250

236251
/**

0 commit comments

Comments
 (0)