Branch: refs/heads/smoke-me/davem/rc_stack2
  Home:   https://github.com/Perl/perl5
  Commit: 3fe82d61f99cef69b642733c096dc3b2b98946f8
      
https://github.com/Perl/perl5/commit/3fe82d61f99cef69b642733c096dc3b2b98946f8
  Author: David Mitchell <da...@iabyn.com>
  Date:   2023-03-15 (Wed, 15 Mar 2023)

  Changed paths:
    M pp_ctl.c

  Log Message:
  -----------
  pp_caller(): set @DB::args earlier

Copy @_ SV pointers to @DB::args earlier, before pp_caller() has the
chance to create any new SVs (e.g. for the package name). This will give
the next commit a chance to discover and skip any freed elements in @_.

This commit makes no changes to the block of code that is moved;
that's saved for the next commit.


  Commit: f67f2243f29cee7407a9ca0e2c1b2ec22ed0ea73
      
https://github.com/Perl/perl5/commit/f67f2243f29cee7407a9ca0e2c1b2ec22ed0ea73
  Author: David Mitchell <da...@iabyn.com>
  Date:   2023-03-15 (Wed, 15 Mar 2023)

  Changed paths:
    M pp_ctl.c
    M t/op/caller.t

  Log Message:
  -----------
  caller(): don't copy freed SV pointer to @DB::args

When pp_caller() aliases the elements of @_ to @DB::args, it may include
pointers to array elements which have been shifted away. So for example
in

    sub f { my $self = shift; ....; croak() }

it populates $DB::args[0] with the SV pointer one position below the
AvARRAY() of @_. This means that the argument lists in the stack
backtrace provided by croak() will include the original first arg,
which is nice, but is very fragile. There is no guarantee that that SV
hasn't been freed or reallocated in the meantime.

This commit adds a check for each SV pointer being copied to @DB::args,
which NULLs it if the SV has a refcount of 0.

This means that in something like:

    package DB:
    () = caller($i);
    my @args = @DB::args;

perl will no longer panic about copying a freed SV.

Note that this commit does not address the issue of the SV having already
been reallocated. In the example above, some elements of @args may
contain a copy of some other random variable. However, the previous
commit moved to earlier in the function, the block of code in
pp_caller() which populates @DB::args, to before pp_caller() allocates
new SVs for things like the package name. Which means the RC==0 test
added by this commit has a better chance of spotting SVs which have been
freed but not yet reallocated.

In summary, @DB::args is still a horrible, fragile hack, but these two
commits make it slightly less fragile in some circumstances.


Compare: https://github.com/Perl/perl5/compare/dec99a6d0e02...f67f2243f29c

Reply via email to