1313 * The `regexMatchedAgainst` predicate mirrors the intent of the Java
1414 * `RegexFlowConfigs.qll` library.
1515 *
16- * Only ECMAScript-grammar regexes are considered analyzable by the Phase 1
17- * parser; literals explicitly constructed with a non-ECMAScript grammar flag
18- * (`basic`, `extended`, `awk`, `grep`, `egrep`) are excluded.
16+ * All standard `std::regex` grammars are now modelled: ECMAScript (default),
17+ * POSIX BRE (`basic`/`grep`), and POSIX ERE (`extended`/`egrep`/`awk`).
18+ * Grammar selection and ReDoS-eligibility are independent axes — see
19+ * `isBacktrackingEngine` for the latter.
1920 */
2021
2122import cpp
@@ -368,10 +369,9 @@ predicate hasMultilineFlag(StringLiteral regex) {
368369 * Holds if `regex` is constructed with an explicit non-ECMAScript grammar
369370 * flag (`basic`, `extended`, `awk`, `grep`, or `egrep`).
370371 *
371- * This predicate remains a purely flag-level classification and does not
372- * gate the parser directly — the parser now uses `regexGrammar` to decide
373- * which dialect to apply. ECMAScript and ERE (`extended`/`egrep`/`awk`)
374- * are both modelled; only BRE (`basic`/`grep`) is currently excluded.
372+ * This predicate is purely informational: nothing is excluded from analysis
373+ * by grammar anymore, since every grammar the standard defines now has a
374+ * concrete parser subclass (`EcmaRegExp`, `EreRegExp`, `BreRegExp`).
375375 */
376376predicate hasNonEcmaScriptGrammarFlag ( StringLiteral regex ) {
377377 exists ( string g | g = [ "basic" , "extended" , "awk" , "grep" , "egrep" ] |
@@ -388,18 +388,17 @@ predicate hasNonEcmaScriptGrammarFlag(StringLiteral regex) {
388388 *
389389 * - `Ecma()` — ECMAScript, the default grammar used by `std::regex`.
390390 * Selected either implicitly (no explicit grammar flag) or
391- * explicitly via `std::regex_constants::ECMAScript`.
391+ * explicitly via `std::regex_constants::ECMAScript`. Modelled
392+ * by `EcmaRegExp`.
392393 * - `Bre()` — POSIX Basic Regular Expressions (selected via the `basic`
393- * or `grep` flags). Not yet modelled by the parser; regexes
394- * in this grammar are excluded from analysis.
394+ * or `grep` flags). Modelled by `BreRegExp`.
395395 * - `Ere()` — POSIX Extended Regular Expressions (selected via the
396396 * `extended`, `egrep`, or `awk` flags). Modelled by
397397 * `EreRegExp`.
398398 *
399- * The `Ecma()` and `Ere()` cases are both exercised by the parser today.
400- * The `Bre()` case is scaffolding for a future phase and is not exercised;
401- * regexes classified as `Bre()` are excluded by the `RegExp` characteristic
402- * predicate.
399+ * All three cases are exercised by the parser today; every grammar has a
400+ * concrete subclass, so `hasConcreteGrammar` holds for every regex the
401+ * parser sees.
403402 */
404403newtype TRegexGrammar =
405404 Ecma ( ) or
@@ -415,9 +414,8 @@ newtype TRegexGrammar =
415414 * - `extended` / `egrep` / `awk` → `Ere()`
416415 * - anything else (default, explicit `ECMAScript`, or unresolved) → `Ecma()`
417416 *
418- * The parser gates on `regexGrammar in [Ecma(), Ere()]`, so both branches
419- * are exercised by the parser today. Regexes classified as `Bre()` are
420- * excluded from analysis until a future phase adds BRE support.
417+ * Every case now has a concrete parser subclass, so `hasConcreteGrammar`
418+ * holds for the result of this predicate.
421419 */
422420TRegexGrammar regexGrammar ( StringLiteral regex ) {
423421 if containsRegexFlag ( getConstructionFlagArg ( regex ) , [ "basic" , "grep" ] )
@@ -428,6 +426,17 @@ TRegexGrammar regexGrammar(StringLiteral regex) {
428426 else result = Ecma ( )
429427}
430428
429+ /**
430+ * Holds if `grammar` has a concrete `RegExp` subclass and can therefore be
431+ * admitted by the parser's characteristic predicate. All three grammars
432+ * (`Ecma()`, `Ere()`, `Bre()`) are modelled today, so this holds for every
433+ * grammar the standard defines. Kept as a helper so that any future grammar
434+ * scaffolding can be admitted by adding a single disjunct here.
435+ */
436+ predicate hasConcreteGrammar ( TRegexGrammar grammar ) {
437+ grammar = Ecma ( ) or grammar = Ere ( ) or grammar = Bre ( )
438+ }
439+
431440/**
432441 * Holds if `regex` is constructed with an explicit ECMAScript grammar flag.
433442 * This is the default, and also the case that the Phase 1 parser handles.
0 commit comments