diff options
author | Father Chrysostomos <sprout@cpan.org> | 2011-08-25 12:38:15 -0700 |
---|---|---|
committer | Father Chrysostomos <sprout@cpan.org> | 2011-08-25 12:38:15 -0700 |
commit | e1a80902e5e9ce316c7cc56f6c15b52b0c0a9144 (patch) | |
tree | a4bb12053aef53ba7217fb900fa832fbcaadc08c /pp_ctl.c | |
parent | c931b03652afbc6f3525df91e6f1b821bf7c9fe3 (diff) | |
download | perl-e1a80902e5e9ce316c7cc56f6c15b52b0c0a9144.tar.gz |
[perl #93320] localising @DB::args leads to coredump
This script, from the RT ticket, crashes:
#!/usr/bin/perl
sub cl{
package DB;
@DB::args = ();
return caller(shift);
}
sub f{
local @DB::args;
my @z = cl($_) for (1..3);
}
f(1,2,3); f(1,2,3);
__END__
PL_dbargs is not refcounted, and it’s not set until pp_caller first
tries to write to it. If that happens when @DB::args is localised,
then the array will be freed on scope exit, leaving PL_dbargs pointing
to a freed SV.
This crash can be reproduced more simply this way:
sub {
package DB;
()=caller(0);
undef *DB::args;
()=caller(0);
}->();
So, basically, pp_caller has to re-fetch PL_dbargs from the %DB::
stash each time it sets it. It cannot rely on the cached value.
(So now I’m wondering whether we even need PL_dbargs.)
Diffstat (limited to 'pp_ctl.c')
-rw-r--r-- | pp_ctl.c | 3 |
1 files changed, 1 insertions, 2 deletions
@@ -1957,8 +1957,7 @@ PP(pp_caller) AV * const ary = cx->blk_sub.argarray; const int off = AvARRAY(ary) - AvALLOC(ary); - if (!PL_dbargs || AvREAL(PL_dbargs)) - Perl_init_dbargs(aTHX); + Perl_init_dbargs(aTHX); if (AvMAX(PL_dbargs) < AvFILLp(ary) + off) av_extend(PL_dbargs, AvFILLp(ary) + off); |