@@ -473,27 +473,46 @@ abstract class RegexString extends StringLiteral {
473473 }
474474
475475 /**
476- * Holds if a parse mode starts between `start` and `end`.
476+ * Holds if the initial part of a parse mode, not containing any
477+ * mode characters is between `start` and `end`.
477478 */
478- private predicate flagGroupStart ( int start , int end ) {
479+ private predicate flagGroupStartNoModes ( int start , int end ) {
479480 this .isGroupStart ( start ) and
480481 this .getChar ( start + 1 ) = "?" and
481482 this .getChar ( start + 2 ) in [ "i" , "m" , "s" , "u" , "x" , "U" ] and
482483 end = start + 2
483484 }
484485
485486 /**
486- * Holds if a parse mode group is between `start` and `end`, and includes the
487- * mode flag `c`. For example the following span, with mode flag `i`:
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`:
488508 * ```
489509 * (?i)
490510 * ```
491511 */
492- private predicate flagGroup ( int start , int end , string c ) {
493- exists ( int inStart , int inEnd |
494- this .flagGroupStart ( start , inStart ) and
495- this .groupContents ( start , end , inStart , inEnd ) and
496- this .getChar ( [ inStart .. inEnd - 1 ] ) = c
512+ private predicate flag ( string c ) {
513+ exists ( int pos |
514+ this .modeCharacter ( _, pos ) and
515+ this .getChar ( pos ) = c
497516 )
498517 }
499518
@@ -502,7 +521,7 @@ abstract class RegexString extends StringLiteral {
502521 * it is defined by a prefix.
503522 */
504523 string getModeFromPrefix ( ) {
505- exists ( string c | this .flagGroup ( _ , _ , c ) |
524+ exists ( string c | this .flag ( c ) |
506525 c = "i" and result = "IGNORECASE"
507526 or
508527 c = "m" and result = "MULTILINE"
0 commit comments