Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 0063cb1

Browse files
committed
add support for \W, \S, \D
1 parent 2dd8b6f commit 0063cb1

3 files changed

Lines changed: 53 additions & 14 deletions

File tree

javascript/ql/src/Performance/ReDoS.ql

Lines changed: 44 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -303,6 +303,25 @@ private module CharacterClasses {
303303
}
304304
}
305305

306+
/**
307+
* Holds if the character class escape `clazz` (\d, \s, or \w) matches `char`.
308+
*/
309+
private predicate classEscapeMatches(string clazz, string char) {
310+
clazz = "d" and
311+
char = "0123456789".charAt(_)
312+
or
313+
clazz = "s" and
314+
(
315+
char = [" ", "\t", "\r", "\n", "\\u000c", "\\u000b"]
316+
or
317+
exists(RegExpConstant constant | constant.getValue().charAt(_) = char) and
318+
char.regexpMatch("\\u000b|\\u000c") // \v|\f (vertical tab | form feed)
319+
)
320+
or
321+
clazz = "w" and
322+
char = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_".charAt(_)
323+
}
324+
306325
/**
307326
* An implementation of `CharacterClass` for \d, \s, and \w.
308327
*/
@@ -322,25 +341,37 @@ private module CharacterClasses {
322341
result = ["a", "Z", "_", "0", "9"]
323342
}
324343

325-
override predicate matches(string char) {
326-
cc.getValue() = "d" and
327-
char = "0123456789".charAt(_)
344+
override predicate matches(string char) { classEscapeMatches(cc.getValue(), char) }
345+
346+
override string choose() { result = min(string c | c = getARelevantChar()) }
347+
}
348+
349+
/**
350+
* An implementation of `CharacterClass` for \D, \S, and \W.
351+
*/
352+
private class NegativeCharacterClassEscape extends CharacterClass {
353+
RegExpCharacterClassEscape cc;
354+
355+
NegativeCharacterClassEscape() { this = CharClass(cc) and cc.getValue() = ["D", "S", "W"] }
356+
357+
override string getARelevantChar() {
358+
cc.getValue() = "D" and
359+
result = ["a", "Z", "!"]
328360
or
329-
cc.getValue() = "s" and
330-
(
331-
char = [" ", "\t", "\r", "\n", "\\u000c", "\\u000b"]
332-
or
333-
exists(RegExpConstant constant | constant.getValue().charAt(_) = char) and
334-
char.regexpMatch("\\u000b|\\u000c") // \v|\f (vertical tab | form feed)
335-
)
361+
cc.getValue() = "S" and
362+
result = ["a", "9", "!"]
336363
or
337-
cc.getValue() = "w" and
338-
char = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_".charAt(_)
364+
cc.getValue() = "W" and
365+
result = [" ", "!"]
366+
}
367+
368+
bindingset[char]
369+
override predicate matches(string char) {
370+
not classEscapeMatches(cc.getValue().toLowerCase(), char)
339371
}
340372

341373
override string choose() { result = min(string c | c = getARelevantChar()) }
342374
}
343-
// TODO: Implementations for inversed RegExpCharacterClassEscape
344375
}
345376

346377
newtype TState =

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,3 +100,5 @@
100100
| tst.js:149:15:149:24 | (\\s\|[\\f])* | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of '\u000c'. |
101101
| tst.js:152:15:152:28 | (\\s\|[\\v]\|\\\\v)* | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of '\u000b'. |
102102
| tst.js:155:15:155:24 | (\\f\|[\\f])* | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of '\u000c'. |
103+
| tst.js:158:15:158:22 | (\\W\|\\D)* | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of '!'. |
104+
| tst.js:161:15:161:22 | (\\S\|\\w)* | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of '0'. |

javascript/ql/test/query-tests/Performance/ReDoS/tst.js

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -152,4 +152,10 @@ var bad33 = /((\s|[\f])*)"/;
152152
var bad34 = /((\s|[\v]|\\v)*)"/;
153153

154154
// NOT GOOD
155-
var bad35 = /((\f|[\f])*)"/;
155+
var bad35 = /((\f|[\f])*)"/;
156+
157+
// NOT GOOD
158+
var bad36 = /((\W|\D)*)"/;
159+
160+
// NOT GOOD
161+
var bad37 = /((\S|\w)*)"/;

0 commit comments

Comments
 (0)