diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 88dfe1b97a..a643721e0c 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,9 @@ +2013-01-03 Nickolai Zeldovich + Nick Clifton + + * elflink.c (get_value): Prevent the use of an undefined shift + operation. Add sanity checks. + 2013-01-02 Kaushik Phatak * config.bfd (cr16*-*-uclinux*): New target support. diff --git a/bfd/elflink.c b/bfd/elflink.c index 661b2eb196..6d80109c47 100644 --- a/bfd/elflink.c +++ b/bfd/elflink.c @@ -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;