@@ -472,20 +472,56 @@ abstract class RegexString extends StringLiteral {
472472 )
473473 }
474474
475- private predicate flagGroupStart ( int start , int end , string c ) {
475+ /**
476+ * Holds if the initial part of a parse mode, not containing any
477+ * mode characters is between `start` and `end`.
478+ */
479+ private predicate flagGroupStartNoModes ( int start , int end ) {
476480 this .isGroupStart ( start ) and
477481 this .getChar ( start + 1 ) = "?" and
478- end = start + 3 and
479- c = this .getChar ( start + 2 ) and
480- c in [ "i" , "m" , "s" , "u" , "x" , "U" ]
482+ this .getChar ( start + 2 ) in [ "i" , "m" , "s" , "u" , "x" , "U" ] and
483+ end = start + 2
484+ }
485+
486+ /**
487+ * Holds if `pos` contains a mode character from the
488+ * flag group starting at `start`.
489+ */
490+ private predicate modeCharacter ( int start , int pos ) {
491+ this .flagGroupStartNoModes ( start , pos )
492+ or
493+ this .modeCharacter ( start , pos - 1 ) and
494+ this .getChar ( pos ) in [ "i" , "m" , "s" , "u" , "x" , "U" ]
495+ }
496+
497+ /**
498+ * Holds if a parse mode group is between `start` and `end`.
499+ */
500+ private predicate flagGroupStart ( int start , int end ) {
501+ this .flagGroupStartNoModes ( start , _) and
502+ end = max ( int i | this .modeCharacter ( start , i ) | i + 1 )
503+ }
504+
505+ /**
506+ * Holds if a parse mode group of this regex includes the mode flag `c`.
507+ * For example the following parse mode group, with mode flag `i`:
508+ * ```
509+ * (?i)
510+ * ```
511+ */
512+ private predicate flag ( string c ) {
513+ exists ( int pos |
514+ this .modeCharacter ( _, pos ) and
515+ this .getChar ( pos ) = c
516+ )
481517 }
482518
483519 /**
484520 * Gets the mode of this regular expression string if
485521 * it is defined by a prefix.
486522 */
487523 string getModeFromPrefix ( ) {
488- exists ( string c | this .flagGroupStart ( _ , _ , c ) |
524+ exists ( string c | this .flag ( c ) |
489525 c = "i" and result = "IGNORECASE"
490526 or
491527 c = "m" and result = "MULTILINE"
@@ -540,7 +576,7 @@ abstract class RegexString extends StringLiteral {
540576 private predicate groupStart ( int start , int end ) {
541577 this .nonCapturingGroupStart ( start , end )
542578 or
543- this .flagGroupStart ( start , end , _ )
579+ this .flagGroupStart ( start , end )
544580 or
545581 this .namedGroupStart ( start , end )
546582 or
0 commit comments