Skip to content

Commit e96dd01

Browse files
committed
when (re)creating @_, zero its elements
When a sub's @_ gets abandoned (e.g. when 'goto &bar' "donates" the current @_ to the new sub), a new AV is created at pad[0] for the old sub. Perl alloc()'s the AvARRAY() buffer for the new AV, but didn't zero it. This didn't used to be a problem, because @_ AVs are created !AvREAL(), so the first thing perl did when someone tries to modify @_, is to call av_reify() on it. And it just so happens that av_reify() zeros out all the unused slots on the array first. So code like $_[1] = 1; do_something_with($_[0]) was fine. However, on PERL_RC_STACK builds, @_ is AvREAL() by default now, so av_reify() doesn't get called, so AvARRAY() can sometimes contain random wild pointers. The fix is simple: zero AvARRAY() when creating it. This was showing as a failure in Test::Trap
1 parent 3f16b5f commit e96dd01

File tree

2 files changed

+22
-2
lines changed

2 files changed

+22
-2
lines changed

pp_hot.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5493,7 +5493,7 @@ Perl_clear_defarray(pTHX_ AV* av, bool abandon)
54935493
/* abandon */
54945494
const SSize_t size = AvFILLp(av) + 1;
54955495
/* The ternary gives consistency with av_extend() */
5496-
AV *newav = newAV_alloc_x(size < PERL_ARRAY_NEW_MIN_KEY ?
5496+
AV *newav = newAV_alloc_xz(size < PERL_ARRAY_NEW_MIN_KEY ?
54975497
PERL_ARRAY_NEW_MIN_KEY : size);
54985498
#ifndef PERL_RC_STACK
54995499
AvREIFY_only(newav);

t/op/goto.t

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ BEGIN {
1212
use warnings;
1313
use strict;
1414
use Config;
15-
plan tests => 133;
15+
plan tests => 134;
1616
our $TODO;
1717

1818
my $deprecated = 0;
@@ -952,3 +952,23 @@ SKIP:
952952
my @a = bar_19936();
953953
is($XS::APItest::GIMME_V, 3, "GH #19936 gimme XS call");
954954
}
955+
956+
# goto &sub could leave AvARRAY() slots of @_ uninitialised.
957+
958+
{
959+
my $i = 0;
960+
my $f = sub {
961+
goto &{ sub {} } unless $i++;
962+
$_[1] = 1; # create a hole
963+
# accessing $_[0] is more for valgrind/ASAN to chew on rather than
964+
# we're too concerned about its value. Or it might give "bizarre
965+
# copy" errors.
966+
is($_[0], undef, "goto and AvARRAY");
967+
};
968+
969+
# first call does goto, which gives &$f a fresh AV in pad[0],
970+
# which formerly allocated an AvARRAY for it, but didn't zero it
971+
$f->();
972+
# second call creates hole in @_ which used to to be a wild SV pointer
973+
$f->();
974+
}

0 commit comments

Comments
 (0)