@@ -92,20 +92,32 @@ private class ParsedStringRegExp extends RegExp {
92
92
override string getFlags ( ) { none ( ) }
93
93
}
94
94
95
+ /** Provides a class for modelling regular expression interpretations. */
96
+ module RegExpInterpretation {
97
+ /**
98
+ * Nodes that are not regular expression literals, but are used in places that
99
+ * may interpret them regular expressions. Typically these are strings that flow
100
+ * to method calls like `RegExp.new`.
101
+ */
102
+ abstract class Range extends DataFlow:: Node { }
103
+ }
104
+
95
105
/**
96
- * Holds if `source` may be interpreted as a regular expression .
106
+ * Nodes interpreted as regular expressions via various standard library methods .
97
107
*/
98
- private predicate isInterpretedAsRegExp ( DataFlow:: Node source ) {
99
- // The first argument to an invocation of `Regexp.new` or `Regexp.compile`.
100
- source = API:: getTopLevelMember ( "Regexp" ) .getAMethodCall ( [ "compile" , "new" ] ) .getArgument ( 0 )
101
- or
102
- // The argument of a call that coerces the argument to a regular expression.
103
- exists ( DataFlow:: CallNode mce |
104
- mce .getMethodName ( ) = [ "match" , "match?" ] and
105
- source = mce .getArgument ( 0 ) and
106
- // exclude https://ruby-doc.org/core-2.4.0/Regexp.html#method-i-match
107
- not mce .getReceiver ( ) .asExpr ( ) .getExpr ( ) instanceof AST:: RegExpLiteral
108
- )
108
+ class StdLibRegExpInterpretation extends RegExpInterpretation:: Range {
109
+ StdLibRegExpInterpretation ( ) {
110
+ // The first argument to an invocation of `Regexp.new` or `Regexp.compile`.
111
+ this = API:: getTopLevelMember ( "Regexp" ) .getAMethodCall ( [ "compile" , "new" ] ) .getArgument ( 0 )
112
+ or
113
+ // The argument of a call that coerces the argument to a regular expression.
114
+ exists ( DataFlow:: CallNode mce |
115
+ mce .getMethodName ( ) = [ "match" , "match?" ] and
116
+ this = mce .getArgument ( 0 ) and
117
+ // exclude https://ruby-doc.org/core-2.4.0/Regexp.html#method-i-match
118
+ not mce .getReceiver ( ) .asExpr ( ) .getExpr ( ) instanceof AST:: RegExpLiteral
119
+ )
120
+ }
109
121
}
110
122
111
123
private class RegExpConfiguration extends Configuration {
@@ -120,7 +132,7 @@ private class RegExpConfiguration extends Configuration {
120
132
)
121
133
}
122
134
123
- override predicate isSink ( DataFlow:: Node sink ) { isInterpretedAsRegExp ( sink ) }
135
+ override predicate isSink ( DataFlow:: Node sink ) { sink instanceof RegExpInterpretation :: Range }
124
136
125
137
override predicate isSanitizer ( DataFlow:: Node node ) {
126
138
// stop flow if `node` is receiver of
0 commit comments