Skip to content

Commit 2b1a789

Browse files
committed
Move ReplaceAll sanitizer to shared code
1 parent 54b3262 commit 2b1a789

File tree

2 files changed

+50
-15
lines changed

2 files changed

+50
-15
lines changed

go/ql/lib/semmle/go/StringOps.qll

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,52 @@ module StringOps {
162162
}
163163
}
164164

165+
/**
166+
* An expression that is equivalent to `strings.ReplaceAll(s, old, new)`.
167+
*
168+
* Extend this class to refine existing API models. If you want to model new APIs,
169+
* extend `StringOps::ReplaceAll::Range` instead.
170+
*/
171+
class ReplaceAll extends DataFlow::Node instanceof ReplaceAll::Range {
172+
/**
173+
* Gets the `old` in `strings.ReplaceAll(s, old, new)`.
174+
*/
175+
string getReplacedString() { result = super.getReplacedString() }
176+
}
177+
178+
/** Provides predicates and classes for working with prefix checks. */
179+
module ReplaceAll {
180+
/**
181+
* An expression that is equivalent to `strings.ReplaceAll(s, old, new)`.
182+
*
183+
* Extend this class to model new APIs. If you want to refine existing API models, extend
184+
* `StringOps::ReplaceAll` instead.
185+
*/
186+
abstract class Range extends DataFlow::Node {
187+
/**
188+
* Gets the `old` in `strings.ReplaceAll(s, old, new)`.
189+
*/
190+
abstract string getReplacedString();
191+
}
192+
193+
/**
194+
* A call to `strings.ReplaceAll` or `strings.Replace` with a negative `n`
195+
* so that all instances are replaced.
196+
*/
197+
private class StringsReplaceAll extends Range, DataFlow::CallNode {
198+
StringsReplaceAll() {
199+
exists(string name | this.getTarget().hasQualifiedName("strings", name) |
200+
name = "ReplaceAll"
201+
or
202+
name = "Replace" and
203+
this.getArgument(3).getNumericValue() < 0
204+
)
205+
}
206+
207+
override string getReplacedString() { result = this.getArgument(1).getStringValue() }
208+
}
209+
}
210+
165211
/** Provides predicates and classes for working with Printf-style formatters. */
166212
module Formatting {
167213
/**

go/ql/lib/semmle/go/security/StringBreakCustomizations.qll

Lines changed: 4 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -84,24 +84,13 @@ module StringBreak {
8484
}
8585

8686
/**
87-
* A call to `strings.Replace` or `strings.ReplaceAll`, considered as a sanitizer
88-
* for unsafe quoting.
87+
* An expression that is equivalent to `strings.ReplaceAll(s, old, new)`,
88+
* considered as a sanitizer for unsafe quoting.
8989
*/
90-
class ReplaceSanitizer extends Sanitizer {
90+
class ReplaceSanitizer extends Sanitizer, StringOps::ReplaceAll {
9191
Quote quote;
9292

93-
ReplaceSanitizer() {
94-
exists(string name, DataFlow::CallNode call |
95-
this = call and
96-
call.getTarget().hasQualifiedName("strings", name) and
97-
call.getArgument(1).getStringValue().matches("%" + quote + "%")
98-
|
99-
name = "Replace" and
100-
call.getArgument(3).getNumericValue() < 0
101-
or
102-
name = "ReplaceAll"
103-
)
104-
}
93+
ReplaceSanitizer() { this.getReplacedString().matches("%" + quote + "%") }
10594

10695
override Quote getQuote() { result = quote }
10796
}

0 commit comments

Comments
 (0)