@@ -92,20 +92,32 @@ private class ParsedStringRegExp extends RegExp {
9292 override string getFlags ( ) { none ( ) }
9393}
9494
95+ /** Provides a class for modeling regular expression interpretations. */
96+ module RegExpInterpretation {
97+ /**
98+ * A node that is not a regular expression literal, but is used in places that
99+ * may interpret it as one. Instances of this class are typically strings that
100+ * flow to method calls like `RegExp.new`.
101+ */
102+ abstract class Range extends DataFlow:: Node { }
103+ }
104+
95105/**
96- * Holds if `source` may be interpreted as a regular expression.
106+ * A node interpreted as a regular expression.
97107 */
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+ }
109121}
110122
111123private class RegExpConfiguration extends Configuration {
@@ -120,7 +132,7 @@ private class RegExpConfiguration extends Configuration {
120132 )
121133 }
122134
123- override predicate isSink ( DataFlow:: Node sink ) { isInterpretedAsRegExp ( sink ) }
135+ override predicate isSink ( DataFlow:: Node sink ) { sink instanceof RegExpInterpretation :: Range }
124136
125137 override predicate isSanitizer ( DataFlow:: Node node ) {
126138 // stop flow if `node` is receiver of
0 commit comments