In perl.git, the branch blead has been updated <http://perl5.git.perl.org/perl.git/commitdiff/da7cf1cc7cedc01f35ceb6724e8260c3b0ee0d12?hp=e1e9e450cffebeb6cd494b47723b965a2d44f10b>
- Log ----------------------------------------------------------------- commit da7cf1cc7cedc01f35ceb6724e8260c3b0ee0d12 Author: Yves Orton <[email protected]> Date: Tue May 10 09:44:31 2016 +0200 fix #128109 - do not move RExC_open_parens[0] in reginsert In d5a00e4af6b155495be31a35728b8fef8e671ebe I merged GOSUB and GOSTART, part of which involved making RExC_open_parens[0] refer to the start of the pattern, and RExC_close_parens[0] referring to the end of the pattern. This tripped up in reginsert in a subtle way, the start of the pattern cannot and should not move in reginsert(). Unlike a paren that might be at the start of the pattern which should move when something is inserted in front of it, the start is a fixed point and should never move. This patches fixes this up, and adds an assert to check that reginsert() is not called once study_chunk() starts, as reginsert() does not adjust RExC_recurse. This was noticed by hv while debugging [perl #128085], thanks hugo! M regcomp.c commit 1bda7a749022793a1a7ec1719cdd3d5b12feba7a Author: Yves Orton <[email protected]> Date: Mon May 9 08:52:16 2016 +0200 fix #128085 - SIGSEGV in S_regmatch with S_study_chunk: Assertion "!frame" failed. The goto target should have been before the if (frame) block. Clearly this code is not well tested in our test suite. This patch does NOT include tests. M regcomp.c ----------------------------------------------------------------------- Summary of changes: regcomp.c | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/regcomp.c b/regcomp.c index 36626e3..e6b352b 100644 --- a/regcomp.c +++ b/regcomp.c @@ -222,6 +222,7 @@ struct RExC_state_t { #endif bool seen_unfolded_sharp_s; bool strict; + bool study_started; }; #define RExC_flags (pRExC_state->flags) @@ -288,6 +289,7 @@ struct RExC_state_t { #define RExC_frame_last (pRExC_state->frame_last) #define RExC_frame_count (pRExC_state->frame_count) #define RExC_strict (pRExC_state->strict) +#define RExC_study_started (pRExC_state->study_started) /* Heuristic check on the complexity of the pattern: if TOO_NAUGHTY, we set * a flag to disable back-off on the fixed/floating substrings - if it's @@ -4102,6 +4104,7 @@ S_study_chunk(pTHX_ RExC_state_t *pRExC_state, regnode **scanp, GET_RE_DEBUG_FLAGS_DECL; PERL_ARGS_ASSERT_STUDY_CHUNK; + RExC_study_started= 1; if ( depth == 0 ) { @@ -5899,15 +5902,10 @@ Perl_re_printf( aTHX_ "LHS=%"UVuf" RHS=%"UVuf"\n", /* Else: zero-length, ignore. */ scan = regnext(scan); } - /* If we are exiting a recursion we can unset its recursed bit - * and allow ourselves to enter it again - no danger of an - * infinite loop there. - if (stopparen > -1 && recursed) { - DEBUG_STUDYDATA("unset:", data,depth); - PAREN_UNSET( recursed, stopparen); - } - */ + + finish: if (frame) { + /* we need to unwind recursion. */ depth = depth - 1; DEBUG_STUDYDATA("frame-end:",data,depth); @@ -5924,7 +5922,6 @@ Perl_re_printf( aTHX_ "LHS=%"UVuf" RHS=%"UVuf"\n", goto fake_study_recurse; } - finish: assert(!frame); DEBUG_STUDYDATA("pre-fin:",data,depth); @@ -6883,6 +6880,7 @@ Perl_re_op_compile(pTHX_ SV ** const patternp, int pat_count, RExC_contains_locale = 0; RExC_contains_i = 0; RExC_strict = cBOOL(pm_flags & RXf_PMf_STRICT); + RExC_study_started = 0; pRExC_state->runtime_code_qr = NULL; RExC_frame_head= NULL; RExC_frame_last= NULL; @@ -18241,7 +18239,9 @@ S_reginsert(pTHX_ RExC_state_t *pRExC_state, U8 op, regnode *opnd, U32 depth) RExC_size += size; return; } - + assert(!RExC_study_started); /* I believe we should never use reginsert once we have started + studying. If this is wrong then we need to adjust RExC_recurse + below like we do with RExC_open_parens/RExC_close_parens. */ src = RExC_emit; RExC_emit += size; dst = RExC_emit; @@ -18252,7 +18252,10 @@ S_reginsert(pTHX_ RExC_state_t *pRExC_state, U8 op, regnode *opnd, U32 depth) * iow it is 1 more than the number of parens seen in * the pattern so far. */ for ( paren=0 ; paren < RExC_npar ; paren++ ) { - if ( RExC_open_parens[paren] >= opnd ) { + /* note, RExC_open_parens[0] is the start of the + * regex, it can't move. RExC_close_parens[0] is the end + * of the regex, it *can* move. */ + if ( paren && RExC_open_parens[paren] >= opnd ) { /*DEBUG_PARSE_FMT("open"," - %d",size);*/ RExC_open_parens[paren] += size; } else { -- Perl5 Master Repository
