develooper Front page | perl.perl5.porters | Postings from February 2009

[perl #52610] Bizarre copy of ARRAY in sassign at Carp/Heavy.pm

Thread Previous | Thread Next
From:
Bram via RT
Date:
February 15, 2009 08:50
Subject:
[perl #52610] Bizarre copy of ARRAY in sassign at Carp/Heavy.pm
Message ID:
rt-3.6.HEAD-12283-1234571201-309.52610-15-0@perl.org
> Thanks for this bug report. The error has been seen before, but not
> with this
> concise a test case. I can reduce it down to this:
> 
> $ cat C.pm
> package C;
> sub longmess_real {
>   package DB;
>   () = caller(2);
> 
>   use Devel::Peek; Dump \@DB::args;
> 
>   foreach(@DB::args) {
>     my $a = $_;
>   }
> }
> 
> 1;
> __END__
> $ cat 52610
> sub longmess {
>     require C;
>     goto &C::longmess_real;
> }
> 
> sub do_carp {
>     longmess;
> }
> 
> sub call_with_args {
>     my ($arg_hash, $func) = @_;
>     $func->(@{$arg_hash->{'args'}});
> }
> 
> my $h = {};
> # Deleting the undef makes it all work again!
> my $arg_hash = {'args' => [undef]};
> call_with_args($arg_hash, sub {
>     $arg_hash->{'args'} = [];
>     do_carp(sub { $h; });
> });
> __END__

'# Deleting the undef makes it all work again!'
=> This is not correct. The problem was only invisible because the 
array was empty.

[...] 

> It looks like the address of something on Perl's stack ends up being
> re-used
> as something (else) that points into a PAD. I'm not entirely sure why,
> and
> it's something "special" with how caller and package DB interact.


Reduced the test case a bit more:

Test case 1: Bizarre copy of ARRAY

#!/usr/bin/perl

my $args = [ "AAA" ];
sub s1 {
  my ($args2) = @_;

  $args = [ "BBB" ];
  my $h = {};
  my $z = sub { $h };
  s2();
}

sub s2 {
  package DB;
  my (@foo) = caller(1);
  print "ARG: $DB::args[0]\n";
  foreach(@DB::args) {
    my $c = $_;
  }
}

s1(@$args);
__END__

Expected output: 'ARG: AAA'

$ miniperl-5.000 rt-52610.pl
ARG: AAA

$ miniperl-5.001 rt-52610.pl
ARG:

$ miniperl-perl-5.001n rt-52610.pl
ARG:

$ miniperl-5.002beta1 rt-52610.pl
ARG:
Bizarre copy of ARRAY in scalar assignment at rt-52610.pl line 18.

$ perl-5.8.8 rt-52610.pl
ARG:
Bizarre copy of ARRAY in sassign at rt-52610.pl line 18.


=> perl-5.000 outputs 'ARG: AAA' because closures were not yet 
implemented. This means that the $arg_hash->{args} in sub s1 is another 
scalar.
=> If the test is repeated with global variables then perl-5.000 also 
outputs 'ARG: '



Test case 2: copy $args before changing it

#!/usr/bin/perl

my $args = [ "AAA" ];
sub s1 {
  my ($args2) = @_;

  my $t = $args;
  $args = [ "BBB" ];
  my $h = {};
  my $z = sub { $h };
  s2();
}

sub s2 {
  package DB;
  my (@foo) = caller(1);
  print "ARG: $DB::args[0]\n";
  foreach(@DB::args) {
    my $c = $_;
  }
}

s1(@$args);

__END__

$ perl-5.8.8 rt-52610.pl
ARG: AAA


Test case 3: Remove $h and $z

#!/usr/bin/perl

my $args = [ "AAA" ];
sub s1 {
  my ($args2) = @_;

  $args = [ "CCC" ];
  s2();
}

sub s2 {
  package DB;
  my (@foo) = caller(1);
  print "ARG: $DB::args[0]\n";
  foreach(@DB::args) {
    my $c = $_;
  }
}

s1(@$args);
__END__

$ perl-5.8.0 rt-52610.pl
ARG:
Segmentation fault

$ perl-5.8.1 rt-52610.pl
ARG:
Use of freed value in iteration at rt-52610.pl line 15.

$ perl-5.8.8 rt-52610.pl
ARG:
Use of freed value in iteration at rt-52610.pl line 15.



Test case 4: use three hashes instead of a hash and a subroutine

#!/usr/bin/perl

my $args = [ "AAA" ];
sub s1 {
  my ($args2) = @_;

  $args = [ "BBB" ];

  my $h = {};
  my $h2 = {};
  my $h3 = {};

  s2();
}

sub s2 {
  package DB;
  my (@foo) = caller(1);
  print "ARG: $DB::args[0]\n";
  foreach(@DB::args) {
    my $c = $_;
  }
}

s1(@$args);
__END__

$ perl-5.8.8 rt-52610.pl
ARG:
Bizarre copy of HASH in sassign at rt-52610.pl line 21.




Test case 5: Use: @foo2 = @DB::args

#!/usr/bin/perl

my $args = [ "AAA" ];
sub s1 {
  my ($args2) = @_;

  $args = [ "BBB" ];
  s2();
}

sub s2 {
  package DB;
  my (@foo) = caller(1);
  print "ARG: $DB::args[0]\n";
  my @foo2 = @DB::args;
}

s1(@$args);
__END__

$ perl-5.8.6 rt-52610.pl
ARG:
Segmentation fault

$ perl-5.8.7 rt-52610.pl
ARG:
semi-panic: attempt to dup freed string at rt-52610.pl line 15.

$ perl-5.8.8 rt-52610.pl
ARG:
semi-panic: attempt to dup freed string at rt-52610.pl line 15.



Kind regards,

Bram


Thread Previous | Thread Next


nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About