summaryrefslogtreecommitdiff
path: root/sv.c
diff options
context:
space:
mode:
authorFather Chrysostomos <sprout@cpan.org>2011-12-01 22:46:22 -0800
committerFather Chrysostomos <sprout@cpan.org>2011-12-01 22:46:22 -0800
commite7d0a3fbd986e18585e457528529ce365ace620e (patch)
tree861106bb893bba99fa58e41951ce03010b3a8cbb /sv.c
parenta82b195bcec8edceae8d7f710b71cfcb1e8b1845 (diff)
downloadperl-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.c5
1 files changed, 2 insertions, 3 deletions
diff --git a/sv.c b/sv.c
index 99d0d5ca0f..ee64e1fe7d 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)