70 lines
2.5 KiB
Diff
70 lines
2.5 KiB
Diff
|
From 42e9b60980bb8e29e76629e14c6aa945194c0647 Mon Sep 17 00:00:00 2001
|
||
|
From: Hugo van der Sanden <hv@crypt.org>
|
||
|
Date: Wed, 5 Oct 2016 02:20:26 +0100
|
||
|
Subject: [PATCH] [perl #129061] CURLYX nodes can be studied more than once
|
||
|
MIME-Version: 1.0
|
||
|
Content-Type: text/plain; charset=UTF-8
|
||
|
Content-Transfer-Encoding: 8bit
|
||
|
|
||
|
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].
|
||
|
|
||
|
Signed-off-by: Petr Písař <ppisar@redhat.com>
|
||
|
---
|
||
|
regcomp.c | 12 +++++++++---
|
||
|
t/re/pat.t | 1 -
|
||
|
2 files changed, 9 insertions(+), 4 deletions(-)
|
||
|
|
||
|
diff --git a/regcomp.c b/regcomp.c
|
||
|
index 850a6c1..48c8d8d 100644
|
||
|
--- a/regcomp.c
|
||
|
+++ b/regcomp.c
|
||
|
@@ -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++;
|
||
|
diff --git a/t/re/pat.t b/t/re/pat.t
|
||
|
index ecd3af1..16bfc8e 100644
|
||
|
--- a/t/re/pat.t
|
||
|
+++ b/t/re/pat.t
|
||
|
@@ -1909,7 +1909,6 @@ EOP
|
||
|
}
|
||
|
{
|
||
|
# [perl #129281] buffer write overflow, detected by ASAN, valgrind
|
||
|
- local $::TODO = "whilem_c bumped too much";
|
||
|
fresh_perl_is('/0(?0)|^*0(?0)|^*(^*())0|/', '', {}, "don't bump whilem_c too much");
|
||
|
}
|
||
|
} # End of sub run_tests
|
||
|
--
|
||
|
2.7.4
|
||
|
|