mirror of
https://github.com/github/codeql.git
synced 2026-04-30 11:15:13 +02:00
Support possessive quantifiers, which cannot backtrack.
They are approximated by limiting them to up to one repetition (effectively making *+ like ? and ++ like a no-op).
This commit is contained in:
@@ -253,7 +253,12 @@ class RegExpQuantifier extends RegExpTerm, TRegExpQuantifier {
|
||||
predicate mayRepeatForever() { may_repeat_forever = true }
|
||||
|
||||
/** Gets the quantifier for this term. That is e.g "?" for "a?". */
|
||||
string getquantifier() { result = re.getText().substring(part_end, end) }
|
||||
string getQuantifier() { result = re.getText().substring(part_end, end) }
|
||||
|
||||
/** Holds if this is a possessive quantifier, e.g. a*+. */
|
||||
predicate isPossessive() {
|
||||
exists(string q | q = this.getQuantifier() | q.length() > 1 and q.charAt(q.length() - 1) = "+")
|
||||
}
|
||||
|
||||
override string getPrimaryQLClass() { result = "RegExpQuantifier" }
|
||||
}
|
||||
@@ -275,7 +280,7 @@ class InfiniteRepetitionQuantifier extends RegExpQuantifier {
|
||||
* ```
|
||||
*/
|
||||
class RegExpStar extends InfiniteRepetitionQuantifier {
|
||||
RegExpStar() { this.getquantifier().charAt(0) = "*" }
|
||||
RegExpStar() { this.getQuantifier().charAt(0) = "*" }
|
||||
|
||||
override string getPrimaryQLClass() { result = "RegExpStar" }
|
||||
}
|
||||
@@ -290,7 +295,7 @@ class RegExpStar extends InfiniteRepetitionQuantifier {
|
||||
* ```
|
||||
*/
|
||||
class RegExpPlus extends InfiniteRepetitionQuantifier {
|
||||
RegExpPlus() { this.getquantifier().charAt(0) = "+" }
|
||||
RegExpPlus() { this.getQuantifier().charAt(0) = "+" }
|
||||
|
||||
override string getPrimaryQLClass() { result = "RegExpPlus" }
|
||||
}
|
||||
@@ -305,7 +310,7 @@ class RegExpPlus extends InfiniteRepetitionQuantifier {
|
||||
* ```
|
||||
*/
|
||||
class RegExpOpt extends RegExpQuantifier {
|
||||
RegExpOpt() { this.getquantifier().charAt(0) = "?" }
|
||||
RegExpOpt() { this.getQuantifier().charAt(0) = "?" }
|
||||
|
||||
override string getPrimaryQLClass() { result = "RegExpOpt" }
|
||||
}
|
||||
|
||||
@@ -608,10 +608,15 @@ State after(RegExpTerm t) {
|
||||
or
|
||||
exists(RegExpGroup grp | t = grp.getAChild() | result = after(grp))
|
||||
or
|
||||
exists(EffectivelyStar star | t = star.getAChild() | result = before(star))
|
||||
exists(EffectivelyStar star | t = star.getAChild() |
|
||||
not isPossessive(star) and
|
||||
result = before(star)
|
||||
)
|
||||
or
|
||||
exists(EffectivelyPlus plus | t = plus.getAChild() |
|
||||
result = before(plus) or
|
||||
not isPossessive(plus) and
|
||||
result = before(plus)
|
||||
or
|
||||
result = after(plus)
|
||||
)
|
||||
or
|
||||
|
||||
@@ -16,6 +16,11 @@ predicate isEscapeClass(RegExpTerm term, string clazz) {
|
||||
term.(RegExpNamedProperty).getBackslashEquivalent() = clazz
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `term` is a possessive quantifier, e.g. `a*+`.
|
||||
*/
|
||||
predicate isPossessive(RegExpQuantifier term) { term.isPossessive() }
|
||||
|
||||
/**
|
||||
* Holds if the regular expression should not be considered.
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user