From f75d66dc9102f4ea9122a96cf5130f2733428021 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 23 Jul 2026 10:04:43 +0000 Subject: [PATCH] C++: Remove Ruby-only \A/\Z/\z/\G anchors from regex grammar --- .../semmle/code/cpp/regex/RegexTreeView.qll | 12 +++---- .../code/cpp/regex/internal/ParseRegExp.qll | 10 +++--- .../test/library-tests/regex/parse.expected | 31 ------------------- cpp/ql/test/library-tests/regex/regexp.cpp | 2 -- .../test/library-tests/regex/regexp.expected | 15 --------- 5 files changed, 11 insertions(+), 59 deletions(-) diff --git a/cpp/ql/lib/semmle/code/cpp/regex/RegexTreeView.qll b/cpp/ql/lib/semmle/code/cpp/regex/RegexTreeView.qll index c91b588e51a..1d961d3b977 100644 --- a/cpp/ql/lib/semmle/code/cpp/regex/RegexTreeView.qll +++ b/cpp/ql/lib/semmle/code/cpp/regex/RegexTreeView.qll @@ -936,17 +936,17 @@ private module Impl implements RegexTreeViewSig { * Example: * * ``` - * \A + * ^ * ``` */ class RegExpAnchor extends RegExpSpecialChar { - RegExpAnchor() { this.getChar() = ["^", "$", "\\A", "\\Z", "\\z"] } + RegExpAnchor() { this.getChar() = ["^", "$"] } override string getAPrimaryQlClass() { result = "RegExpAnchor" } } /** - * A dollar assertion `$` or `\Z` matching the end of a line. + * A dollar assertion `$` matching the end of a line. * * Example: * @@ -955,7 +955,7 @@ private module Impl implements RegexTreeViewSig { * ``` */ class RegExpDollar extends RegExpAnchor { - RegExpDollar() { this.getChar() = ["$", "\\Z", "\\z"] } + RegExpDollar() { this.getChar() = "$" } override string getAPrimaryQlClass() { result = "RegExpDollar" } @@ -963,7 +963,7 @@ private module Impl implements RegexTreeViewSig { } /** - * A caret assertion `^` or `\A` matching the beginning of a line. + * A caret assertion `^` matching the beginning of a line. * * Example: * @@ -972,7 +972,7 @@ private module Impl implements RegexTreeViewSig { * ``` */ class RegExpCaret extends RegExpAnchor { - RegExpCaret() { this.getChar() = ["^", "\\A"] } + RegExpCaret() { this.getChar() = "^" } override string getAPrimaryQlClass() { result = "RegExpCaret" } diff --git a/cpp/ql/lib/semmle/code/cpp/regex/internal/ParseRegExp.qll b/cpp/ql/lib/semmle/code/cpp/regex/internal/ParseRegExp.qll index d9163bb3af0..a7d0d38919a 100644 --- a/cpp/ql/lib/semmle/code/cpp/regex/internal/ParseRegExp.qll +++ b/cpp/ql/lib/semmle/code/cpp/regex/internal/ParseRegExp.qll @@ -476,7 +476,7 @@ abstract class RegExp extends StringLiteral { end = start + 2 and this.escapingChar(start) and char = this.getText().substring(start, end) and - char = ["\\A", "\\Z", "\\z", "\\G", "\\b", "\\B"] + char = ["\\b", "\\B"] ) } @@ -958,8 +958,8 @@ abstract class RegExp extends StringLiteral { or this.qualifiedItem(x, start, true, _) or - // ^ and \A match the start of the string - this.specialCharacter(x, start, ["^", "\\A"]) + // ^ matches the start of the string + this.specialCharacter(x, start, "^") ) or exists(int y | this.firstPart(start, y) | @@ -984,8 +984,8 @@ abstract class RegExp extends StringLiteral { or this.qualifiedItem(end, y, true, _) or - // $, \Z, and \z match the end of the string. - this.specialCharacter(end, y, ["$", "\\Z", "\\z"]) + // $ matches the end of the string. + this.specialCharacter(end, y, "$") ) or this.lastPart(_, end) and diff --git a/cpp/ql/test/library-tests/regex/parse.expected b/cpp/ql/test/library-tests/regex/parse.expected index 1f92debd8e5..6eba9076ae4 100644 --- a/cpp/ql/test/library-tests/regex/parse.expected +++ b/cpp/ql/test/library-tests/regex/parse.expected @@ -80,8 +80,6 @@ #-----| [RegExpConstant, RegExpNormalChar] !a -#-----| [RegExpConstant, RegExpNormalChar] abc - #-----| [RegExpConstant, RegExpEscape] \n #-----| [RegExpConstant, RegExpEscape] \r @@ -136,12 +134,6 @@ #-----| [RegExpCharacterClassEscape] \w -#-----| [RegExpConstant, RegExpNormalChar] + - -#-----| [RegExpConstant, RegExpNormalChar] - - -#-----| [RegExpCharacterClassEscape] \d - #-----| [RegExpConstant, RegExpNormalChar] a #-----| [RegExpConstant, RegExpNormalChar] f @@ -229,10 +221,6 @@ #-----| 1 -> [RegExpConstant, RegExpNormalChar] !a #-----| 2 -> [RegExpNonWordBoundary] \B -#-----| [RegExpSequence] \Gabc -#-----| 0 -> [RegExpSpecialChar] \G -#-----| 1 -> [RegExpConstant, RegExpNormalChar] abc - #-----| [RegExpSequence] \n\r\t #-----| 0 -> [RegExpConstant, RegExpEscape] \n #-----| 1 -> [RegExpConstant, RegExpEscape] \r @@ -263,11 +251,6 @@ #-----| 1 -> [RegExpConstant, RegExpEscape] \] #-----| 2 -> [RegExpCharacterClass] [123] -#-----| [RegExpSequence] \A[+-]?\d+ -#-----| 0 -> [RegExpCaret] \A -#-----| 1 -> [RegExpOpt] [+-]? -#-----| 2 -> [RegExpPlus] \d+ - #-----| [RegExpSequence] a*b+c?d #-----| 0 -> [RegExpStar] a* #-----| 1 -> [RegExpPlus] b+ @@ -302,14 +285,10 @@ #-----| [RegExpNonWordBoundary] \B -#-----| [RegExpSpecialChar] \G - #-----| [RegExpDot] . #-----| [RegExpDot] . -#-----| [RegExpCaret] \A - #-----| [RegExpGroup] (?q+) #-----| 0 -> [RegExpPlus] q+ @@ -412,10 +391,6 @@ #-----| [RegExpCharacterClass] [\w] #-----| 0 -> [RegExpCharacterClassEscape] \w -#-----| [RegExpCharacterClass] [+-] -#-----| 0 -> [RegExpConstant, RegExpNormalChar] + -#-----| 1 -> [RegExpConstant, RegExpNormalChar] - - #-----| [RegExpCharacterClass] [a-fA-F0-9_] #-----| 0 -> [RegExpCharacterRange] a-f #-----| 1 -> [RegExpCharacterRange] A-F @@ -491,12 +466,6 @@ #-----| [RegExpPlus] [\w]+ #-----| 0 -> [RegExpCharacterClass] [\w] -#-----| [RegExpOpt] [+-]? -#-----| 0 -> [RegExpCharacterClass] [+-] - -#-----| [RegExpPlus] \d+ -#-----| 0 -> [RegExpCharacterClassEscape] \d - #-----| [RegExpRange] a{7} #-----| 0 -> [RegExpConstant, RegExpNormalChar] a diff --git a/cpp/ql/test/library-tests/regex/regexp.cpp b/cpp/ql/test/library-tests/regex/regexp.cpp index 63bb73d3244..e323213ef23 100644 --- a/cpp/ql/test/library-tests/regex/regexp.cpp +++ b/cpp/ql/test/library-tests/regex/regexp.cpp @@ -30,7 +30,6 @@ std::regex r_alt("foo|bar"); // Character classes std::regex r_cc1("[abc]"); std::regex r_cc2("[a-fA-F0-9_]"); -std::regex r_cc3("\\A[+-]?\\d+"); std::regex r_cc4("[\\w]+"); std::regex r_cc5("\\[\\][123]"); std::regex r_cc6("[^A-Z]"); @@ -52,7 +51,6 @@ std::regex r_meta5("\\h\\H"); std::regex r_meta6("\\n\\r\\t"); // Anchors -std::regex r_anc1("\\Gabc"); std::regex r_anc2("\\b!a\\B"); // Groups diff --git a/cpp/ql/test/library-tests/regex/regexp.expected b/cpp/ql/test/library-tests/regex/regexp.expected index e671353d19f..31168fbae14 100644 --- a/cpp/ql/test/library-tests/regex/regexp.expected +++ b/cpp/ql/test/library-tests/regex/regexp.expected @@ -30,8 +30,6 @@ term | file://:0:0:0:0 | (foo)* | RegExpStar | | file://:0:0:0:0 | (foo)*bar | RegExpSequence | | file://:0:0:0:0 | (o\|b) | RegExpGroup | -| file://:0:0:0:0 | + | RegExpConstant,RegExpNormalChar | -| file://:0:0:0:0 | - | RegExpConstant,RegExpNormalChar | | file://:0:0:0:0 | - | RegExpConstant,RegExpNormalChar | | file://:0:0:0:0 | . | RegExpDot | | file://:0:0:0:0 | . | RegExpDot | @@ -51,8 +49,6 @@ term | file://:0:0:0:0 | Z | RegExpConstant,RegExpNormalChar | | file://:0:0:0:0 | [ | RegExpConstant,RegExpNormalChar | | file://:0:0:0:0 | [123] | RegExpCharacterClass | -| file://:0:0:0:0 | [+-] | RegExpCharacterClass | -| file://:0:0:0:0 | [+-]? | RegExpOpt | | file://:0:0:0:0 | [:alpha:] | RegExpNamedCharacterProperty | | file://:0:0:0:0 | [:alpha:] | RegExpNamedCharacterProperty | | file://:0:0:0:0 | [:digit:] | RegExpNamedCharacterProperty | @@ -78,12 +74,8 @@ term | file://:0:0:0:0 | [a-f\\p{Digit}]+ | RegExpPlus | | file://:0:0:0:0 | [abc] | RegExpCharacterClass | | file://:0:0:0:0 | \\1 | RegExpBackRef | -| file://:0:0:0:0 | \\A | RegExpCaret | -| file://:0:0:0:0 | \\A[+-]?\\d+ | RegExpSequence | | file://:0:0:0:0 | \\B | RegExpNonWordBoundary | | file://:0:0:0:0 | \\D | RegExpCharacterClassEscape | -| file://:0:0:0:0 | \\G | RegExpSpecialChar | -| file://:0:0:0:0 | \\Gabc | RegExpSequence | | file://:0:0:0:0 | \\H | RegExpCharacterClassEscape | | file://:0:0:0:0 | \\P{Digit} | RegExpNamedCharacterProperty | | file://:0:0:0:0 | \\P{Digit}+ | RegExpPlus | @@ -95,8 +87,6 @@ term | file://:0:0:0:0 | \\b | RegExpSpecialChar | | file://:0:0:0:0 | \\b!a\\B | RegExpSequence | | file://:0:0:0:0 | \\d | RegExpCharacterClassEscape | -| file://:0:0:0:0 | \\d | RegExpCharacterClassEscape | -| file://:0:0:0:0 | \\d+ | RegExpPlus | | file://:0:0:0:0 | \\d\\D | RegExpSequence | | file://:0:0:0:0 | \\h | RegExpCharacterClassEscape | | file://:0:0:0:0 | \\h\\H | RegExpSequence | @@ -162,7 +152,6 @@ term | file://:0:0:0:0 | abc | RegExpConstant,RegExpNormalChar | | file://:0:0:0:0 | abc | RegExpConstant,RegExpNormalChar | | file://:0:0:0:0 | abc | RegExpConstant,RegExpNormalChar | -| file://:0:0:0:0 | abc | RegExpConstant,RegExpNormalChar | | file://:0:0:0:0 | ar | RegExpConstant,RegExpNormalChar | | file://:0:0:0:0 | a{3,} | InfiniteRepetitionQuantifier,RegExpRange | | file://:0:0:0:0 | a{4,8} | RegExpRange | @@ -208,8 +197,6 @@ regExpNormalCharValue | file://:0:0:0:0 | 3 | 3 | | file://:0:0:0:0 | 9 | 9 | | file://:0:0:0:0 | !a | !a | -| file://:0:0:0:0 | + | + | -| file://:0:0:0:0 | - | - | | file://:0:0:0:0 | - | - | | file://:0:0:0:0 | : | : | | file://:0:0:0:0 | A | A | @@ -227,7 +214,6 @@ regExpNormalCharValue | file://:0:0:0:0 | \\[ | [ | | file://:0:0:0:0 | \\] | ] | | file://:0:0:0:0 | \\d | d | -| file://:0:0:0:0 | \\d | d | | file://:0:0:0:0 | \\h | h | | file://:0:0:0:0 | \\n | \n | | file://:0:0:0:0 | \\n | \n | @@ -269,7 +255,6 @@ regExpNormalCharValue | file://:0:0:0:0 | abc | abc | | file://:0:0:0:0 | abc | abc | | file://:0:0:0:0 | abc | abc | -| file://:0:0:0:0 | abc | abc | | file://:0:0:0:0 | ar | ar | | file://:0:0:0:0 | b | b | | file://:0:0:0:0 | b | b |