Skip to content

Commit de8f64c

Browse files
committed
sync with python
1 parent 80d784e commit de8f64c

File tree

2 files changed

+47
-29
lines changed

2 files changed

+47
-29
lines changed

python/ql/src/semmle/python/security/performance/ReDoSUtil.qll

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,49 @@ private int ascii(string char) {
7171
)
7272
}
7373

74+
/**
75+
* Holds if `t` matches at least an epsilon symbol.
76+
*
77+
* That is, this term does not restrict the language of the enclosing regular expression.
78+
*
79+
* This is implemented as an under-approximation, and this predicate does not hold for sub-patterns in particular.
80+
*/
81+
predicate matchesEpsilon(RegExpTerm t) {
82+
t instanceof RegExpStar
83+
or
84+
t instanceof RegExpOpt
85+
or
86+
t.(RegExpRange).getLowerBound() = 0
87+
or
88+
exists(RegExpTerm child |
89+
child = t.getAChild() and
90+
matchesEpsilon(child)
91+
|
92+
t instanceof RegExpAlt or
93+
t instanceof RegExpGroup or
94+
t instanceof RegExpPlus or
95+
t instanceof RegExpRange
96+
)
97+
or
98+
matchesEpsilon(t.(RegExpBackRef).getGroup())
99+
or
100+
forex(RegExpTerm child | child = t.(RegExpSequence).getAChild() | matchesEpsilon(child))
101+
}
102+
103+
/**
104+
* A lookahead/lookbehind that matches the empty string.
105+
*/
106+
class EmptyPositiveSubPatttern extends RegExpSubPattern {
107+
EmptyPositiveSubPatttern() {
108+
(
109+
this instanceof RegExpPositiveLookahead
110+
or
111+
this instanceof RegExpPositiveLookbehind
112+
) and
113+
matchesEpsilon(this.getOperand())
114+
}
115+
}
116+
74117
/**
75118
* A branch in a disjunction that is the root node in a literal, or a literal
76119
* whose root node is not a disjunction.
@@ -550,6 +593,10 @@ predicate delta(State q1, EdgeLabel lbl, State q2) {
550593
exists(RegExpDollar dollar | q1 = before(dollar) |
551594
lbl = Epsilon() and q2 = Accept(getRoot(dollar))
552595
)
596+
or
597+
exists(EmptyPositiveSubPatttern empty | q1 = before(empty) |
598+
lbl = Epsilon() and q2 = after(empty)
599+
)
553600
}
554601

555602
/**

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

Lines changed: 0 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -363,35 +363,6 @@ predicate polynimalReDoS(RegExpTerm t, string pump, string prefixMsg, RegExpTerm
363363
)
364364
}
365365

366-
/**
367-
* Holds if `t` matches at least an epsilon symbol.
368-
*
369-
* That is, this term does not restrict the language of the enclosing regular expression.
370-
*
371-
* This is implemented as an under-approximation, and this predicate does not hold for sub-patterns in particular.
372-
*/
373-
private predicate matchesEpsilon(RegExpTerm t) {
374-
t instanceof RegExpStar
375-
or
376-
t instanceof RegExpOpt
377-
or
378-
t.(RegExpRange).getLowerBound() = 0
379-
or
380-
exists(RegExpTerm child |
381-
child = t.getAChild() and
382-
matchesEpsilon(child)
383-
|
384-
t instanceof RegExpAlt or
385-
t instanceof RegExpGroup or
386-
t instanceof RegExpPlus or
387-
t instanceof RegExpRange
388-
)
389-
or
390-
matchesEpsilon(t.(RegExpBackRef).getGroup())
391-
or
392-
forex(RegExpTerm child | child = t.(RegExpSequence).getAChild() | matchesEpsilon(child))
393-
}
394-
395366
/**
396367
* Gets a message for why `term` can cause polynomial backtracking.
397368
*/

0 commit comments

Comments
 (0)