Skip to content

Commit 8b12f32

Browse files
authored
Add BRE query test coverage and change note; regenerate .expected
1 parent c1cb146 commit 8b12f32

9 files changed

Lines changed: 931 additions & 532 deletions

File tree

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
category: minorAnalysis
3+
---
4+
* The C++ regular-expression parser (`semmle.code.cpp.regex.internal.ParseRegExp`) now models POSIX Basic Regular Expressions (BRE) via a new concrete `BreRegExp` subclass. BRE is selected by the `std::regex_constants::basic` and `grep` flags. Where BRE inverts the metacharacter/escape convention relative to POSIX ERE and ECMAScript — backslash-prefixed `\(...\)` are capturing groups (bare `(...)` are literals), `\{n,m\}` is the interval quantifier (bare braces are literal text), and `+`, `?`, `|` are literal characters — the parser follows the POSIX specification. Positional rules for `*` (literal at the start of a subexpression), `^` (anchor only at start of subexpression) and `$` (anchor only at end of subexpression) are implemented; `\1`..`\9` numbered back-references are supported. The GNU-BRE extensions `\+`, `\?`, `\|` are not modeled — they are treated as escaped literals. Along with ECMAScript (`EcmaRegExp`) and POSIX ERE (`EreRegExp`), all six of the `std::regex_constants` grammar flags now have a concrete parser subclass and every regex is analyzed.
5+
* The C++ ReDoS queries (`cpp/redos` and `cpp/polynomial-redos`) now analyze regexes constructed with the `std::regex_constants::basic` grammar flag; `grep` remains excluded via `isBacktrackingEngine` (POSIX tool-style engines are treated as linear-time), mirroring the existing `extended`-vs-`egrep`/`awk` split for ERE.

cpp/ql/test/library-tests/regex/RegexFlow.expected

Lines changed: 82 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -34,72 +34,96 @@ usedAsRegex_
3434
| test.cpp:218:18:218:23 | foo+ |
3535
| test.cpp:225:18:225:23 | bar+ |
3636
| test.cpp:231:18:231:23 | abc+ |
37-
| test.cpp:237:18:237:23 | abc+ |
38-
| test.cpp:238:19:238:26 | ^gr+ep |
39-
| test.cpp:247:19:247:24 | abc+ |
40-
| test.cpp:250:19:250:32 | [[:alpha:]]+ |
41-
| test.cpp:254:19:254:34 | a\\.b\\(c\\).* |
42-
| test.cpp:256:19:256:34 | (foo\|bar){2,3} |
43-
| test.cpp:258:19:258:24 | awk+ |
44-
| test.cpp:260:19:260:26 | (x\|y)+ |
45-
| test.cpp:262:19:262:26 | ^a.*b$ |
46-
| test.cpp:266:19:266:29 | ([a-z]+)+ |
47-
| test.cpp:272:14:272:19 | baz+ |
48-
| test.cpp:277:18:277:26 | pat+ern |
49-
| test.cpp:287:42:287:48 | hel+o |
50-
| test.cpp:303:18:303:32 | [[:alpha:]].* |
51-
| test.cpp:305:18:305:31 | [[:digit:]]+ |
52-
| test.cpp:307:18:307:33 | [a[:space:]].* |
53-
| test.cpp:309:18:309:41 | [[:alpha:][:digit:]].* |
54-
| test.cpp:311:18:311:33 | [^[:space:]].* |
55-
| test.cpp:313:18:313:28 | [[.a.]].* |
56-
| test.cpp:315:18:315:28 | [[=a=]].* |
57-
| test.cpp:318:18:318:34 | ([[:alpha:]]+)+ |
58-
| test.cpp:337:19:337:31 | [:alpha:].* |
59-
| test.cpp:343:19:343:29 | a[:b:]c.* |
60-
| test.cpp:346:19:346:51 | [[:alpha:][:digit:][:space:]].* |
61-
| test.cpp:350:19:350:35 | []a[:alpha:]].* |
62-
| test.cpp:357:19:357:35 | [[:alpha:]-z].* |
63-
| test.cpp:363:19:363:31 | [[:alpha].* |
64-
| test.cpp:372:19:372:88 | ^([[:alpha:]]+[[:digit:]]*[[:space:]]?)+([[:punct:]]\|[[:xdigit:]])+$ |
37+
| test.cpp:242:18:242:23 | abc+ |
38+
| test.cpp:245:19:245:26 | ^gr+ep |
39+
| test.cpp:249:19:249:32 | \\(ab\\)*c.* |
40+
| test.cpp:250:19:250:27 | a(b)c.* |
41+
| test.cpp:252:19:252:32 | a\\{2,5\\}.* |
42+
| test.cpp:253:19:253:28 | a{2,5}.* |
43+
| test.cpp:255:19:255:26 | a+b?.* |
44+
| test.cpp:258:19:258:26 | *abc.* |
45+
| test.cpp:259:19:259:24 | a*.* |
46+
| test.cpp:263:20:263:28 | a^b$c.* |
47+
| test.cpp:265:20:265:33 | \\(a\\)\\1.* |
48+
| test.cpp:268:20:268:33 | \\.\\*\\\\.* |
49+
| test.cpp:271:20:271:41 | \\([[:alpha:]]\\)*.* |
50+
| test.cpp:275:20:275:30 | \\(a*\\)* |
51+
| test.cpp:290:19:290:24 | abc+ |
52+
| test.cpp:293:19:293:32 | [[:alpha:]]+ |
53+
| test.cpp:297:19:297:34 | a\\.b\\(c\\).* |
54+
| test.cpp:299:19:299:34 | (foo\|bar){2,3} |
55+
| test.cpp:301:19:301:24 | awk+ |
56+
| test.cpp:303:19:303:26 | (x\|y)+ |
57+
| test.cpp:305:19:305:26 | ^a.*b$ |
58+
| test.cpp:309:19:309:29 | ([a-z]+)+ |
59+
| test.cpp:315:14:315:19 | baz+ |
60+
| test.cpp:320:18:320:26 | pat+ern |
61+
| test.cpp:330:42:330:48 | hel+o |
62+
| test.cpp:346:18:346:32 | [[:alpha:]].* |
63+
| test.cpp:348:18:348:31 | [[:digit:]]+ |
64+
| test.cpp:350:18:350:33 | [a[:space:]].* |
65+
| test.cpp:352:18:352:41 | [[:alpha:][:digit:]].* |
66+
| test.cpp:354:18:354:33 | [^[:space:]].* |
67+
| test.cpp:356:18:356:28 | [[.a.]].* |
68+
| test.cpp:358:18:358:28 | [[=a=]].* |
69+
| test.cpp:361:18:361:34 | ([[:alpha:]]+)+ |
70+
| test.cpp:380:19:380:31 | [:alpha:].* |
71+
| test.cpp:386:19:386:29 | a[:b:]c.* |
72+
| test.cpp:389:19:389:51 | [[:alpha:][:digit:][:space:]].* |
73+
| test.cpp:393:19:393:35 | []a[:alpha:]].* |
74+
| test.cpp:400:19:400:35 | [[:alpha:]-z].* |
75+
| test.cpp:406:19:406:31 | [[:alpha].* |
76+
| test.cpp:415:19:415:88 | ^([[:alpha:]]+[[:digit:]]*[[:space:]]?)+([[:punct:]]\|[[:xdigit:]])+$ |
6577
regexMatchedAgainst_
6678
| test.cpp:209:18:209:25 | (a+)+b | test.cpp:211:28:211:34 | subject |
6779
| test.cpp:209:18:209:25 | (a+)+b | test.cpp:212:29:212:35 | subject |
6880
| test.cpp:209:18:209:25 | (a+)+b | test.cpp:213:30:213:36 | subject |
6981
| test.cpp:218:18:218:23 | foo+ | test.cpp:220:28:220:28 | s |
70-
| test.cpp:277:18:277:26 | pat+ern | test.cpp:280:29:280:29 | a |
71-
| test.cpp:277:18:277:26 | pat+ern | test.cpp:281:29:281:29 | b |
72-
| test.cpp:287:42:287:48 | hel+o | test.cpp:287:28:287:28 | s |
73-
| test.cpp:303:18:303:32 | [[:alpha:]].* | test.cpp:304:29:304:32 | subj |
74-
| test.cpp:305:18:305:31 | [[:digit:]]+ | test.cpp:306:29:306:32 | subj |
75-
| test.cpp:307:18:307:33 | [a[:space:]].* | test.cpp:308:29:308:32 | subj |
76-
| test.cpp:309:18:309:41 | [[:alpha:][:digit:]].* | test.cpp:310:29:310:32 | subj |
77-
| test.cpp:311:18:311:33 | [^[:space:]].* | test.cpp:312:29:312:32 | subj |
78-
| test.cpp:313:18:313:28 | [[.a.]].* | test.cpp:314:29:314:32 | subj |
79-
| test.cpp:315:18:315:28 | [[=a=]].* | test.cpp:316:29:316:32 | subj |
80-
| test.cpp:318:18:318:34 | ([[:alpha:]]+)+ | test.cpp:319:29:319:32 | subj |
81-
| test.cpp:337:19:337:31 | [:alpha:].* | test.cpp:338:29:338:32 | subj |
82-
| test.cpp:343:19:343:29 | a[:b:]c.* | test.cpp:344:29:344:32 | subj |
83-
| test.cpp:346:19:346:51 | [[:alpha:][:digit:][:space:]].* | test.cpp:347:29:347:32 | subj |
84-
| test.cpp:350:19:350:35 | []a[:alpha:]].* | test.cpp:351:29:351:32 | subj |
85-
| test.cpp:357:19:357:35 | [[:alpha:]-z].* | test.cpp:358:29:358:32 | subj |
86-
| test.cpp:363:19:363:31 | [[:alpha].* | test.cpp:364:29:364:32 | subj |
87-
| test.cpp:372:19:372:88 | ^([[:alpha:]]+[[:digit:]]*[[:space:]]?)+([[:punct:]]\|[[:xdigit:]])+$ | test.cpp:373:29:373:32 | subj |
82+
| test.cpp:320:18:320:26 | pat+ern | test.cpp:323:29:323:29 | a |
83+
| test.cpp:320:18:320:26 | pat+ern | test.cpp:324:29:324:29 | b |
84+
| test.cpp:330:42:330:48 | hel+o | test.cpp:330:28:330:28 | s |
85+
| test.cpp:346:18:346:32 | [[:alpha:]].* | test.cpp:347:29:347:32 | subj |
86+
| test.cpp:348:18:348:31 | [[:digit:]]+ | test.cpp:349:29:349:32 | subj |
87+
| test.cpp:350:18:350:33 | [a[:space:]].* | test.cpp:351:29:351:32 | subj |
88+
| test.cpp:352:18:352:41 | [[:alpha:][:digit:]].* | test.cpp:353:29:353:32 | subj |
89+
| test.cpp:354:18:354:33 | [^[:space:]].* | test.cpp:355:29:355:32 | subj |
90+
| test.cpp:356:18:356:28 | [[.a.]].* | test.cpp:357:29:357:32 | subj |
91+
| test.cpp:358:18:358:28 | [[=a=]].* | test.cpp:359:29:359:32 | subj |
92+
| test.cpp:361:18:361:34 | ([[:alpha:]]+)+ | test.cpp:362:29:362:32 | subj |
93+
| test.cpp:380:19:380:31 | [:alpha:].* | test.cpp:381:29:381:32 | subj |
94+
| test.cpp:386:19:386:29 | a[:b:]c.* | test.cpp:387:29:387:32 | subj |
95+
| test.cpp:389:19:389:51 | [[:alpha:][:digit:][:space:]].* | test.cpp:390:29:390:32 | subj |
96+
| test.cpp:393:19:393:35 | []a[:alpha:]].* | test.cpp:394:29:394:32 | subj |
97+
| test.cpp:400:19:400:35 | [[:alpha:]-z].* | test.cpp:401:29:401:32 | subj |
98+
| test.cpp:406:19:406:31 | [[:alpha].* | test.cpp:407:29:407:32 | subj |
99+
| test.cpp:415:19:415:88 | ^([[:alpha:]]+[[:digit:]]*[[:space:]]?)+([[:punct:]]\|[[:xdigit:]])+$ | test.cpp:416:29:416:32 | subj |
88100
hasIgnoreCaseFlag_
89101
| test.cpp:218:18:218:23 | foo+ |
90102
| test.cpp:225:18:225:23 | bar+ |
91-
| test.cpp:238:19:238:26 | ^gr+ep |
92-
| test.cpp:272:14:272:19 | baz+ |
103+
| test.cpp:245:19:245:26 | ^gr+ep |
104+
| test.cpp:315:14:315:19 | baz+ |
93105
hasMultilineFlag_
94106
| test.cpp:225:18:225:23 | bar+ |
95107
hasNonEcmaScriptGrammarFlag_
96-
| test.cpp:237:18:237:23 | abc+ |
97-
| test.cpp:238:19:238:26 | ^gr+ep |
98-
| test.cpp:247:19:247:24 | abc+ |
99-
| test.cpp:250:19:250:32 | [[:alpha:]]+ |
100-
| test.cpp:254:19:254:34 | a\\.b\\(c\\).* |
101-
| test.cpp:256:19:256:34 | (foo\|bar){2,3} |
102-
| test.cpp:258:19:258:24 | awk+ |
103-
| test.cpp:260:19:260:26 | (x\|y)+ |
104-
| test.cpp:262:19:262:26 | ^a.*b$ |
105-
| test.cpp:266:19:266:29 | ([a-z]+)+ |
108+
| test.cpp:242:18:242:23 | abc+ |
109+
| test.cpp:245:19:245:26 | ^gr+ep |
110+
| test.cpp:249:19:249:32 | \\(ab\\)*c.* |
111+
| test.cpp:250:19:250:27 | a(b)c.* |
112+
| test.cpp:252:19:252:32 | a\\{2,5\\}.* |
113+
| test.cpp:253:19:253:28 | a{2,5}.* |
114+
| test.cpp:255:19:255:26 | a+b?.* |
115+
| test.cpp:258:19:258:26 | *abc.* |
116+
| test.cpp:259:19:259:24 | a*.* |
117+
| test.cpp:263:20:263:28 | a^b$c.* |
118+
| test.cpp:265:20:265:33 | \\(a\\)\\1.* |
119+
| test.cpp:268:20:268:33 | \\.\\*\\\\.* |
120+
| test.cpp:271:20:271:41 | \\([[:alpha:]]\\)*.* |
121+
| test.cpp:275:20:275:30 | \\(a*\\)* |
122+
| test.cpp:290:19:290:24 | abc+ |
123+
| test.cpp:293:19:293:32 | [[:alpha:]]+ |
124+
| test.cpp:297:19:297:34 | a\\.b\\(c\\).* |
125+
| test.cpp:299:19:299:34 | (foo\|bar){2,3} |
126+
| test.cpp:301:19:301:24 | awk+ |
127+
| test.cpp:303:19:303:26 | (x\|y)+ |
128+
| test.cpp:305:19:305:26 | ^a.*b$ |
129+
| test.cpp:309:19:309:29 | ([a-z]+)+ |

cpp/ql/test/library-tests/regex/flags.expected

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,12 @@ ignoreCase
22
| RegExpParent |
33
| RegExpParent |
44
| RegExpParent |
5+
| RegExpParent |
56
multiline
67
| RegExpParent |
78
dotAll
89
flags
910
| RegExpParent | i |
1011
| RegExpParent | i |
12+
| RegExpParent | i |
1113
| RegExpParent | im |

0 commit comments

Comments
 (0)