fix RT#114068 optimizer handles MEOL in middle of pattern improperly
authorYves Orton <demerphq@gmail.com>
Wed, 11 Jul 2012 07:03:09 +0000 (09:03 +0200)
committerFather Chrysostomos <sprout@cpan.org>
Sat, 14 Jul 2012 03:10:43 +0000 (20:10 -0700)
It seems that under certain circumstances the optimiser handles the
MEOL operator (what $ turns into under /m), improperly including
things that follow. This results in compilation like this:

    Compiling REx "( [^z] $ [^z]+ )"
    Final program:
        1: OPEN1 (3)
        3:   ANYOF[\x00-y{-\xff][{unicode}0100-INFINITY] (14)
       14:   MEOL (15)
       15:   PLUS (27)
       16:     ANYOF[\x00-y{-\xff][{unicode}0100-INFINITY] (0)
       27: CLOSE1 (29)
       29: END (0)
    anchored ""$ at 2 stclass ANYOF[\x00-y{-\xff][{unicode}0100-INFINITY]

Where the '""$ at 2' is sign of the bug. The problem is that the optimiser
does not "commit" the string when it encounters an MEOL, which means that
text that follows it is included. This has probably always been wrong as
$ is a multichar pattern (it matches before an \n or including an \n). This
failure to commit then interacts with the implementation for PLUS leading to
an incorrect offset. By adding a SCAN_COMMIT() as part of the optimisers
handling of EOL constructs this problem is avoided. Note that most uses of
$ were ok due to other reasons.

regcomp.c
t/re/re_tests

index 8889ef1..f9dc26c 100644 (file)
--- a/regcomp.c
+++ b/regcomp.c
@@ -4404,6 +4404,8 @@ S_study_chunk(pTHX_ RExC_state_t *pRExC_state, regnode **scanp,
            data->flags |= (OP(scan) == MEOL
                            ? SF_BEFORE_MEOL
                            : SF_BEFORE_SEOL);
+           SCAN_COMMIT(pRExC_state, data, minlenp);
+
        }
        else if (  PL_regkind[OP(scan)] == BRANCHJ
                 /* Lookbehind, or need to calculate parens/evals/stclass: */
index 318ef89..83bc235 100644 (file)
@@ -1680,4 +1680,6 @@ ab[c\\\](??{"x"})]{3}d    ab\\](d y       -       -
 
 # rt 113770
 \A(?>\[(?:(?:)(?:R){1}|T|V?|A)\])\z    [A]     y       $&      [A]
+# rt 114068
+/( [^z] $ [^z]+)/xm    aa\nbb\ncc\n    y       $1      a\nbb\ncc\n
 # vim: softtabstop=0 noexpandtab