In perl.git, the branch blead has been updated <http://perl5.git.perl.org/perl.git/commitdiff/b20c4ee1fc23699f6cbe3ce96cc8fe6eb4c52c4c?hp=1ccd2973f698bfdb82dfadf6ef09ec337061a97f>
- Log ----------------------------------------------------------------- commit b20c4ee1fc23699f6cbe3ce96cc8fe6eb4c52c4c Author: Father Chrysostomos <spr...@cpan.org> Date: Mon Oct 4 12:24:37 2010 -0700 [perl #20661] Constant strings representing a number can BECOME numbers The & | ^ operators now avoid turning on numericness of read-only arguments. ----------------------------------------------------------------------- Summary of changes: pod/perldelta.pod | 5 +++++ pp.c | 8 ++++++++ t/op/bop.t | 16 +++++++++++++++- 3 files changed, 28 insertions(+), 1 deletions(-) diff --git a/pod/perldelta.pod b/pod/perldelta.pod index ef58531..5cd276e 100644 --- a/pod/perldelta.pod +++ b/pod/perldelta.pod @@ -672,6 +672,11 @@ L<[perl #78058]|http://rt.perl.org/rt3/Public/Bug/Display.html?id=78058>. Subroutine redefinition works once more in the debugger L<[perl #48332]|http://rt.perl.org/rt3/Public/Bug/Display.html?id=48332>. +=item * + +The C<&> C<|> C<^> bitwise operators no longer coerce read-only arguments +L<[perl #20661]|http://rt.perl.org/rt3/Public/Bug/Display.html?id=20661>. + =back =head1 Known Problems diff --git a/pp.c b/pp.c index c478a47..a1558de 100644 --- a/pp.c +++ b/pp.c @@ -2386,6 +2386,8 @@ PP(pp_bit_and) { dPOPTOPssrl; if (SvNIOKp(left) || SvNIOKp(right)) { + const bool left_ro_nonnum = !SvNIOKp(left) && SvREADONLY(left); + const bool right_ro_nonnum = !SvNIOKp(right) && SvREADONLY(right); if (PL_op->op_private & HINT_INTEGER) { const IV i = SvIV_nomg(left) & SvIV_nomg(right); SETi(i); @@ -2394,6 +2396,8 @@ PP(pp_bit_and) const UV u = SvUV_nomg(left) & SvUV_nomg(right); SETu(u); } + if (left_ro_nonnum) SvNIOK_off(left); + if (right_ro_nonnum) SvNIOK_off(right); } else { do_vop(PL_op->op_type, TARG, left, right); @@ -2412,6 +2416,8 @@ PP(pp_bit_or) { dPOPTOPssrl; if (SvNIOKp(left) || SvNIOKp(right)) { + const bool left_ro_nonnum = !SvNIOKp(left) && SvREADONLY(left); + const bool right_ro_nonnum = !SvNIOKp(right) && SvREADONLY(right); if (PL_op->op_private & HINT_INTEGER) { const IV l = (USE_LEFT(left) ? SvIV_nomg(left) : 0); const IV r = SvIV_nomg(right); @@ -2424,6 +2430,8 @@ PP(pp_bit_or) const UV result = op_type == OP_BIT_OR ? (l | r) : (l ^ r); SETu(result); } + if (left_ro_nonnum) SvNIOK_off(left); + if (right_ro_nonnum) SvNIOK_off(right); } else { do_vop(op_type, TARG, left, right); diff --git a/t/op/bop.t b/t/op/bop.t index b7f82ee..fdcded1 100644 --- a/t/op/bop.t +++ b/t/op/bop.t @@ -15,7 +15,7 @@ BEGIN { # If you find tests are failing, please try adding names to tests to track # down where the failure is, and supply your new names as a patch. # (Just-in-time test naming) -plan tests => 161 + (10*13*2) + 4; +plan tests => 170 + (10*13*2) + 4; # numerics ok ((0xdead & 0xbeef) == 0x9ead); @@ -63,6 +63,20 @@ is (($foo | $bar), ($Aoz x 75 . $zap)); # ^ does not truncate is (($foo ^ $bar), ($Axz x 75 . $zap)); +# string constants +sub _and($) { $_[0] & "+0" } +sub _oar($) { $_[0] | "+0" } +sub _xor($) { $_[0] ^ "+0" } +is _and "waf", '# ', 'str var & const str'; # These three +is _and 0, '0', 'num var & const str'; # are from +is _and "waf", '# ', 'str var & const str again'; # [perl #20661] +is _oar "yit", '{yt', 'str var | const str'; +is _oar 0, '0', 'num var | const str'; +is _oar "yit", '{yt', 'str var | const str again'; +is _xor "yit", 'RYt', 'str var ^ const str'; +is _xor 0, '0', 'num var ^ const str'; +is _xor "yit", 'RYt', 'str var ^ const str again'; + # is ("ok \xFF\xFF\n" & "ok 19\n", "ok 19\n"); is ("ok 20\n" | "ok \0\0\n", "ok 20\n"); -- Perl5 Master Repository