diff options
author | David Mitchell <davem@iabyn.com> | 2011-02-06 19:48:34 +0000 |
---|---|---|
committer | David Mitchell <davem@iabyn.com> | 2011-02-06 21:34:44 +0000 |
commit | c95ca9b8cd1e9cb94201b96527b666a2e68bd781 (patch) | |
tree | ab92c0c925828c7074e56e36f2947349af4d7387 /pp_hot.c | |
parent | 33fb6f35374f797590a5f7df9532ead893676812 (diff) | |
download | perl-c95ca9b8cd1e9cb94201b96527b666a2e68bd781.tar.gz |
fix a s/non-utf8/is-utf8/ bit of nastiness
Commit 3e462cdc2087ddf90984010fabd80c30db92bfa0 provided a fix
for the s/non-utf8/is-utf8/ case by upgrading TARG to UTF8 after the
match, but before the substitution. It used sv_utf8_upgrade() rather than
sv_utf8_upgrade_nomg(), so for example, with a tied variable, FETCH would
get called again, and all the char* pointers such as s would be left
dangling. If the length of the string was unchanged, the code wouldn't
notice this.
Fix by using the _nomg() variant, and by checking whether the string
has been reallocated
Diffstat (limited to 'pp_hot.c')
-rw-r--r-- | pp_hot.c | 5 |
1 files changed, 3 insertions, 2 deletions
@@ -2185,12 +2185,13 @@ PP(pp_subst) * http://www.nntp.perl.org/group/perl.perl5.porters/2010/04/msg158809.html */ if (matched && DO_UTF8(dstr) && ! DO_UTF8(TARG)) { - const STRLEN new_len = sv_utf8_upgrade(TARG); + char * const orig_pvx = SvPVX(TARG); + const STRLEN new_len = sv_utf8_upgrade_nomg(TARG); /* If the lengths are the same, the pattern contains only * invariants, can keep going; otherwise, various internal markers * could be off, so redo */ - if (new_len != len) { + if (new_len != len || orig_pvx != SvPVX(TARG)) { goto setup_match; } } |