Closed p5pRT closed 21 years ago
I've managed to do something evil to bleadperl (this is patch 16767) Segmentation fault (core dumped)
(gdb) where #0 0x80a177a in S_new_xrv () #1 0x80a1fe5 in Perl_sv_upgrade () #2 0x80a4dc2 in Perl_sv_setsv_flags () #3 0x809abfe in Perl_pp_sassign () #4 0x809a8d0 in Perl_runops_standard () #5 0x805eace in S_call_body () #6 0x805e8b2 in Perl_call_sv () #7 0x8061322 in S_call_list_body () #8 0x8061030 in Perl_call_list () #9 0x805c4a7 in perl_destruct () #10 0x805b920 in main () #11 0x805b7fd in _start ()
It's a bit late\, and I've not done too well at pruning the test case because I need to go to bed. The simpler version is this:
#!./perl -w
my @warnings; sub BEGIN { $SIG{__WARN__} = sub { push @warnings\, $_[0]; print STDERR $_[0]; }; }
use strict;
BEGIN { push @warnings\, \'Storable::FOO'; } $Storable::FOO = 1;
print "'$_'\n"\, @warnings;
my $unexpected = 0; while (@warnings and my $instruction = shift @warnings) { $instruction = $$instruction; warn $instruction; my ($expect\, $got); if ($instruction =~ /^!(.*)/) { # Don't expect to see a warning for this variable. # So should either be at the end\, or next item is another instruction. } else { # Expect a used only once warning. $expect = "/^Name \"$instruction\" used only once/"; }
if (@warnings and ref $warnings[0]) { # Something not an instruction follows us. $got = shift @warnings; # Clear any extra unexpected warnings. while (@warnings and !ref $warnings[0]) { shift @warnings; $unexpected++; } } } __END__
On FreeBSD that gives this slew of warnings\, most of which are expected:
Name "Storable::FOO" used only once: possible typo at /home/nick/test/CorePerl line 16. Use of uninitialized value in concatenation (.) or string at /home/nick/test/CorePerl line 18. '' SCALAR(0x8123d44)Name "Storable::FOO" used only once: possible typo at /home/nick/test/CorePerl line 16. Use of uninitialized value in concatenation (.) or string at /home/nick/test/CorePerl line 18. Use of uninitialized value in warn at /home/nick/test/CorePerl line 23. Warning: something's wrong at /home/nick/test/CorePerl line 23. Use of uninitialized value in pattern match (m//) at /home/nick/test/CorePerl line 25. Use of uninitialized value in concatenation (.) or string at /home/nick/test/CorePerl line 30. perl16767-32 in free(): warning: modified (chunk-) pointer Can't use string ("Name "Storable::FOO" used only o") as a SCALAR ref while "strict refs" in use at /home/nick/test/CorePerl line 22.
BUT NOT THAT ONE: perl16767-32 in free(): warning: modified (chunk-) pointer
Something is scribbling on RAM. The original program gave this:
1..2 ok 1 - No warnings before we start Use of uninitialized value in pattern match (m//) at t/variables.t line 73. Use of uninitialized value in concatenation (.) or string at t/variables.t line 78. Use of uninitialized value in concatenation (.) or string at t/variables.t line 92. not ok 2 - Should be a warning for # Failed test (t/variables.t at line 90) # 'SCALAR(0x8119fcc)' # doesn't match '/^Name "" used only once/' Can't use string ("Use of uninitialized value in co") as a SCALAR ref while "strict refs" in use at t/variables.t line 71. Segmentation fault (core dumped)
I can't see why the logic should end up with me attempting to dereferencing a non-reference. Or why the string has been truncated\, although that looks like it's a side effect of RAM scribbling.
The original program is somewhat longer. I include it\, because it does SEGV for me\, whereas my cutdown version does not.
#!./perl -w
# # Copyright 2002\, Larry Wall. # # You may redistribute only under the same terms as Perl 5\, as specified # in the README file that comes with the distribution. #
# I ought to keep this test easily backwards compatible to 5.004\, so no # qr//;
# This test checks downgrade behaviour on pre-5.8 perls when new 5.8 features # are encountered.
# This might be rather sick way of doing things\, but it should work without # spawning a new perl.
# Array accumulates things we're trying (as refs to scalar)\, interspersed with # warnings seen.
my @warnings; sub BEGIN { if ($ENV{PERL_CORE}){ chdir('t') if -d 't'; @INC = ('.'\, '../lib'); } else { unshift @INC\, 't'; } require Config; import Config; if ($ENV{PERL_CORE} and $Config{'extensions'} !~ /\bStorable\b/) { print "1..0 # Skip: Storable was not built\n"; exit 0; } $SIG{__WARN__} = sub { push @warnings\, $_[0]; print STDERR $_[0] unless $_[0] =~ /^Name "Storable::[a-zA-Z_]+" used only once/; }; }
use Test::More tests => 2; use Storable; use strict;
BEGIN { push @warnings\, \'Storable::FOO'; } $Storable::FOO = 1;
# The idea is that we don't have DEBUGME enabled on shipping code. BEGIN { push @warnings\, \'Storable::DEBUGME'; # Grr' } $Storable::DEBUGME = 1;
# Coredump (no change actually) with our without this one: delete $SIG{__WARN__};
# Now eat our warnings. my $early = 0; while (!ref $warnings[0]) { shift @warnings; $early++; } is ($early\, 0\, "No warnings before we start");
my $unexpected = 0; while (@warnings and my $instruction = shift @warnings) { $instruction = $$instruction; my ($expect\, $got); if ($instruction =~ /^!(.*)/) { # Don't expect to see a warning for this variable. # So should either be at the end\, or next item is another instruction. } else { # Expect a used only once warning. $expect = "/^Name \"$instruction\" used only once/"; }
if (@warnings and ref $warnings[0]) { # Something not an instruction follows us. $got = shift @warnings; # Clear any extra unexpected warnings. while (@warnings and !ref $warnings[0]) { shift @warnings; $unexpected++; } } if ($expect) { # expecting a warning. like ($got\, $expect\, "Should be a warning for $instruction"); } else { is ($got\, $expect\, "Should be no warning for $1"); } }
is ($unexpected\, 0\, "No unexpected warnings"); __END__
Hopefully someone in a more appropriate timezone who isn't going out tomorrow can cut this down to a terse coredump\, or better still patch it.
Bug seems to be present in 5.6.1\, 5.6.0\, 5.005_03 and 5.004_05 too\, although 5.6.0 isn't showing the warning from FreeBSD malloc about modified (chunk-) pointer
Nicholas Clark
Using your simpler version\, 16792\, and Third Degree I get this before the core dump:
---------------------------------------------------------------- fih -- 7 -- util.c: 151: freeing heap at byte 32 of 1008-byte block free libc.so Perl_safesysfree libperl.so\, util.c\, line 151 Perl_sv_setsv_flags libperl.so\, sv.c\, line 3911 Perl_pp_sassign libperl.so\, pp_hot.c\, line 108 Perl_runops_debug libperl.so\, dump.c\, line 1398 S_run_body libperl.so\, perl.c\, line 1673 perl_run libperl.so\, perl.c\, line 1594 main perl\, perlmain.c\, line 85 __start perl
This block at address 0x140045710 was allocated at: malloc libc.so Perl_safesysmalloc libperl.so\, util.c\, line 78 S_more_xrv libperl.so\, sv.c\, line 692 S_new_xrv libperl.so\, sv.c\, line 666 Perl_sv_upgrade libperl.so\, sv.c\, line 1354 S_refto libperl.so\, pp.c\, line 482 Perl_pp_refgen libperl.so\, pp.c\, line 446 Perl_runops_debug libperl.so\, dump.c\, line 1398 S_call_body libperl.so\, perl.c\, line 2037 Perl_call_sv libperl.so\, perl.c\, line 1955 S_call_list_body libperl.so\, perl.c\, line 4053 Perl_call_list libperl.so\, perl.c\, line 3981 Perl_newATTRSUB libperl.so\, op.c\, line 5100 Perl_yyparse libperl.so\, perly.c\, line 1600 S_parse_body libperl.so\, perl.c\, line 1513 perl_parse libperl.so\, perl.c\, line 1040 main perl\, perlmain.c\, line 83 __start perl
-- $jhi++; # http://www.iki.fi/jhi/ # There is this special biologist word we use for 'stable'. # It is 'dead'. -- Jack Cohen
On Sun\, May 26\, 2002 at 05:06:54AM +0300\, Jarkko Hietaniemi wrote:
Using your simpler version\, 16792\, and Third Degree I get this before the core dump:
With the longer version the same heap violation but the script runs a little bit further before barfing.
---------------------------------------------------------------- fih -- 7 -- util.c: 151: freeing heap at byte 32 of 1008-byte block free libc.so Perl_safesysfree libperl.so\, util.c\, line 151 Perl_sv_setsv_flags libperl.so\, sv.c\, line 3911 Perl_pp_sassign libperl.so\, pp_hot.c\, line 108 Perl_runops_debug libperl.so\, dump.c\, line 1398 S_run_body libperl.so\, perl.c\, line 1673 perl_run libperl.so\, perl.c\, line 1594 main perl\, perlmain.c\, line 85 __start perl
This block at address 0x140045710 was allocated at: malloc libc.so Perl_safesysmalloc libperl.so\, util.c\, line 78 S_more_xrv libperl.so\, sv.c\, line 692 S_new_xrv libperl.so\, sv.c\, line 666 Perl_sv_upgrade libperl.so\, sv.c\, line 1354 S_refto libperl.so\, pp.c\, line 482 Perl_pp_refgen libperl.so\, pp.c\, line 446 Perl_runops_debug libperl.so\, dump.c\, line 1398 S_call_body libperl.so\, perl.c\, line 2037 Perl_call_sv libperl.so\, perl.c\, line 1955 S_call_list_body libperl.so\, perl.c\, line 4053 Perl_call_list libperl.so\, perl.c\, line 3981 Perl_newATTRSUB libperl.so\, op.c\, line 5100 Perl_yyparse libperl.so\, perly.c\, line 1600 S_parse_body libperl.so\, perl.c\, line 1513 perl_parse libperl.so\, perl.c\, line 1040 main perl\, perlmain.c\, line 83 __start perl
-- $jhi++; # http://www.iki.fi/jhi/ # There is this special biologist word we use for 'stable'. # It is 'dead'. -- Jack Cohen
-- $jhi++; # http://www.iki.fi/jhi/ # There is this special biologist word we use for 'stable'. # It is 'dead'. -- Jack Cohen
This is the minimum I can in Tru64 whittle it down and still get the mid-heap free seen by Third Degree (notes: $SIG{__WARN__} is now outside of a BEGIN\, while loop has been unrolled\, the $expect has been simplified (it still needs to be a "")\, the constant scalar ref has been simplified.
Note that I get SIGILL\, not SIGSEGV. If I remove the $SIG{__WARN__} bit\, no more the mid-heap free\, but I still do get the SIGILL.
#!./perl -w
my @warnings;
BEGIN { push @warnings\, \'FOO'; }
$SIG{__WARN__} = sub { push @warnings\, $_[0]; };
my $instruction; my $expect;
$instruction = shift @warnings; $instruction = $$instruction; $expect = "\"$instruction\""; $instruction = shift @warnings;
__END__
-- $jhi++; # http://www.iki.fi/jhi/ # There is this special biologist word we use for 'stable'. # It is 'dead'. -- Jack Cohen
And here's Purify trace for my cut-down version:
**** Purify instrumented pureperl (pid 22849 at Sun May 26 11:49:30 2002)
* Purify 2001a.04.00 Solaris 2 (32-bit) Copyright (C) 1992-2001 Rational Software Corp. All rights reserved.
* For contact information type: "purify -help"
* Options settings: -chain-length=25 -windows=no -log-file=perl.log \
-append-logfile=yes -purify \
-purify-home=/usr/common/apps/purify/releases/purify.sol.2001a.04.00
* License successfully checked out.
* Command-line: pureperl -Ilib /home/jpl/pt
**** Purify instrumented pureperl (pid 22849) **** FMR: Free memory read: * This is occurring while in: Perl_sv_clear [sv.c:4984] Perl_sv_free [sv.c:5188] Perl_av_undef [av.c:455] Perl_sv_clear [sv.c:5016] Perl_sv_free [sv.c:5188] Perl_cv_undef [op.c:4409] Perl_sv_clear [sv.c:5010] Perl_sv_free [sv.c:5188] Perl_cv_undef [op.c:4388] Perl_sv_clear [sv.c:5010] Perl_sv_free [sv.c:5188] Perl_sv_clear [sv.c:5042] Perl_sv_free [sv.c:5188] Perl_hv_free_ent [hv.c:1594] S_hfreeentries [hv.c:1681] Perl_hv_undef [hv.c:1707] Perl_sv_clear [sv.c:5013] Perl_sv_free [sv.c:5188] Perl_gp_free [gv.c:1247] Perl_sv_clear [sv.c:5022] Perl_sv_free [sv.c:5188] do_clean_all [sv.c:400] S_visit [sv.c:292] Perl_sv_clean_all [sv.c:418] perl_destruct [perl.c:770] * Reading 4 bytes from 0x3ca3e0 in the heap. * Address 0x3ca3e0 is 21 bytes past end of a freed block at 0x3ca3c8 of 4 bytes. * This block was allocated from: malloc [rtlib.o] Perl_safesysmalloc [util.c:78] Perl_sv_upgrade [sv.c:1354] Perl_sv_setsv_flags [sv.c:3627] Perl_pp_sassign [pp_hot.c:108] Perl_runops_debug [dump.c:1398] S_run_body [perl.c:1673] perl_run [perl.c:1594] main [perlmain.c:85] _start [crt1.o] * There have been 687 frees since this block was freed.
**** Purify instrumented pureperl (pid 22849) **** FMR: Free memory read: * This is occurring while in: Perl_mg_free [mg.c:351] Perl_sv_clear [sv.c:4985] Perl_sv_free [sv.c:5188] Perl_av_undef [av.c:455] Perl_sv_clear [sv.c:5016] Perl_sv_free [sv.c:5188] Perl_cv_undef [op.c:4409] Perl_sv_clear [sv.c:5010] Perl_sv_free [sv.c:5188] Perl_cv_undef [op.c:4388] Perl_sv_clear [sv.c:5010] Perl_sv_free [sv.c:5188] Perl_sv_clear [sv.c:5042] Perl_sv_free [sv.c:5188] Perl_hv_free_ent [hv.c:1594] S_hfreeentries [hv.c:1681] Perl_hv_undef [hv.c:1707] Perl_sv_clear [sv.c:5013] Perl_sv_free [sv.c:5188] Perl_gp_free [gv.c:1247] Perl_sv_clear [sv.c:5022] Perl_sv_free [sv.c:5188] do_clean_all [sv.c:400] S_visit [sv.c:292] Perl_sv_clean_all [sv.c:418] * Reading 4 bytes from 0x3ca3e0 in the heap. * Address 0x3ca3e0 is 21 bytes past end of a freed block at 0x3ca3c8 of 4 bytes. * This block was allocated from: malloc [rtlib.o] Perl_safesysmalloc [util.c:78] Perl_sv_upgrade [sv.c:1354] Perl_sv_setsv_flags [sv.c:3627] Perl_pp_sassign [pp_hot.c:108] Perl_runops_debug [dump.c:1398] S_run_body [perl.c:1673] perl_run [perl.c:1594] main [perlmain.c:85] _start [crt1.o] * There have been 687 frees since this block was freed.
**** Purify instrumented pureperl (pid 22849) **** MSE: Memory segment error: * This is occurring while in: Perl_mg_free [mg.c:354] Perl_sv_clear [sv.c:4985] Perl_sv_free [sv.c:5188] Perl_av_undef [av.c:455] Perl_sv_clear [sv.c:5016] Perl_sv_free [sv.c:5188] Perl_cv_undef [op.c:4409] Perl_sv_clear [sv.c:5010] Perl_sv_free [sv.c:5188] Perl_cv_undef [op.c:4388] Perl_sv_clear [sv.c:5010] Perl_sv_free [sv.c:5188] Perl_sv_clear [sv.c:5042] Perl_sv_free [sv.c:5188] Perl_hv_free_ent [hv.c:1594] S_hfreeentries [hv.c:1681] Perl_hv_undef [hv.c:1707] Perl_sv_clear [sv.c:5013] Perl_sv_free [sv.c:5188] Perl_gp_free [gv.c:1247] Perl_sv_clear [sv.c:5022] Perl_sv_free [sv.c:5188] do_clean_all [sv.c:400] S_visit [sv.c:292] Perl_sv_clean_all [sv.c:418] * Accessing a memory range that crosses a memory segment boundary. Addressing 0x1000010 for 4 bytes ending at 0x1000014\, which is neither in the heap nor the main stack.
**** Purify instrumented pureperl (pid 22849) **** COR: Fatal core dump: * This is occurring while in: Perl_mg_free [mg.c:354] Perl_sv_clear [sv.c:4985] Perl_sv_free [sv.c:5188] Perl_av_undef [av.c:455] Perl_sv_clear [sv.c:5016] Perl_sv_free [sv.c:5188] Perl_cv_undef [op.c:4409] Perl_sv_clear [sv.c:5010] Perl_sv_free [sv.c:5188] Perl_cv_undef [op.c:4388] Perl_sv_clear [sv.c:5010] Perl_sv_free [sv.c:5188] Perl_sv_clear [sv.c:5042] Perl_sv_free [sv.c:5188] Perl_hv_free_ent [hv.c:1594] S_hfreeentries [hv.c:1681] Perl_hv_undef [hv.c:1707] Perl_sv_clear [sv.c:5013] Perl_sv_free [sv.c:5188] Perl_gp_free [gv.c:1247] Perl_sv_clear [sv.c:5022] Perl_sv_free [sv.c:5188] do_clean_all [sv.c:400] S_visit [sv.c:292] Perl_sv_clean_all [sv.c:418] * Received signal 11 (SIGSEGV - Segmentation Fault) * Faulting address = 0x1000010 * Signal mask: (SIGSEGV) * Pending signals:
-- $jhi++; # http://www.iki.fi/jhi/ # There is this special biologist word we use for 'stable'. # It is 'dead'. -- Jack Cohen
I have Jarkko's test case down to:
#!./perl
my @warnings;
BEGIN { push @warnings\, \'FOO'; }
my $instruction = shift @warnings; $instruction = $$instruction;
Sadly it causes a the `impossible' happened bug in valgrind\, so I'm at a bit of a loss. However\, with this version the SEGV happens in global destruction. So\, if I change the above to this:
SV = RV(0x817a1ac) at 0x81791dc REFCNT = 1 FLAGS = (PADMY\,ROK) RV = 0x8179230 SV = PV(0x816aaf4) at 0x8179230 REFCNT = 1 FLAGS = (POK\,READONLY\,pPOK) PV = 0x816e338 "FOO"\0 CUR = 3 LEN = 4 SV = UNKNOWN(0xff) (0x817a1ac) at 0x81791dc REFCNT = 1 FLAGS = (PADMY)
but if I take the BEGIN block out no SEGV\, and I see this:
SV = RV(0x8179f34) at 0x81791f4 REFCNT = 1 FLAGS = (PADMY\,ROK) RV = 0x81791dc SV = PV(0x816aadc) at 0x81791dc REFCNT = 2 FLAGS = (POK\,READONLY\,pPOK) PV = 0x8179e70 "FOO"\0 CUR = 3 LEN = 4 SV = PV(0x816aa10) at 0x81791f4 REFCNT = 1 FLAGS = (PADMY\,POK\,pPOK) PV = 0x81805e0 "FOO"\0 CUR = 3 LEN = 4
What is so special about the BEGIN block that it is trashing the stack\, and causing a later SEGV?
(this is still a bug in current blead)
Nicholas Clark
OK. I found this via the RT web interface\, and added a comment there\, but it's not yet shown up here despite the fact that I added perl5-porters@perl.org as a CC
On Sun\, May 26\, 2002 at 05:46:06AM +0300\, Jarkko Hietaniemi wrote:
#!./perl -w
my @warnings;
BEGIN { push @warnings\, \'FOO'; }
$SIG{__WARN__} = sub { push @warnings\, $_[0]; };
my $instruction; my $expect;
$instruction = shift @warnings; $instruction = $$instruction; $expect = "\"$instruction\""; $instruction = shift @warnings;
__END__
I have Jarkko's test case down to:
#!./perl
my @warnings;
BEGIN { push @warnings\, \'FOO'; }
my $instruction = shift @warnings; $instruction = $$instruction;
Sadly it causes a the `impossible' happened bug in valgrind\, so I'm at a bit of a loss. However\, with this version the SEGV happens in global destruction. So\, if I change the above to Devel::Peek::Dump $instruction before and after the last line\, I see:
SV = RV(0x817a1ac) at 0x81791dc REFCNT = 1 FLAGS = (PADMY\,ROK) RV = 0x8179230 SV = PV(0x816aaf4) at 0x8179230 REFCNT = 1 FLAGS = (POK\,READONLY\,pPOK) PV = 0x816e338 "FOO"\0 CUR = 3 LEN = 4 SV = UNKNOWN(0xff) (0x817a1ac) at 0x81791dc REFCNT = 1 FLAGS = (PADMY)
but if I take the BEGIN block out no SEGV\, and I see this:
SV = RV(0x8179f34) at 0x81791f4 REFCNT = 1 FLAGS = (PADMY\,ROK) RV = 0x81791dc SV = PV(0x816aadc) at 0x81791dc REFCNT = 2 FLAGS = (POK\,READONLY\,pPOK) PV = 0x8179e70 "FOO"\0 CUR = 3 LEN = 4 SV = PV(0x816aa10) at 0x81791f4 REFCNT = 1 FLAGS = (PADMY\,POK\,pPOK) PV = 0x81805e0 "FOO"\0 CUR = 3 LEN = 4
What is so special about the BEGIN block that it is trashing the stack\, and causing a later SEGV? Is there some dangling reference to an SV constant held in an OP that gets freed up when the BEGIN block completes?
(this is still a bug in current blead)
Nicholas Clark
On Fri\, Jan 17\, 2003 at 09:46:40PM +0000\, Nicholas Clark wrote:
I have Jarkko's test case down to:
#!./perl
my @warnings;
BEGIN { push @warnings\, \'FOO'; }
my $instruction = shift @warnings; $instruction = $$instruction;
It reduces to the even simpler case:
my $y; BEGIN { $y=\1; } $y = $$y;
What is happening is that $y is an RV pointing to an IV(1).
Initially the IV has a refcnt of 2 (one pointer from $y\, the other pointerr in its capacity as a constant\, either in BEGIN's pad or BEGIN's const op (depending on threading)).
After the BEGIN CV has finished executing and is undef'ed\, the pad/opconst pointer is thrown away\, and the IV(1) is left with a refcnt of 1\, *and* it is SvREADONLY.
When the $y = $$y is done\, the following is called:
Perl_sv_setsv_flags(dstr=RV(IV(1))\, sstr=IV(1)) is called\,
which does
SV_CHECK_THINKFIRST_COW_DROP(dstr);
which does
if (SvROK(sv)) sv_unref_flags(sv\, flags);
which does
if (SvREFCNT(rv) != 1 || SvREADONLY(rv) || (flags & SV_IMMEDIATE_UNREF)) SvREFCNT_dec(rv);
which blows away the IV(1)\, which eventually leaves $y as a freed SV:
as shown by the output of -DstR:
(/tmp/p:5) padsv($y)
=> \IV(1)
(/tmp/p:5) rv2sv
=> IV(1)
(/tmp/p:5) padsv($y)
=> IV(1) \IV(1)
(/tmp/p:5) sassign
=> FREED
So it's a combination of the fact that the IV is SvREADONLY (because its a constant)\, and it has refcnt of 1 (because it appeared in a BEGIN).
That's what the problem is\, I haven't a clue what the solution is.
Dave.
-- "You're so sadly neglected\, and often ignored. A poor second to Belgium\, When going abroad." Monty Python - "Finland"
On Fri\, Jan 17\, 2003 at 09:46:40PM +0000\, Nicholas Clark wrote:
I have Jarkko's test case down to:
#!./perl
my @warnings;
BEGIN { push @warnings\, \'FOO'; }
my $instruction = shift @warnings; $instruction = $$instruction;
$mild_expletive that:
perl -le 'my $a; BEGIN {$a = \"Foo"}; $a = $$a; Segmentation fault (core dumped)
take out the my\, no SEGV. However\, if you try to print $a\, you see that something is going wrong:
$ perl -le '$a; BEGIN {$a = \"Foo"}; $a = $$a; print $a'
Dumping (as before)
$ ./perl -Ilib -MDevel::Peek -le '$a; BEGIN {$a = \"Foo"}; Dump $a; $a = $$a; Dump $a' SV = RV(0x817ec28) at 0x817383c REFCNT = 1 FLAGS = (ROK) RV = 0x817386c SV = PV(0x8164580) at 0x817386c REFCNT = 1 FLAGS = (POK\,READONLY\,pPOK) PV = 0x8163f50 "Foo"\0 CUR = 3 LEN = 4 SV = UNKNOWN(0xff) (0x817ec28) at 0x817383c REFCNT = 1 FLAGS = ()
What is so special about the BEGIN block that it is trashing the stack\, and causing a later SEGV? Is there some dangling reference to an SV constant held in an OP that gets freed up when the BEGIN block completes?
(this is still a bug in current blead)
Answer:
Perl_sv_setsv_flags (dstr=0x81707d8\, sstr=0x8173c6c\, flags=2) at sv.c:3572 3572 if (sstr == dstr) (gdb) call Perl_sv_dump(dstr) SV = RV(0x8175410) at 0x81707d8 REFCNT = 1 FLAGS = (PADBUSY\,PADMY\,ROK) RV = 0x8173c6c (gdb) call Perl_sv_dump(sstr) SV = PV(0x8164550) at 0x8173c6c REFCNT = 1 FLAGS = (POK\,READONLY\,pPOK) PV = 0x8163ef0 "Foo"\0 CUR = 3 LEN = 4 (gdb) step 3574 SV_CHECK_THINKFIRST_COW_DROP(dstr); (gdb) next 3575 if (!sstr) (gdb) call Perl_sv_dump(sstr) SV = UNKNOWN(0xff) (0x816415c) at 0x8173c6c REFCNT = 0 FLAGS = ()
In the assignment $a = $$a\, $a (the destination) holds the last reference to $$a (the source). So at that SV_CHECK_THINKFIRST_COW_DROP(dstr); clears the destination\, which causes the refcount of the source to drop to zero\, and it gets freed. Whoops.
All this happens due to a rather unusual combination of circumstances. There is no IMMEDIATE_UNREF flag\, so one wouldn't expect an immediate unref. However\, the logic in Perl_sv_unref_flags goes like this:
if (SvREFCNT(rv) != 1 || SvREADONLY(rv) || (flags & SV_IMMEDIATE_UNREF)) SvREFCNT_dec(rv); else /* XXX Hack\, but hard to make $a=$a->[1] work otherwise */ sv_2mortal(rv); /* Schedule for freeing later */
so as the rv is READONLY (it's the readonly string "Foo") it gets zapped.
The reason we don't normally see this is because usually there's an OP holding onto another reference for the constant. So the destination scalar isn't the last referent.
Now that I know the cause of the problem\, here's another without the BEGIN block\, albeit 5.8.0 specific.
$ ./perl -Ilib -MDevel::Peek -le '%a = perl=>"rules"; my $a = \keys %a; Dump $a; $a = $$a; Dump $a' SV = RV(0x817ec28) at 0x81738b4 REFCNT = 1 FLAGS = (PADBUSY\,PADMY\,ROK) RV = 0x81641ec SV = PVIV(0x8164820) at 0x81641ec REFCNT = 1 FLAGS = (POK\,FAKE\,READONLY\,pPOK) IV = -1271882440 PV = 0x81630f8 "perl" CUR = 4 LEN = 0 SV = UNKNOWN(0xff) (0x817ec28) at 0x81738b4 REFCNT = 1 FLAGS = (PADBUSY\,PADMY) Bus error (core dumped)
I think that the READONLY test should go. Any reason why it must stay?
Nicholas Clark
On Fri\, Jan 17\, 2003 at 11:25:34PM -0000\, Dave Mitchell wrote:
It reduces to the even simpler case:
my $y; BEGIN \{ $y=\\1; \} $y = $$y;
That's what the problem is\, I haven't a clue what the solution is.
Thanks. Offline I've just worked out the same thing. :-)
Nicholas Clark
Nicholas Clark \nick@​unfortu\.net writes:
I think that the READONLY test should go. Any reason why it must stay?
Can't see one so far.
Nicholas Clark -- Nick Ing-Simmons http://www.ni-s.u-net.com/
On Sat\, Jan 18\, 2003 at 06:07:14PM +0000\, Nick Ing-Simmons wrote:
Nicholas Clark \nick@​unfortu\.net writes:
I think that the READONLY test should go. Any reason why it must stay?
Can't see one so far.
This passes all tests for a normal\, and ithreads with -DPERL_COPY_OR_WRITE -DDEBUGGING
Nicholas Clark
Presumably the patch fixed this bug\, so I'm marking it as resolved.
Dave.
@iabyn - Status changed from 'open' to 'resolved'
Migrated from rt.perl.org#9394 (status was 'resolved')
Searchable as RT9394$