Skip to content

Commit

Permalink
Fix RT #121321 - Fencepost error causes infinite loop in regex compil…
Browse files Browse the repository at this point in the history
…ation

Due to a fencepost error if a pattern had more than 9 capture buffers
and after the last capture buffer there was an octal style escape which
when interpreted as decimal evaluated to one more than the number of
defined buffers then the regex compiler would go into an infinite loop.

This fixes the fencepost error, adds tests, and adds some comments to
explain what is going on.
  • Loading branch information
demerphq committed Feb 25, 2014
1 parent 313e09e commit 845ab12
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 2 deletions.
12 changes: 10 additions & 2 deletions regcomp.c
Expand Up @@ -11542,11 +11542,15 @@ S_regatom(pTHX_ RExC_state_t *pRExC_state, I32 *flagp, U32 depth)
}
else {
num = S_backref_value(RExC_parse);
/* bare \NNN might be backref or octal */
/* bare \NNN might be backref or octal - if it is larger than or equal
* RExC_npar then it is assumed to be and octal escape.
* Note RExC_npar is +1 from the actual number of parens*/
if (num == I32_MAX || (num > 9 && num >= RExC_npar
&& *RExC_parse != '8' && *RExC_parse != '9'))
{
/* Probably a character specified in octal, e.g. \35 */
goto defchar;
}
}

/* at this point RExC_parse definitely points to a backref
Expand Down Expand Up @@ -11852,7 +11856,11 @@ S_regatom(pTHX_ RExC_state_t *pRExC_state, I32 *flagp, U32 depth)
* 118 OR as "\11" . "8" depending on whether there
* were 118 capture buffers defined already in the
* pattern. */
if ( !isDIGIT(p[1]) || S_backref_value(p) <= RExC_npar)

/* NOTE, RExC_npar is 1 more than the actual number of
* parens we have seen so far, hence the < RExC_npar below. */

if ( !isDIGIT(p[1]) || S_backref_value(p) < RExC_npar)
{ /* Not to be treated as an octal constant, go
find backref */
--p;
Expand Down
12 changes: 12 additions & 0 deletions t/re/re_tests
Expand Up @@ -1867,5 +1867,17 @@ A+(*PRUNE)BC(?{}) AAABC y $& AAABC
/^(.\1?)(?1)$/ aba y $1 a
/^ (\3(?2)\3)? ((.)) (?1) $/x aaba y $2 a
/^ (a|\3(?1)\2|(?2)) ((b|c)(?4)?) (?1) (d(?1)) $/x abbcdcabbda y $2 b

# RT #121321 - perl 5.19.10 infinite loops on backrefs > number of capture buffers (npar) where npar>9
/(a)\2/ a\2 c - Reference to nonexistent group in regex
/(a)(b)\3/ ab\3 c - Reference to nonexistent group in regex
/(a)(b)(c)\4/ abc\4 c - Reference to nonexistent group in regex
/(a)(b)(c)(d)\5/ abcd\5 c - Reference to nonexistent group in regex
/(a)(b)(c)(d)(e)\6/ abcde\6 c - Reference to nonexistent group in regex
/(a)(b)(c)(d)(e)(f)\7/ abcdef\7 c - Reference to nonexistent group in regex
/(a)(b)(c)(d)(e)(f)(g)(h)(i)\10/ abcdefghi\10 y $& abcdefghi\10
/(a)(b)(c)(d)(e)(f)(g)(h)(i)(j)\11/ abcdefghij\11 y $& abcdefghij\11
/(a)(b)(c)(d)(e)(f)(g)(h)(i)(j)(k)\12/ abcdefghijk\12 y $& abcdefghijk\12
/(a)(b)(c)(d)(e)(f)(g)(h)(i)(j)(k)\12\13\14/ abcdefghijk\12\13\14 y $& abcdefghijk\12\13\14
# Keep these lines at the end of the file
# vim: softtabstop=0 noexpandtab

0 comments on commit 845ab12

Please sign in to comment.