@@ -62,30 +62,23 @@ predicate escapingScheme(string metachar, string regex) {
6262}
6363
6464/**
65- * A call to `String.prototype.replace` that replaces all instances of a pattern .
65+ * A method call that performs string replacement .
6666 */
67- class Replacement extends DataFlow:: Node {
68- RegExpLiteral pattern ;
67+ abstract class Replacement extends DataFlow:: Node {
68+ /**
69+ * Holds if this replacement replaces the string `input` with `output`.
70+ */
71+ abstract predicate replaces ( string input , string output ) ;
6972
70- Replacement ( ) {
71- exists ( DataFlow:: MethodCallNode mcn | this = mcn |
72- mcn .getMethodName ( ) = "replace" and
73- pattern .flow ( ) .( DataFlow:: SourceNode ) .flowsTo ( mcn .getArgument ( 0 ) ) and
74- mcn .getNumArgument ( ) = 2 and
75- pattern .isGlobal ( )
76- )
77- }
73+ /**
74+ * Gets the input of this replacement.
75+ */
76+ abstract DataFlow:: Node getInput ( ) ;
7877
7978 /**
80- * Holds if this replacement replaces the string `input` with `output` .
79+ * Gets the output of this replacement .
8180 */
82- predicate replaces ( string input , string output ) {
83- exists ( DataFlow:: MethodCallNode mcn |
84- mcn = this and
85- input = getStringValue ( pattern ) and
86- output = mcn .getArgument ( 1 ) .getStringValue ( )
87- )
88- }
81+ abstract DataFlow:: SourceNode getOutput ( ) ;
8982
9083 /**
9184 * Holds if this replacement escapes `char` using `metachar`.
@@ -119,7 +112,7 @@ class Replacement extends DataFlow::Node {
119112 * Gets the previous replacement in this chain of replacements.
120113 */
121114 Replacement getPreviousReplacement ( ) {
122- result = getASimplePredecessor * ( this . ( DataFlow :: MethodCallNode ) . getReceiver ( ) )
115+ result . getOutput ( ) = getASimplePredecessor * ( getInput ( ) )
123116 }
124117
125118 /**
@@ -147,6 +140,33 @@ class Replacement extends DataFlow::Node {
147140 }
148141}
149142
143+ /**
144+ * A call to `String.prototype.replace` that replaces all instances of a pattern.
145+ */
146+ class GlobalStringReplacement extends Replacement , DataFlow:: MethodCallNode {
147+ RegExpLiteral pattern ;
148+
149+ GlobalStringReplacement ( ) {
150+ this .getMethodName ( ) = "replace" and
151+ pattern .flow ( ) .( DataFlow:: SourceNode ) .flowsTo ( this .getArgument ( 0 ) ) and
152+ this .getNumArgument ( ) = 2 and
153+ pattern .isGlobal ( )
154+ }
155+
156+ override predicate replaces ( string input , string output ) {
157+ input = getStringValue ( pattern ) and
158+ output = this .getArgument ( 1 ) .getStringValue ( )
159+ }
160+
161+ override DataFlow:: Node getInput ( ) {
162+ result = this .getReceiver ( )
163+ }
164+
165+ override DataFlow:: SourceNode getOutput ( ) {
166+ result = this
167+ }
168+ }
169+
150170from Replacement primary , Replacement supplementary , string message , string metachar
151171where
152172 primary .escapes ( metachar , _) and
0 commit comments