diff options
author | Father Chrysostomos <sprout@cpan.org> | 2011-12-01 22:46:22 -0800 |
---|---|---|
committer | Father Chrysostomos <sprout@cpan.org> | 2011-12-01 22:46:22 -0800 |
commit | e7d0a3fbd986e18585e457528529ce365ace620e (patch) | |
tree | 861106bb893bba99fa58e41951ce03010b3a8cbb /sv.c | |
parent | a82b195bcec8edceae8d7f710b71cfcb1e8b1845 (diff) | |
download | perl-e7d0a3fbd986e18585e457528529ce365ace620e.tar.gz |
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[]}
Diffstat (limited to 'sv.c')
-rw-r--r-- | sv.c | 5 |
1 files changed, 2 insertions, 3 deletions
@@ -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) |