@@ -71,78 +71,78 @@ int main(int argc, char** argv) {
7171 // -------------------------------------------------------------------------
7272
7373 // BAD: (a*)*b
74- { std::regex re (" (a*)*b" ); run (re, input); }
74+ { std::regex re (" (a*)*b" ); run (re, input); } // $ Alert
7575 // BAD: (a+)*b
76- { std::regex re (" (a+)*b" ); run (re, input); }
76+ { std::regex re (" (a+)*b" ); run (re, input); } // $ Alert
7777 // BAD: (a*)+b
78- { std::regex re (" (a*)+b" ); run (re, input); }
78+ { std::regex re (" (a*)+b" ); run (re, input); } // $ Alert
7979 // BAD: (a+)+b
80- { std::regex re (" (a+)+b" ); run (re, input); }
80+ { std::regex re (" (a+)+b" ); run (re, input); } // $ Alert
8181 // BAD: (a*)+
82- { std::regex re (" ^(a*)+$" ); run (re, input); }
82+ { std::regex re (" ^(a*)+$" ); run (re, input); } // $ Alert
8383 // BAD: ((a+a?)*)+b+ (Ruby bad48)
84- { std::regex re (" (((a+a?)*)+b+)" ); run (re, input); }
84+ { std::regex re (" (((a+a?)*)+b+)" ); run (re, input); } // $ Alert
8585 // BAD: (a?a?)*b (Ruby bad71)
86- { std::regex re (" (a?a?)*b" ); run (re, input); }
86+ { std::regex re (" (a?a?)*b" ); run (re, input); } // $ Alert
8787 // BAD: (a?)+b via non-capturing alt (Ruby bad73)
88- { std::regex re (" (?:a|a?)+b" ); run (re, input); }
88+ { std::regex re (" (?:a|a?)+b" ); run (re, input); } // $ Alert
8989 // BAD: foo([\w-]*)+bar (Ruby bad69)
90- { std::regex re (" foo([\\ w-]*)+bar" ); run (re, input); }
90+ { std::regex re (" foo([\\ w-]*)+bar" ); run (re, input); } // $ Alert
9191 // BAD: ((ab)*)+c (Ruby bad70)
92- { std::regex re (" ((ab)*)+c" ); run (re, input); }
92+ { std::regex re (" ((ab)*)+c" ); run (re, input); } // $ Alert
9393
9494 // -------------------------------------------------------------------------
9595 // 2. Anchored nested-quantifier patterns (Ruby bad7..bad10, bad77, bad78).
9696 // -------------------------------------------------------------------------
9797
9898 // BAD: ^([a-z]+)+$
99- { std::regex re (" ^([a-z]+)+$" ); run (re, input); }
99+ { std::regex re (" ^([a-z]+)+$" ); run (re, input); } // $ Alert
100100 // BAD: ^([a-z]*)*$
101- { std::regex re (" ^([a-z]*)*$" ); run (re, input); }
101+ { std::regex re (" ^([a-z]*)*$" ); run (re, input); } // $ Alert
102102 // BAD: e-mail-like regex
103- { std::regex re (" ^([a-zA-Z0-9])(([\\ .-]|[_]+)?([a-zA-Z0-9]+))*(@){1}[a-z0-9]+[.]{1}(([a-z]{2,3})|([a-z]{2,3}[.]{1}[a-z]{2,3}))$" );
103+ { std::regex re (" ^([a-zA-Z0-9])(([\\ .-]|[_]+)?([a-zA-Z0-9]+))*(@){1}[a-z0-9]+[.]{1}(([a-z]{2,3})|([a-z]{2,3}[.]{1}[a-z]{2,3}))$" ); // $ Alert
104104 run (re, input); }
105105 // BAD: ^(([a-z])+.)+[A-Z]([a-z])+$
106- { std::regex re (" ^(([a-z])+.)+[A-Z]([a-z])+$" ); run (re, input); }
106+ { std::regex re (" ^(([a-z])+.)+[A-Z]([a-z])+$" ); run (re, input); } // $ Alert
107107 // BAD: ^((a)+\w)+$
108- { std::regex re (" ^((a)+\\ w)+$" ); run (re, input); }
108+ { std::regex re (" ^((a)+\\ w)+$" ); run (re, input); } // $ Alert
109109 // BAD: ^(b+.)+$
110- { std::regex re (" ^(b+.)+$" ); run (re, input); }
110+ { std::regex re (" ^(b+.)+$" ); run (re, input); } // $ Alert
111111 // BAD: ^ab(c+)+$ (Ruby bad66)
112- { std::regex re (" ^ab(c+)+$" ); run (re, input); }
112+ { std::regex re (" ^ab(c+)+$" ); run (re, input); } // $ Alert
113113
114114 // -------------------------------------------------------------------------
115115 // 3. Alternations with overlapping / identical branches inside a repetition.
116116 // -------------------------------------------------------------------------
117117
118118 // BAD: (a|a)*
119- { std::regex re (" ^(a|a)*$" ); run (re, input); }
119+ { std::regex re (" ^(a|a)*$" ); run (re, input); } // $ Alert
120120 // BAD: (a|aa?)*b (Ruby bad15)
121- { std::regex re (" (a|aa?)*b" ); run (re, input); }
121+ { std::regex re (" (a|aa?)*b" ); run (re, input); } // $ Alert
122122 // BAD: (b|a?b)*c (Ruby bad13)
123- { std::regex re (" (b|a?b)*c" ); run (re, input); }
123+ { std::regex re (" (b|a?b)*c" ); run (re, input); } // $ Alert
124124 // BAD: (a+|b+|c+)*c (Ruby bad47)
125- { std::regex re (" (a+|b+|c+)*c" ); run (re, input); }
125+ { std::regex re (" (a+|b+|c+)*c" ); run (re, input); } // $ Alert
126126
127127 // -------------------------------------------------------------------------
128128 // 4. Character-class / complement ambiguity (Ruby bad52, bad53, bad18,
129129 // bad20, bad21, bad22, bad23, bad43).
130130 // -------------------------------------------------------------------------
131131
132132 // BAD: ([^X]+)*$
133- { std::regex re (" ([^X]+)*$" ); run (re, input); }
133+ { std::regex re (" ([^X]+)*$" ); run (re, input); } // $ Alert
134134 // BAD: (([^X]b)+)*$
135- { std::regex re (" (([^X]b)+)*$" ); run (re, input); }
135+ { std::regex re (" (([^X]b)+)*$" ); run (re, input); } // $ Alert
136136 // BAD: (([\S\s]|[^a])*)"
137- { std::regex re (" (([\\ S\\ s]|[^a])*)\" " ); run (re, input); }
137+ { std::regex re (" (([\\ S\\ s]|[^a])*)\" " ); run (re, input); } // $ Alert
138138 // BAD: ((.|[^a])*)"
139- { std::regex re (" ((.|[^a])*)\" " ); run (re, input); }
139+ { std::regex re (" ((.|[^a])*)\" " ); run (re, input); } // $ Alert
140140 // BAD: ((b|[^a])*)"
141- { std::regex re (" ((b|[^a])*)\" " ); run (re, input); }
141+ { std::regex re (" ((b|[^a])*)\" " ); run (re, input); } // $ Alert
142142 // BAD: (([0-9]|[^a])*)"
143- { std::regex re (" (([0-9]|[^a])*)\" " ); run (re, input); }
143+ { std::regex re (" (([0-9]|[^a])*)\" " ); run (re, input); } // $ Alert
144144 // BAD: ^([^>a]+)*(>|$)
145- { std::regex re (" ^([^>a]+)*(>|$)" ); run (re, input); }
145+ { std::regex re (" ^([^>a]+)*(>|$)" ); run (re, input); } // $ Alert
146146
147147 // -------------------------------------------------------------------------
148148 // 5. Anchored-vs-unanchored GOOD/BAD pairs (Ruby good16/bad50,
@@ -154,17 +154,17 @@ int main(int argc, char** argv) {
154154 // GOOD: (a+)+aaaaa*a+ -- Ruby good16 (no rejecting suffix)
155155 { std::regex re (" (a+)+aaaaa*a+" ); run (re, input); }
156156 // BAD: (a+)+aaaaa$ -- Ruby bad50
157- { std::regex re (" (a+)+aaaaa$" ); run (re, input); }
157+ { std::regex re (" (a+)+aaaaa$" ); run (re, input); } // $ Alert
158158
159159 // GOOD: (\n+)+\n\n -- Ruby good17
160160 { std::regex re (" (\\ n+)+\\ n\\ n" ); run (re, input); }
161161 // BAD: (\n+)+\n\n$ -- Ruby bad51
162- { std::regex re (" (\\ n+)+\\ n\\ n$" ); run (re, input); }
162+ { std::regex re (" (\\ n+)+\\ n\\ n$" ); run (re, input); } // $ Alert
163163
164164 // GOOD: (([^X]b)+)*($|[^X]b) -- Ruby good18
165165 { std::regex re (" (([^X]b)+)*($|[^X]b)" ); run (re, input); }
166166 // BAD: (([^X]b)+)*($|[^X]c) -- Ruby bad54
167- { std::regex re (" (([^X]b)+)*($|[^X]c)" ); run (re, input); }
167+ { std::regex re (" (([^X]b)+)*($|[^X]c)" ); run (re, input); } // $ Alert
168168
169169 // GOOD: ((ab)+)*ababab -- Ruby good20
170170 { std::regex re (" ((ab)+)*ababab" ); run (re, input); }
@@ -173,7 +173,7 @@ int main(int argc, char** argv) {
173173 // GOOD: ((ab)+)* -- Ruby good22
174174 { std::regex re (" ((ab)+)*" ); run (re, input); }
175175 // BAD: ((ab)+)*$ -- Ruby bad55
176- { std::regex re (" ((ab)+)*$" ); run (re, input); }
176+ { std::regex re (" ((ab)+)*$" ); run (re, input); } // $ Alert
177177
178178 // -------------------------------------------------------------------------
179179 // 6. GOOD patterns that specifically guard against false positives.
@@ -226,7 +226,7 @@ int main(int argc, char** argv) {
226226 // -------------------------------------------------------------------------
227227
228228 // BAD: exponential regex with icase - case-insensitivity does not suppress the alert.
229- { std::regex re (" ^([a-z]+)+$" , std::regex_constants::icase); run (re, input); }
229+ { std::regex re (" ^([a-z]+)+$" , std::regex_constants::icase); run (re, input); } // $ Alert
230230 // BAD: BRE grammar (`basic`) is modeled by the parser (`BreRegExp`,
231231 // Phase D) and is backtracking-eligible, so the nested-quantifier is
232232 // reported as exponential. Note that `(...)` in BRE is *literal* - the
@@ -238,7 +238,7 @@ int main(int argc, char** argv) {
238238 // BAD: extended selects the ERE grammar (modeled by `EreRegExp` since
239239 // Phase C) and is backtracking-eligible, so the shared engine reports
240240 // the nested-quantifier as exponential - same as the ECMAScript case.
241- { std::regex re (" ^(a+)+$" , std::regex_constants::extended); run (re, input); }
241+ { std::regex re (" ^(a+)+$" , std::regex_constants::extended); run (re, input); } // $ Alert
242242 // GOOD: awk parses as ERE (same as `extended`) but is excluded from the
243243 // ReDoS queries by `isBacktrackingEngine` (POSIX tool-style engines are
244244 // treated as linear-time), *not* by any parsing/grammar difference.
@@ -262,9 +262,9 @@ int main(int argc, char** argv) {
262262 // -------------------------------------------------------------------------
263263
264264 // BAD: nested-quantifier exponential regex using a POSIX character class.
265- { std::regex re (" ^([[:alpha:]]+)+$" ); run (re, input); }
265+ { std::regex re (" ^([[:alpha:]]+)+$" ); run (re, input); } // $ Alert
266266 // BAD: same pattern under icase - case-folding must not suppress the alert.
267- { std::regex re (" ^([[:alpha:]]+)+$" , std::regex_constants::icase); run (re, input); }
267+ { std::regex re (" ^([[:alpha:]]+)+$" , std::regex_constants::icase); run (re, input); } // $ Alert
268268 // Opaque POSIX character class: `[:punct:]` has no clean `\d`/`\s`/`\w`
269269 // equivalent (see the discussion in RegexTreeView.qll::isEscapeClass).
270270 // It is therefore left as an opaque atom in the shared engine's view;
@@ -328,7 +328,7 @@ int main(int argc, char** argv) {
328328 // -------------------------------------------------------------------------
329329
330330 // BAD: ERE grammar via `extended` - parsed as ERE and backtracking-eligible.
331- { std::regex re (" ^([a-z]+)+$" , std::regex_constants::extended); run (re, input); }
331+ { std::regex re (" ^([a-z]+)+$" , std::regex_constants::extended); run (re, input); } // $ Alert
332332 // GOOD: same pattern under `egrep` - parses identically as ERE but
333333 // excluded by `isBacktrackingEngine`.
334334 { std::regex re (" ^([a-z]+)+$" , std::regex_constants::egrep); run (re, input); }
@@ -372,7 +372,7 @@ int main(int argc, char** argv) {
372372 // exponentially many ways). BRE has no `+`, so this is the BRE
373373 // analogue of the ECMAScript `^(a*)*$` (or the more familiar
374374 // `^(a+)+$`) shape.
375- { std::regex re (" ^\\ (a*\\ )*$" , std::regex_constants::basic); run (re, input); }
375+ { std::regex re (" ^\\ (a*\\ )*$" , std::regex_constants::basic); run (re, input); } // $ Alert
376376 // GOOD: same pattern under `grep` - parses identically as BRE but
377377 // excluded by `isBacktrackingEngine`.
378378 { std::regex re (" ^\\ (a*\\ )*$" , std::regex_constants::grep); run (re, input); }
0 commit comments