diff options
author | Nick Clifton <nickc@redhat.com> | 2014-12-09 12:42:18 +0000 |
---|---|---|
committer | Nick Clifton <nickc@redhat.com> | 2014-12-09 12:42:18 +0000 |
commit | f64e188b58f4aab4cbd03aa6e9fc1aa602546e26 (patch) | |
tree | 46d8f90891842ce15eee893ce5489835e9e65a20 /bfd/libbfd.c | |
parent | 137d1369ac054744d27f19e95aa8a739e6c0068d (diff) | |
download | gdb-f64e188b58f4aab4cbd03aa6e9fc1aa602546e26.zip gdb-f64e188b58f4aab4cbd03aa6e9fc1aa602546e26.tar.gz gdb-f64e188b58f4aab4cbd03aa6e9fc1aa602546e26.tar.bz2 |
More fixes for memory access violations triggered by fuzzed binaries.
PR binutils/17512
* objdump.c (display_any_bfd): Avoid infinite loop closing and
opening the same archive again and again.
* archive64.c (bfd_elf64_archive_slurp_armap): Add range checks.
* libbfd.c (safe_read_leb128): New function.
* libbfd-in.h (safe_read_leb128): Add prototype.
* libbfd.h: Regenerate.
* elf-attrs.c (_bfd_elf_parse_attributes): Use safe_read_leb128.
Check for an over-long subsection length.
* elf.c (elf_parse_notes): Check that the namedata is long enough
for the string comparison that is about to be performed.
(elf_read_notes): Zero-terminate the note buffer.
Diffstat (limited to 'bfd/libbfd.c')
-rw-r--r-- | bfd/libbfd.c | 39 |
1 files changed, 39 insertions, 0 deletions
diff --git a/bfd/libbfd.c b/bfd/libbfd.c index ade8e0f..c079247 100644 --- a/bfd/libbfd.c +++ b/bfd/libbfd.c @@ -1003,6 +1003,45 @@ read_unsigned_leb128 (bfd *abfd ATTRIBUTE_UNUSED, return result; } +/* Read in a LEB128 encoded value from ABFD starting at DATA. + If SIGN is true, return a signed LEB128 value. + If LENGTH_RETURN is not NULL, return in it the number of bytes read. + No bytes will be read at address END or beyond. */ + +bfd_vma +safe_read_leb128 (bfd *abfd ATTRIBUTE_UNUSED, + bfd_byte *data, + unsigned int *length_return, + bfd_boolean sign, + const bfd_byte * const end) +{ + bfd_vma result = 0; + unsigned int num_read = 0; + unsigned int shift = 0; + unsigned char byte = 0; + + while (data < end) + { + byte = bfd_get_8 (abfd, data); + data++; + num_read++; + + result |= ((bfd_vma) (byte & 0x7f)) << shift; + + shift += 7; + if ((byte & 0x80) == 0) + break; + } + + if (length_return != NULL) + *length_return = num_read; + + if (sign && (shift < 8 * sizeof (result)) && (byte & 0x40)) + result |= (bfd_vma) -1 << shift; + + return result; +} + /* Helper function for reading sleb128 encoded data. */ bfd_signed_vma |