diff options
author | Father Chrysostomos <sprout@cpan.org> | 2013-08-03 23:58:56 -0700 |
---|---|---|
committer | Father Chrysostomos <sprout@cpan.org> | 2013-08-04 00:04:32 -0700 |
commit | c56ed9f6dbe3d89129c7f5a37b28d4fc398561e4 (patch) | |
tree | fb3a242b29412fd38c7d32b000268ea928dff42f /lib | |
parent | 9dbc968d1a9a9f1e73f1da3d0cd81229c81b27ab (diff) | |
download | perl-c56ed9f6dbe3d89129c7f5a37b28d4fc398561e4.tar.gz |
[perl #119043] Allow utf8 up/downgrade on ro COWs
Commit 1913067 allowed COW constants to be read-only. This broke
Glib, so I reverted it with ba36554e02. That caused this bug to reë-
merge (I hadn’t realised that I had fixed it in 1913067):
perl -e 'for(1..10){for(__PACKAGE__){warn $_; $_++}}'
main at -e line 1.
maio at -e line 1.
maip at -e line 1.
maiq at -e line 1.
mair at -e line 1.
so I reverted the revert two commits ago.
Glib was triggering a read-only error because it called
sv_utf8_upgrade on a read-only COW scalar, and sv_utf8_upgrade does
sv_force_normal on COWs to de-COW them. sv_force_normal croaks on
read-only scalars.
The real problem here is that sv_force_normal means ‘I am going to
modify this scalar’, yet sv_utf8_upgrade conceptually does not modify
the scalar, but only changes the internal representation.
Having to call sv_force_normal to get the *side effect* of de-COWing
without triggering the various other things it does is no good.
What we need is a separate sv_uncow function that sv_force_normal
uses. This commit introduces such a function.
Diffstat (limited to 'lib')
-rw-r--r-- | lib/utf8.t | 25 |
1 files changed, 25 insertions, 0 deletions
diff --git a/lib/utf8.t b/lib/utf8.t index 8e2b8ea00e..e6c94e6dc4 100644 --- a/lib/utf8.t +++ b/lib/utf8.t @@ -563,4 +563,29 @@ for my $pos (0..5) { is($s, "A\xc8\x81\xe8\xab\x86","(pos $pos) str after U; utf8::encode"); } +# [perl #119043] utf8::upgrade should not croak on read-only COWs +for(__PACKAGE__) { + # First make sure we have a COW, otherwise this test is useless. + my $copy = $_; + my @addrs = unpack "L!L!", pack "pp", $copy, $_; + if ($addrs[0] != $addrs[1]) { + fail("__PACKAGE__ did not produce a COW - if this change was " + ."intentional, please provide me with another ro COW scalar") + } + else { + eval { utf8::upgrade($_) }; + is $@, "", 'no error with utf8::upgrade on read-only COW'; + } +} +# This one croaks, but not because the scalar is read-only +eval "package \x{100};\n" . <<'END' + for(__PACKAGE__) { + eval { utf8::downgrade($_) }; + ::like $@, qr/^Wide character/, + 'right error with utf8::downgrade on read-only COW'; + } + 1 +END +or die $@; + done_testing(); |