99 * Theorem 3 from the paper describes the basic idea.
1010 *
1111 * The following explains the idea using variables and predicate names that are used in the implementation:
12- * We consider a pair of repetitions, which we will call `pivot` and `succ `.
12+ * We consider a pair of repetitions, which we will call `pivot` and `pumpEnd `.
1313 *
1414 * We create a product automaton of 3-tuples of states (see `StateTuple`).
1515 * There exists a transition `(a,b,c) -> (d,e,f)` in the product automaton
1616 * iff there exists three transitions in the NFA `a->d, b->e, c->f` where those three
1717 * transitions all match a shared character `char`. (see `getAThreewayIntersect`)
1818 *
19- * We start a search in the product automaton at `(pivot, pivot, succ )`,
19+ * We start a search in the product automaton at `(pivot, pivot, pumpEnd )`,
2020 * and search for a series of transitions (a `Trace`), such that we end
21- * at `(pivot, succ, succ )` (see `isReachableFromStartTuple`).
21+ * at `(pivot, pumpEnd, pumpEnd )` (see `isReachableFromStartTuple`).
2222 *
2323 * For example, consider the regular expression `/^\d*5\w*$/`.
2424 * The search will start at the tuple `(\d*, \d*, \w*)` and search
@@ -52,7 +52,7 @@ module Make<RegexTreeViewSig TreeImpl> {
5252
5353 private newtype TStateTuple =
5454 MkStateTuple ( State q1 , State q2 , State q3 ) {
55- // starts at (pivot, pivot, succ )
55+ // starts at (pivot, pivot, pumpEnd )
5656 isStartLoops ( q1 , q3 ) and q1 = q2
5757 or
5858 step ( _, _, _, _, q1 , q2 , q3 ) and FeasibleTuple:: isFeasibleTuple ( q1 , q2 , q3 )
@@ -64,7 +64,7 @@ module Make<RegexTreeViewSig TreeImpl> {
6464 *
6565 * We lazily only construct those states that we are actually
6666 * going to need.
67- * Either a start state `(pivot, pivot, succ )`, or a state
67+ * Either a start state `(pivot, pivot, pumpEnd )`, or a state
6868 * where there exists a transition from an already existing state.
6969 *
7070 * The exponential variant of this query (`js/redos`) uses an optimization
@@ -108,9 +108,9 @@ module Make<RegexTreeViewSig TreeImpl> {
108108 // The states are reachable in the NFA in the order r1 -> r2 -> r3
109109 delta + ( r1 ) = r2 and
110110 delta + ( r2 ) = r3 and
111- // The first element can reach a beginning (the "pivot" state in a `(pivot, succ )` pair).
111+ // The first element can reach a beginning (the "pivot" state in a `(pivot, pumpEnd )` pair).
112112 canReachABeginning ( r1 ) and
113- // The last element can reach a target (the "succ " state in a `(pivot, succ )` pair).
113+ // The last element can reach a target (the "pumpEnd " state in a `(pivot, pumpEnd )` pair).
114114 canReachATarget ( r3 )
115115 }
116116
@@ -132,33 +132,33 @@ module Make<RegexTreeViewSig TreeImpl> {
132132
133133 /**
134134 * Holds if there exists a path in the NFA from `s` to a "pivot" state
135- * (from a `(pivot, succ )` pair that starts the search).
135+ * (from a `(pivot, pumpEnd )` pair that starts the search).
136136 */
137137 pragma [ noinline]
138138 private predicate canReachABeginning ( State s ) {
139139 delta + ( s ) = any ( State pivot | isStartLoops ( pivot , _) )
140140 }
141141
142142 /**
143- * Holds if there exists a path in the NFA from `s` to a "succ " state
144- * (from a `(pivot, succ )` pair that starts the search).
143+ * Holds if there exists a path in the NFA from `s` to a "pumpEnd " state
144+ * (from a `(pivot, pumpEnd )` pair that starts the search).
145145 */
146146 pragma [ noinline]
147147 private predicate canReachATarget ( State s ) {
148- delta + ( s ) = any ( State succ | isStartLoops ( _, succ ) )
148+ delta + ( s ) = any ( State pumpEnd | isStartLoops ( _, pumpEnd ) )
149149 }
150150 }
151151
152152 /**
153- * Holds if `pivot` and `succ ` are a pair of loops that could be the beginning of a quadratic blowup.
153+ * Holds if `pivot` and `pumpEnd ` are a pair of loops that could be the beginning of a quadratic blowup.
154154 *
155- * There is a slight implementation difference compared to the paper: this predicate requires that `pivot != succ `.
156- * The case where `pivot = succ ` causes exponential backtracking and is handled by the `js/redos` query.
155+ * There is a slight implementation difference compared to the paper: this predicate requires that `pivot != pumpEnd `.
156+ * The case where `pivot = pumpEnd ` causes exponential backtracking and is handled by the `js/redos` query.
157157 */
158- predicate isStartLoops ( State pivot , State succ ) {
159- pivot != succ and
160- succ .getRepr ( ) instanceof InfiniteRepetitionQuantifier and
161- delta + ( pivot ) = succ and
158+ predicate isStartLoops ( State pivot , State pumpEnd ) {
159+ pivot != pumpEnd and
160+ pumpEnd .getRepr ( ) instanceof InfiniteRepetitionQuantifier and
161+ delta + ( pivot ) = pumpEnd and
162162 (
163163 pivot .getRepr ( ) instanceof InfiniteRepetitionQuantifier
164164 or
@@ -296,7 +296,7 @@ module Make<RegexTreeViewSig TreeImpl> {
296296
297297 /**
298298 * Holds if `tuple` is an end state in our search.
299- * That means there exists a pair of loops `(pivot, succ )` such that `tuple = (pivot, succ, succ )`.
299+ * That means there exists a pair of loops `(pivot, pumpEnd )` such that `tuple = (pivot, pumpEnd, pumpEnd )`.
300300 */
301301 predicate isEndTuple ( StateTuple tuple ) { tuple = getAnEndTuple ( _, _) }
302302
@@ -311,45 +311,45 @@ module Make<RegexTreeViewSig TreeImpl> {
311311 shortestDistances( isEndTuple / 1 , tupleDeltaBackwards / 2 ) ( end , r , result )
312312
313313 /**
314- * Holds if there exists a pair of repetitions `(pivot, succ )` in the regular expression such that:
315- * `tuple` is reachable from `(pivot, pivot, succ )` in the product automaton,
316- * and there is a distance of `dist` from `tuple` to the nearest end-tuple `(pivot, succ, succ )`,
314+ * Holds if there exists a pair of repetitions `(pivot, pumpEnd )` in the regular expression such that:
315+ * `tuple` is reachable from `(pivot, pivot, pumpEnd )` in the product automaton,
316+ * and there is a distance of `dist` from `tuple` to the nearest end-tuple `(pivot, pumpEnd, pumpEnd )`,
317317 * and a path from a start-state to `tuple` follows the transitions in `trace`.
318318 */
319319 private predicate isReachableFromStartTuple (
320- State pivot , State succ , StateTuple tuple , Trace trace , int dist
320+ State pivot , State pumpEnd , StateTuple tuple , Trace trace , int dist
321321 ) {
322322 exists ( InputSymbol s1 , InputSymbol s2 , InputSymbol s3 , Trace v |
323- isReachableFromStartTuple ( pivot , succ , v , s1 , s2 , s3 , tuple , dist ) and
323+ isReachableFromStartTuple ( pivot , pumpEnd , v , s1 , s2 , s3 , tuple , dist ) and
324324 trace = Step ( s1 , s2 , s3 , v )
325325 )
326326 }
327327
328328 private predicate isReachableFromStartTuple (
329- State pivot , State succ , Trace trace , InputSymbol s1 , InputSymbol s2 , InputSymbol s3 ,
329+ State pivot , State pumpEnd , Trace trace , InputSymbol s1 , InputSymbol s2 , InputSymbol s3 ,
330330 StateTuple tuple , int dist
331331 ) {
332332 // base case.
333- isStartLoops ( pivot , succ ) and
334- step ( MkStateTuple ( pivot , pivot , succ ) , s1 , s2 , s3 , tuple ) and
333+ isStartLoops ( pivot , pumpEnd ) and
334+ step ( MkStateTuple ( pivot , pivot , pumpEnd ) , s1 , s2 , s3 , tuple ) and
335335 tuple = MkStateTuple ( _, _, _) and
336336 trace = Nil ( ) and
337- dist = distBackFromEnd ( tuple , MkStateTuple ( pivot , succ , succ ) )
337+ dist = distBackFromEnd ( tuple , MkStateTuple ( pivot , pumpEnd , pumpEnd ) )
338338 or
339339 // recursive case
340340 exists ( StateTuple p |
341- isReachableFromStartTuple ( pivot , succ , p , trace , dist + 1 ) and
342- dist = distBackFromEnd ( tuple , MkStateTuple ( pivot , succ , succ ) ) and
341+ isReachableFromStartTuple ( pivot , pumpEnd , p , trace , dist + 1 ) and
342+ dist = distBackFromEnd ( tuple , MkStateTuple ( pivot , pumpEnd , pumpEnd ) ) and
343343 step ( p , s1 , s2 , s3 , tuple )
344344 )
345345 }
346346
347347 /**
348- * Gets the tuple `(pivot, succ, succ )` from the product automaton.
348+ * Gets the tuple `(pivot, pumpEnd, pumpEnd )` from the product automaton.
349349 */
350- StateTuple getAnEndTuple ( State pivot , State succ ) {
351- isStartLoops ( pivot , succ ) and
352- result = MkStateTuple ( pivot , succ , succ )
350+ StateTuple getAnEndTuple ( State pivot , State pumpEnd ) {
351+ isStartLoops ( pivot , pumpEnd ) and
352+ result = MkStateTuple ( pivot , pumpEnd , pumpEnd )
353353 }
354354
355355 /** An implementation of a chain containing chars for use by `Concretizer`. */
@@ -360,8 +360,8 @@ module Make<RegexTreeViewSig TreeImpl> {
360360
361361 /** Holds if `n` is used in `isPumpable`. */
362362 predicate isARelevantEnd ( CharNode n ) {
363- exists ( State pivot , State succ |
364- isReachableFromStartTuple ( pivot , succ , getAnEndTuple ( pivot , succ ) , n , _)
363+ exists ( State pivot , State pumpEnd |
364+ isReachableFromStartTuple ( pivot , pumpEnd , getAnEndTuple ( pivot , pumpEnd ) , n , _)
365365 )
366366 }
367367
@@ -375,19 +375,19 @@ module Make<RegexTreeViewSig TreeImpl> {
375375 /**
376376 * Holds if matching repetitions of `pump` can:
377377 * 1) Transition from `pivot` back to `pivot`.
378- * 2) Transition from `pivot` to `succ `.
379- * 3) Transition from `succ ` to `succ `.
378+ * 2) Transition from `pivot` to `pumpEnd `.
379+ * 3) Transition from `pumpEnd ` to `pumpEnd `.
380380 *
381381 * From theorem 3 in the paper linked in the top of this file we can therefore conclude that
382382 * the regular expression has polynomial backtracking - if a rejecting suffix exists.
383383 *
384384 * This predicate is used by `SuperLinearReDoSConfiguration`, and the final results are
385385 * available in the `hasReDoSResult` predicate.
386386 */
387- predicate isPumpable ( State pivot , State succ , string pump ) {
387+ predicate isPumpable ( State pivot , State pumpEnd , string pump ) {
388388 exists ( StateTuple q , Trace t |
389- isReachableFromStartTuple ( pivot , succ , q , t , _) and
390- q = getAnEndTuple ( pivot , succ ) and
389+ isReachableFromStartTuple ( pivot , pumpEnd , q , t , _) and
390+ q = getAnEndTuple ( pivot , pumpEnd ) and
391391 pump = Concretizer< CharTreeImpl > :: concretize ( t )
392392 )
393393 }
@@ -439,8 +439,8 @@ module Make<RegexTreeViewSig TreeImpl> {
439439 * Holds if all non-empty successors to the polynomial backtracking term matches the end of the line.
440440 */
441441 predicate isAtEndLine ( ) {
442- forall ( RegExpTerm succ | super .getSuccessor + ( ) = succ and not matchesEpsilon ( succ ) |
443- succ instanceof RegExpDollar
442+ forall ( RegExpTerm pumpEnd | super .getSuccessor + ( ) = pumpEnd and not matchesEpsilon ( pumpEnd ) |
443+ pumpEnd instanceof RegExpDollar
444444 )
445445 }
446446
0 commit comments