From 845ab12d77c07580053486e445977dc895d747f8 Mon Sep 17 00:00:00 2001 From: Yves Orton Date: Tue, 25 Feb 2014 12:07:18 +0100 Subject: [PATCH] Fix RT #121321 - Fencepost error causes infinite loop in regex compilation 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. --- regcomp.c | 12 ++++++++++-- t/re/re_tests | 12 ++++++++++++ 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/regcomp.c b/regcomp.c index ea9f42b..85077e6 100644 --- a/regcomp.c +++ b/regcomp.c @@ -11542,11 +11542,15 @@ tryagain: } 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 @@ -11852,7 +11856,11 @@ tryagain: * 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; diff --git a/t/re/re_tests b/t/re/re_tests index ab867f5..44e94c7 100644 --- a/t/re/re_tests +++ b/t/re/re_tests @@ -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 -- 2.7.4