From 4e82c85b1c9c9b30253b8624470da6f20a6c0604 Mon Sep 17 00:00:00 2001 From: Karl Williamson Date: Mon, 15 Mar 2021 21:01:47 -0600 Subject: [PATCH] Fix broken left shift of IV_MIN under 'use integer' MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This fixes GH 18639 When I wrote this code, I conflated casting and complementing. Signed-off-by: Petr Písař --- pp.c | 3 --- t/op/bop.t | 9 ++++++++- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/pp.c b/pp.c index d365afea4c..baf0777a47 100644 --- a/pp.c +++ b/pp.c @@ -2007,9 +2007,6 @@ static IV S_iv_shift(IV iv, int shift, bool left) * 18446744073709551552 * */ if (left) { - if (iv == IV_MIN) { /* Casting this to a UV is undefined behavior */ - return 0; - } return (IV) (((UV) iv) << shift); } diff --git a/t/op/bop.t b/t/op/bop.t index 07f057d0a9..31b6531a03 100644 --- a/t/op/bop.t +++ b/t/op/bop.t @@ -18,7 +18,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 => 502; +plan tests => 503; # numerics ok ((0xdead & 0xbeef) == 0x9ead); @@ -33,6 +33,13 @@ ok ((33023 >> 7) == 257); # signed vs. unsigned ok ((~0 > 0 && do { use integer; ~0 } == -1)); +{ # GH #18639 + my $iv_min = -(~0 >> 1) - 1; + my $shifted; + { use integer; $shifted = $iv_min << 0 }; + is($shifted, $iv_min, "IV_MIN << 0 yields IV_MIN under 'use integer'"); +} + my $bits = 0; for (my $i = ~0; $i; $i >>= 1) { ++$bits; } my $cusp = 1 << ($bits - 1); -- 2.26.3