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

Skip to content

Commit 36b9f02

Browse files
committed
performance improvements for suffix check in js/redos
1 parent e177d46 commit 36b9f02

1 file changed

Lines changed: 30 additions & 10 deletions

File tree

javascript/ql/src/Performance/ReDoS.ql

Lines changed: 30 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1022,20 +1022,41 @@ module SuffixConstruction {
10221022
* Holds if there likely exists a suffix starting from `s` that leads to the regular expression being rejected.
10231023
* This predicate might find impossible suffixes when searching for suffixes of length > 1, which can cause FPs.
10241024
*/
1025+
pragma[nomagic]
10251026
private predicate isLikelyRejectable(StateInPumpableRegexp s) {
10261027
// exists a reject edge with some char.
1027-
hasRejectEdge(s, _)
1028+
hasRejectEdge(s)
10281029
or
1030+
hasEdgeToLikelyRejectable(s)
1031+
or
1032+
// stopping here is rejection
1033+
isRejectState(s)
1034+
}
1035+
1036+
/**
1037+
* Holds if `s` is not an accept state, and there is no epsilon transition to an accept state.
1038+
*/
1039+
predicate isRejectState(StateInPumpableRegexp s) { not epsilonSucc*(s) = Accept(_) }
1040+
1041+
/**
1042+
* Holds if there is likely a non-empty suffix leading to rejection starting in `s`.
1043+
*/
1044+
predicate hasEdgeToLikelyRejectable(StateInPumpableRegexp s) {
10291045
// all edges (at least one) with some char leads to another state that is rejectable.
10301046
// the `next` states might not share a common suffix, which can cause FPs.
10311047
exists(string char | char = relevant() |
1032-
forex(State next | deltaClosed(s, getAnInputSymbolMatching(char), next) |
1033-
isLikelyRejectable(next)
1034-
)
1048+
forex(State next | deltaClosedChar(s, char, next) | isLikelyRejectable(next))
10351049
)
1036-
or
1037-
// stopping here is rejection
1038-
not epsilonSucc*(s) = Accept(_)
1050+
}
1051+
1052+
/**
1053+
* Holds if there is a state `next` that can be reached from `prev`
1054+
* along epsilon edges, such that there is a transition from
1055+
* `prev` to `next` that the character symbol `char`.
1056+
*/
1057+
predicate deltaClosedChar(StateInPumpableRegexp prev, string char, StateInPumpableRegexp next) {
1058+
char = relevant() and
1059+
deltaClosed(prev, getAnInputSymbolMatching(char), next)
10391060
}
10401061

10411062
/**
@@ -1047,9 +1068,8 @@ module SuffixConstruction {
10471068
* Holds if there is no edge from `s` labeled `char` in our NFA.
10481069
* The NFA does not model reject states, so the above is the same as saying there is a reject edge.
10491070
*/
1050-
private predicate hasRejectEdge(StateInPumpableRegexp s, string char) {
1051-
char = relevant() and
1052-
not deltaClosed(s, getAnInputSymbolMatching(char), _)
1071+
private predicate hasRejectEdge(State s) {
1072+
exists(string char | char = relevant() | not deltaClosedChar(s, char, _))
10531073
}
10541074

10551075
/**

0 commit comments

Comments
 (0)