diff options
author | Father Chrysostomos <sprout@cpan.org> | 2012-01-10 08:55:08 -0800 |
---|---|---|
committer | Father Chrysostomos <sprout@cpan.org> | 2012-01-10 08:55:26 -0800 |
commit | 7e482323fb2aaa4e52b80f3c50b716c8b6ef41c8 (patch) | |
tree | 731b8d9c5678c5118861ed33a42c4a699cd0985c /pp_hot.c | |
parent | 47d235f1839af4a64487fd5c07a58ff1b937da7c (diff) | |
download | perl-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.c | 1 |
1 files changed, 1 insertions, 0 deletions
@@ -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 |