Skip to content

Commit effa52f

Browse files
committed
JS: Step through string replace callbacks
1 parent 7c20c4a commit effa52f

File tree

3 files changed

+22
-1
lines changed

3 files changed

+22
-1
lines changed

javascript/ql/src/semmle/javascript/StandardLibrary.qll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ class StringReplaceCall extends DataFlow::MethodCallNode {
107107
}
108108

109109
/** Gets the regular expression passed as the first argument to `replace`, if any. */
110-
DataFlow::RegExpLiteralNode getRegExp() { result.flowsTo(getArgument(0)) }
110+
DataFlow::RegExpCreationNode getRegExp() { result.flowsTo(getArgument(0)) }
111111

112112
/** Gets a string that is being replaced by this call. */
113113
string getAReplacedString() {

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1624,6 +1624,9 @@ class RegExpCreationNode extends DataFlow::SourceNode {
16241624
result = this.(RegExpLiteralNode).getFlags()
16251625
}
16261626

1627+
/** Holds if the constructed predicate has the `g` flag. */
1628+
predicate isGlobal() { RegExp::isGlobal(getFlags()) }
1629+
16271630
/** Gets a data flow node referring to this regular expression. */
16281631
private DataFlow::SourceNode getAReference(DataFlow::TypeTracker t) {
16291632
t.start() and

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

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -697,10 +697,28 @@ module TaintTracking {
697697
name = "encodeURIComponent" or
698698
name = "decodeURIComponent"
699699
)
700+
or
701+
// In and out of .replace callbacks
702+
exists(StringReplaceCall call |
703+
// Into the callback if the regexp does not sanitize matches
704+
hasWildcardReplaceRegExp(call) and
705+
pred = call.getReceiver() and
706+
succ = call.getReplacementCallback().getParameter(0)
707+
or
708+
// Out of the callback
709+
pred = call.getReplacementCallback().getReturnNode() and
710+
succ = call
711+
)
700712
)
701713
}
702714
}
703715

716+
/** Holds if the given call takes a regexp containing a wildcard. */
717+
pragma[noinline]
718+
private predicate hasWildcardReplaceRegExp(StringReplaceCall call) {
719+
RegExp::isWildcardLike(call.getRegExp().getRoot().getAChild*())
720+
}
721+
704722
/**
705723
* A taint propagating data flow edge arising from string formatting.
706724
*/

0 commit comments

Comments
 (0)