In perl.git, the branch blead has been updated <http://perl5.git.perl.org/perl.git/commitdiff/e7d0a3fbd986e18585e457528529ce365ace620e?hp=a82b195bcec8edceae8d7f710b71cfcb1e8b1845>
- Log ----------------------------------------------------------------- commit e7d0a3fbd986e18585e457528529ce365ace620e Author: Father Chrysostomos <spr...@cpan.org> Date: Thu Dec 1 22:46:22 2011 -0800 Allow COW PVMGs to be tied This logic in sv_magic is wrong: if (SvREADONLY(sv)) { if ( /* its okay to attach magic to shared strings; the subsequent * upgrade to PVMG will unshare the string */ !(SvFAKE(sv) && SvTYPE(sv) < SVt_PVMG) && IN_PERL_RUNTIME && !PERL_MAGIC_TYPE_READONLY_ACCEPTABLE(how) ) { Perl_croak_no_modify(aTHX); } } There is nothing wrong with attaching magic to a shared string that will stay shared. Also, shared strings are not always < SVt_PVMG. Sometimes a PVMG or PVLV can end up with a shared string. In those cases, the logic above treats them as read-only, which they ainât. The easiest example is a downgraded typeglob: $x = *foo; # now a PVGV undef $x ; # downgraded to PVMG $x = __PACKAGE__; # now a shared string (COW) tie $x, "main"; # bang! $x is considered read-only sub main::TIESCALAR{bless[]} ----------------------------------------------------------------------- Summary of changes: sv.c | 5 ++--- t/op/tie.t | 21 +++++++++++++++++++++ 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/sv.c b/sv.c index 99d0d5c..ee64e1f 100644 --- a/sv.c +++ b/sv.c @@ -5299,9 +5299,8 @@ Perl_sv_magic(pTHX_ register SV *const sv, SV *const obj, const int how, #endif if (SvREADONLY(sv)) { if ( - /* its okay to attach magic to shared strings; the subsequent - * upgrade to PVMG will unshare the string */ - !(SvFAKE(sv) && SvTYPE(sv) < SVt_PVMG) + /* its okay to attach magic to shared strings */ + (!SvFAKE(sv) || isGV_with_GP(sv)) && IN_PERL_RUNTIME && !PERL_MAGIC_TYPE_READONLY_ACCEPTABLE(how) diff --git a/t/op/tie.t b/t/op/tie.t index 887fa96..bbd789c 100644 --- a/t/op/tie.t +++ b/t/op/tie.t @@ -1008,6 +1008,27 @@ print "ok\n"; EXPECT ok ######## +# +# Nor should it be impossible to tie COW scalars that are already PVMGs. + +sub TIESCALAR { bless [] } +$x = *foo; # PVGV +undef $x; # downgrade to PVMG +$x = __PACKAGE__; # PVMG + COW +tie $x, ""; # bang! + +print STDERR "ok\n"; + +# However, one should not be able to tie read-only glob copies, which look +# a bit like kine internally (FAKE + READONLY). +$y = *foo; +Internals::SvREADONLY($y,1); +tie $y, ""; + +EXPECT +ok +Modification of a read-only value attempted at - line 16. +######## # tied() should still work on tied scalars after glob assignment sub TIESCALAR {bless[]} -- Perl5 Master Repository