Perl / perl5

🐪 The Perl programming language
https://dev.perl.org/perl5/
Other
1.94k stars 554 forks source link

"panic: attept to copy freed scalar" during destruction #11661

Closed p5pRT closed 13 years ago

p5pRT commented 13 years ago

Migrated from rt.perl.org#99660 (status was 'resolved')

Searchable as RT99660$

p5pRT commented 13 years ago

From @doy

Created by @doy

Attempting to access a hash entry where an object was just removed from during that object's destructor causes a panic​:

#!/usr/bin/env perl use strict; use warnings; use Test​::More;

my $called;

{   my %cache;   sub get { $cache{$_[0]} }   sub store { $cache{$_[0]} = $_[1] }   sub remove { delete $cache{$_[0]}; return } }

{   package Thing;   sub new { my $class = shift; bless { name => $_[0] }\, $class }   sub name { shift->{name} }   sub DESTROY {   my $self = shift;   my $thing = :​:get($self->name);   $called = 1;   } }

store(foo => Thing->new('foo')); remove('foo');

is($called\, 1\, "got through the DESTROY method");

done_testing;

__END__   (in cleanup) panic​: attempt to copy freed scalar d5f500 to d5f4e8 at test.pl line 21. not ok 1 - got through the DESTROY method # Failed test 'got through the DESTROY method' # at test.pl line 29. # got​: undef # expected​: '1' 1..1 # Looks like you failed 1 test of 1.

Bisecting points to this commit as causing the issue​:

commit f50383f58716bc0faa50de094d47cad8ad3fcbdb Author​: Ton Hospel \me\-02@​ton\.iguana\.be Date​: Thu May 19 17​:05​:16 2011 -0700

  [perl #85026] Deleting the current iterator in void context  
  Looking at the delete code I see another strange thing. If the delete   of the current iterator is done with the G_DISCARD flag\, the corres-   ponding value is not freed and survives until the lazy deleted entry   gets removed on the next hash iteration. This is easily demonstrated   like this​:  
  perl -wle '   sub DESTROY { print "DESTROY" }   %a=(a=>bless[]);   each %a;   delete $a{a};   print "END"   '  
  This prints​:  
  END   DESTROY  
  notice the difference with​:  
  perl -wle '   sub DESTROY { print "DESTROY" }   %hash = (a => bless[]);   each %hash;   $dummy = delete $hash{a}; $dummy = 0;   print "END"   '  
  This prints​:  
  DESTROY   END  
  This is easily solved by always replacing the deleted entry value with   &PL_sv_placeholder. It actually simplifies the code a bit except for the   fact that the mro_method_changed from free_hash_ent now has to be done   in hv_delete

Perl Info ``` Flags: category=core severity=medium Site configuration information for perl 5.15.3: Configured by doy at Tue Sep 20 14:03:06 CDT 2011. Summary of my perl5 (revision 5 version 15 subversion 3) configuration: Platform: osname=linux, osvers=3.0-arch, archname=x86_64-linux uname='linux zaon 3.0-arch #1 smp preempt tue aug 30 08:53:25 cest 2011 x86_64 intel(r) core(tm) i5 cpu m 520 @ 2.40ghz genuineintel gnulinux ' config_args='-de -Dprefix=/home/doy/perl5/perlbrew/perls/perl-5.15.3 -Dusedevel' hint=recommended, useposix=true, d_sigaction=define useithreads=undef, usemultiplicity=undef useperlio=define, d_sfio=undef, uselargefiles=define, usesocks=undef use64bitint=define, use64bitall=define, uselongdouble=undef usemymalloc=n, bincompat5005=undef Compiler: cc='cc', ccflags ='-fno-strict-aliasing -pipe -fstack-protector -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64', optimize='-O2', cppflags='-fno-strict-aliasing -pipe -fstack-protector -I/usr/local/include' ccversion='', gccversion='4.6.1 20110819 (prerelease)', gccosandvers='' intsize=4, longsize=8, ptrsize=8, doublesize=8, byteorder=12345678 d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=16 ivtype='long', ivsize=8, nvtype='double', nvsize=8, Off_t='off_t', lseeksize=8 alignbytes=8, prototype=define Linker and Libraries: ld='cc', ldflags =' -fstack-protector -L/usr/local/lib' libpth=/usr/local/lib /lib/../lib /usr/lib/../lib /lib /usr/lib libs=-lnsl -lgdbm -ldb -ldl -lm -lcrypt -lutil -lc -lgdbm_compat perllibs=-lnsl -ldl -lm -lcrypt -lutil -lc libc=/lib/libc-2.14.so, so=so, useshrplib=false, libperl=libperl.a gnulibc_version='2.14' Dynamic Linking: dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef, ccdlflags='-Wl,-E' cccdlflags='-fPIC', lddlflags='-shared -O2 -L/usr/local/lib -fstack-protector' Locally applied patches: @INC for perl 5.15.3: /home/doy/perl5/local/ /home/doy/perl5/local/lib/perl5/site_perl/5.10.0/i686-linux /home/doy/perl5/perlbrew/perls/perl-5.15.3/lib/site_perl/5.15.3/x86_64-linux /home/doy/perl5/perlbrew/perls/perl-5.15.3/lib/site_perl/5.15.3 /home/doy/perl5/perlbrew/perls/perl-5.15.3/lib/5.15.3/x86_64-linux /home/doy/perl5/perlbrew/perls/perl-5.15.3/lib/5.15.3 . Environment for perl 5.15.3: HOME=/home/doy LANG=en_US.UTF-8 LANGUAGE (unset) LD_LIBRARY_PATH (unset) LOGDIR (unset) PATH=/home/doy/perl5/perlbrew/bin:/home/doy/perl5/perlbrew/perls/perl-5.15.3/bin:/home/doy/.bin/marathon:/home/doy/.bin/nethack:/home/doy/.bin:/usr/local/sbin:/usr/local/bin:/usr/lib/ccache/bin:/usr/local/bin:/usr/bin:/bin:/usr/local/sbin:/usr/sbin:/sbin:/usr/bin/site_perl:/usr/bin/core_perl PERL5LIB=/home/doy/perl5/local/:/home/doy/perl5/local/lib/perl5/site_perl/5.10.0/i686-linux PERLBREW_HOME=/home/doy/.perlbrew PERLBREW_PATH=/home/doy/perl5/perlbrew/bin:/home/doy/perl5/perlbrew/perls/perl-5.15.3/bin PERLBREW_PERL=perl-5.15.3 PERLBREW_ROOT=/home/doy/perl5/perlbrew PERLBREW_VERSION=0.28 PERL_BADLANG (unset) PERL_CPANM_OPT=-q --mirror file:///home/doy/perl5/minicpan/ --mirror http://mirrors.kernel.org/cpan/ --mirror http://search.cpan.org/CPAN --prompt SHELL=/bin/bash ```
p5pRT commented 13 years ago

From @cpansprout

Fixed locally; running tests....

p5pRT commented 13 years ago

The RT System itself - Status changed from 'new' to 'open'

p5pRT commented 13 years ago

From @cpansprout

Fixed with commit 7058221.

p5pRT commented 13 years ago

@cpansprout - Status changed from 'open' to 'resolved'