summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFather Chrysostomos <sprout@cpan.org>2014-01-18 19:16:55 -0800
committerTony Cook <tony@develop-help.com>2014-04-16 11:20:29 +1000
commit2c60386e935e57af3d9202ad4b798662d2e997a1 (patch)
tree73ed27ce9df3179a98d2beadf70e3b46ad81dca9
parent1d88b12bc04aeae558bc19c4b08b7e682bbdd598 (diff)
downloadperl-2c60386e935e57af3d9202ad4b798662d2e997a1.tar.gz
[perl #119949] Stop undef *_, goto &sub from crashing
Commit 049bd5ffd62b fixed problems with the wrong @_ being visible after *_ modification followed by goto. In so doing, it made it possible for a null to be placed at the start of the target sub’s pad, because it was not checking that the array it got from PL_defgv was actually non-null. Simply adding the check makes everything work. Conflicts: t/op/goto.t
-rw-r--r--pp_ctl.c6
-rw-r--r--t/op/goto.t19
2 files changed, 22 insertions, 3 deletions
diff --git a/pp_ctl.c b/pp_ctl.c
index c8735e9afc..19d172e60f 100644
--- a/pp_ctl.c
+++ b/pp_ctl.c
@@ -2956,8 +2956,10 @@ PP(pp_goto)
to freed memory as the result of undef *_. So put
it in the callee’s pad, donating our refer-
ence count. */
- SvREFCNT_dec(PAD_SVl(0));
- PAD_SVl(0) = (SV *)(cx->blk_sub.argarray = arg);
+ if (arg) {
+ SvREFCNT_dec(PAD_SVl(0));
+ PAD_SVl(0) = (SV *)(cx->blk_sub.argarray = arg);
+ }
/* GvAV(PL_defgv) might have been modified on scope
exit, so restore it. */
diff --git a/t/op/goto.t b/t/op/goto.t
index 37b69e38df..a2d9df85aa 100644
--- a/t/op/goto.t
+++ b/t/op/goto.t
@@ -10,7 +10,7 @@ BEGIN {
use warnings;
use strict;
-plan tests => 89;
+plan tests => 91;
our $TODO;
my $deprecated = 0;
@@ -482,6 +482,23 @@ sub { *__ = \@_; goto &null } -> ("rough and tubbery");
is ${*__}[0], 'rough and tubbery', 'goto &foo leaves reified @_ alone';
+# goto &perlsub when @_ itself does not exist [perl #119949]
+# This was only crashing when the replaced sub call had an argument list.
+# (I.e., &{ sub { goto ... } } did not crash.)
+sub {
+ undef *_;
+ goto sub {
+ is *_{ARRAY}, undef, 'goto &perlsub when @_ does not exist';
+ }
+}->();
+sub {
+ local *_;
+ goto sub {
+ is *_{ARRAY}, undef, 'goto &sub when @_ does not exist (local *_)';
+ }
+}->();
+
+
# [perl #36521] goto &foo in warn handler could defeat recursion avoider
{