summaryrefslogtreecommitdiff
path: root/pp_hot.c
diff options
context:
space:
mode:
authorFather Chrysostomos <sprout@cpan.org>2012-01-10 08:55:08 -0800
committerFather Chrysostomos <sprout@cpan.org>2012-01-10 08:55:26 -0800
commit7e482323fb2aaa4e52b80f3c50b716c8b6ef41c8 (patch)
tree731b8d9c5678c5118861ed33a42c4a699cd0985c /pp_hot.c
parent47d235f1839af4a64487fd5c07a58ff1b937da7c (diff)
downloadperl-7e482323fb2aaa4e52b80f3c50b716c8b6ef41c8.tar.gz
[perl #35865, #43011] FETCH after autovivifying
After autovivification, perl should not assume that the value it has assigned to a magical scalar is the one that would have been returned. The result of this assumption is that any tie class that copies things assigned to it will cause autovivification to assign to a temporary aggregate without warning, in cases like this: $tied{nonexistent}{foo} = 7; The hash implicitly assigned to $tied{nonexistent} ends up being freed after the =7 assignment. This commit changes autovivification to do FETCH immediately after doing STORE. This required changing some recently-added tests in gmagic.t. Without this change, you end up with horrific workarounds (using B.pm to get the reference count), like the one in JE::Object (which I’m pasting here, in case it has changed by the time you read this): sub STORE { my($self, $key, $val) = @_; my $global = $self->global; if(ref $val eq 'HASH' && !blessed $val && !%$val && svref_2object($val)->REFCNT == 2) { $val = tie %$val, __PACKAGE__, __PACKAGE__->new( $global); } elsif (ref $val eq 'ARRAY' && !blessed $val && !@$val && svref_2object($val)->REFCNT == 2) { require JE::Object::Array; $val = tie @$val, 'JE::Object::Array', JE::Object::Array->new($global); } $self->prop($key => $global->upgrade($val)) }
Diffstat (limited to 'pp_hot.c')
-rw-r--r--pp_hot.c1
1 files changed, 1 insertions, 0 deletions
diff --git a/pp_hot.c b/pp_hot.c
index ff834a924e..a66a690608 100644
--- a/pp_hot.c
+++ b/pp_hot.c
@@ -2898,6 +2898,7 @@ Perl_vivify_ref(pTHX_ SV *sv, U32 to_what)
}
SvROK_on(sv);
SvSETMAGIC(sv);
+ SvGETMAGIC(sv);
}
if (SvGMAGICAL(sv)) {
/* copy the sv without magic to prevent magic from being