@@ -798,6 +798,16 @@ class RegExpParseError extends Error, @regexp_parse_error {
798798 override string toString ( ) { result = getMessage ( ) }
799799}
800800
801+ /**
802+ * Holds if `func` is a method defined on `String.prototype` with name `name`.
803+ */
804+ private predicate isNativeStringMethod ( Function func , string name ) {
805+ exists ( ExternalInstanceMemberDecl decl |
806+ decl .hasQualifiedName ( "String" , name ) and
807+ func = decl .getInit ( )
808+ )
809+ }
810+
801811/**
802812 * Holds if `source` may be interpreted as a regular expression.
803813 */
@@ -808,18 +818,23 @@ predicate isInterpretedAsRegExp(DataFlow::Node source) {
808818 source = DataFlow:: globalVarRef ( "RegExp" ) .getAnInvocation ( ) .getArgument ( 0 )
809819 or
810820 // The argument of a call that coerces the argument to a regular expression.
811- exists ( MethodCallExpr mce , string methodName |
821+ exists ( DataFlow :: MethodCallNode mce , string methodName |
812822 mce .getReceiver ( ) .analyze ( ) .getAType ( ) = TTString ( ) and
813- mce .getMethodName ( ) = methodName
823+ mce .getMethodName ( ) = methodName and
824+ not exists ( Function func |
825+ func = mce .getACallee ( )
826+ |
827+ not isNativeStringMethod ( func , methodName )
828+ )
814829 |
815- methodName = "match" and source . asExpr ( ) = mce .getArgument ( 0 ) and mce .getNumArgument ( ) = 1
830+ methodName = "match" and source = mce .getArgument ( 0 ) and mce .getNumArgument ( ) = 1
816831 or
817832 methodName = "search" and
818- source . asExpr ( ) = mce .getArgument ( 0 ) and
833+ source = mce .getArgument ( 0 ) and
819834 mce .getNumArgument ( ) = 1 and
820835 // "search" is a common method name, and so we exclude chained accesses
821836 // because `String.prototype.search` returns a number
822- not exists ( PropAccess p | p .getBase ( ) = mce )
837+ not exists ( PropAccess p | p .getBase ( ) = mce . getEnclosingExpr ( ) )
823838 )
824839 )
825840}
0 commit comments