This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
FREETMPS when leaving eval, even when void/dying
authorDavid Mitchell <davem@iabyn.com>
Mon, 22 Aug 2016 08:50:43 +0000 (09:50 +0100)
committerDavid Mitchell <davem@iabyn.com>
Mon, 5 Jun 2017 13:59:25 +0000 (14:59 +0100)
commitb66d79a6843486dbfe3a6f0a5fb78ffb86dd82e2
tree3b0ffad007ef042821dc1248a1d7a5614c49102c
parent655f5b268af8bf50c44ba4ae4803a33c9b792b8b
FREETMPS when leaving eval, even when void/dying

[ This commit was originally added as v5.25.2-77-g214949f then reverted
by v5.25.2-89-gcc040a9, since it broke Variable::Magic. That distribution
has since been fixed, so this fix can be re-applied to blead ]

When a scope is exited normally (e.g. pp_leavetry, pp_leavesub),
we do a FREETMPS only in scalar or list context; in void context
we don't bother for efficiency reasons. Similarly, when there's an
exception and we unwind to (and then pop) an EVAL context, we haven't
been bothering to FREETMPS.

The problem with this in try/eval (exiting normally or via an exception)
is that it can delay some SVs getting freed until *after* $@ has been
set. If that freeing calls a destructor which happens to set $@,
then that overwrites the "real" value of $@.

For example

    sub DESTROY { eval { die "died in DESTROY"; } }
    eval { bless []; };
    is ($@, "");

Before this commit, that test would fail because $@ is "died in DESTROY".

This commit ensures that leaving an eval/try by whatever means always
clears the tmps stack before setting $@.

See http://nntp.perl.org/group/perl.perl5.porters/237380.

For now, I haven't added a FREETMPS to the other pp_leavefoo()
void context cases, since I can't think of a case where it would
matter.
pp_ctl.c
t/op/eval.t