From: Jarkko Hietaniemi Date: Wed, 11 Apr 2001 02:54:39 +0000 (+0000) Subject: Integrate changes #9675,9676 from maintperl into mainline. X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=b8ef571c47de93e867861f93a04f9c8d328bd473;p=p5sagit%2Fp5-mst-13.2.git Integrate changes #9675,9676 from maintperl into mainline. fix for bug 20010410.006, undo change#7115 port the OpenBSD glob() security patch p4raw-link: @9676 on //depot/maint-5.6/perl: 3f3c3e312f619efa81ad88565a24e92f15dff662 p4raw-link: @9675 on //depot/maint-5.6/perl: c84593816ace2807d5ff27bb0745a28ec29187b1 p4raw-link: @7115 on //depot/perl: 5675c1a6395a0842c857fc8de159747577df6c4b p4raw-id: //depot/perl@9677 p4raw-integrated: from //depot/maint-5.6/perl@9672 'copy in' ext/File/Glob/bsd_glob.h (@9264..) ext/File/Glob/bsd_glob.c (@9512..) ext/File/Glob/Glob.xs (@9545..) 'merge in' t/op/pat.t (@9138..) regexec.c (@9288..) ext/File/Glob/Glob.pm (@9512..) --- diff --git a/ext/File/Glob/Glob.pm b/ext/File/Glob/Glob.pm index b843a16..a9ba2e5 100644 --- a/ext/File/Glob/Glob.pm +++ b/ext/File/Glob/Glob.pm @@ -22,6 +22,7 @@ use XSLoader (); GLOB_CSH GLOB_ERR GLOB_ERROR + GLOB_LIMIT GLOB_MARK GLOB_NOCASE GLOB_NOCHECK @@ -41,6 +42,7 @@ use XSLoader (); GLOB_CSH GLOB_ERR GLOB_ERROR + GLOB_LIMIT GLOB_MARK GLOB_NOCASE GLOB_NOCHECK @@ -242,6 +244,15 @@ The POSIX defined flags for bsd_glob() are: Force bsd_glob() to return an error when it encounters a directory it cannot open or read. Ordinarily bsd_glob() continues to find matches. +=item C + +Make bsd_glob() return an error (GLOB_NOSPACE) when the pattern expands +to a size bigger than the system constant C (usually found in +limits.h). If your system does not define this constant, bsd_glob() uses +C or C<_POSIX_ARG_MAX> where available (in that +order). You can inspect these values using the standard C +extension. + =item C Each pathname that is a directory that matches the pattern has a slash diff --git a/ext/File/Glob/Glob.xs b/ext/File/Glob/Glob.xs index ee8c0c9..ce03ef8 100644 --- a/ext/File/Glob/Glob.xs +++ b/ext/File/Glob/Glob.xs @@ -69,6 +69,12 @@ constant(char *name, int arg) case 'K': break; case 'L': + if (strEQ(name, "GLOB_LIMIT")) +#ifdef GLOB_LIMIT + return GLOB_LIMIT; +#else + goto not_there; +#endif break; case 'M': if (strEQ(name, "GLOB_MARK")) diff --git a/ext/File/Glob/bsd_glob.c b/ext/File/Glob/bsd_glob.c index 15ee659..47e96d6 100644 --- a/ext/File/Glob/bsd_glob.c +++ b/ext/File/Glob/bsd_glob.c @@ -87,6 +87,26 @@ static char sccsid[] = "@(#)glob.c 8.3 (Berkeley) 10/13/93"; # endif #endif +#ifdef I_LIMITS +#include +#endif + +#ifndef ARG_MAX +# ifdef _SC_ARG_MAX +# define ARG_MAX (sysconf(_SC_ARG_MAX)) +# else +# ifdef _POSIX_ARG_MAX +# define ARG_MAX _POSIX_ARG_MAX +# else +# ifdef WIN32 +# define ARG_MAX 14500 /* from VC's limits.h */ +# else +# define ARG_MAX 4096 /* from POSIX, be conservative */ +# endif +# endif +# endif +#endif + #define BG_DOLLAR '$' #define BG_DOT '.' #define BG_EOS '\0' @@ -146,20 +166,20 @@ typedef U8 Char; static int compare(const void *, const void *); static int ci_compare(const void *, const void *); -static void g_Ctoc(const Char *, char *); +static int g_Ctoc(const Char *, char *, STRLEN); static int g_lstat(Char *, Stat_t *, glob_t *); static DIR *g_opendir(Char *, glob_t *); static Char *g_strchr(Char *, int); -#ifdef notdef -static Char *g_strcat(Char *, const Char *); -#endif static int g_stat(Char *, Stat_t *, glob_t *); static int glob0(const Char *, glob_t *); -static int glob1(Char *, glob_t *); -static int glob2(Char *, Char *, Char *, glob_t *); -static int glob3(Char *, Char *, Char *, Char *, glob_t *); -static int globextend(const Char *, glob_t *); -static const Char * globtilde(const Char *, Char *, glob_t *); +static int glob1(Char *, Char *, glob_t *, size_t *); +static int glob2(Char *, Char *, Char *, Char *, Char *, Char *, + glob_t *, size_t *); +static int glob3(Char *, Char *, Char *, Char *, Char *, Char *, + Char *, Char *, glob_t *, size_t *); +static int globextend(const Char *, glob_t *, size_t *); +static const Char * + globtilde(const Char *, Char *, size_t, glob_t *); static int globexp1(const Char *, glob_t *); static int globexp2(const Char *, const Char *, glob_t *, int *); static int match(Char *, Char *, Char *, int); @@ -185,7 +205,7 @@ bsd_glob(const char *pattern, int flags, { const U8 *patnext; int c; - Char *bufnext, *bufend, patbuf[MAXPATHLEN+1]; + Char *bufnext, *bufend, patbuf[MAXPATHLEN]; patnext = (U8 *) pattern; if (!(flags & GLOB_APPEND)) { @@ -199,7 +219,7 @@ bsd_glob(const char *pattern, int flags, pglob->gl_matchc = 0; bufnext = patbuf; - bufend = bufnext + MAXPATHLEN; + bufend = bufnext + MAXPATHLEN - 1; #ifdef DOSISH /* Nasty hack to treat patterns like "C:*" correctly. In this * case, the * should match any file in the current directory @@ -239,13 +259,11 @@ bsd_glob(const char *pattern, int flags, --patnext; } *bufnext++ = c | M_PROTECT; - } - else + } else *bufnext++ = c; - } - else - while (bufnext < bufend && (c = *patnext++) != BG_EOS) - *bufnext++ = c; + } else + while (bufnext < bufend && (c = *patnext++) != BG_EOS) + *bufnext++ = c; *bufnext = BG_EOS; if (flags & GLOB_BRACE) @@ -259,7 +277,8 @@ bsd_glob(const char *pattern, int flags, * invoke the standard globbing routine to glob the rest of the magic * characters */ -static int globexp1(const Char *pattern, glob_t *pglob) +static int +globexp1(const Char *pattern, glob_t *pglob) { const Char* ptr = pattern; int rv; @@ -281,17 +300,19 @@ static int globexp1(const Char *pattern, glob_t *pglob) * If it succeeds then it invokes globexp1 with the new pattern. * If it fails then it tries to glob the rest of the pattern and returns. */ -static int globexp2(const Char *ptr, const Char *pattern, - glob_t *pglob, int *rv) +static int +globexp2(const Char *ptr, const Char *pattern, + glob_t *pglob, int *rv) { int i; Char *lm, *ls; const Char *pe, *pm, *pl; - Char patbuf[MAXPATHLEN + 1]; + Char patbuf[MAXPATHLEN]; /* copy part up to the brace */ for (lm = patbuf, pm = pattern; pm != ptr; *lm++ = *pm++) - continue; + ; + *lm = BG_EOS; ls = lm; /* Find the balanced brace */ @@ -299,7 +320,7 @@ static int globexp2(const Char *ptr, const Char *pattern, if (*pe == BG_LBRACKET) { /* Ignore everything between [] */ for (pm = pe++; *pe != BG_RBRACKET && *pe != BG_EOS; pe++) - continue; + ; if (*pe == BG_EOS) { /* * We could not find a matching BG_RBRACKET. @@ -307,8 +328,7 @@ static int globexp2(const Char *ptr, const Char *pattern, */ pe = pm; } - } - else if (*pe == BG_LBRACE) + } else if (*pe == BG_LBRACE) i++; else if (*pe == BG_RBRACE) { if (i == 0) @@ -322,12 +342,12 @@ static int globexp2(const Char *ptr, const Char *pattern, return 0; } - for (i = 0, pl = pm = ptr; pm <= pe; pm++) + for (i = 0, pl = pm = ptr; pm <= pe; pm++) { switch (*pm) { case BG_LBRACKET: /* Ignore everything between [] */ for (pl = pm++; *pm != BG_RBRACKET && *pm != BG_EOS; pm++) - continue; + ; if (*pm == BG_EOS) { /* * We could not find a matching BG_RBRACKET. @@ -343,8 +363,8 @@ static int globexp2(const Char *ptr, const Char *pattern, case BG_RBRACE: if (i) { - i--; - break; + i--; + break; } /* FALLTHROUGH */ case BG_COMMA: @@ -353,13 +373,14 @@ static int globexp2(const Char *ptr, const Char *pattern, else { /* Append the current string */ for (lm = ls; (pl < pm); *lm++ = *pl++) - continue; + ; + /* * Append the rest of the pattern after the * closing brace */ - for (pl = pe + 1; (*lm++ = *pl++) != BG_EOS;) - continue; + for (pl = pe + 1; (*lm++ = *pl++) != BG_EOS; ) + ; /* Expand the current pattern */ #ifdef GLOB_DEBUG @@ -375,6 +396,7 @@ static int globexp2(const Char *ptr, const Char *pattern, default: break; } + } *rv = 0; return 0; } @@ -385,7 +407,7 @@ static int globexp2(const Char *ptr, const Char *pattern, * expand tilde from the passwd file. */ static const Char * -globtilde(const Char *pattern, Char *patbuf, glob_t *pglob) +globtilde(const Char *pattern, Char *patbuf, size_t limit, glob_t *pglob) { struct passwd *pwd; char *h; @@ -398,10 +420,15 @@ globtilde(const Char *pattern, Char *patbuf, glob_t *pglob) /* Copy up to the end of the string or / */ for (p = pattern + 1, h = (char *) patbuf; *p && *p != BG_SLASH; *h++ = *p++) - continue; + ; *h = BG_EOS; +#if 0 + if (h == (char *)eb) + return what; +#endif + if (((char *) patbuf)[0] == BG_EOS) { /* * handle a plain ~ or ~/ by expanding $HOME @@ -417,8 +444,7 @@ globtilde(const Char *pattern, Char *patbuf, glob_t *pglob) return pattern; #endif } - } - else { + } else { /* * Expand a ~user */ @@ -434,11 +460,11 @@ globtilde(const Char *pattern, Char *patbuf, glob_t *pglob) /* Copy the home directory */ for (b = patbuf; *h; *b++ = *h++) - continue; + ; /* Append the rest of the pattern */ while ((*b++ = *p++) != BG_EOS) - continue; + ; return patbuf; } @@ -456,7 +482,8 @@ glob0(const Char *pattern, glob_t *pglob) { const Char *qpat, *qpatnext; int c, err, oldflags, oldpathc; - Char *bufnext, patbuf[MAXPATHLEN+1]; + Char *bufnext, patbuf[MAXPATHLEN]; + size_t limit = 0; #ifdef MACOS_TRADITIONAL if ( (*pattern == BG_TILDE) && (pglob->gl_flags & GLOB_TILDE) ) { @@ -464,7 +491,7 @@ glob0(const Char *pattern, glob_t *pglob) } #endif - qpat = globtilde(pattern, patbuf, pglob); + qpat = globtilde(pattern, patbuf, MAXPATHLEN, pglob); qpatnext = qpat; oldflags = pglob->gl_flags; oldpathc = pglob->gl_pathc; @@ -510,7 +537,7 @@ glob0(const Char *pattern, glob_t *pglob) * to avoid exponential behavior */ if (bufnext == patbuf || bufnext[-1] != M_ALL) - *bufnext++ = M_ALL; + *bufnext++ = M_ALL; break; default: *bufnext++ = CHAR(c); @@ -522,7 +549,7 @@ glob0(const Char *pattern, glob_t *pglob) qprintf("glob0:", patbuf); #endif /* GLOB_DEBUG */ - if ((err = glob1(patbuf, pglob)) != 0) { + if ((err = glob1(patbuf, patbuf+MAXPATHLEN-1, pglob, &limit)) != 0) { pglob->gl_flags = oldflags; return(err); } @@ -542,7 +569,7 @@ glob0(const Char *pattern, glob_t *pglob) printf("calling globextend from glob0\n"); #endif /* GLOB_DEBUG */ pglob->gl_flags = oldflags; - return(globextend(qpat, pglob)); + return(globextend(qpat, pglob, &limit)); } else if (!(pglob->gl_flags & GLOB_NOSORT)) qsort(pglob->gl_pathv + pglob->gl_offs + oldpathc, @@ -556,19 +583,19 @@ glob0(const Char *pattern, glob_t *pglob) static int ci_compare(const void *p, const void *q) { - const char *pp = *(const char **)p; - const char *qq = *(const char **)q; - int ci; - while (*pp && *qq) { - if (tolower(*pp) != tolower(*qq)) - break; - ++pp; - ++qq; - } - ci = tolower(*pp) - tolower(*qq); - if (ci == 0) - return compare(p, q); - return ci; + const char *pp = *(const char **)p; + const char *qq = *(const char **)q; + int ci; + while (*pp && *qq) { + if (tolower(*pp) != tolower(*qq)) + break; + ++pp; + ++qq; + } + ci = tolower(*pp) - tolower(*qq); + if (ci == 0) + return compare(p, q); + return ci; } static int @@ -578,14 +605,16 @@ compare(const void *p, const void *q) } static int -glob1(Char *pattern, glob_t *pglob) +glob1(Char *pattern, Char *pattern_last, glob_t *pglob, size_t *limitp) { - Char pathbuf[MAXPATHLEN+1]; + Char pathbuf[MAXPATHLEN]; /* A null pathname is invalid -- POSIX 1003.1 sect. 2.4. */ if (*pattern == BG_EOS) return(0); - return(glob2(pathbuf, pathbuf, pattern, pglob)); + return(glob2(pathbuf, pathbuf+MAXPATHLEN-1, + pathbuf, pathbuf+MAXPATHLEN-1, + pattern, pattern_last, pglob, limitp)); } /* @@ -594,7 +623,8 @@ glob1(Char *pattern, glob_t *pglob) * meta characters. */ static int -glob2(Char *pathbuf, Char *pathend, Char *pattern, glob_t *pglob) +glob2(Char *pathbuf, Char *pathbuf_last, Char *pathend, Char *pathend_last, + Char *pattern, Char *pattern_last, glob_t *pglob, size_t *limitp) { Stat_t sb; Char *p, *q; @@ -616,10 +646,12 @@ glob2(Char *pathbuf, Char *pathend, Char *pattern, glob_t *pglob) #ifdef DOSISH && pathend[-1] != BG_SEP2 #endif - ) && (S_ISDIR(sb.st_mode) - || (S_ISLNK(sb.st_mode) && + ) && (S_ISDIR(sb.st_mode) || + (S_ISLNK(sb.st_mode) && (g_stat(pathbuf, &sb, pglob) == 0) && S_ISDIR(sb.st_mode)))) { + if (pathend+1 > pathend_last) + return (1); *pathend++ = BG_SEP; *pathend = BG_EOS; } @@ -627,7 +659,7 @@ glob2(Char *pathbuf, Char *pathend, Char *pattern, glob_t *pglob) #ifdef GLOB_DEBUG printf("calling globextend from glob2\n"); #endif /* GLOB_DEBUG */ - return(globextend(pathbuf, pglob)); + return(globextend(pathbuf, pglob, limitp)); } /* Find end of next segment, copy tentatively to pathend. */ @@ -640,6 +672,8 @@ glob2(Char *pathbuf, Char *pathend, Char *pattern, glob_t *pglob) ) { if (ismeta(*p)) anymeta = 1; + if (q+1 > pathend_last) + return (1); *q++ = *p++; } @@ -650,17 +684,24 @@ glob2(Char *pathbuf, Char *pathend, Char *pattern, glob_t *pglob) #ifdef DOSISH || *pattern == BG_SEP2 #endif - ) + ) { + if (pathend+1 > pathend_last) + return (1); *pathend++ = *pattern++; - } else /* Need expansion, recurse. */ - return(glob3(pathbuf, pathend, pattern, p, pglob)); + } + } else + /* Need expansion, recurse. */ + return(glob3(pathbuf, pathbuf_last, pathend, + pathend_last, pattern, pattern_last, + p, pattern_last, pglob, limitp)); } /* NOTREACHED */ } static int -glob3(Char *pathbuf, Char *pathend, Char *pattern, - Char *restpattern, glob_t *pglob) +glob3(Char *pathbuf, Char *pathbuf_last, Char *pathend, Char *pathend_last, + Char *pattern, Char *pattern_last, + Char *restpattern, Char *restpattern_last, glob_t *pglob, size_t *limitp) { register Direntry_t *dp; DIR *dirp; @@ -676,6 +717,8 @@ glob3(Char *pathbuf, Char *pathend, Char *pattern, */ Direntry_t *(*readdirfunc)(DIR*); + if (pathend > pathend_last) + return (1); *pathend = BG_EOS; errno = 0; @@ -697,7 +740,8 @@ glob3(Char *pathbuf, Char *pathend, Char *pattern, if ((dirp = g_opendir(pathbuf, pglob)) == NULL) { /* TODO: don't call for ENOENT or ENOTDIR? */ if (pglob->gl_errfunc) { - g_Ctoc(pathbuf, buf); + if (g_Ctoc(pathbuf, buf, sizeof(buf))) + return (GLOB_ABEND); if (pglob->gl_errfunc(buf, errno) || (pglob->gl_flags & GLOB_ERR)) return (GLOB_ABEND); @@ -710,7 +754,7 @@ glob3(Char *pathbuf, Char *pathend, Char *pattern, /* Search directory for matching names. */ if (pglob->gl_flags & GLOB_ALTDIRFUNC) - readdirfunc = (Direntry_t *(*)(DIR *))pglob->gl_readdir; + readdirfunc = (Direntry_t *(*)(DIR *))pglob->gl_readdir; else readdirfunc = my_readdir; while ((dp = (*readdirfunc)(dirp))) { @@ -720,14 +764,22 @@ glob3(Char *pathbuf, Char *pathend, Char *pattern, /* Initial BG_DOT must be matched literally. */ if (dp->d_name[0] == BG_DOT && *pattern != BG_DOT) continue; - for (sc = (U8 *) dp->d_name, dc = pathend; - (*dc++ = *sc++) != BG_EOS;) - continue; + dc = pathend; + sc = (U8 *) dp->d_name; + while (dc < pathend_last && (*dc++ = *sc++) != BG_EOS) + ; + if (dc >= pathend_last) { + *dc = BG_EOS; + err = 1; + break; + } + if (!match(pathend, pattern, restpattern, nocase)) { *pathend = BG_EOS; continue; } - err = glob2(pathbuf, --dc, restpattern, pglob); + err = glob2(pathbuf, pathbuf_last, --dc, pathend_last, + restpattern, restpattern_last, pglob, limitp); if (err) break; } @@ -755,10 +807,11 @@ glob3(Char *pathbuf, Char *pathend, Char *pattern, * gl_pathv points to (gl_offs + gl_pathc + 1) items. */ static int -globextend(const Char *path, glob_t *pglob) +globextend(const Char *path, glob_t *pglob, size_t *limitp) { register char **pathv; register int i; + STRLEN newsize, len; char *copy; const Char *p; @@ -769,13 +822,18 @@ globextend(const Char *path, glob_t *pglob) printf("\n"); #endif /* GLOB_DEBUG */ + newsize = sizeof(*pathv) * (2 + pglob->gl_pathc + pglob->gl_offs); if (pglob->gl_pathv) - pathv = Renew(pglob->gl_pathv, - (2 + pglob->gl_pathc + pglob->gl_offs),char*); + pathv = Renew(pglob->gl_pathv,newsize,char*); else - New(0,pathv,(2 + pglob->gl_pathc + pglob->gl_offs),char*); - if (pathv == NULL) + New(0,pathv,newsize,char*); + if (pathv == NULL) { + if (pglob->gl_pathv) { + Safefree(pglob->gl_pathv); + pglob->gl_pathv = NULL; + } return(GLOB_NOSPACE); + } if (pglob->gl_pathv == NULL && pglob->gl_offs > 0) { /* first time around -- clear initial gl_offs items */ @@ -786,13 +844,23 @@ globextend(const Char *path, glob_t *pglob) pglob->gl_pathv = pathv; for (p = path; *p++;) - continue; + ; + len = (STRLEN)(p - path); New(0, copy, p-path, char); if (copy != NULL) { - g_Ctoc(path, copy); + if (g_Ctoc(path, copy, len)) { + Safefree(copy); + return(GLOB_NOSPACE); + } pathv[pglob->gl_offs + pglob->gl_pathc++] = copy; } pathv[pglob->gl_offs + pglob->gl_pathc] = NULL; + + if ((pglob->gl_flags & GLOB_LIMIT) && + newsize + *limitp >= ARG_MAX) { + errno = 0; + return(GLOB_NOSPACE); + } return(copy == NULL ? GLOB_NOSPACE : 0); } @@ -816,7 +884,8 @@ match(register Char *name, register Char *pat, register Char *patend, int nocase do if (match(name, pat, patend, nocase)) return(1); - while (*name++ != BG_EOS); + while (*name++ != BG_EOS) + ; return(0); case M_ONE: if (*name++ == BG_EOS) @@ -866,6 +935,7 @@ bsd_globfree(glob_t *pglob) if (*pp) Safefree(*pp); Safefree(pglob->gl_pathv); + pglob->gl_pathv = NULL; } } @@ -881,7 +951,8 @@ g_opendir(register Char *str, glob_t *pglob) strcpy(buf, "."); #endif } else { - g_Ctoc(str, buf); + if (g_Ctoc(str, buf, sizeof(buf))) + return(NULL); } if (pglob->gl_flags & GLOB_ALTDIRFUNC) @@ -895,7 +966,8 @@ g_lstat(register Char *fn, Stat_t *sb, glob_t *pglob) { char buf[MAXPATHLEN]; - g_Ctoc(fn, buf); + if (g_Ctoc(fn, buf, sizeof(buf))) + return(-1); if (pglob->gl_flags & GLOB_ALTDIRFUNC) return((*pglob->gl_lstat)(buf, sb)); #ifdef HAS_LSTAT @@ -910,7 +982,8 @@ g_stat(register Char *fn, Stat_t *sb, glob_t *pglob) { char buf[MAXPATHLEN]; - g_Ctoc(fn, buf); + if (g_Ctoc(fn, buf, sizeof(buf))) + return(-1); if (pglob->gl_flags & GLOB_ALTDIRFUNC) return((*pglob->gl_stat)(buf, sb)); return(PerlLIO_stat(buf, sb)); @@ -926,29 +999,14 @@ g_strchr(Char *str, int ch) return (NULL); } -#ifdef notdef -static Char * -g_strcat(Char *dst, const Char *src) -{ - Char *sdst = dst; - - while (*dst++) - continue; - --dst; - while((*dst++ = *src++) != BG_EOS) - continue; - - return (sdst); -} -#endif - -static void -g_Ctoc(register const Char *str, char *buf) +static int +g_Ctoc(register const Char *str, char *buf, STRLEN len) { - register char *dc; - - for (dc = buf; (*dc++ = *str++) != BG_EOS;) - continue; + while (len--) { + if ((*buf++ = *str++) == BG_EOS) + return (0); + } + return (1); } #ifdef GLOB_DEBUG diff --git a/ext/File/Glob/bsd_glob.h b/ext/File/Glob/bsd_glob.h index 5d04fff..c8a3abd 100644 --- a/ext/File/Glob/bsd_glob.h +++ b/ext/File/Glob/bsd_glob.h @@ -73,6 +73,8 @@ typedef struct { #define GLOB_TILDE 0x0800 /* Expand tilde names from the passwd file. */ #define GLOB_NOCASE 0x1000 /* Treat filenames without regard for case. */ #define GLOB_ALPHASORT 0x2000 /* Alphabetic, not ASCII sort, like csh. */ +#define GLOB_LIMIT 0x4000 /* Limit pattern match output to ARG_MAX + (usually from limits.h). */ #define GLOB_NOSPACE (-1) /* Malloc call failed. */ #define GLOB_ABEND (-2) /* Unignored error. */ diff --git a/regexec.c b/regexec.c index 625f8eb..481ac58 100644 --- a/regexec.c +++ b/regexec.c @@ -391,19 +391,18 @@ Perl_re_intuit_start(pTHX_ regexp *prog, SV *sv, char *strpos, || ( (prog->reganch & ROPT_ANCH_BOL) && !PL_multiline ) ); /* Check after \n? */ - if (!ml_anch) { - if ( !(prog->reganch & ROPT_ANCH_GPOS) /* Checked by the caller */ - /* SvCUR is not set on references: SvRV and SvPVX overlap */ - && sv && !SvROK(sv) - && (strpos != strbeg)) { - DEBUG_r(PerlIO_printf(Perl_debug_log, "Not at start...\n")); - goto fail; - } - if (prog->check_offset_min == prog->check_offset_max && - !(prog->reganch & ROPT_SANY_SEEN)) { + if ((prog->check_offset_min == prog->check_offset_max) && !ml_anch) { /* Substring at constant offset from beg-of-str... */ I32 slen; + if ( !(prog->reganch & ROPT_ANCH_GPOS) /* Checked by the caller */ + /* SvCUR is not set on references: SvRV and SvPVX overlap */ + && sv && !SvROK(sv) + && (strpos != strbeg)) { + DEBUG_r(PerlIO_printf(Perl_debug_log, "Not at start...\n")); + goto fail; + } + PL_regeol = strend; /* Used in HOP() */ s = HOP3c(strpos, prog->check_offset_min, strend); if (SvTAIL(check)) { slen = SvCUR(check); /* >= 1 */ @@ -428,7 +427,6 @@ Perl_re_intuit_start(pTHX_ regexp *prog, SV *sv, char *strpos, && memNE(SvPVX(check), s, slen))) goto report_neq; goto success_at_start; - } } /* Match is anchored, but substr is not anchored wrt beg-of-str. */ s = strpos; diff --git a/t/op/pat.t b/t/op/pat.t index c3024a2..9cd6e9d 100755 --- a/t/op/pat.t +++ b/t/op/pat.t @@ -5,7 +5,7 @@ # that does fit that format, add it to op/re_tests, not here. $| = 1; -print "1..581\n"; +print "1..586\n"; BEGIN { chdir 't' if -d 't'; @@ -1547,3 +1547,28 @@ print "ok 247\n"; print "ok 581\n"; } + +{ + # bugid 20010410.006 + for my $rx ( + '/(.*?)\{(.*?)\}/csg', + '/(.*?)\{(.*?)\}/cg', + '/(.*?)\{(.*?)\}/sg', + '/(.*?)\{(.*?)\}/g', + '/(.+?)\{(.+?)\}/csg', + ) + { + my($input, $i); + + $i = 0; + $input = "a{b}c{d}"; + eval <