diff options
author | Father Chrysostomos <sprout@cpan.org> | 2012-09-28 05:52:53 -0700 |
---|---|---|
committer | Father Chrysostomos <sprout@cpan.org> | 2012-10-01 12:51:54 -0700 |
commit | cc02ebe5373ef9dc4ac786b90cb5db113958408e (patch) | |
tree | 11ff06e1d83186312a2bf211f7ebc725b4920fcc /mg.c | |
parent | 4ddea69a03520899f0beb1187b9ae3c69f278179 (diff) | |
download | perl-cc02ebe5373ef9dc4ac786b90cb5db113958408e.tar.gz |
Make magic_setsubstr check UTF8 flag after stringification
By checking it before, it can end up treating a UTF8 string as bytes
when calculating offsets if the UTF8 flag is not turned on until
the target is stringified. This can happen with overloading and
typeglobs.
This is a regression from 5.14. 5.14 itself was buggy, too, but one
would have to modify the target after creating the substr lvalue but
before assigning to it; and that because of another bug fixed by
83f78d1a27, which was cancelling out this one.
package o {
use overload '""' => sub { $_[0][0] }
}
my $refee = bless ["\x{100}a"], o::;
my $substr = \substr $refee, -2;
$$substr = "b";
warn $refee;
That prints:
Wide character in warn at - line 7.
Āb at - line 7.
In 5.14 it prints:
b at - line 7.
Diffstat (limited to 'mg.c')
-rw-r--r-- | mg.c | 5 |
1 files changed, 3 insertions, 2 deletions
@@ -2246,6 +2246,7 @@ Perl_magic_setsubstr(pTHX_ SV *sv, MAGIC *mg) dVAR; STRLEN len, lsv_len, oldtarglen, newtarglen; const char * const tmps = SvPV_const(sv, len); + const char *targs; SV * const lsv = LvTARG(sv); STRLEN lvoff = LvTARGOFF(sv); STRLEN lvlen = LvTARGLEN(sv); @@ -2260,8 +2261,8 @@ Perl_magic_setsubstr(pTHX_ SV *sv, MAGIC *mg) Perl_ck_warner(aTHX_ packWARN(WARN_SUBSTR), "Attempt to use reference as lvalue in substr" ); - if (SvUTF8(lsv)) lsv_len = sv_len_utf8_nomg(lsv); - else (void)SvPV_nomg(lsv,lsv_len); + targs = SvPV_nomg(lsv,lsv_len); + if (SvUTF8(lsv)) lsv_len = sv_or_pv_len_utf8(lsv,targs,lsv_len); if (!translate_substr_offsets( lsv_len, negoff ? -(IV)lvoff : (IV)lvoff, !negoff, |