summaryrefslogtreecommitdiff
path: root/pp_hot.c
diff options
context:
space:
mode:
authorDavid Mitchell <davem@iabyn.com>2011-02-06 19:48:34 +0000
committerDavid Mitchell <davem@iabyn.com>2011-02-06 21:34:44 +0000
commitc95ca9b8cd1e9cb94201b96527b666a2e68bd781 (patch)
treeab92c0c925828c7074e56e36f2947349af4d7387 /pp_hot.c
parent33fb6f35374f797590a5f7df9532ead893676812 (diff)
downloadperl-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.c5
1 files changed, 3 insertions, 2 deletions
diff --git a/pp_hot.c b/pp_hot.c
index 5a920d4d4d..7316c5aabb 100644
--- a/pp_hot.c
+++ b/pp_hot.c
@@ -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;
}
}