summaryrefslogtreecommitdiff
path: root/scope.c
diff options
context:
space:
mode:
authorDavid Mitchell <davem@iabyn.com>2010-04-11 15:52:43 +0100
committerDavid Mitchell <davem@iabyn.com>2010-04-11 16:15:31 +0100
commit459defa14829d1e98582a2fcd871ef3425e1fe38 (patch)
tree8a5ea764cabff130a96e8baf4576ca186c975e45 /scope.c
parentd97c33b505dd45c052a8bf42014917701b4502a5 (diff)
downloadperl-459defa14829d1e98582a2fcd871ef3425e1fe38.tar.gz
RT 8857: premature free in local of tied element
[The original bug report concerned local($_) remained tied, but while looking at it, Nicholas found some related code that popped up premature free errors. This commit fixes the freeing issue rather than the issue of the original bug report ] Background: local $a[0] does, approximately: svp = av_fetch(av); SAVE(av,*svp); sv = newSV(); *svp = sv; This used to leak when av was tied, as the new sv only got embedded in *svp, which for tied arrays is a temporary placeholder rather than somewhere within AvARRAY. This leak was fixed in 2002 by adding the following: if (SvTIED_mg(sv, PERL_MAGIC_tiedelem)) sv_2mortal(sv); which worked, except for the following: sub f { local $_[0] } f($_) for ($tied[0]); Here, @_ is a real array not a tied one, yet its first element is a PERL_MAGIC_tiedelem which trigged the test above. So the sv got mortalised *and* stored in the array, so got freed twice. The fix is to test the *array/hash* for tied-ness rather than the element.
Diffstat (limited to 'scope.c')
-rw-r--r--scope.c4
1 files changed, 2 insertions, 2 deletions
diff --git a/scope.c b/scope.c
index 414f5b5225..de7d20593f 100644
--- a/scope.c
+++ b/scope.c
@@ -619,7 +619,7 @@ Perl_save_aelem_flags(pTHX_ AV *av, I32 idx, SV **sptr, const U32 flags)
* won't actually be stored in the array - so it won't get
* reaped when the localize ends. Ensure it gets reaped by
* mortifying it instead. DAPM */
- if (SvTIED_mg(sv, PERL_MAGIC_tiedelem))
+ if (SvTIED_mg(av, PERL_MAGIC_tied))
sv_2mortal(sv);
}
@@ -645,7 +645,7 @@ Perl_save_helem_flags(pTHX_ HV *hv, SV *key, SV **sptr, const U32 flags)
* won't actually be stored in the hash - so it won't get
* reaped when the localize ends. Ensure it gets reaped by
* mortifying it instead. DAPM */
- if (SvTIED_mg(sv, PERL_MAGIC_tiedelem))
+ if (SvTIED_mg(hv, PERL_MAGIC_tied))
sv_2mortal(sv);
}