@@ -347,15 +347,11 @@ predicate isPumpable(State pivot, State succ, string pump) {
347347/**
348348 * Holds if repetitions of `pump` at `t` will cause polynomial backtracking.
349349 */
350- predicate polynimalReDoS ( RegExpTerm t , string msg ) {
351- exists ( string pump , State s , string prefixMsg |
350+ predicate polynimalReDoS ( RegExpTerm t , string pump , string prefixMsg , RegExpTerm prev ) {
351+ exists ( State s , State pivot |
352352 hasReDoSResult ( t , pump , s , prefixMsg ) and
353- exists ( State pivot |
354- isPumpable ( pivot , s , _) and
355- msg =
356- "Strings " + prefixMsg + "with many repetitions of '" + pump +
357- "' can start matching anywhere after the start of the preceeding " + pivot .getRepr ( )
358- )
353+ isPumpable ( pivot , s , _) and
354+ prev = pivot .getRepr ( )
359355 )
360356}
361357
@@ -388,17 +384,30 @@ private predicate matchesEpsilon(RegExpTerm t) {
388384 forex ( RegExpTerm child | child = t .( RegExpSequence ) .getAChild ( ) | matchesEpsilon ( child ) )
389385}
390386
387+ /**
388+ * Gets a message for why `term` can cause polynomial backtracking.
389+ */
390+ string getReasonString ( RegExpTerm term , string pump , string prefixMsg , RegExpTerm prev ) {
391+ polynimalReDoS ( term , pump , prefixMsg , prev ) and
392+ result =
393+ "Strings " + prefixMsg + "with many repetitions of '" + pump +
394+ "' can start matching anywhere after the start of the preceeding " + prev
395+ }
396+
391397/**
392398 * A term that may cause a regular expression engine to perform a
393399 * polynomial number of match attempts, relative to the input length.
394400 */
395401class PolynomialBackTrackingTerm extends InfiniteRepetitionQuantifier {
396402 string reason ;
403+ string pump ;
404+ string prefixMsg ;
405+ RegExpTerm prev ;
397406
398407 PolynomialBackTrackingTerm ( ) {
399- polynimalReDoS ( this , _ ) and
408+ reason = getReasonString ( this , pump , prefixMsg , prev ) and
400409 // there might be many reasons for this term to have polynomial backtracking - we pick an arbitary one.
401- reason = min ( string msg | polynimalReDoS ( this , msg ) )
410+ reason = min ( string msg | msg = getReasonString ( this , _ , _ , _ ) )
402411 }
403412
404413 /**
@@ -410,6 +419,21 @@ class PolynomialBackTrackingTerm extends InfiniteRepetitionQuantifier {
410419 )
411420 }
412421
422+ /**
423+ * Gets the string that should be repeated to cause this regular expression to perform polynomially.
424+ */
425+ string getPumpString ( ) { result = pump }
426+
427+ /**
428+ * Gets a message for which prefix a matching string must start with for this term to cause polynomial backtracking.
429+ */
430+ string getPrefixMessage ( ) { result = prefixMsg }
431+
432+ /**
433+ * Gets a predecessor to `this`, which also loops on the pump string, and thereby causes polynomial backtracking.
434+ */
435+ RegExpTerm getPreviousLoop ( ) { result = prev }
436+
413437 /**
414438 * Gets the reason for the number of match attempts.
415439 */
0 commit comments