Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

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[]}
  • Loading branch information...
commit e7d0a3fbd986e18585e457528529ce365ace620e 1 parent a82b195
Father Chrysostomos authored
Showing with 23 additions and 3 deletions.
  1. +2 −3 sv.c
  2. +21 −0 t/op/tie.t
View
5 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)
View
21 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[]}
Please sign in to comment.
Something went wrong with that request. Please try again.