Skip to content

Commit

Permalink
Allow COW PVMGs to be tied
Browse files Browse the repository at this point in the history
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
Father Chrysostomos committed Dec 2, 2011
1 parent a82b195 commit e7d0a3f
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 3 deletions.
5 changes: 2 additions & 3 deletions sv.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
21 changes: 21 additions & 0 deletions t/op/tie.t
Original file line number Diff line number Diff line change
Expand Up @@ -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[]}
Expand Down

0 comments on commit e7d0a3f

Please sign in to comment.