Branch: refs/heads/blead
  Home:   https://github.com/Perl/perl5
  Commit: 58cf04199f69d7a775bc88024df0bbb48712ea37
      
https://github.com/Perl/perl5/commit/58cf04199f69d7a775bc88024df0bbb48712ea37
  Author: David Mitchell <da...@iabyn.com>
  Date:   2022-07-06 (Wed, 06 Jul 2022)

  Changed paths:
    M ext/XS-APItest/APItest.pm
    M ext/XS-APItest/APItest.xs
    M pp_ctl.c
    M t/op/goto.t

  Log Message:
  -----------
  goto(&xs_sub): provide correct caller context

GH #19188

in something like

    sub foo { goto &xs_sub }

if the XS subroutine tries to get its caller context using GIMME_V,
it used to always be reported as scalar, since the OP_GOTO is the
current op being executed, and that op is marked as scalar.

The correct answer should be to return the context of the caller of
foo(), but that information is lost as, just before calling the XS sub,
pp_goto pops the CXt_SUB off the context stack which holds the recorded
value of the context of the caller.

The fix in principle is for goto, just before calling the XS sub, to
grab the gimme value from  the about-to-be-popped CXt_SUB frame, and set
OP_GOTO op's op_flag field with that gimme value.

However, modifying ops at runtime isn't allowed, as ops are shared
between threads. So instead set up a fake copy of the OP_GOTO and alter
the gimme value in that instead.

I'm pretty confident that on an exception, a LEAVE_SCOPE() will always
be done before the JMPENV_JUMP(), so PL_op will be restored to its
original value *before* the CPU stack is restored to it's old value
(leaving the temporary OP_GOTO as garbage in an abandoned stack frame).


Reply via email to