Skip to content

Commit ebc4856

Browse files
committed
detect more expensive regexps in js/polynomial-redos
1 parent 5ac8475 commit ebc4856

File tree

4 files changed

+181
-6
lines changed

4 files changed

+181
-6
lines changed

javascript/ql/src/semmle/javascript/security/performance/SuperlinearBackTracking.qll

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -124,10 +124,20 @@ class PolynomialBackTrackingTerm extends InfiniteRepetitionQuantifier {
124124
forall(RegExpTerm pred | pred = this.getPredecessor+() | matchesEpsilon(pred)) and
125125
reason = "it can start matching anywhere"
126126
or
127-
exists(InfiniteRepetitionQuantifier pred |
128-
pred = getAMatchPredecessor(this.getPredecessor()) and
129-
compatible(pred.getAChild(), this.getAChild())
127+
exists(RegExpTerm pred |
128+
pred instanceof InfiniteRepetitionQuantifier
129+
or
130+
forall(RegExpTerm predpred | predpred = pred.getPredecessor+() | matchesEpsilon(predpred))
130131
|
132+
pred = getAMatchPredecessor(this.getPredecessor()) and
133+
(
134+
// compatible children
135+
compatible(pred.getAChild(), this.getAChild())
136+
or
137+
// or `this` is compatible with everything (and the predecessor is something)
138+
unique( | | this.getAChild()) instanceof RegExpDot and
139+
exists([pred, pred.getAChild()].getAMatchedString())
140+
) and
131141
reason =
132142
"it can start matching anywhere after the start of the preceeding '" + pred.toString() +
133143
"'"

javascript/ql/test/query-tests/Performance/ReDoS/PolynomialBackTracking.expected

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,44 @@
1212
| polynomial-redos.js:22:57:22:59 | \\d+ | it can start matching anywhere after the start of the preceeding '\\d*' |
1313
| polynomial-redos.js:22:57:22:59 | \\d+ | it can start matching anywhere after the start of the preceeding '\\d+' |
1414
| polynomial-redos.js:25:37:25:56 | [a-zA-Z0-9+\\/ \\t\\n]+ | it can start matching anywhere after the start of the preceeding '[ \\t]+' |
15+
| polynomial-redos.js:25:63:25:64 | .* | it can start matching anywhere after the start of the preceeding '[=]*' |
16+
| polynomial-redos.js:25:63:25:64 | .* | it can start matching anywhere after the start of the preceeding '[a-zA-Z0-9+\\/ \\t\\n]+' |
1517
| polynomial-redos.js:27:14:27:22 | [A-Z]{2,} | it can start matching anywhere |
1618
| polynomial-redos.js:30:19:30:22 | [?]+ | it can start matching anywhere |
19+
| polynomial-redos.js:30:23:30:24 | .* | it can start matching anywhere after the start of the preceeding '[?]' |
20+
| polynomial-redos.js:30:23:30:24 | .* | it can start matching anywhere after the start of the preceeding '[?]+' |
1721
| polynomial-redos.js:31:42:31:43 | -+ | it can start matching anywhere |
1822
| polynomial-redos.js:32:45:32:47 | \\n* | it can start matching anywhere |
1923
| polynomial-redos.js:33:17:33:20 | (.)* | it can start matching anywhere |
24+
| polynomial-redos.js:36:18:36:19 | .* | it can start matching anywhere after the start of the preceeding '<' |
25+
| polynomial-redos.js:37:18:37:19 | .* | it can start matching anywhere after the start of the preceeding '<' |
26+
| polynomial-redos.js:38:18:38:19 | .* | it can start matching anywhere after the start of the preceeding '<' |
2027
| polynomial-redos.js:48:22:48:24 | \\s* | it can start matching anywhere |
28+
| polynomial-redos.js:50:4:50:5 | .* | it can start matching anywhere after the start of the preceeding 'Y' |
29+
| polynomial-redos.js:51:11:51:17 | (YH\|J)* | it can start matching anywhere after the start of the preceeding '(YH\|K)' |
30+
| polynomial-redos.js:51:11:51:17 | (YH\|J)* | it can start matching anywhere after the start of the preceeding 'YH\|K' |
31+
| polynomial-redos.js:52:12:52:13 | .* | it can start matching anywhere after the start of the preceeding '(YH\|K)' |
32+
| polynomial-redos.js:52:12:52:13 | .* | it can start matching anywhere after the start of the preceeding 'K' |
33+
| polynomial-redos.js:52:12:52:13 | .* | it can start matching anywhere after the start of the preceeding 'YH' |
34+
| polynomial-redos.js:52:12:52:13 | .* | it can start matching anywhere after the start of the preceeding 'YH\|K' |
35+
| polynomial-redos.js:53:3:53:8 | (B\|Y)+ | it can start matching anywhere |
36+
| polynomial-redos.js:53:9:53:12 | (Y)* | it can start matching anywhere after the start of the preceeding '(B\|Y)' |
37+
| polynomial-redos.js:53:9:53:12 | (Y)* | it can start matching anywhere after the start of the preceeding '(B\|Y)+' |
38+
| polynomial-redos.js:53:9:53:12 | (Y)* | it can start matching anywhere after the start of the preceeding 'B\|Y' |
39+
| polynomial-redos.js:54:4:54:9 | (B\|Y)+ | it can start matching anywhere |
40+
| polynomial-redos.js:55:11:55:14 | (Y)* | it can start matching anywhere after the start of the preceeding '(B\|Y)+' |
41+
| polynomial-redos.js:56:10:56:13 | (Y)* | it can start matching anywhere after the start of the preceeding '(B\|Y)+' |
42+
| polynomial-redos.js:57:11:57:16 | (Y\|K)* | it can start matching anywhere after the start of the preceeding '(B\|Y)+' |
43+
| polynomial-redos.js:58:11:58:12 | .* | it can start matching anywhere after the start of the preceeding '(B\|Y)+' |
44+
| polynomial-redos.js:62:7:62:8 | Y* | it can start matching anywhere after the start of the preceeding 'Y*' |
45+
| polynomial-redos.js:63:11:63:12 | Y* | it can start matching anywhere after the start of the preceeding '(K\|Y)+' |
46+
| polynomial-redos.js:64:14:64:15 | Y* | it can start matching anywhere after the start of the preceeding '(K\|Y)+' |
47+
| polynomial-redos.js:65:14:65:15 | .* | it can start matching anywhere after the start of the preceeding '(K\|Y)+' |
48+
| polynomial-redos.js:66:9:66:10 | .* | it can start matching anywhere after the start of the preceeding '(K\|Y)' |
49+
| polynomial-redos.js:66:9:66:10 | .* | it can start matching anywhere after the start of the preceeding 'K' |
50+
| polynomial-redos.js:66:9:66:10 | .* | it can start matching anywhere after the start of the preceeding 'K\|Y' |
51+
| polynomial-redos.js:66:9:66:10 | .* | it can start matching anywhere after the start of the preceeding 'Y' |
52+
| polynomial-redos.js:67:8:67:9 | .* | it can start matching anywhere after the start of the preceeding '[^Y]' |
2153
| regexplib/address.js:18:26:18:31 | [ \\w]* | it can start matching anywhere after the start of the preceeding '[ \\w]{3,}' |
2254
| regexplib/address.js:20:144:20:147 | [ ]+ | it can start matching anywhere after the start of the preceeding '[a-zA-Z0-9 \\-.]{6,}' |
2355
| regexplib/address.js:24:26:24:31 | [ \\w]* | it can start matching anywhere after the start of the preceeding '[ \\w]{3,}' |
@@ -36,7 +68,11 @@
3668
| regexplib/address.js:75:631:75:635 | \\x20* | it can start matching anywhere after the start of the preceeding '\\x20*' |
3769
| regexplib/address.js:75:796:75:798 | \\s+ | it can start matching anywhere after the start of the preceeding '\\s+' |
3870
| regexplib/address.js:85:15:85:49 | ([0-9]\|[ ]\|[-]\|[\\(]\|[\\)]\|ext.\|[,])+ | it can start matching anywhere |
71+
| regexplib/address.js:85:51:85:67 | ([ ]\|[:]\|\\t\|[-])* | it can start matching anywhere after the start of the preceeding '([0-9]\|[ ]\|[-]\|[\\(]\|[\\)]\|ext.\|[,])' |
3972
| regexplib/address.js:85:51:85:67 | ([ ]\|[:]\|\\t\|[-])* | it can start matching anywhere after the start of the preceeding '([0-9]\|[ ]\|[-]\|[\\(]\|[\\)]\|ext.\|[,])+' |
73+
| regexplib/address.js:85:51:85:67 | ([ ]\|[:]\|\\t\|[-])* | it can start matching anywhere after the start of the preceeding '[0-9]\|[ ]\|[-]\|[\\(]\|[\\)]\|ext.\|[,]' |
74+
| regexplib/address.js:85:51:85:67 | ([ ]\|[:]\|\\t\|[-])* | it can start matching anywhere after the start of the preceeding '[ ]' |
75+
| regexplib/address.js:85:51:85:67 | ([ ]\|[:]\|\\t\|[-])* | it can start matching anywhere after the start of the preceeding '[-]' |
4076
| regexplib/address.js:93:3:93:5 | \\s* | it can start matching anywhere |
4177
| regexplib/address.js:93:48:93:50 | \\s* | it can start matching anywhere |
4278
| regexplib/address.js:93:93:93:95 | \\s* | it can start matching anywhere |
@@ -50,19 +86,28 @@
5086
| regexplib/email.js:28:73:28:87 | [0-9a-zA-Z'\\.]+ | it can start matching anywhere |
5187
| regexplib/email.js:28:125:28:139 | [0-9a-zA-Z'\\.]+ | it can start matching anywhere |
5288
| regexplib/email.js:29:2:29:7 | [\\w-]+ | it can start matching anywhere |
89+
| regexplib/markup.js:1:11:1:12 | .* | it can start matching anywhere after the start of the preceeding '<' |
5390
| regexplib/markup.js:6:99:6:113 | [\\s\\w\\d\\)\\(\\,]* | it can start matching anywhere after the start of the preceeding '[\\d\\w]+' |
91+
| regexplib/markup.js:11:6:11:8 | .*? | it can start matching anywhere after the start of the preceeding '<!--' |
92+
| regexplib/markup.js:13:14:13:16 | .+? | it can start matching anywhere after the start of the preceeding '<' |
93+
| regexplib/markup.js:14:10:14:11 | .* | it can start matching anywhere after the start of the preceeding '<' |
94+
| regexplib/markup.js:14:13:14:14 | .* | it can start matching anywhere after the start of the preceeding '<' |
5495
| regexplib/markup.js:19:2:19:12 | (<meta\\s+)* | it can start matching anywhere |
5596
| regexplib/markup.js:20:155:20:156 | '+ | it can start matching anywhere after the start of the preceeding ''+' |
5697
| regexplib/markup.js:20:197:20:198 | "+ | it can start matching anywhere after the start of the preceeding '"+' |
5798
| regexplib/markup.js:37:15:37:19 | [\\w]* | it can start matching anywhere after the start of the preceeding '\\w+' |
5899
| regexplib/markup.js:53:15:53:19 | [\\w]* | it can start matching anywhere after the start of the preceeding '\\w+' |
100+
| regexplib/markup.js:62:35:62:37 | .*? | it can start matching anywhere after the start of the preceeding '[\\s\\"\\']+' |
59101
| regexplib/markup.js:62:39:62:45 | [\\"\\']+ | it can start matching anywhere after the start of the preceeding '[\\s\\"\\']+' |
102+
| regexplib/markup.js:62:46:62:48 | .*? | it can start matching anywhere after the start of the preceeding '[\\"\\']+' |
60103
| regexplib/misc.js:76:2:76:27 | (AUX\|PRN\|NUL\|COM\\d\|LPT\\d)+ | it can start matching anywhere |
61104
| regexplib/misc.js:83:15:83:17 | \\d* | it can start matching anywhere after the start of the preceeding '\\d*' |
62105
| regexplib/misc.js:83:69:83:71 | \\d* | it can start matching anywhere after the start of the preceeding '\\d*' |
63106
| regexplib/misc.js:93:3:93:4 | .* | it can start matching anywhere |
107+
| regexplib/misc.js:95:25:95:26 | .+ | it can start matching anywhere after the start of the preceeding 'at\\s' |
64108
| regexplib/misc.js:112:3:112:5 | \\s* | it can start matching anywhere |
65109
| regexplib/misc.js:112:32:112:34 | \\s* | it can start matching anywhere |
110+
| regexplib/misc.js:116:3:116:4 | .* | it can start matching anywhere after the start of the preceeding '{' |
66111
| regexplib/misc.js:119:9:119:11 | \\s* | it can start matching anywhere |
67112
| regexplib/misc.js:119:12:119:14 | \\(* | it can start matching anywhere |
68113
| regexplib/misc.js:119:16:119:18 | \\s* | it can start matching anywhere |
@@ -114,13 +159,17 @@
114159
| regexplib/strings.js:91:2:91:7 | (\\S*)+ | it can start matching anywhere |
115160
| regexplib/strings.js:91:3:91:5 | \\S* | it can start matching anywhere |
116161
| regexplib/uri.js:2:45:2:66 | [\\w\\-\\.,@?^=%&:/~\\+#]* | it can start matching anywhere after the start of the preceeding '[\\w\\-_]+' |
162+
| regexplib/uri.js:5:42:5:43 | .* | it can start matching anywhere after the start of the preceeding '[\\w ]*' |
117163
| regexplib/uri.js:13:69:13:102 | [a-zA-Z0-9\\-\\.\\?\\,\\'\\/\\\\\\+&%\\$#_]* | it can start matching anywhere after the start of the preceeding '[a-zA-Z0-9\\-\\._]+' |
164+
| regexplib/uri.js:17:42:17:43 | .* | it can start matching anywhere after the start of the preceeding '[\\w ]*' |
118165
| regexplib/uri.js:18:47:18:96 | ([ A-Za-z0-9'~` !@#$%&^_+=\\(\\){},\\-\\[\\];]\|([.]))*? | it can start matching anywhere after the start of the preceeding '([A-Za-z0-9'~`!@#$%&^_+=\\(\\){},\\-\\[\\]\\;])+?' |
119166
| regexplib/uri.js:18:148:18:189 | ([A-Za-z0-9'~`!@#$%&^_+=\\(\\){},\\-\\[ \\];])+ | it can start matching anywhere after the start of the preceeding '[ A-Za-z0-9'~`!@#$ %&^_+=\\(\\){},\\-\\[\\]\\;]*?' |
120167
| regexplib/uri.js:23:2:23:74 | (((file\|gopher\|news\|nntp\|telnet\|http\|ftp\|https\|ftps\|sftp):\\/\\/)\|(www\\.))+ | it can start matching anywhere |
168+
| regexplib/uri.js:23:77:23:92 | [a-zA-Z0-9\\._-]+ | it can start matching anywhere after the start of the preceeding 'www\\.' |
121169
| regexplib/uri.js:28:2:28:13 | [a-zA-Z]{3,} | it can start matching anywhere |
122170
| regexplib/uri.js:29:2:29:45 | ((http\\:\\/\\/\|https\\:\\/\\/\|ftp\\:\\/\\/)\|(www.))+ | it can start matching anywhere |
123171
| regexplib/uri.js:34:3:34:9 | [^\\=&]+ | it can start matching anywhere |
172+
| regexplib/uri.js:39:7:39:9 | .*? | it can start matching anywhere after the start of the preceeding '<a' |
124173
| regexplib/uri.js:44:2:44:4 | .*? | it can start matching anywhere |
125174
| regexplib/uri.js:53:3:53:9 | [^\\=&]+ | it can start matching anywhere |
126175
| regexplib/uri.js:58:2:58:45 | ((http\\:\\/\\/\|https\\:\\/\\/\|ftp\\:\\/\\/)\|(www.))+ | it can start matching anywhere |
@@ -129,8 +178,12 @@
129178
| tst.js:14:13:14:18 | (.*,)+ | it can start matching anywhere |
130179
| tst.js:14:14:14:15 | .* | it can start matching anywhere |
131180
| tst.js:47:15:47:37 | (?:[^"']\|".*?"\|'.*?')*? | it can start matching anywhere |
181+
| tst.js:47:25:47:27 | .*? | it can start matching anywhere after the start of the preceeding '"' |
182+
| tst.js:47:31:47:33 | .*? | it can start matching anywhere after the start of the preceeding ''' |
132183
| tst.js:66:15:66:44 | ([\\w#:.~>+()\\s-]+\|\\*\|\\[.*?\\])+ | it can start matching anywhere |
133184
| tst.js:66:16:66:31 | [\\w#:.~>+()\\s-]+ | it can start matching anywhere |
185+
| tst.js:66:38:66:40 | .*? | it can start matching anywhere after the start of the preceeding '\\[' |
186+
| tst.js:66:46:66:48 | \\s* | it can start matching anywhere after the start of the preceeding '[\\w#:.~>+()\\s-]' |
134187
| tst.js:66:46:66:48 | \\s* | it can start matching anywhere after the start of the preceeding '[\\w#:.~>+()\\s-]+' |
135188
| tst.js:74:14:74:21 | (b\|a?b)* | it can start matching anywhere |
136189
| tst.js:77:14:77:21 | (a\|aa?)* | it can start matching anywhere |

0 commit comments

Comments
 (0)