* 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. */
/* 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;
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
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. */
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;
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) {
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");
}
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 == '|') {
return(NULL);
regtail(lastbr, br); /* BRANCH -> BRANCH. */
lastbr = br;
- if (!(flags&HASWIDTH))
- *flagp &= ~HASWIDTH;
+ if (flags&HASWIDTH)
+ *flagp |= HASWIDTH;
*flagp |= flags&SPSTART;
}
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);
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) {
nextchar();
- *flagp = (op != '+') ? (WORST|SPSTART) : (WORST|HASWIDTH);
+ *flagp = (op != '+') ? (WORST|SPSTART|HASWIDTH) : (WORST|HASWIDTH);
if (op == '*' && (flags&SIMPLE)) {
reginsert(STAR, ret);
*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;
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)
case 'A':
case 'G':
case 'Z':
+ case 'z':
case 'w':
case 'W':
case 'b':
case EOL:
p = "EOL";
break;
+ case EOS:
+ p = "EOS";
+ break;
case MEOL:
p = "MEOL";
break;