* elflink.c (get_value): Prevent the use of an undefined shift
authorNick Clifton <nickc@redhat.com>
Thu, 3 Jan 2013 15:47:46 +0000 (15:47 +0000)
committerNick Clifton <nickc@redhat.com>
Thu, 3 Jan 2013 15:47:46 +0000 (15:47 +0000)
operation.  Add sanity checks.

bfd/ChangeLog
bfd/elflink.c

index 88dfe1b97a14e901436813a34c9334545dd15e4b..a643721e0cbe4fdd7c1bba3a2da5cf930bab1030 100644 (file)
@@ -1,3 +1,9 @@
+2013-01-03  Nickolai Zeldovich  <nickolai@csail.mit.edu>
+           Nick Clifton  <nickc@redhat.com>
+
+       * elflink.c (get_value): Prevent the use of an undefined shift
+       operation.  Add sanity checks.
+
 2013-01-02  Kaushik Phatak  <kaushik.phatak@kpitcummins.com>
 
        * config.bfd (cr16*-*-uclinux*): New target support.
index 661b2eb19693e2432a0c9ebacdb0b118ca050afe..6d80109c47bbadf97ddc61c5816e51aa045571ae 100644 (file)
@@ -1,6 +1,6 @@
 /* ELF linking support for BFD.
    Copyright 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
-   2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012
+   2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013
    Free Software Foundation, Inc.
 
    This file is part of BFD, the Binary File Descriptor library.
@@ -7917,31 +7917,49 @@ get_value (bfd_vma size,
           bfd *input_bfd,
           bfd_byte *location)
 {
+  int shift;
   bfd_vma x = 0;
 
+  /* Sanity checks.  */
+  BFD_ASSERT (chunksz <= sizeof (x)
+             && size >= chunksz
+             && chunksz != 0
+             && (size % chunksz) == 0
+             && input_bfd != NULL
+             && location != NULL);
+
+  if (chunksz == sizeof (x))
+    {
+      BFD_ASSERT (size == chunksz);
+
+      /* Make sure that we do not perform an undefined shift operation.
+        We know that size == chunksz so there will only be one iteration
+        of the loop below.  */
+      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;