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

Skip to content

Commit 8270bf5

Browse files
committed
make the character search skip unencodable characters
1 parent 55f2f86 commit 8270bf5

2 files changed

Lines changed: 23 additions & 8 deletions

File tree

  • javascript/ql

javascript/ql/src/Performance/ReDoS.ql

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,13 @@ class RegExpRepetition extends RegExpParent {
122122
}
123123
}
124124

125+
/**
126+
* A constant in a regular expression that represents valid Unicode character(s).
127+
*/
128+
class RegexpCharacterConstant extends RegExpConstant {
129+
RegexpCharacterConstant() { this.isCharacter() }
130+
}
131+
125132
/**
126133
* Gets the root containing the given term, that is, the root of the literal,
127134
* or a branch of the root disjunction.
@@ -136,7 +143,9 @@ RegExpRoot getRoot(RegExpTerm term) {
136143
*/
137144
newtype TInputSymbol =
138145
/** An input symbol corresponding to character `c`. */
139-
Char(string c) { c = any(RegExpConstant cc | getRoot(cc).isRelevant()).getValue().charAt(_) } or
146+
Char(string c) {
147+
c = any(RegexpCharacterConstant cc | getRoot(cc).isRelevant()).getValue().charAt(_)
148+
} or
140149
/**
141150
* An input symbol representing all characters matched by
142151
* (non-universal) character class `recc`.
@@ -173,7 +182,7 @@ private predicate sharesRoot(TInputSymbol a, TInputSymbol b) {
173182
*/
174183
private predicate belongsTo(TInputSymbol a, RegExpRoot root) {
175184
exists(RegExpTerm term | getRoot(term) = root |
176-
a = Char(term.(RegExpConstant).getValue().charAt(_))
185+
a = Char(term.(RegexpCharacterConstant).getValue().charAt(_))
177186
or
178187
a = CharClass(term)
179188
)
@@ -236,7 +245,7 @@ private module CharacterClasses {
236245
predicate hasChildThatMatches(RegExpCharacterClass cc, string char) {
237246
exists(CharClass(cc)) and
238247
exists(RegExpTerm child | child = cc.getAChild() |
239-
char = child.(RegExpConstant).getValue()
248+
char = child.(RegexpCharacterConstant).getValue()
240249
or
241250
rangeMatchesOnLetterOrDigits(child, char)
242251
or
@@ -300,7 +309,7 @@ private module CharacterClasses {
300309
private string getARelevantChar() {
301310
exists(ascii(result))
302311
or
303-
exists(RegExpConstant c | result = c.getValue().charAt(_))
312+
exists(RegexpCharacterConstant c | result = c.getValue().charAt(_))
304313
or
305314
classEscapeMatches(_, result)
306315
}
@@ -310,7 +319,7 @@ private module CharacterClasses {
310319
*/
311320
private string getAMentionedChar(RegExpCharacterClass c) {
312321
exists(RegExpTerm child | child = c.getAChild() |
313-
result = child.(RegExpConstant).getValue()
322+
result = child.(RegexpCharacterConstant).getValue()
314323
or
315324
child.(RegExpCharacterRange).isRange(result, _)
316325
or
@@ -439,7 +448,7 @@ newtype TState =
439448
(
440449
i = 0
441450
or
442-
exists(t.(RegExpConstant).getValue().charAt(i))
451+
exists(t.(RegexpCharacterConstant).getValue().charAt(i))
443452
)
444453
} or
445454
Accept(RegExpRoot l) { l.isRelevant() }
@@ -511,7 +520,7 @@ State after(RegExpTerm t) {
511520
* Holds if the NFA has a transition from `q1` to `q2` labelled with `lbl`.
512521
*/
513522
predicate delta(State q1, EdgeLabel lbl, State q2) {
514-
exists(RegExpConstant s, int i |
523+
exists(RegexpCharacterConstant s, int i |
515524
q1 = Match(s, i) and
516525
lbl = Char(s.getValue().charAt(i)) and
517526
(

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

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -272,4 +272,10 @@ var bad60 = /(.thisisagoddamnlongstringforstresstestingthequery|\sthisisagoddamn
272272
var bad61 = /(thisisagoddamnlongstringforstresstestingthequery|this\w+query)*-/
273273

274274
// GOOD
275-
var good27 = /(thisisagoddamnlongstringforstresstestingthequery|imanotherbutunrelatedstringcomparedtotheotherstring)*-/
275+
var good27 = /(thisisagoddamnlongstringforstresstestingthequery|imanotherbutunrelatedstringcomparedtotheotherstring)*-/
276+
277+
// GOOD
278+
var good28 = /foo([\uDC66\uDC67]|[\uDC68\uDC69])*foo/
279+
280+
// GOOD
281+
var good29 = /foo((\uDC66|\uDC67)|(\uDC68|\uDC69))*foo/

0 commit comments

Comments
 (0)