diff mbox series

c++: Avoid UB in signed shift [PR 98625]

Message ID 87d03737-1a59-45f8-4f41-9ea103c6b096@acm.org
State New
Headers show
Series c++: Avoid UB in signed shift [PR 98625] | expand

Commit Message

Nathan Sidwell Jan. 20, 2021, 5:23 p.m. UTC
Thanks Jakub & Martin for unconfusing me about where the UB was!

I'd forgotten that left	shifting a negative value is UB	until C++20.
Insert some casts to do	unsigned shifts.

	PR c++/98625
	gcc/cp/
         * module.cc (bytes_in::i, bytes_in::wi): Avoid left shift of
         signed type.
diff mbox series

Patch

diff --git i/gcc/cp/module.cc w/gcc/cp/module.cc
index 1fd0bcfe3eb..8f9c7940ef8 100644
--- i/gcc/cp/module.cc
+++ w/gcc/cp/module.cc
@@ -881,9 +881,12 @@  bytes_in::i ()
 	  v &= 0xf;
 	  if (v & 0x8)
 	    v |= -1 ^ 0x7;
+	  /* unsigned necessary due to left shifts of -ve values.  */
+	  unsigned uv = unsigned (v);
 	  if ((ptr = read (++bytes)))
 	    while (bytes--)
-	      v = (v << 8) | (*ptr++ & 0xff);
+	      uv = (uv << 8) | (*ptr++ & 0xff);
+	  v = int (uv);
 	}
       else if (v & 0x40)
 	v |= -1 ^ 0x3f;
@@ -972,9 +975,12 @@  bytes_in::wi ()
 	  v &= 0xf;
 	  if (v & 0x8)
 	    v |= -1 ^ 0x7;
+	  /* unsigned necessary due to left shifts of -ve values.  */
+	  unsigned HOST_WIDE_INT uv = (unsigned HOST_WIDE_INT) v;
 	  if ((ptr = read (++bytes)))
 	    while (bytes--)
-	      v = (v << 8) | (*ptr++ & 0xff);
+	      uv = (uv << 8) | (*ptr++ & 0xff);
+	  v = (HOST_WIDE_INT) uv;
 	}
       else if (v & 0x40)
 	v |= -1 ^ 0x3f;