diff options
author | Nicholas Clark <nick@ccl4.org> | 2006-04-30 19:07:43 +0000 |
---|---|---|
committer | Nicholas Clark <nick@ccl4.org> | 2006-04-30 19:07:43 +0000 |
commit | 12abf4f0efbd7338e12bce75e8fe77c524383458 (patch) | |
tree | b227b0a3d34e63fbd7b0db037981d2e51e7efdbf /doop.c | |
parent | c2955298f73609931e7742722d6cdab7cad91e16 (diff) | |
download | perl-12abf4f0efbd7338e12bce75e8fe77c524383458.tar.gz |
do_vop() couldn't correctly handle surprises from UTF-8 overloading.
p4raw-id: //depot/perl@28029
Diffstat (limited to 'doop.c')
-rw-r--r-- | doop.c | 31 |
1 files changed, 25 insertions, 6 deletions
@@ -1173,19 +1173,38 @@ Perl_do_vop(pTHX_ I32 optype, SV *sv, SV *left, SV *right) STRLEN lensave; const char *lsave; const char *rsave; - const bool left_utf = DO_UTF8(left); - const bool right_utf = DO_UTF8(right); + bool left_utf; + bool right_utf; STRLEN needlen = 0; - if (left_utf && !right_utf) - sv_utf8_upgrade(right); - else if (!left_utf && right_utf) - sv_utf8_upgrade(left); if (sv != left || (optype != OP_BIT_AND && !SvOK(sv) && !SvGMAGICAL(sv))) sv_setpvn(sv, "", 0); /* avoid undef warning on |= and ^= */ lsave = lc = SvPV_nomg_const(left, leftlen); rsave = rc = SvPV_nomg_const(right, rightlen); + + /* This need to come after SvPV to ensure that string overloading has + fired off. */ + + left_utf = DO_UTF8(left); + right_utf = DO_UTF8(right); + + if (left_utf && !right_utf) { + /* Avoid triggering overloading again by using temporaries. + Maybe there should be a variant of sv_utf8_upgrade that takes pvn + */ + right = sv_2mortal(newSVpvn(rsave, rightlen)); + sv_utf8_upgrade(right); + rsave = rc = SvPV_nomg_const(right, rightlen); + right_utf = TRUE; + } + else if (!left_utf && right_utf) { + left = sv_2mortal(newSVpvn(lsave, leftlen)); + sv_utf8_upgrade(left); + lsave = lc = SvPV_nomg_const(left, leftlen); + left_utf = TRUE; + } + len = leftlen < rightlen ? leftlen : rightlen; lensave = len; SvCUR_set(sv, len); |