9
9
* Theorem 3 from the paper describes the basic idea.
10
10
*
11
11
* 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 `.
13
13
*
14
14
* We create a product automaton of 3-tuples of states (see `StateTuple`).
15
15
* There exists a transition `(a,b,c) -> (d,e,f)` in the product automaton
16
16
* iff there exists three transitions in the NFA `a->d, b->e, c->f` where those three
17
17
* transitions all match a shared character `char`. (see `getAThreewayIntersect`)
18
18
*
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 )`,
20
20
* 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`).
22
22
*
23
23
* For example, consider the regular expression `/^\d*5\w*$/`.
24
24
* The search will start at the tuple `(\d*, \d*, \w*)` and search
@@ -52,7 +52,7 @@ module Make<RegexTreeViewSig TreeImpl> {
52
52
53
53
private newtype TStateTuple =
54
54
MkStateTuple ( State q1 , State q2 , State q3 ) {
55
- // starts at (pivot, pivot, succ )
55
+ // starts at (pivot, pivot, pumpEnd )
56
56
isStartLoops ( q1 , q3 ) and q1 = q2
57
57
or
58
58
step ( _, _, _, _, q1 , q2 , q3 ) and FeasibleTuple:: isFeasibleTuple ( q1 , q2 , q3 )
@@ -64,7 +64,7 @@ module Make<RegexTreeViewSig TreeImpl> {
64
64
*
65
65
* We lazily only construct those states that we are actually
66
66
* 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
68
68
* where there exists a transition from an already existing state.
69
69
*
70
70
* The exponential variant of this query (`js/redos`) uses an optimization
@@ -108,9 +108,9 @@ module Make<RegexTreeViewSig TreeImpl> {
108
108
// The states are reachable in the NFA in the order r1 -> r2 -> r3
109
109
delta + ( r1 ) = r2 and
110
110
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).
112
112
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).
114
114
canReachATarget ( r3 )
115
115
}
116
116
@@ -132,33 +132,33 @@ module Make<RegexTreeViewSig TreeImpl> {
132
132
133
133
/**
134
134
* 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).
136
136
*/
137
137
pragma [ noinline]
138
138
private predicate canReachABeginning ( State s ) {
139
139
delta + ( s ) = any ( State pivot | isStartLoops ( pivot , _) )
140
140
}
141
141
142
142
/**
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).
145
145
*/
146
146
pragma [ noinline]
147
147
private predicate canReachATarget ( State s ) {
148
- delta + ( s ) = any ( State succ | isStartLoops ( _, succ ) )
148
+ delta + ( s ) = any ( State pumpEnd | isStartLoops ( _, pumpEnd ) )
149
149
}
150
150
}
151
151
152
152
/**
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.
154
154
*
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.
157
157
*/
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
162
162
(
163
163
pivot .getRepr ( ) instanceof InfiniteRepetitionQuantifier
164
164
or
@@ -296,7 +296,7 @@ module Make<RegexTreeViewSig TreeImpl> {
296
296
297
297
/**
298
298
* 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 )`.
300
300
*/
301
301
predicate isEndTuple ( StateTuple tuple ) { tuple = getAnEndTuple ( _, _) }
302
302
@@ -311,45 +311,45 @@ module Make<RegexTreeViewSig TreeImpl> {
311
311
shortestDistances( isEndTuple / 1 , tupleDeltaBackwards / 2 ) ( end , r , result )
312
312
313
313
/**
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 )`,
317
317
* and a path from a start-state to `tuple` follows the transitions in `trace`.
318
318
*/
319
319
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
321
321
) {
322
322
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
324
324
trace = Step ( s1 , s2 , s3 , v )
325
325
)
326
326
}
327
327
328
328
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 ,
330
330
StateTuple tuple , int dist
331
331
) {
332
332
// 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
335
335
tuple = MkStateTuple ( _, _, _) and
336
336
trace = Nil ( ) and
337
- dist = distBackFromEnd ( tuple , MkStateTuple ( pivot , succ , succ ) )
337
+ dist = distBackFromEnd ( tuple , MkStateTuple ( pivot , pumpEnd , pumpEnd ) )
338
338
or
339
339
// recursive case
340
340
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
343
343
step ( p , s1 , s2 , s3 , tuple )
344
344
)
345
345
}
346
346
347
347
/**
348
- * Gets the tuple `(pivot, succ, succ )` from the product automaton.
348
+ * Gets the tuple `(pivot, pumpEnd, pumpEnd )` from the product automaton.
349
349
*/
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 )
353
353
}
354
354
355
355
/** An implementation of a chain containing chars for use by `Concretizer`. */
@@ -360,8 +360,8 @@ module Make<RegexTreeViewSig TreeImpl> {
360
360
361
361
/** Holds if `n` is used in `isPumpable`. */
362
362
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 , _)
365
365
)
366
366
}
367
367
@@ -375,19 +375,19 @@ module Make<RegexTreeViewSig TreeImpl> {
375
375
/**
376
376
* Holds if matching repetitions of `pump` can:
377
377
* 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 `.
380
380
*
381
381
* From theorem 3 in the paper linked in the top of this file we can therefore conclude that
382
382
* the regular expression has polynomial backtracking - if a rejecting suffix exists.
383
383
*
384
384
* This predicate is used by `SuperLinearReDoSConfiguration`, and the final results are
385
385
* available in the `hasReDoSResult` predicate.
386
386
*/
387
- predicate isPumpable ( State pivot , State succ , string pump ) {
387
+ predicate isPumpable ( State pivot , State pumpEnd , string pump ) {
388
388
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
391
391
pump = Concretizer< CharTreeImpl > :: concretize ( t )
392
392
)
393
393
}
@@ -439,8 +439,8 @@ module Make<RegexTreeViewSig TreeImpl> {
439
439
* Holds if all non-empty successors to the polynomial backtracking term matches the end of the line.
440
440
*/
441
441
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
444
444
)
445
445
}
446
446
0 commit comments