allow eval-groups in patterns only if they C<use re 'eval';>
[p5sagit/p5-mst-13.2.git] / regcomp.c
index 45f1e9a..b18740c 100644 (file)
--- a/regcomp.c
+++ b/regcomp.c
@@ -93,7 +93,7 @@
  * Flags to be passed up and down.
  */
 #define        WORST           0       /* Worst case. */
-#define        HASWIDTH        0x1     /* Known never to match null string. */
+#define        HASWIDTH        0x1     /* Known to match non-null strings. */
 #define        SIMPLE          0x2     /* Simple enough to be STAR/PLUS operand. */
 #define        SPSTART         0x4     /* Starts with * or +. */
 #define TRYAGAIN       0x8     /* Weeded out a declaration. */
@@ -267,6 +267,10 @@ study_chunk(regnode **scanp, I32 *deltap, regnode *last, scan_data_t *data, U32
            /* Allow dumping */
            n = scan + (*OPERAND(scan) + 2 - 1)/sizeof(regnode) + 2;
            while (n <= stop) {
+               /* Purify reports a benign UMR here sometimes, because we
+                * don't initialize the OP() slot of a node when that node
+                * is occupied by just the trailing null of the string in
+                * an EXACT node */
                if (regkind[(U8)OP(n)] != NOTHING || OP(n) == NOTHING) {
                    OP(n) = OPTIMIZED;
                    NEXT_OFF(n) = 0;
@@ -421,7 +425,8 @@ study_chunk(regnode **scanp, I32 *deltap, regnode *last, scan_data_t *data, U32
                if (!scan)              /* It was not CURLYX, but CURLY. */
                    scan = next;
                if (dowarn && (minnext + deltanext == 0) 
-                   && !(data->flags & (SF_HAS_PAR|SF_IN_PAR))) 
+                   && !(data->flags & (SF_HAS_PAR|SF_IN_PAR))
+                   && maxcount <= 10000) /* Complement check for big count */
                    warn("Strange *+?{} on zero-length expression");
                min += minnext * mincount;
                is_inf |= (maxcount == REG_INFTY && (minnext + deltanext) > 0
@@ -760,6 +765,7 @@ pregcomp(char *exp, char *xend, PMOP *pm)
     r->prelen = xend - exp;
     r->precomp = regprecomp;
     r->subbeg = r->subbase = NULL;
+    r->nparens = regnpar - 1;          /* set early to validate backrefs */
     regcomp_rx = r;
 
     /* Second pass: emit code. */
@@ -931,7 +937,6 @@ pregcomp(char *exp, char *xend, PMOP *pm)
        r->check_substr = r->anchored_substr = r->float_substr = Nullsv;
     }
 
-    r->nparens = regnpar - 1;
     r->minlen = minlen;
     if (regseen & REG_SEEN_GPOS) 
        r->reganch |= ROPT_GPOS_SEEN;
@@ -966,7 +971,7 @@ reg(I32 paren, I32 *flagp)
     I32 flags, oregflags = regflags, have_branch = 0, open = 0;
     char c;
 
-    *flagp = HASWIDTH; /* Tentatively. */
+    *flagp = 0;                                /* Tentatively. */
 
     /* Make an OPEN node, if parenthesized. */
     if (paren) {
@@ -1038,6 +1043,13 @@ reg(I32 paren, I32 *flagp)
                    regcomp_rx->data->data[n+2] = (void*)sop;
                    SvREFCNT_dec(sv);
                } else {                /* First pass */
+                   if (curcop == &compiling) {
+                       if (!(hints & HINT_RE_EVAL))
+                           FAIL("Eval-group not allowed, use re 'eval'");
+                   }
+                   else {
+                       FAIL("Eval-group not allowed at run time");
+                   }
                    if (tainted)
                        FAIL("Eval-group in insecure regular expression");
                }
@@ -1140,8 +1152,8 @@ reg(I32 paren, I32 *flagp)
        regtail(ret, br);               /* OPEN -> first. */
     } else if (paren != '?')           /* Not Conditional */
        ret = br;
-    if (!(flags&HASWIDTH))
-       *flagp &= ~HASWIDTH;
+    if (flags&HASWIDTH)
+       *flagp |= HASWIDTH;
     *flagp |= flags&SPSTART;
     lastbr = br;
     while (*regcomp_parse == '|') {
@@ -1157,8 +1169,8 @@ reg(I32 paren, I32 *flagp)
            return(NULL);
        regtail(lastbr, br);            /* BRANCH -> BRANCH. */
        lastbr = br;
-       if (!(flags&HASWIDTH))
-           *flagp &= ~HASWIDTH;
+       if (flags&HASWIDTH)
+           *flagp |= HASWIDTH;
        *flagp |= flags&SPSTART;
     }
 
@@ -1172,12 +1184,13 @@ reg(I32 paren, I32 *flagp)
            ender = reganode(CLOSE, parno);
            break;
        case '<':
-       case '>':
        case ',':
        case '=':
        case '!':
-           ender = reg_node(SUCCEED);
            *flagp &= ~HASWIDTH;
+           /* FALL THROUGH */
+       case '>':
+           ender = reg_node(SUCCEED);
            break;
        case 0:
            ender = reg_node(END);
@@ -1368,7 +1381,9 @@ regpiece(I32 *flagp)
            ret->flags = 0;
 
            if (min > 0)
-               *flagp = (WORST|HASWIDTH);
+               *flagp = WORST;
+           if (max > 0)
+               *flagp |= HASWIDTH;
            if (max && max < min)
                FAIL("Can't do {n,m} with n > m");
            if (!SIZE_ONLY) {
@@ -1392,7 +1407,7 @@ regpiece(I32 *flagp)
 
     nextchar();
 
-    *flagp = (op != '+') ? (WORST|SPSTART) : (WORST|HASWIDTH);
+    *flagp = (op != '+') ? (WORST|SPSTART|HASWIDTH) : (WORST|HASWIDTH);
 
     if (op == '*' && (flags&SIMPLE)) {
        reginsert(STAR, ret);
@@ -1535,6 +1550,12 @@ tryagain:
            *flagp |= SIMPLE;
            nextchar();
            break;
+       case 'z':
+           ret = reg_node(EOS);
+           *flagp |= SIMPLE;
+           seen_zerolen++;             /* Do not optimize RE away */
+           nextchar();
+           break;
        case 'w':
            ret = reg_node((regflags & PMf_LOCALE) ? ALNUML : ALNUM);
            *flagp |= HASWIDTH|SIMPLE;
@@ -1595,6 +1616,8 @@ tryagain:
                if (num > 9 && num >= regnpar)
                    goto defchar;
                else {
+                   if (!SIZE_ONLY && num > regcomp_rx->nparens)
+                       FAIL("reference to nonexistent group");
                    regsawback = 1;
                    ret = reganode((regflags & PMf_FOLD)
                                   ? ((regflags & PMf_LOCALE) ? REFFL : REFF)
@@ -1661,6 +1684,7 @@ tryagain:
                    case 'A':
                    case 'G':
                    case 'Z':
+                   case 'z':
                    case 'w':
                    case 'W':
                    case 'b':
@@ -2325,6 +2349,9 @@ regprop(SV *sv, regnode *o)
     case EOL:
        p = "EOL";
        break;
+    case EOS:
+       p = "EOS";
+       break;
     case MEOL:
        p = "MEOL";
        break;