Skip to content

Commit c38062c

Browse files
committed
convert RelevantState to a class in the PrefixConstruction module
1 parent c339a2d commit c38062c

File tree

4 files changed

+88
-108
lines changed

4 files changed

+88
-108
lines changed

java/ql/lib/semmle/code/java/security/regexp/NfaUtils.qll

Lines changed: 22 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -887,11 +887,10 @@ module PrefixConstruction<isCandidateSig/1 isCandidate> {
887887
/**
888888
* Holds if `state` is the textually last start state for the regular expression.
889889
*/
890-
private predicate lastStartState(State state) {
890+
private predicate lastStartState(RelevantState state) {
891891
exists(RegExpRoot root |
892892
state =
893893
max(State s, Location l |
894-
s = stateInRelevantRegexp() and
895894
isStartState(s) and
896895
getRoot(s.getRepr()) = root and
897896
l = s.getRepr().getLocation()
@@ -963,10 +962,13 @@ module PrefixConstruction<isCandidateSig/1 isCandidate> {
963962
min(string c | delta(prev, any(InputSymbol symbol | c = intersect(Any(), symbol)), next))
964963
}
965964

966-
/** Gets a state within a regular expression that contains a candidate state. */
967-
pragma[noinline]
968-
State stateInRelevantRegexp() {
969-
exists(State s | isCandidate(s) | getRoot(s.getRepr()) = getRoot(result.getRepr()))
965+
/** A state within a regular expression that contains a candidate state. */
966+
class RelevantState instanceof State {
967+
RelevantState() {
968+
exists(State s | isCandidate(s) | getRoot(s.getRepr()) = getRoot(this.getRepr()))
969+
}
970+
971+
string toString() { result = "RelevantState" }
970972
}
971973
}
972974

@@ -1007,6 +1009,8 @@ module ReDoSPruning<isCandidateSig/2 isCandidate> {
10071009

10081010
import PrefixConstruction<isCandidateState/1> as Prefix
10091011

1012+
class RelevantState = Prefix::RelevantState;
1013+
10101014
/**
10111015
* Predicates for testing the presence of a rejecting suffix.
10121016
*
@@ -1040,32 +1044,26 @@ module ReDoSPruning<isCandidateSig/2 isCandidate> {
10401044
* This predicate might find impossible suffixes when searching for suffixes of length > 1, which can cause FPs.
10411045
*/
10421046
pragma[noinline]
1043-
private predicate isLikelyRejectable(State s) {
1044-
s = Prefix::stateInRelevantRegexp() and
1045-
(
1046-
// exists a reject edge with some char.
1047-
hasRejectEdge(s)
1048-
or
1049-
hasEdgeToLikelyRejectable(s)
1050-
or
1051-
// stopping here is rejection
1052-
isRejectState(s)
1053-
)
1047+
private predicate isLikelyRejectable(RelevantState s) {
1048+
// exists a reject edge with some char.
1049+
hasRejectEdge(s)
1050+
or
1051+
hasEdgeToLikelyRejectable(s)
1052+
or
1053+
// stopping here is rejection
1054+
isRejectState(s)
10541055
}
10551056

10561057
/**
10571058
* Holds if `s` is not an accept state, and there is no epsilon transition to an accept state.
10581059
*/
1059-
predicate isRejectState(State s) {
1060-
s = Prefix::stateInRelevantRegexp() and not epsilonSucc*(s) = Accept(_)
1061-
}
1060+
predicate isRejectState(RelevantState s) { not epsilonSucc*(s) = Accept(_) }
10621061

10631062
/**
10641063
* Holds if there is likely a non-empty suffix leading to rejection starting in `s`.
10651064
*/
10661065
pragma[noopt]
1067-
predicate hasEdgeToLikelyRejectable(State s) {
1068-
s = Prefix::stateInRelevantRegexp() and
1066+
predicate hasEdgeToLikelyRejectable(RelevantState s) {
10691067
// all edges (at least one) with some char leads to another state that is rejectable.
10701068
// the `next` states might not share a common suffix, which can cause FPs.
10711069
exists(string char | char = hasEdgeToLikelyRejectableHelper(s) |
@@ -1080,8 +1078,7 @@ module ReDoSPruning<isCandidateSig/2 isCandidate> {
10801078
* and `s` has not been found to be rejectable by `hasRejectEdge` or `isRejectState`.
10811079
*/
10821080
pragma[noinline]
1083-
private string hasEdgeToLikelyRejectableHelper(State s) {
1084-
s = Prefix::stateInRelevantRegexp() and
1081+
private string hasEdgeToLikelyRejectableHelper(RelevantState s) {
10851082
not hasRejectEdge(s) and
10861083
not isRejectState(s) and
10871084
deltaClosedChar(s, result, _)
@@ -1092,9 +1089,7 @@ module ReDoSPruning<isCandidateSig/2 isCandidate> {
10921089
* along epsilon edges, such that there is a transition from
10931090
* `prev` to `next` that the character symbol `char`.
10941091
*/
1095-
predicate deltaClosedChar(State prev, string char, State next) {
1096-
prev = Prefix::stateInRelevantRegexp() and
1097-
next = Prefix::stateInRelevantRegexp() and
1092+
predicate deltaClosedChar(RelevantState prev, string char, RelevantState next) {
10981093
deltaClosed(prev, getAnInputSymbolMatchingRelevant(char), next)
10991094
}
11001095

javascript/ql/lib/semmle/javascript/security/regexp/NfaUtils.qll

Lines changed: 22 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -887,11 +887,10 @@ module PrefixConstruction<isCandidateSig/1 isCandidate> {
887887
/**
888888
* Holds if `state` is the textually last start state for the regular expression.
889889
*/
890-
private predicate lastStartState(State state) {
890+
private predicate lastStartState(RelevantState state) {
891891
exists(RegExpRoot root |
892892
state =
893893
max(State s, Location l |
894-
s = stateInRelevantRegexp() and
895894
isStartState(s) and
896895
getRoot(s.getRepr()) = root and
897896
l = s.getRepr().getLocation()
@@ -963,10 +962,13 @@ module PrefixConstruction<isCandidateSig/1 isCandidate> {
963962
min(string c | delta(prev, any(InputSymbol symbol | c = intersect(Any(), symbol)), next))
964963
}
965964

966-
/** Gets a state within a regular expression that contains a candidate state. */
967-
pragma[noinline]
968-
State stateInRelevantRegexp() {
969-
exists(State s | isCandidate(s) | getRoot(s.getRepr()) = getRoot(result.getRepr()))
965+
/** A state within a regular expression that contains a candidate state. */
966+
class RelevantState instanceof State {
967+
RelevantState() {
968+
exists(State s | isCandidate(s) | getRoot(s.getRepr()) = getRoot(this.getRepr()))
969+
}
970+
971+
string toString() { result = "RelevantState" }
970972
}
971973
}
972974

@@ -1007,6 +1009,8 @@ module ReDoSPruning<isCandidateSig/2 isCandidate> {
10071009

10081010
import PrefixConstruction<isCandidateState/1> as Prefix
10091011

1012+
class RelevantState = Prefix::RelevantState;
1013+
10101014
/**
10111015
* Predicates for testing the presence of a rejecting suffix.
10121016
*
@@ -1040,32 +1044,26 @@ module ReDoSPruning<isCandidateSig/2 isCandidate> {
10401044
* This predicate might find impossible suffixes when searching for suffixes of length > 1, which can cause FPs.
10411045
*/
10421046
pragma[noinline]
1043-
private predicate isLikelyRejectable(State s) {
1044-
s = Prefix::stateInRelevantRegexp() and
1045-
(
1046-
// exists a reject edge with some char.
1047-
hasRejectEdge(s)
1048-
or
1049-
hasEdgeToLikelyRejectable(s)
1050-
or
1051-
// stopping here is rejection
1052-
isRejectState(s)
1053-
)
1047+
private predicate isLikelyRejectable(RelevantState s) {
1048+
// exists a reject edge with some char.
1049+
hasRejectEdge(s)
1050+
or
1051+
hasEdgeToLikelyRejectable(s)
1052+
or
1053+
// stopping here is rejection
1054+
isRejectState(s)
10541055
}
10551056

10561057
/**
10571058
* Holds if `s` is not an accept state, and there is no epsilon transition to an accept state.
10581059
*/
1059-
predicate isRejectState(State s) {
1060-
s = Prefix::stateInRelevantRegexp() and not epsilonSucc*(s) = Accept(_)
1061-
}
1060+
predicate isRejectState(RelevantState s) { not epsilonSucc*(s) = Accept(_) }
10621061

10631062
/**
10641063
* Holds if there is likely a non-empty suffix leading to rejection starting in `s`.
10651064
*/
10661065
pragma[noopt]
1067-
predicate hasEdgeToLikelyRejectable(State s) {
1068-
s = Prefix::stateInRelevantRegexp() and
1066+
predicate hasEdgeToLikelyRejectable(RelevantState s) {
10691067
// all edges (at least one) with some char leads to another state that is rejectable.
10701068
// the `next` states might not share a common suffix, which can cause FPs.
10711069
exists(string char | char = hasEdgeToLikelyRejectableHelper(s) |
@@ -1080,8 +1078,7 @@ module ReDoSPruning<isCandidateSig/2 isCandidate> {
10801078
* and `s` has not been found to be rejectable by `hasRejectEdge` or `isRejectState`.
10811079
*/
10821080
pragma[noinline]
1083-
private string hasEdgeToLikelyRejectableHelper(State s) {
1084-
s = Prefix::stateInRelevantRegexp() and
1081+
private string hasEdgeToLikelyRejectableHelper(RelevantState s) {
10851082
not hasRejectEdge(s) and
10861083
not isRejectState(s) and
10871084
deltaClosedChar(s, result, _)
@@ -1092,9 +1089,7 @@ module ReDoSPruning<isCandidateSig/2 isCandidate> {
10921089
* along epsilon edges, such that there is a transition from
10931090
* `prev` to `next` that the character symbol `char`.
10941091
*/
1095-
predicate deltaClosedChar(State prev, string char, State next) {
1096-
prev = Prefix::stateInRelevantRegexp() and
1097-
next = Prefix::stateInRelevantRegexp() and
1092+
predicate deltaClosedChar(RelevantState prev, string char, RelevantState next) {
10981093
deltaClosed(prev, getAnInputSymbolMatchingRelevant(char), next)
10991094
}
11001095

python/ql/lib/semmle/python/security/regexp/NfaUtils.qll

Lines changed: 22 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -887,11 +887,10 @@ module PrefixConstruction<isCandidateSig/1 isCandidate> {
887887
/**
888888
* Holds if `state` is the textually last start state for the regular expression.
889889
*/
890-
private predicate lastStartState(State state) {
890+
private predicate lastStartState(RelevantState state) {
891891
exists(RegExpRoot root |
892892
state =
893893
max(State s, Location l |
894-
s = stateInRelevantRegexp() and
895894
isStartState(s) and
896895
getRoot(s.getRepr()) = root and
897896
l = s.getRepr().getLocation()
@@ -963,10 +962,13 @@ module PrefixConstruction<isCandidateSig/1 isCandidate> {
963962
min(string c | delta(prev, any(InputSymbol symbol | c = intersect(Any(), symbol)), next))
964963
}
965964

966-
/** Gets a state within a regular expression that contains a candidate state. */
967-
pragma[noinline]
968-
State stateInRelevantRegexp() {
969-
exists(State s | isCandidate(s) | getRoot(s.getRepr()) = getRoot(result.getRepr()))
965+
/** A state within a regular expression that contains a candidate state. */
966+
class RelevantState instanceof State {
967+
RelevantState() {
968+
exists(State s | isCandidate(s) | getRoot(s.getRepr()) = getRoot(this.getRepr()))
969+
}
970+
971+
string toString() { result = "RelevantState" }
970972
}
971973
}
972974

@@ -1007,6 +1009,8 @@ module ReDoSPruning<isCandidateSig/2 isCandidate> {
10071009

10081010
import PrefixConstruction<isCandidateState/1> as Prefix
10091011

1012+
class RelevantState = Prefix::RelevantState;
1013+
10101014
/**
10111015
* Predicates for testing the presence of a rejecting suffix.
10121016
*
@@ -1040,32 +1044,26 @@ module ReDoSPruning<isCandidateSig/2 isCandidate> {
10401044
* This predicate might find impossible suffixes when searching for suffixes of length > 1, which can cause FPs.
10411045
*/
10421046
pragma[noinline]
1043-
private predicate isLikelyRejectable(State s) {
1044-
s = Prefix::stateInRelevantRegexp() and
1045-
(
1046-
// exists a reject edge with some char.
1047-
hasRejectEdge(s)
1048-
or
1049-
hasEdgeToLikelyRejectable(s)
1050-
or
1051-
// stopping here is rejection
1052-
isRejectState(s)
1053-
)
1047+
private predicate isLikelyRejectable(RelevantState s) {
1048+
// exists a reject edge with some char.
1049+
hasRejectEdge(s)
1050+
or
1051+
hasEdgeToLikelyRejectable(s)
1052+
or
1053+
// stopping here is rejection
1054+
isRejectState(s)
10541055
}
10551056

10561057
/**
10571058
* Holds if `s` is not an accept state, and there is no epsilon transition to an accept state.
10581059
*/
1059-
predicate isRejectState(State s) {
1060-
s = Prefix::stateInRelevantRegexp() and not epsilonSucc*(s) = Accept(_)
1061-
}
1060+
predicate isRejectState(RelevantState s) { not epsilonSucc*(s) = Accept(_) }
10621061

10631062
/**
10641063
* Holds if there is likely a non-empty suffix leading to rejection starting in `s`.
10651064
*/
10661065
pragma[noopt]
1067-
predicate hasEdgeToLikelyRejectable(State s) {
1068-
s = Prefix::stateInRelevantRegexp() and
1066+
predicate hasEdgeToLikelyRejectable(RelevantState s) {
10691067
// all edges (at least one) with some char leads to another state that is rejectable.
10701068
// the `next` states might not share a common suffix, which can cause FPs.
10711069
exists(string char | char = hasEdgeToLikelyRejectableHelper(s) |
@@ -1080,8 +1078,7 @@ module ReDoSPruning<isCandidateSig/2 isCandidate> {
10801078
* and `s` has not been found to be rejectable by `hasRejectEdge` or `isRejectState`.
10811079
*/
10821080
pragma[noinline]
1083-
private string hasEdgeToLikelyRejectableHelper(State s) {
1084-
s = Prefix::stateInRelevantRegexp() and
1081+
private string hasEdgeToLikelyRejectableHelper(RelevantState s) {
10851082
not hasRejectEdge(s) and
10861083
not isRejectState(s) and
10871084
deltaClosedChar(s, result, _)
@@ -1092,9 +1089,7 @@ module ReDoSPruning<isCandidateSig/2 isCandidate> {
10921089
* along epsilon edges, such that there is a transition from
10931090
* `prev` to `next` that the character symbol `char`.
10941091
*/
1095-
predicate deltaClosedChar(State prev, string char, State next) {
1096-
prev = Prefix::stateInRelevantRegexp() and
1097-
next = Prefix::stateInRelevantRegexp() and
1092+
predicate deltaClosedChar(RelevantState prev, string char, RelevantState next) {
10981093
deltaClosed(prev, getAnInputSymbolMatchingRelevant(char), next)
10991094
}
11001095

0 commit comments

Comments
 (0)