X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=regcomp.c;h=0872c2ca8c50ebf44e33a8a1afc29708eecd67c2;hb=2680586ee66b8de4d2b5f26a2013220f2bec9d5f;hp=2f39b279d84f79b0297bf5498225ecc2dc2dba59;hpb=54b6e2faa887aa86b7b0c280adebcdc0f0804c55;p=p5sagit%2Fp5-mst-13.2.git diff --git a/regcomp.c b/regcomp.c index 2f39b27..0872c2c 100644 --- a/regcomp.c +++ b/regcomp.c @@ -146,6 +146,8 @@ static void regtail _((regnode *, regnode *)); static char* regwhite _((char *, char *)); static char* nextchar _((void)); static void re_croak2 _((const char* pat1,const char* pat2,...)) __attribute__((noreturn)); +static char* regpposixcc _((I32 value)); +static void clear_re _((void *r)); #endif /* Length of a variant. */ @@ -170,7 +172,8 @@ typedef struct { } scan_data_t; #endif -static scan_data_t zero_scan_data = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; +static scan_data_t zero_scan_data = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0 }; #define SF_BEFORE_EOL (SF_BEFORE_SEOL|SF_BEFORE_MEOL) #define SF_BEFORE_SEOL 0x1 @@ -206,6 +209,12 @@ static scan_data_t zero_scan_data = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; #define CHR_DIST(a,b) (UTF ? utf8_distance(a,b) : a - b) STATIC void +clear_re(void *r) +{ + ReREFCNT_dec((regexp *)r); +} + +STATIC void scan_commit(scan_data_t *data) { dTHR; @@ -776,7 +785,7 @@ reginitcolors(void) PL_colors[i] = ++s; } else - PL_colors[i] = ""; + PL_colors[i] = s = ""; } } else { while (i < 6) @@ -867,7 +876,12 @@ pregcomp(char *exp, char *xend, PMOP *pm) r->prelen = xend - exp; r->precomp = PL_regprecomp; r->subbeg = r->subbase = NULL; - r->nparens = PL_regnpar - 1; /* set early to validate backrefs */ + r->nparens = PL_regnpar - 1; /* set early to validate backrefs */ + + r->substrs = 0; /* Useful during FAIL. */ + r->startp = 0; /* Useful during FAIL. */ + r->endp = 0; /* Useful during FAIL. */ + PL_regcomp_rx = r; /* Second pass: emit code. */ @@ -1158,10 +1172,10 @@ reg(I32 paren, I32 *flagp) rop = sv_compile_2op(sv, &sop, "re", &av); - n = add_data(3, "nso"); + n = add_data(3, "nop"); PL_regcomp_rx->data->data[n] = (void*)rop; - PL_regcomp_rx->data->data[n+1] = (void*)av; - PL_regcomp_rx->data->data[n+2] = (void*)sop; + PL_regcomp_rx->data->data[n+1] = (void*)sop; + PL_regcomp_rx->data->data[n+2] = (void*)av; SvREFCNT_dec(sv); } else { /* First pass */ @@ -1377,8 +1391,11 @@ reg(I32 paren, I32 *flagp) } /* Check for proper termination. */ - if (paren && (PL_regcomp_parse >= PL_regxend || *nextchar() != ')')) { - FAIL("unmatched () in regexp"); + if (paren) { + PL_regflags = oregflags; + if (PL_regcomp_parse >= PL_regxend || *nextchar() != ')') { + FAIL("unmatched () in regexp"); + } } else if (!paren && PL_regcomp_parse < PL_regxend) { if (*PL_regcomp_parse == ')') { @@ -1388,9 +1405,6 @@ reg(I32 paren, I32 *flagp) FAIL("junk on end of regexp"); /* "Can't happen". */ /* NOTREACHED */ } - if (paren != 0) { - PL_regflags = oregflags; - } return(ret); } @@ -1764,6 +1778,7 @@ tryagain: break; case 'b': PL_seen_zerolen++; + PL_regseen |= REG_SEEN_LOOKBEHIND; ret = reg_node( UTF ? (LOC ? BOUNDLUTF8 : BOUNDUTF8) @@ -1775,6 +1790,7 @@ tryagain: break; case 'B': PL_seen_zerolen++; + PL_regseen |= REG_SEEN_LOOKBEHIND; ret = reg_node( UTF ? (LOC ? NBOUNDLUTF8 : NBOUNDUTF8) @@ -1878,6 +1894,8 @@ tryagain: FAIL("trailing \\ in regexp"); /* FALL THROUGH */ default: + /* Do not generate `unrecognized' warnings here, we fall + back into the quick-grab loop below */ goto defchar; } break; @@ -2008,6 +2026,11 @@ tryagain: FAIL("trailing \\ in regexp"); /* FALL THROUGH */ default: + if (!SIZE_ONLY && ckWARN(WARN_UNSAFE) && isALPHA(*p)) + warner(WARN_UNSAFE, + "/%.127s/: Unrecognized escape \\%c passed through", + PL_regprecomp, + *p); goto normal_default; } break; @@ -2097,6 +2120,7 @@ regwhite(char *p, char *e) STATIC char* regpposixcc(I32 value) { + dTHR; char *posixcc = 0; if (value == '[' && PL_regcomp_parse + 1 < PL_regxend && @@ -3100,13 +3124,30 @@ pregfree(struct regexp *r) } if (r->data) { int n = r->data->count; + AV* new_comppad = NULL; + AV* old_comppad; + SV** old_curpad; + while (--n >= 0) { switch (r->data->what[n]) { case 's': SvREFCNT_dec((SV*)r->data->data[n]); break; + case 'p': + new_comppad = (AV*)r->data->data[n]; + break; case 'o': + if (new_comppad == NULL) + croak("panic: pregfree comppad"); + old_comppad = PL_comppad; + old_curpad = PL_curpad; + PL_comppad = new_comppad; + PL_curpad = AvARRAY(new_comppad); op_free((OP_4tree*)r->data->data[n]); + PL_comppad = old_comppad; + PL_curpad = old_curpad; + SvREFCNT_dec((SV*)new_comppad); + new_comppad = NULL; break; case 'n': break;