diff options
author | David Mitchell <davem@iabyn.com> | 2015-06-25 16:08:02 +0100 |
---|---|---|
committer | David Mitchell <davem@iabyn.com> | 2016-02-03 08:59:33 +0000 |
commit | cd17cc2e752d3e7e4d2cbdac9869cc7de3e9b075 (patch) | |
tree | ab1009eba75e9bb58a85166a2d5f50ddf8ec7777 /t/op/goto.t | |
parent | 88c11d84310c49339e73fcab80dad89a73d74263 (diff) | |
download | perl-cd17cc2e752d3e7e4d2cbdac9869cc7de3e9b075.tar.gz |
pp_goto: SvREFCNT_dec(oldcv) *after* undef test
pp_goto does a LEAVE, then checks that the new CV hasn't been undefed
by the LEAVE. If it has, it croaks.
Move the decrementing of the old CV's ref count and depth to *after*
this check, since the POPSUB done during the croak unwind will do the
decrement also. Otherwise the old sub will be doubly freed.
Diffstat (limited to 't/op/goto.t')
-rw-r--r-- | t/op/goto.t | 26 |
1 files changed, 25 insertions, 1 deletions
diff --git a/t/op/goto.t b/t/op/goto.t index d1e88d71f5..73a6b9584d 100644 --- a/t/op/goto.t +++ b/t/op/goto.t @@ -10,7 +10,7 @@ BEGIN { use warnings; use strict; -plan tests => 96; +plan tests => 97; our $TODO; my $deprecated = 0; @@ -216,6 +216,30 @@ package _99850 { like $@, qr/^Goto undefined subroutine &_99850::reftype at /, 'goto &foo undefining &foo on sub cleanup'; +# When croaking after discovering that the new CV you're about to goto is +# undef, make sure that the old CV isn't doubly freed. + +package Do_undef { + my $count; + + # creating a new closure here encourages any prematurely freed + # CV to be reallocated + sub DESTROY { undef &undef_sub; my $x = sub { $count } } + + sub f { + $count++; + my $guard = bless []; # trigger DESTROY during goto + *undef_sub = sub {}; + goto &undef_sub + } + + for (1..10) { + eval { f() }; + } + ::is($count, 10, "goto undef_sub safe"); +} + + # bug #22181 - this used to coredump or make $x undefined, due to # erroneous popping of the inner BLOCK context |