CC: | DDUMONT [...] cpan.org, ANDK [...] cpan.org |
Subject: | Bad ERRSV handling in BUILD call |
mouse_call_sv_safe in MouseUtil.xs has these two lines:
SAVESPTR(ERRSV);
ERRSV = sv_newmortal();
The problem with setting $@ to a temp variable with a refcount of 1 is that perl thinks it can
steal its string buffer, resulting in bugs like this:
use Test::More tests => 1;
{use Mouse}
sub BUILD {
$@ = "foo";
my $x = $@;
is $@, "foo"; # fails because $@ is undef
}
new main;
__END__
(This is the cause of CPAN bug #74900.)
In fact, by using SAVESPTR for a refcounted location, you are causing the temps stack and
*@{SCALAR} both to share the same refcount. Or another way of putting it is that *@{SCALAR}
is no longer refcounted, but the rest of perl doesn’t know that. That results in bugs like this:
{use Mouse}
sub BUILD {
$foo = \$@;
*@ = \my $x;
}
new main;
use Devel::Peek;
Dump $$foo
__END__
The output is something like this:
SV = UNKNOWN(0xff) (0x82ae80) at 0x82adf0
REFCNT = 0
FLAGS = ()
So a scalar with refcount of 0 becomes accessible to Perl space.
I believe by changing those two lines to
SAVEGENERICSV(ERRSV);
ERRSV = SvREFCNT_inc(sv_newmortal());
you can fix the bugs, but I haven’t actually tested it.