c++: Avoid UB in signed shift [PR 98625]
authorNathan Sidwell <nathan@acm.org>
Wed, 20 Jan 2021 17:21:02 +0000 (09:21 -0800)
committerNathan Sidwell <nathan@acm.org>
Wed, 20 Jan 2021 19:41:51 +0000 (11:41 -0800)
I'd forgotten that left shifting a negative value is UB until C++20.
Insert some casts to do unsigned shifts.

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

gcc/cp/module.cc

index 3b40c7ead05170e3d84760bcdc777ed97cd6b1e9..7f88e3fea896084fd2aeeaa081f491d517cd97f0 100644 (file)
@@ -878,9 +878,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;
@@ -969,9 +972,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;