Blame SOURCES/perl-5.30.0-Remove-undefined-behavior-from-IV-shifting.patch

7586d2
From 7e5b390a008ccad094a39c350f385d58e8a5102a Mon Sep 17 00:00:00 2001
7586d2
From: Karl Williamson <khw@cpan.org>
7586d2
Date: Fri, 3 May 2019 13:57:47 -0600
7586d2
Subject: [PATCH] Remove undefined behavior from IV shifting
7586d2
MIME-Version: 1.0
7586d2
Content-Type: text/plain; charset=UTF-8
7586d2
Content-Transfer-Encoding: 8bit
7586d2
7586d2
It is undefined behavior to shift a negative integer to the left.  This
7586d2
commit avoids that by treating the value as unsigned, then casting back
7586d2
to integer for return.
7586d2
7586d2
Petr Písař: Ported to 5.30.0 from
7586d2
814735a391b874af8f00eaf89469e5ec7f38cd4aa.
7586d2
7586d2
Signed-off-by: Petr Písař <ppisar@redhat.com>
7586d2
---
7586d2
 asan_ignore |  5 -----
7586d2
 pp.c        | 21 ++++++++++++++++++++-
7586d2
 2 files changed, 20 insertions(+), 6 deletions(-)
7586d2
7586d2
diff --git a/asan_ignore b/asan_ignore
7586d2
index e0f5685..f520546 100644
7586d2
--- a/asan_ignore
7586d2
+++ b/asan_ignore
7586d2
@@ -18,11 +18,6 @@
7586d2
 
7586d2
 fun:Perl_pp_i_*
7586d2
 
7586d2
-# Perl's << is defined as using the underlying C's << operator, with the
7586d2
-# same undefined behaviour for shifts greater than the word size.
7586d2
-# (UVs normally, IVs with 'use integer')
7586d2
-
7586d2
-fun:Perl_pp_left_shift
7586d2
 
7586d2
 # this function numifies the field width in eg printf "%10f".
7586d2
 # It has its own overflow detection, so don't warn about it
7586d2
diff --git a/pp.c b/pp.c
7586d2
index 7afb090..3ca04e1 100644
7586d2
--- a/pp.c
7586d2
+++ b/pp.c
7586d2
@@ -1991,10 +1991,29 @@ static IV S_iv_shift(IV iv, int shift, bool left)
7586d2
        shift = -shift;
7586d2
        left = !left;
7586d2
    }
7586d2
+
7586d2
    if (UNLIKELY(shift >= IV_BITS)) {
7586d2
        return iv < 0 && !left ? -1 : 0;
7586d2
    }
7586d2
-   return left ? iv << shift : iv >> shift;
7586d2
+   /* For left shifts, perl 5 has chosen to treat the value as unsigned for
7586d2
+    * the * purposes of shifting, then cast back to signed.  This is very
7586d2
+    * different from perl 6:
7586d2
+    *
7586d2
+    * $ perl6 -e 'say -2 +< 5'
7586d2
+    * -64
7586d2
+    *
7586d2
+    * $ ./perl -le 'print -2 << 5'
7586d2
+    * 18446744073709551552
7586d2
+    * */
7586d2
+   if (left) {
7586d2
+       if (iv == IV_MIN) { /* Casting this to a UV is undefined behavior */
7586d2
+           return 0;
7586d2
+       }
7586d2
+       return (IV) (((UV) iv) << shift);
7586d2
+   }
7586d2
+
7586d2
+   /* Here is right shift */
7586d2
+   return iv >> shift;
7586d2
 }
7586d2
 
7586d2
 #define UV_LEFT_SHIFT(uv, shift) S_uv_shift(uv, shift, TRUE)
7586d2
-- 
7586d2
2.20.1
7586d2