[PATCH] avoid undefined behavior due to oversized shifts

nick clifton nickc@redhat.com
Thu Jan 3 10:58:00 GMT 2013


Hi Jan, Hi Nikolai,

> But that wouldn't eliminate the need for fixing the shifts, as the
> checks above don't entirely exclude the chunksz == sizeof(x) case.

Agreed.  How about this version instead ?


@@ -7917,31 +7917,46 @@ get_value (bfd_vma size,
            bfd *input_bfd,
            bfd_byte *location)
  {
+  int shift;
    bfd_vma x = 0;

+  /* Sanity checks.  */
+  if (chunksz > sizeof (x)
+      || size < chunksz
+      || size % chunksz != 0
+      || input_bfd == NULL
+      || location == NULL)
+    abort ();
+
+  if (chunksz == sizeof (x))
+    {
+      if (size > chunksz)
+       abort ();
+      shift = 0;
+    }
+  else
+    shift = 8 * chunksz;
+
    for (; size; size -= chunksz, location += chunksz)
      {
        switch (chunksz)
         {
-       default:
-       case 0:
-         abort ();
         case 1:
-         x = (x << (8 * chunksz)) | bfd_get_8 (input_bfd, location);
+         x = (x << shift) | bfd_get_8 (input_bfd, location);
           break;
         case 2:
-         x = (x << (8 * chunksz)) | bfd_get_16 (input_bfd, location);
+         x = (x << shift) | bfd_get_16 (input_bfd, location);
           break;
         case 4:
-         x = (x << (8 * chunksz)) | bfd_get_32 (input_bfd, location);
+         x = (x << shift) | bfd_get_32 (input_bfd, location);
           break;
-       case 8:
  #ifdef BFD64
-         x = (x << (8 * chunksz)) | bfd_get_64 (input_bfd, location);
-#else
-         abort ();
-#endif
+       case 8:
+         x = (x << shift) | bfd_get_64 (input_bfd, location);
           break;
+#endif
+       default:
+         abort ();
         }
      }
    return x;



More information about the Binutils mailing list