This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Make it possible to have read-only glob copies
authorFather Chrysostomos <sprout@cpan.org>
Tue, 12 Jul 2011 18:13:31 +0000 (11:13 -0700)
committerFather Chrysostomos <sprout@cpan.org>
Tue, 12 Jul 2011 20:00:02 +0000 (13:00 -0700)
commit21690b721fd5cd765bcc0330aa94f9172c24582d
tree5ddfb93a4d420b196d10440b92fba67f3fd17625
parent09127a34482a01b8c6c1da4c8f716092df06820a
Make it possible to have read-only glob copies

(aka Fun with Hash::Util)

This script gives ‘Modification of a read-only value’:

use Hash::Util lock_value;
*foo::; # autovivify
lock_value %::, foo::::;
*foo:: = [];

So far so good.  That’s to be expected.  But this one crashes:

use Hash::Util lock_value;
$a{h} = *foo;
lock_value %a, h;
$a{h} = [];

Under debugging builds, it gives assertion failures.

Anyone who knows how the flags work will see immediately what’s wrong,
but for the sake of those who don’t:

The SVf_FAKE flag is set on a copy of a typeglob, meaning that assign-
ing something other than a glob to it will overwrite the glob, instead
of writing to one of its slots.

The SVf_FAKE flag on a read-only (SVf_READONLY-flagged) string means
that it’s not actually read-only, but a copy-on-write string.

SVf_READONLY on a glob means that you can’t even assign *through* it.
See the first Hash::Util example above.

The crashing occurs when the two flags are combined.
sv_force_normal_flags assumes that anything marked fake AND read-only
is a copy-on-write string, so it proceeds to gut it, even if it’s
actually just corrupting a glob.

So this commit changes that check to take typeglobs into account.
sv.c
t/lib/universal.t