diff options
author | Hugo van der Sanden <hv@crypt.org> | 2016-10-05 02:20:26 +0100 |
---|---|---|
committer | Hugo van der Sanden <hv@crypt.org> | 2017-02-06 15:15:31 +0000 |
commit | 42e9b60980bb8e29e76629e14c6aa945194c0647 (patch) | |
tree | cfb768f339b21150739e7140f7080d05ee124e3e /regcomp.c | |
parent | d2ba660af00f1bf2e7012741615eff7c19f29707 (diff) | |
download | perl-42e9b60980bb8e29e76629e14c6aa945194c0647.tar.gz |
[perl #129061] CURLYX nodes can be studied more than once
study_chunk() for CURLYX is used to set flags on the linked WHILEM
node to say it is the whilem_c'th of whilem_seen. However it assumes
each CURLYX can be studied only once, which is not the case - there
are various cases such as GOSUB which call study_chunk() recursively
on already-visited parts of the program.
Storing the wrong index can cause the super-linear cache handling in
regmatch() to read/write the byte after the end of poscache.
Also reported in [perl #129281].
Diffstat (limited to 'regcomp.c')
-rw-r--r-- | regcomp.c | 12 |
1 files changed, 9 insertions, 3 deletions
@@ -5218,15 +5218,21 @@ S_study_chunk(pTHX_ RExC_state_t *pRExC_state, regnode **scanp, However, this time it's not a subexpression we care about, but the expression itself. */ && (maxcount == REG_INFTY) - && data && ++data->whilem_c < 16) { + && data) { /* This stays as CURLYX, we can put the count/of pair. */ /* Find WHILEM (as in regexec.c) */ regnode *nxt = oscan + NEXT_OFF(oscan); if (OP(PREVOPER(nxt)) == NOTHING) /* LONGJMP */ nxt += ARG(nxt); - PREVOPER(nxt)->flags = (U8)(data->whilem_c - | (RExC_whilem_seen << 4)); /* On WHILEM */ + nxt = PREVOPER(nxt); + if (nxt->flags & 0xf) { + /* we've already set whilem count on this node */ + } else if (++data->whilem_c < 16) { + assert(data->whilem_c <= RExC_whilem_seen); + nxt->flags = (U8)(data->whilem_c + | (RExC_whilem_seen << 4)); /* On WHILEM */ + } } if (data && fl & (SF_HAS_PAR|SF_IN_PAR)) pars++; |