summaryrefslogtreecommitdiff
path: root/t/op/goto.t
diff options
context:
space:
mode:
authorDavid Mitchell <davem@iabyn.com>2015-06-25 16:08:02 +0100
committerDavid Mitchell <davem@iabyn.com>2016-02-03 08:59:33 +0000
commitcd17cc2e752d3e7e4d2cbdac9869cc7de3e9b075 (patch)
treeab1009eba75e9bb58a85166a2d5f50ddf8ec7777 /t/op/goto.t
parent88c11d84310c49339e73fcab80dad89a73d74263 (diff)
downloadperl-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.t26
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