summaryrefslogtreecommitdiff
path: root/pp_ctl.c
diff options
context:
space:
mode:
authorDavid Mitchell <davem@iabyn.com>2015-03-18 17:06:49 +0000
committerDavid Mitchell <davem@iabyn.com>2015-03-19 14:51:52 +0000
commite8fe1b7c7ff6b3263ab2423a9a3f63ad85ea3aff (patch)
tree1d98c05604dce7807f0d0cb607376ec06c4f18a3 /pp_ctl.c
parent72e5fb6312b534c67eb2da0525dd3c09b5f9222b (diff)
downloadperl-e8fe1b7c7ff6b3263ab2423a9a3f63ad85ea3aff.tar.gz
smartmatch: handle stack realloc
When smartmatch is matching a pattern against something, it was failing to do appropriate PUTBACK and SPAGAIN's before calling matcher_matches_sv() (which pushes an arg an calls pp_match()). If the stack was almost full, the extra push in matcher_matches_sv() could cause a stack realloc, which would then be ignored when pp_smartmatch() returned, setting PL_stack_sp to point to the old (freed) stack. Adding SPAGAIN ensures that PL_stack_sp points to the new stack, while PUTBACK causes PL_stack_sp to no longer see the two args to pp_smartmatch, so the PUSH in matcher_matches_sv() pushes the SV us9ng ones of two two reclaimed slots, so the stack won't re-alloc anyway. Thus by doing the "right thing" with both PUTBACK and SPAGAIN, we doubly ensure that PL_stack_sp will always be right.
Diffstat (limited to 'pp_ctl.c')
-rw-r--r--pp_ctl.c15
1 files changed, 11 insertions, 4 deletions
diff --git a/pp_ctl.c b/pp_ctl.c
index 23094e805d..ac0f1bcd3d 100644
--- a/pp_ctl.c
+++ b/pp_ctl.c
@@ -4581,7 +4581,7 @@ S_do_smartmatch(pTHX_ HV *seen_this, HV *seen_other, const bool copied)
}
SP -= 2; /* Pop the values */
-
+ PUTBACK;
/* ~~ undef */
if (!SvOK(e)) {
@@ -4778,11 +4778,14 @@ S_do_smartmatch(pTHX_ HV *seen_this, HV *seen_other, const bool copied)
(void) hv_iterinit(hv);
while ( (he = hv_iternext(hv)) ) {
DEBUG_M(Perl_deb(aTHX_ " testing key against pattern...\n"));
+ PUTBACK;
if (matcher_matches_sv(matcher, hv_iterkeysv(he))) {
+ SPAGAIN;
(void) hv_iterinit(hv);
destroy_matcher(matcher);
RETPUSHYES;
}
+ SPAGAIN;
}
destroy_matcher(matcher);
RETPUSHNO;
@@ -4887,10 +4890,13 @@ S_do_smartmatch(pTHX_ HV *seen_this, HV *seen_other, const bool copied)
for(i = 0; i <= this_len; ++i) {
SV * const * const svp = av_fetch(MUTABLE_AV(SvRV(e)), i, FALSE);
DEBUG_M(Perl_deb(aTHX_ " testing element against pattern...\n"));
+ PUTBACK;
if (svp && matcher_matches_sv(matcher, *svp)) {
+ SPAGAIN;
destroy_matcher(matcher);
RETPUSHYES;
}
+ SPAGAIN;
}
destroy_matcher(matcher);
RETPUSHNO;
@@ -4951,12 +4957,13 @@ S_do_smartmatch(pTHX_ HV *seen_this, HV *seen_other, const bool copied)
}
else {
PMOP * const matcher = make_matcher((REGEXP*) SvRV(e));
+ bool result;
DEBUG_M(Perl_deb(aTHX_ " applying rule Any-Regex\n"));
PUTBACK;
- PUSHs(matcher_matches_sv(matcher, d)
- ? &PL_sv_yes
- : &PL_sv_no);
+ result = matcher_matches_sv(matcher, d);
+ SPAGAIN;
+ PUSHs(result ? &PL_sv_yes : &PL_sv_no);
destroy_matcher(matcher);
RETURN;
}