This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Disallow weakening of read-only references
authorFather Chrysostomos <sprout@cpan.org>
Fri, 16 Sep 2011 16:25:10 +0000 (09:25 -0700)
committerFather Chrysostomos <sprout@cpan.org>
Fri, 16 Sep 2011 16:34:51 +0000 (09:34 -0700)
commit5d4ff2313b84e128251ca88da0f7a2eef62adb24
treea3dab58f882da20e47781a0cccae754fe614822d
parentd6cf23679a41a0be58c53407b9a6d8bd44882eae
Disallow weakening of read-only references

$ perl -MScalar::Util=weaken -le 'DESTROY{return if$_++;weaken$_[0]}$x=bless[]'
DESTROY created new reference to dead object 'main' during global destruction.

It says that because the reference count has gone down to -1 (or the
max unsigned value, whichever it is), and the error occurs when
SvREFCNT is true.  So there is no new reference to the dead object;
it’s just the refcount that’s off.

This case is worse:

$ perl -MScalar::Util=weaken -le 'DESTROY{weaken$_[0];$x=$_[0]}bless[];'
Segmentation fault

$_[0]’s reference count is normally lowered manually by sv_clear, to
avoid a recursive call to sv_clear (as lowering the reference count
normally triggers that).  If the variable has been weakened, then
$_[0] no longer holds a reference count.  sv_clear proceeds to destroy
at, as its reference count is 1 (held by $x), causing $x to point to a
freed scalar.  Not good.

Since $_[0] is read-only anyway, it should not be weakenable.
pod/perldelta.pod
sv.c
t/op/ref.t