@@ -206,6 +206,68 @@ module StringOps {
206
206
207
207
override string getReplacedString ( ) { result = this .getArgument ( 1 ) .getStringValue ( ) }
208
208
}
209
+
210
+ /**
211
+ * A call to `strings.NewReplacer`.
212
+ */
213
+ private class StringsNewReplacerCall extends DataFlow:: CallNode {
214
+ StringsNewReplacerCall ( ) { this .getTarget ( ) .hasQualifiedName ( "strings" , "NewReplacer" ) }
215
+
216
+ /**
217
+ * Gets an argument to this call corresponding to a string that will be
218
+ * replaced.
219
+ */
220
+ DataFlow:: Node getAReplacedArgument ( ) {
221
+ exists ( int n | n % 2 = 0 and result = this .getArgument ( n ) )
222
+ }
223
+ }
224
+
225
+ /**
226
+ * A configuration for tracking flow from a call to `strings.NewReplacer` to
227
+ * the receiver of a call to `strings.Replacer.Replace` or
228
+ * `strings.Replacer.WriteString`.
229
+ */
230
+ private class StringsNewReplacerConfiguration extends DataFlow2:: Configuration {
231
+ StringsNewReplacerConfiguration ( ) { this = "StringsNewReplacerConfiguration" }
232
+
233
+ override predicate isSource ( DataFlow:: Node source ) {
234
+ source instanceof StringsNewReplacerCall
235
+ }
236
+
237
+ override predicate isSink ( DataFlow:: Node sink ) {
238
+ exists ( DataFlow:: MethodCallNode call |
239
+ sink = call .getReceiver ( ) and
240
+ call .getTarget ( ) .hasQualifiedName ( "strings" , "Replacer" , [ "Replace" , "WriteString" ] )
241
+ )
242
+ }
243
+ }
244
+
245
+ /**
246
+ * A call to `strings.Replacer.Replace` or `strings.Replacer.WriteString`.
247
+ */
248
+ private class StringsReplacerReplaceOrWriteString extends Range {
249
+ string replacedString ;
250
+
251
+ StringsReplacerReplaceOrWriteString ( ) {
252
+ exists (
253
+ StringsNewReplacerConfiguration config , StringsNewReplacerCall source ,
254
+ DataFlow:: Node sink , DataFlow:: MethodCallNode call
255
+ |
256
+ config .hasFlow ( source , sink ) and
257
+ sink = call .getReceiver ( ) and
258
+ replacedString = source .getAReplacedArgument ( ) .getStringValue ( ) and
259
+ (
260
+ call .getTarget ( ) .hasQualifiedName ( "strings" , "Replacer" , "Replace" ) and
261
+ this = call .getResult ( )
262
+ or
263
+ call .getTarget ( ) .hasQualifiedName ( "strings" , "Replacer" , "WriteString" ) and
264
+ this = call .getArgument ( 1 )
265
+ )
266
+ )
267
+ }
268
+
269
+ override string getReplacedString ( ) { result = replacedString }
270
+ }
209
271
}
210
272
211
273
/** Provides predicates and classes for working with Printf-style formatters. */
0 commit comments