diff options
author | Father Chrysostomos <sprout@cpan.org> | 2012-04-24 16:00:36 -0700 |
---|---|---|
committer | Father Chrysostomos <sprout@cpan.org> | 2012-05-21 16:51:37 -0700 |
commit | 27cc3b5a047e2e329f60a8c56fd2f8204b2a626b (patch) | |
tree | 20a3af4f756399aa9ebcf5b78c5f052a7e6a4b16 /dist | |
parent | f22549bbfa35b17fad20cb25463164fea72b9754 (diff) | |
download | perl-27cc3b5a047e2e329f60a8c56fd2f8204b2a626b.tar.gz |
[perl #112358] Storable: Don’t create RV with no refcnt
Otherwise assigning to it will cause the referent to be freed, because
nothing but Storable knows that it has no reference count.
Storable.xs was creating a new RV without increasing the refe-
rence count on the referent. It was then using it to call the
STORABLE_freeze method on the object. Since Perl passes arguments
by reference, it was possible to unref the reference by assigning to
$_[0] within STORABLE_freeze. That would cause the object’s reference
count to go down.
Diffstat (limited to 'dist')
-rw-r--r-- | dist/Storable/Storable.xs | 3 | ||||
-rw-r--r-- | dist/Storable/t/blessed.t | 11 |
2 files changed, 11 insertions, 3 deletions
diff --git a/dist/Storable/Storable.xs b/dist/Storable/Storable.xs index ca6f9b48ec..30f9281bb5 100644 --- a/dist/Storable/Storable.xs +++ b/dist/Storable/Storable.xs @@ -2916,9 +2916,8 @@ static int store_hook( TRACEME(("about to call STORABLE_freeze on class %s", classname)); - ref = newRV_noinc(sv); /* Temporary reference */ + ref = newRV_inc(sv); /* Temporary reference */ av = array_call(aTHX_ ref, hook, clone); /* @a = $object->STORABLE_freeze($c) */ - SvRV_set(ref, NULL); SvREFCNT_dec(ref); /* Reclaim temporary reference */ count = AvFILLp(av) + 1; diff --git a/dist/Storable/t/blessed.t b/dist/Storable/t/blessed.t index 6657e3c424..6b25f37270 100644 --- a/dist/Storable/t/blessed.t +++ b/dist/Storable/t/blessed.t @@ -27,7 +27,7 @@ use Storable qw(freeze thaw store retrieve); ); my $test = 12; -my $tests = $test + 22 + 2 * 6 * keys %::immortals; +my $tests = $test + 23 + 2 * 6 * keys %::immortals; plan(tests => $tests); package SHORT_NAME; @@ -249,3 +249,12 @@ is($STRESS_THE_STACK::freeze_count, 1); is($STRESS_THE_STACK::thaw_count, 1); isnt($t, undef); is(ref $t, 'STRESS_THE_STACK'); + +{ + package ModifyARG112358; + sub STORABLE_freeze { $_[0] = "foo"; } + my $o= {str=>bless {}}; + my $f= ::freeze($o); + ::is ref $o->{str}, __PACKAGE__, + 'assignment to $_[0] in STORABLE_freeze does not corrupt things'; +} |