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