diff options
author | Hugo van der Sanden <hv@crypt.org> | 2021-01-31 22:51:15 +0000 |
---|---|---|
committer | Karl Williamson <khw@cpan.org> | 2021-02-09 08:42:52 -0800 |
commit | 459be019bda14de383329366de4cdec161526c3f (patch) | |
tree | 62eb255181004cc9a8ca38161cc79cf8aff9abe8 /regcomp.c | |
parent | 3c7beb8da4692313468432f7e66606e56360d79c (diff) | |
download | perl-459be019bda14de383329366de4cdec161526c3f.tar.gz |
gh18515: fix special handling of specific split() patterns
Commit 122af31004 acted on the wrong assumption that NEXTOPER() and
regnext() were equivalent, and in fixing a valgrind complaint tried
to simplify code for detecting specific patterns for split() that
merited special-case handling by making them all use regnext().
As a result, the special case /\s+/ was no longer correctly detected,
resulting in a degree of pessimisation.
This commit fixes that, and avoids reading via the calculated 'next'
pointer except for the ops we need (in which cases we know it'll point
to another regop) - for the EXACT case (which we don't need), valgrind
was correctly pointing out that it points to potentially uninitialized
data.
Diffstat (limited to 'regcomp.c')
-rw-r--r-- | regcomp.c | 12 |
1 files changed, 8 insertions, 4 deletions
@@ -8434,8 +8434,12 @@ Perl_re_op_compile(pTHX_ SV ** const patternp, int pat_count, * flags appropriately - Yves */ regnode *first = RExC_rxi->program + 1; U8 fop = OP(first); - regnode *next = regnext(first); - U8 nop = OP(next); + regnode *next = NEXTOPER(first); + /* It's safe to read through *next only if OP(first) is a regop of + * the right type (not EXACT, for example). + */ + U8 nop = (fop == NOTHING || fop == MBOL || fop == SBOL || fop == PLUS) + ? OP(next) : 0; if (PL_regkind[fop] == NOTHING && nop == END) RExC_rx->extflags |= RXf_NULL; @@ -8448,13 +8452,13 @@ Perl_re_op_compile(pTHX_ SV ** const patternp, int pat_count, RExC_rx->extflags |= RXf_START_ONLY; else if (fop == PLUS && PL_regkind[nop] == POSIXD && FLAGS(next) == _CC_SPACE - && nop == END) + && OP(regnext(first)) == END) RExC_rx->extflags |= RXf_WHITE; else if ( RExC_rx->extflags & RXf_SPLIT && (PL_regkind[fop] == EXACT && ! isEXACTFish(fop)) && STR_LEN(first) == 1 && *(STRING(first)) == ' ' - && nop == END ) + && OP(regnext(first)) == END ) RExC_rx->extflags |= (RXf_SKIPWHITE|RXf_WHITE); } |