summaryrefslogtreecommitdiff
path: root/pp.c
diff options
context:
space:
mode:
authorFather Chrysostomos <sprout@cpan.org>2012-10-25 13:00:55 -0700
committerFather Chrysostomos <sprout@cpan.org>2012-10-25 20:02:55 -0700
commit3ed356df9354193bbcc5202f066f3c07ae84b443 (patch)
tree6a9fd54462d581f52672a517b461498fb798166e /pp.c
parent33b889b0162a4f12e7c2a8d184afb63213130f07 (diff)
downloadperl-3ed356df9354193bbcc5202f066f3c07ae84b443.tar.gz
[perl #115440] Fix various leaks with fatal FETCH
Various pieces of code were creating an SV and then assigning to it from a value that might be magical. If the source scalar is magical, it could die when magic is called, leaking the scalar that would have been assigned to. So we call get-magic before creating the new scalar, and then use a non-magical assignment. Also, anonhash and anonlist were doing nothing to protect the aggre- gate if an argument should die on FETCH, resulting in a leak.
Diffstat (limited to 'pp.c')
-rw-r--r--pp.c28
1 files changed, 20 insertions, 8 deletions
diff --git a/pp.c b/pp.c
index 1c68e5af02..d1cac93ba8 100644
--- a/pp.c
+++ b/pp.c
@@ -4804,20 +4804,30 @@ PP(pp_anonlist)
PP(pp_anonhash)
{
dVAR; dSP; dMARK; dORIGMARK;
- HV* const hv = newHV();
+ HV* const hv = (HV *)sv_2mortal((SV *)newHV());
while (MARK < SP) {
- SV * const key = *++MARK;
- SV * const val = newSV(0);
+ SV * const key =
+ (MARK++, SvGMAGICAL(*MARK) ? sv_mortalcopy(*MARK) : *MARK);
+ SV *val;
if (MARK < SP)
- sv_setsv(val, *++MARK);
+ {
+ MARK++;
+ SvGETMAGIC(*MARK);
+ val = newSV(0);
+ sv_setsv(val, *MARK);
+ }
else
+ {
Perl_ck_warner(aTHX_ packWARN(WARN_MISC), "Odd number of elements in anonymous hash");
+ val = newSV(0);
+ }
(void)hv_store_ent(hv,key,val,0);
}
SP = ORIGMARK;
- mXPUSHs((PL_op->op_flags & OPf_SPECIAL)
- ? newRV_noinc(MUTABLE_SV(hv)) : MUTABLE_SV(hv));
+ if (PL_op->op_flags & OPf_SPECIAL)
+ mXPUSHs(newRV_inc(MUTABLE_SV(hv)));
+ else XPUSHs(MUTABLE_SV(hv));
RETURN;
}
@@ -5072,9 +5082,11 @@ PP(pp_push)
else {
PL_delaymagic = DM_DELAY;
for (++MARK; MARK <= SP; MARK++) {
- SV * const sv = newSV(0);
+ SV *sv;
+ if (*MARK) SvGETMAGIC(*MARK);
+ sv = newSV(0);
if (*MARK)
- sv_setsv(sv, *MARK);
+ sv_setsv_nomg(sv, *MARK);
av_store(ary, AvFILLp(ary)+1, sv);
}
if (PL_delaymagic & DM_ARRAY_ISA)