This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Prevent destructors called from gp_free from seeing freed SVs
authorFather Chrysostomos <sprout@cpan.org>
Thu, 10 Feb 2011 22:04:54 +0000 (14:04 -0800)
committerFather Chrysostomos <sprout@cpan.org>
Thu, 10 Feb 2011 22:04:54 +0000 (14:04 -0800)
commitb0d55c99a8de16cc4fca0775760e63595cef1d0d
tree5d701199d6b3e6af561b06922cd676d69babf2c0
parent0e0f0835b5eca2377b130714ebb797e625f8e4e9
Prevent destructors called from gp_free from seeing freed SVs

perl5.13.9 -e 'local *foo; $foo = bless[]; (); DESTROY { use Devel::Peek; Dump $foo; }'

This prints:
SV = UNKNOWN(0xff) (0x8044dc) at 0x8044e0
  REFCNT = 0
  FLAGS = ()

If I do anything with $foo inside the destructor, such as
‘local $foo’, it crashes, of course.

gp_free (called when *foo is being unlocalised on scope exit) does
SvREFCNT_dec(gp->gp_xv) on each of its slots.

SvREFCNT_dec(gp->gp_sv) lowers the refcount of $foo to zero, which
causes the object it references to be destroyed, too. The objects
destructor sees the same $foo still there in the typeglob.

This commit changes gp_free to use a loop, the way S_hfreeentries
(in hv.c) does, checking that everything has been freed before exit-
ing the loop.

(The one-liner above is a reduced version of

perl -MWWW::Scripter -e '$w = new WWW::Scripter; $w->use_plugin(JavaScript); $w->get(q|data:text/html,<a href onclick="throw new Error(&quot;XMLHttpRequest&quot;)">|); $w->document->links->[0]->click'

which involved *@ and a destructor localising $@.)
gv.c
pod/perldiag.pod
t/op/gv.t