Skip to content

Commit 2f491a1

Browse files
authored
Merge pull request #230 from github/redos-enable-tounicode
enable unicode parsing in the ReDoS query
2 parents d986bea + 632ad51 commit 2f491a1

3 files changed

Lines changed: 43 additions & 37 deletions

File tree

ql/src/codeql_ruby/regexp/RegExpTreeView.qll

Lines changed: 35 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -351,49 +351,48 @@ class RegExpEscape extends RegExpNormalChar {
351351
* E.g. for `\u0061` this returns "a".
352352
*/
353353
private string getUnicode() {
354-
// TODO: uncomment when toUnicode() is available
355-
none()
356-
//exists(int codepoint | codepoint = sum(getHexValueFromUnicode(_)) |
357-
// result = codepoint.toUnicode()
358-
//)
354+
exists(int codepoint | codepoint = sum(getHexValueFromUnicode(_)) |
355+
result = codepoint.toUnicode()
356+
)
357+
}
358+
359+
/**
360+
* Gets int value for the `index`th char in the hex number of the unicode escape.
361+
* E.g. for `\u0061` and `index = 2` this returns 96 (the number `6` interpreted as hex).
362+
*/
363+
private int getHexValueFromUnicode(int index) {
364+
isUnicode() and
365+
exists(string hex, string char | hex = getText().suffix(2) |
366+
char = hex.charAt(index) and
367+
result = 16.pow(hex.length() - index - 1) * toHex(char)
368+
)
359369
}
360370

361-
// TODO: uncomment when toUnicode() is available
362-
///**
363-
// * Gets int value for the `index`th char in the hex number of the unicode escape.
364-
// * E.g. for `\u0061` and `index = 2` this returns 96 (the number `6` interpreted as hex).
365-
// */
366-
//private int getHexValueFromUnicode(int index) {
367-
// isUnicode() and
368-
// exists(string hex, string char | hex = getText().suffix(2) |
369-
// char = hex.charAt(index) and
370-
// result = 16.pow(hex.length() - index - 1) * toHex(char)
371-
// )
372-
//}
373371
string getUnescaped() { result = this.getText().suffix(1) }
374372

375373
override string getAPrimaryQlClass() { result = "RegExpEscape" }
376374
}
377375

378-
///**
379-
// * Gets the hex number for the `hex` char.
380-
// */
381-
//private int toHex(string hex) {
382-
// hex = [0 .. 9].toString() and
383-
// result = hex.toInt()
384-
// or
385-
// result = 10 and hex = ["a", "A"]
386-
// or
387-
// result = 11 and hex = ["b", "B"]
388-
// or
389-
// result = 12 and hex = ["c", "C"]
390-
// or
391-
// result = 13 and hex = ["d", "D"]
392-
// or
393-
// result = 14 and hex = ["e", "E"]
394-
// or
395-
// result = 15 and hex = ["f", "F"]
396-
//}
376+
/**
377+
* Gets the hex number for the `hex` char.
378+
*/
379+
private int toHex(string hex) {
380+
hex = [0 .. 9].toString() and
381+
result = hex.toInt()
382+
or
383+
result = 10 and hex = ["a", "A"]
384+
or
385+
result = 11 and hex = ["b", "B"]
386+
or
387+
result = 12 and hex = ["c", "C"]
388+
or
389+
result = 13 and hex = ["d", "D"]
390+
or
391+
result = 14 and hex = ["e", "E"]
392+
or
393+
result = 15 and hex = ["f", "F"]
394+
}
395+
397396
/**
398397
* A character class escape in a regular expression.
399398
* That is, an escaped character that denotes multiple characters.

ql/test/query-tests/security/cwe-1333/ReDoS.expected

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,3 +90,4 @@
9090
| tst.rb:361:11:361:29 | ((?:a{0\|-)\|\\w\\{\\d)+ | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of 'a{0'. |
9191
| tst.rb:362:11:362:31 | ((?:a{0,\|-)\|\\w\\{\\d,)+ | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of 'a{0,'. |
9292
| tst.rb:363:11:363:34 | ((?:a{0,2\|-)\|\\w\\{\\d,\\d)+ | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of 'a{0,2'. |
93+
| tst.rb:369:12:369:22 | (\\u0061\|a)* | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of 'a'. |

ql/test/query-tests/security/cwe-1333/tst.rb

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -363,4 +363,10 @@
363363
bad86 = /^((?:a{0,2|-)|\w\{\d,\d)+X$/
364364

365365
# GOOD:
366-
good42 = /^((?:a{0,2}|-)|\w\{\d,\d\})+X$/
366+
good42 = /^((?:a{0,2}|-)|\w\{\d,\d\})+X$/
367+
368+
# NOT GOOD
369+
bad87 = /^X(\u0061|a)*Y$/
370+
371+
# GOOD
372+
good43 = /^X(\u0061|b)+Y$/

0 commit comments

Comments
 (0)