summaryrefslogtreecommitdiff
path: root/pp.c
diff options
context:
space:
mode:
authorFather Chrysostomos <sprout@cpan.org>2013-06-07 08:26:03 -0700
committerFather Chrysostomos <sprout@cpan.org>2013-06-07 08:26:40 -0700
commit9332b95f7fd17b2400da85452a406bc151d30d91 (patch)
tree7b4f1875a9a35c6afb583bcd778e74061293a8b5 /pp.c
parente987ad1c31f774bda2a3a14929ae1fc88f759ccc (diff)
downloadperl-9332b95f7fd17b2400da85452a406bc151d30d91.tar.gz
Stop delete local $ENV{foo} from leaking
It was only leaking when the env var did not already exist. The code in question in pp.c:S_do_delete_local was calling hv_delete to delete the element, which autovivifies, deletes, and returns a mag- ical mortal for magical hashes. It was assuming that if a value was returned the element must have existed, so it was calling SvREFCNT_inc on the returned mortal to de-mortalize it (since it has to be restored). Whether the element had existed previously was already recorded in a bool named ‘preeminent’ (strange name). This variable should be checked before the SvREFCNT_inc. I found the same bug in the array code path, potentially affecting @- and @+, so I fixed it. But I didn’t write a test, as that would involve a custom regexp engine.
Diffstat (limited to 'pp.c')
-rw-r--r--pp.c6
1 files changed, 4 insertions, 2 deletions
diff --git a/pp.c b/pp.c
index ea7b4c2691..3eb3cea6af 100644
--- a/pp.c
+++ b/pp.c
@@ -4511,7 +4511,8 @@ S_do_delete_local(pTHX)
}
else {
sv = hv_delete_ent(hv, keysv, 0, 0);
- SvREFCNT_inc_simple_void(sv); /* De-mortalize */
+ if (preeminent)
+ SvREFCNT_inc_simple_void(sv); /* De-mortalize */
}
if (preeminent) {
if (!sv) DIE(aTHX_ PL_no_helem_sv, SVfARG(keysv));
@@ -4546,7 +4547,8 @@ S_do_delete_local(pTHX)
}
else {
sv = av_delete(av, idx, 0);
- SvREFCNT_inc_simple_void(sv); /* De-mortalize */
+ if (preeminent)
+ SvREFCNT_inc_simple_void(sv); /* De-mortalize */
}
if (preeminent) {
save_aelem_flags(av, idx, &sv, SAVEf_KEEPOLDELEM);