diff options
author | Alan Modra <amodra@gmail.com> | 2019-03-12 16:19:25 +1030 |
---|---|---|
committer | Alan Modra <amodra@gmail.com> | 2019-03-12 23:54:09 +1030 |
commit | 7a6e0d89bb018cef0d8d13c497d8f340aa2a0fc8 (patch) | |
tree | 651ca43c71bbdac13aba4be8a5a106e23ac494e5 | |
parent | 0919bfe915906382611011f123b5ae68a0bafbb2 (diff) | |
download | gdb-7a6e0d89bb018cef0d8d13c497d8f340aa2a0fc8.zip gdb-7a6e0d89bb018cef0d8d13c497d8f340aa2a0fc8.tar.gz gdb-7a6e0d89bb018cef0d8d13c497d8f340aa2a0fc8.tar.bz2 |
Don't use bfd_get_file_size in objdump
Compressed debug sections can have uncompressed sizes that exceed the
original file size, so we can't use bfd_get_file_size. objdump also
used bfd_get_file_size to limit reloc section size, but I believe the
underlying bug causing the PR22508 out of bounds buffer access was
that we had an integer overflow when calculating the reloc buffer
size. I've fixed that instead in most of the backends, som and
vms-alpha being the exceptions. SOM and vmd-alpha have rather more
serious bugs in their slurp_relocs routines that would need fixing
first if we want to fuss about making them safe against fuzzed object
files.
The patch also fixes a number of other potential overflows by using
the bfd_alloc2/malloc2/zalloc2 memory allocation functions.
bfd/
* coffcode.h (buy_and_read): Delete unnecessary forward decl. Add
nmemb parameter. Use bfd_alloc2.
(coff_slurp_line_table): Use bfd_alloc2. Update buy_and_read calls.
Delete assertion.
(coff_slurp_symbol_table): Use bfd_alloc2 and bfd_zalloc2.
(coff_slurp_reloc_table): Use bfd_alloc2. Update buy_and_read calls.
* coffgen.c (coff_get_reloc_upper_bound): Ensure size calculation
doesn't overflow.
* elf.c (bfd_section_from_shdr): Use bfd_zalloc2. Style fix.
(assign_section_numbers): Style fix.
(swap_out_syms): Use bfd_malloc2.
(_bfd_elf_get_reloc_upper_bound): Ensure size calculation doesn't
overflow.
(_bfd_elf_make_empty_symbol): Style fix.
(elfobj_grok_stapsdt_note_1): Formatting.
* elfcode.h (elf_object_p): Use bfd_alloc2.
(elf_write_relocs, elf_write_shdrs_and_ehdr): Likewise.
(elf_slurp_symbol_table): Use bfd_zalloc2.
(elf_slurp_reloc_table): Use bfd_alloc2.
(_bfd_elf_bfd_from_remote_memory): Use bfd_malloc2.
* elf64-sparc (elf64_sparc_get_reloc_upper_bound): Ensure
size calculation doesn't overflow.
(elf64_sparc_get_dynamic_reloc_upper_bound): Likewise.
* mach-o.c (bfd_mach_o_get_reloc_upper_bound): Likewise.
* pdp11.c (get_reloc_upper_bound): Copy aoutx.h version.
binutils/
* objdump.c (load_specific_debug_section): Don't compare section
size against file size.
(dump_relocs_in_section): Don't compare reloc size against file size.
Print "failed to read relocs" on bfd_get_reloc_upper_bound error.
-rw-r--r-- | bfd/ChangeLog | 28 | ||||
-rw-r--r-- | bfd/coffcode.h | 51 | ||||
-rw-r--r-- | bfd/coffgen.c | 13 | ||||
-rw-r--r-- | bfd/elf.c | 32 | ||||
-rw-r--r-- | bfd/elf64-sparc.c | 23 | ||||
-rw-r--r-- | bfd/elfcode.h | 39 | ||||
-rw-r--r-- | bfd/mach-o.c | 15 | ||||
-rw-r--r-- | bfd/pdp11.c | 42 | ||||
-rw-r--r-- | binutils/ChangeLog | 7 | ||||
-rw-r--r-- | binutils/objdump.c | 37 |
10 files changed, 180 insertions, 107 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 18f1804..3e7d683 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,31 @@ +2019-03-12 Alan Modra <amodra@gmail.com> + + * coffcode.h (buy_and_read): Delete unnecessary forward decl. Add + nmemb parameter. Use bfd_alloc2. + (coff_slurp_line_table): Use bfd_alloc2. Update buy_and_read calls. + Delete assertion. + (coff_slurp_symbol_table): Use bfd_alloc2 and bfd_zalloc2. + (coff_slurp_reloc_table): Use bfd_alloc2. Update buy_and_read calls. + * coffgen.c (coff_get_reloc_upper_bound): Ensure size calculation + doesn't overflow. + * elf.c (bfd_section_from_shdr): Use bfd_zalloc2. Style fix. + (assign_section_numbers): Style fix. + (swap_out_syms): Use bfd_malloc2. + (_bfd_elf_get_reloc_upper_bound): Ensure size calculation doesn't + overflow. + (_bfd_elf_make_empty_symbol): Style fix. + (elfobj_grok_stapsdt_note_1): Formatting. + * elfcode.h (elf_object_p): Use bfd_alloc2. + (elf_write_relocs, elf_write_shdrs_and_ehdr): Likewise. + (elf_slurp_symbol_table): Use bfd_zalloc2. + (elf_slurp_reloc_table): Use bfd_alloc2. + (_bfd_elf_bfd_from_remote_memory): Use bfd_malloc2. + * elf64-sparc (elf64_sparc_get_reloc_upper_bound): Ensure + size calculation doesn't overflow. + (elf64_sparc_get_dynamic_reloc_upper_bound): Likewise. + * mach-o.c (bfd_mach_o_get_reloc_upper_bound): Likewise. + * pdp11.c (get_reloc_upper_bound): Copy aoutx.h version. + 2019-03-08 Alan Modra <amodra@gmail.com> PR 24311 diff --git a/bfd/coffcode.h b/bfd/coffcode.h index 2cea998..f4bfea0 100644 --- a/bfd/coffcode.h +++ b/bfd/coffcode.h @@ -423,8 +423,6 @@ static bfd_boolean coff_write_object_contents (bfd *) ATTRIBUTE_UNUSED; static bfd_boolean coff_set_section_contents (bfd *, asection *, const void *, file_ptr, bfd_size_type); -static void * buy_and_read - (bfd *, file_ptr, bfd_size_type); static bfd_boolean coff_slurp_line_table (bfd *, asection *); static bfd_boolean coff_slurp_symbol_table @@ -4197,12 +4195,14 @@ coff_set_section_contents (bfd * abfd, } static void * -buy_and_read (bfd *abfd, file_ptr where, bfd_size_type size) +buy_and_read (bfd *abfd, file_ptr where, + bfd_size_type nmemb, bfd_size_type size) { - void * area = bfd_alloc (abfd, size); + void *area = bfd_alloc2 (abfd, nmemb, size); if (!area) return NULL; + size *= nmemb; if (bfd_seek (abfd, where, SEEK_SET) != 0 || bfd_bread (area, size, abfd) != size) return NULL; @@ -4255,7 +4255,6 @@ coff_slurp_line_table (bfd *abfd, asection *asect) { LINENO *native_lineno; alent *lineno_cache; - bfd_size_type amt; unsigned int counter; alent *cache_ptr; bfd_vma prev_offset = 0; @@ -4278,13 +4277,15 @@ coff_slurp_line_table (bfd *abfd, asection *asect) return FALSE; } - amt = ((bfd_size_type) asect->lineno_count + 1) * sizeof (alent); - lineno_cache = (alent *) bfd_alloc (abfd, amt); + lineno_cache = (alent *) bfd_alloc2 (abfd, + (bfd_size_type) asect->lineno_count + 1, + sizeof (alent)); if (lineno_cache == NULL) return FALSE; - amt = (bfd_size_type) bfd_coff_linesz (abfd) * asect->lineno_count; - native_lineno = (LINENO *) buy_and_read (abfd, asect->line_filepos, amt); + native_lineno = (LINENO *) buy_and_read (abfd, asect->line_filepos, + asect->lineno_count, + bfd_coff_linesz (abfd)); if (native_lineno == NULL) { _bfd_error_handler @@ -4393,7 +4394,7 @@ coff_slurp_line_table (bfd *abfd, asection *asect) alent *n_lineno_cache; /* Create a table of functions. */ - func_table = (alent **) bfd_alloc (abfd, nbr_func * sizeof (alent *)); + func_table = (alent **) bfd_alloc2 (abfd, nbr_func, sizeof (alent *)); if (func_table != NULL) { alent **p = func_table; @@ -4409,8 +4410,8 @@ coff_slurp_line_table (bfd *abfd, asection *asect) qsort (func_table, nbr_func, sizeof (alent *), coff_sort_func_alent); /* Create the new sorted table. */ - amt = (bfd_size_type) asect->lineno_count * sizeof (alent); - n_lineno_cache = (alent *) bfd_alloc (abfd, amt); + n_lineno_cache = (alent *) bfd_alloc2 (abfd, asect->lineno_count, + sizeof (alent)); if (n_lineno_cache != NULL) { alent *n_cache_ptr = n_lineno_cache; @@ -4430,9 +4431,9 @@ coff_slurp_line_table (bfd *abfd, asection *asect) *n_cache_ptr++ = *old_ptr++; while (old_ptr->line_number != 0); } - BFD_ASSERT ((bfd_size_type) (n_cache_ptr - n_lineno_cache) == (amt / sizeof (alent))); - memcpy (lineno_cache, n_lineno_cache, amt); + memcpy (lineno_cache, n_lineno_cache, + asect->lineno_count * sizeof (alent)); } else ret = FALSE; @@ -4455,7 +4456,6 @@ coff_slurp_symbol_table (bfd * abfd) combined_entry_type *native_symbols; coff_symbol_type *cached_area; unsigned int *table_ptr; - bfd_size_type amt; unsigned int number_of_symbols = 0; bfd_boolean ret = TRUE; @@ -4467,15 +4467,14 @@ coff_slurp_symbol_table (bfd * abfd) return FALSE; /* Allocate enough room for all the symbols in cached form. */ - amt = obj_raw_syment_count (abfd); - amt *= sizeof (coff_symbol_type); - cached_area = (coff_symbol_type *) bfd_alloc (abfd, amt); + cached_area = (coff_symbol_type *) bfd_alloc2 (abfd, + obj_raw_syment_count (abfd), + sizeof (coff_symbol_type)); if (cached_area == NULL) return FALSE; - amt = obj_raw_syment_count (abfd); - amt *= sizeof (unsigned int); - table_ptr = (unsigned int *) bfd_zalloc (abfd, amt); + table_ptr = (unsigned int *) bfd_zalloc2 (abfd, obj_raw_syment_count (abfd), + sizeof (unsigned int)); if (table_ptr == NULL) return FALSE; @@ -4963,7 +4962,6 @@ coff_slurp_reloc_table (bfd * abfd, sec_ptr asect, asymbol ** symbols) arelent *reloc_cache; arelent *cache_ptr; unsigned int idx; - bfd_size_type amt; if (asect->relocation) return TRUE; @@ -4974,10 +4972,11 @@ coff_slurp_reloc_table (bfd * abfd, sec_ptr asect, asymbol ** symbols) if (!coff_slurp_symbol_table (abfd)) return FALSE; - amt = (bfd_size_type) bfd_coff_relsz (abfd) * asect->reloc_count; - native_relocs = (RELOC *) buy_and_read (abfd, asect->rel_filepos, amt); - amt = (bfd_size_type) asect->reloc_count * sizeof (arelent); - reloc_cache = (arelent *) bfd_alloc (abfd, amt); + native_relocs = (RELOC *) buy_and_read (abfd, asect->rel_filepos, + asect->reloc_count, + bfd_coff_relsz (abfd)); + reloc_cache = (arelent *) bfd_alloc2 (abfd, asect->reloc_count, + sizeof (arelent)); if (reloc_cache == NULL || native_relocs == NULL) return FALSE; diff --git a/bfd/coffgen.c b/bfd/coffgen.c index 5f5c5f6..5db35c7 100644 --- a/bfd/coffgen.c +++ b/bfd/coffgen.c @@ -37,6 +37,7 @@ coff_data (abfd). */ #include "sysdep.h" +#include <limits.h> #include "bfd.h" #include "libbfd.h" #include "coff/internal.h" @@ -2006,6 +2007,10 @@ coff_get_normalized_symtab (bfd *abfd) return internal; } +#if GCC_VERSION >= 4003 +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wtype-limits" +#endif long coff_get_reloc_upper_bound (bfd *abfd, sec_ptr asect) { @@ -2014,8 +2019,16 @@ coff_get_reloc_upper_bound (bfd *abfd, sec_ptr asect) bfd_set_error (bfd_error_invalid_operation); return -1; } + if (asect->reloc_count >= LONG_MAX / sizeof (arelent *)) + { + bfd_set_error (bfd_error_file_too_big); + return -1; + } return (asect->reloc_count + 1) * sizeof (arelent *); } +#if GCC_VERSION >= 4003 +# pragma GCC diagnostic pop +#endif asymbol * coff_make_empty_symbol (bfd *abfd) @@ -2036,9 +2036,8 @@ bfd_section_from_shdr (bfd *abfd, unsigned int shindex) sections_being_created = NULL; if (sections_being_created == NULL) { - /* FIXME: It would be more efficient to attach this array to the bfd somehow. */ sections_being_created = (bfd_boolean *) - bfd_zalloc (abfd, elf_numsections (abfd) * sizeof (bfd_boolean)); + bfd_zalloc2 (abfd, elf_numsections (abfd), sizeof (bfd_boolean)); sections_being_created_abfd = abfd; } if (sections_being_created [shindex]) @@ -2259,7 +2258,7 @@ bfd_section_from_shdr (bfd *abfd, unsigned int shindex) if (entry->ndx == shindex) goto success; - entry = bfd_alloc (abfd, sizeof * entry); + entry = bfd_alloc (abfd, sizeof (*entry)); if (entry == NULL) goto fail; entry->ndx = shindex; @@ -3737,11 +3736,11 @@ assign_section_numbers (bfd *abfd, struct bfd_link_info *link_info) _bfd_elf_strtab_addref (elf_shstrtab (abfd), t->symtab_hdr.sh_name); if (section_number > ((SHN_LORESERVE - 2) & 0xFFFF)) { - elf_section_list * entry; + elf_section_list *entry; BFD_ASSERT (elf_symtab_shndx_list (abfd) == NULL); - entry = bfd_zalloc (abfd, sizeof * entry); + entry = bfd_zalloc (abfd, sizeof (*entry)); entry->ndx = section_number++; elf_symtab_shndx_list (abfd) = entry; entry->hdr.sh_name @@ -7901,8 +7900,8 @@ swap_out_syms (bfd *abfd, symstrtab_hdr->sh_type = SHT_STRTAB; /* Allocate buffer to swap out the .strtab section. */ - symstrtab = (struct elf_sym_strtab *) bfd_malloc ((symcount + 1) - * sizeof (*symstrtab)); + symstrtab = (struct elf_sym_strtab *) bfd_malloc2 (symcount + 1, + sizeof (*symstrtab)); if (symstrtab == NULL) { _bfd_elf_strtab_free (stt); @@ -8269,12 +8268,25 @@ _bfd_elf_get_dynamic_symtab_upper_bound (bfd *abfd) return symtab_size; } +#if GCC_VERSION >= 4003 +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wtype-limits" +#endif long _bfd_elf_get_reloc_upper_bound (bfd *abfd ATTRIBUTE_UNUSED, sec_ptr asect) { + + if (asect->reloc_count >= LONG_MAX / sizeof (arelent *)) + { + bfd_set_error (bfd_error_file_too_big); + return -1; + } return (asect->reloc_count + 1) * sizeof (arelent *); } +#if GCC_VERSION >= 4003 +# pragma GCC diagnostic pop +#endif /* Canonicalize the relocs. */ @@ -8753,7 +8765,7 @@ _bfd_elf_make_empty_symbol (bfd *abfd) { elf_symbol_type *newsym; - newsym = (elf_symbol_type *) bfd_zalloc (abfd, sizeof * newsym); + newsym = (elf_symbol_type *) bfd_zalloc (abfd, sizeof (*newsym)); if (!newsym) return NULL; newsym->symbol.the_bfd = abfd; @@ -10233,8 +10245,8 @@ static bfd_boolean elfobj_grok_stapsdt_note_1 (bfd *abfd, Elf_Internal_Note *note) { struct sdt_note *cur = - (struct sdt_note *) bfd_alloc (abfd, sizeof (struct sdt_note) - + note->descsz); + (struct sdt_note *) bfd_alloc (abfd, + sizeof (struct sdt_note) + note->descsz); cur->next = (struct sdt_note *) (elf_tdata (abfd))->sdt_note_head; cur->size = (bfd_size_type) note->descsz; diff --git a/bfd/elf64-sparc.c b/bfd/elf64-sparc.c index bd29be3..f523ce7 100644 --- a/bfd/elf64-sparc.c +++ b/bfd/elf64-sparc.c @@ -19,6 +19,7 @@ MA 02110-1301, USA. */ #include "sysdep.h" +#include <limits.h> #include "bfd.h" #include "libbfd.h" #include "elf-bfd.h" @@ -33,16 +34,36 @@ section can represent up to two relocs, we must tell the user to allocate more space. */ +#if GCC_VERSION >= 4003 +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wtype-limits" +#endif static long elf64_sparc_get_reloc_upper_bound (bfd *abfd ATTRIBUTE_UNUSED, asection *sec) { + if (sec->reloc_count >= LONG_MAX / 2 / sizeof (arelent *)) + { + bfd_set_error (bfd_error_file_too_big); + return -1; + } return (sec->reloc_count * 2 + 1) * sizeof (arelent *); } +#if GCC_VERSION >= 4003 +# pragma GCC diagnostic pop +#endif static long elf64_sparc_get_dynamic_reloc_upper_bound (bfd *abfd) { - return _bfd_elf_get_dynamic_reloc_upper_bound (abfd) * 2; + long ret = _bfd_elf_get_dynamic_reloc_upper_bound (abfd); + if (ret > LONG_MAX / 2) + { + bfd_set_error (bfd_error_file_too_big); + ret = -1; + } + else if (ret > 0) + ret *= 2; + return ret; } /* Read relocations for ASECT from REL_HDR. There are RELOC_COUNT of diff --git a/bfd/elfcode.h b/bfd/elfcode.h index ec5ea76..a0487b0 100644 --- a/bfd/elfcode.h +++ b/bfd/elfcode.h @@ -503,7 +503,6 @@ elf_object_p (bfd *abfd) unsigned int shindex; const struct elf_backend_data *ebd; asection *s; - bfd_size_type amt; const bfd_target *target; /* Read in the ELF header in external format. */ @@ -688,14 +687,14 @@ elf_object_p (bfd *abfd) if (i_ehdrp->e_shnum > ((bfd_size_type) -1) / sizeof (*i_shdrp)) goto got_wrong_format_error; #endif - amt = sizeof (*i_shdrp) * (bfd_size_type) i_ehdrp->e_shnum; - i_shdrp = (Elf_Internal_Shdr *) bfd_alloc (abfd, amt); + i_shdrp = (Elf_Internal_Shdr *) bfd_alloc2 (abfd, i_ehdrp->e_shnum, + sizeof (*i_shdrp)); if (!i_shdrp) goto got_no_match; num_sec = i_ehdrp->e_shnum; elf_numsections (abfd) = num_sec; - amt = sizeof (i_shdrp) * num_sec; - elf_elfsections (abfd) = (Elf_Internal_Shdr **) bfd_alloc (abfd, amt); + elf_elfsections (abfd) + = (Elf_Internal_Shdr **) bfd_alloc2 (abfd, num_sec, sizeof (i_shdrp)); if (!elf_elfsections (abfd)) goto got_no_match; @@ -789,8 +788,9 @@ elf_object_p (bfd *abfd) if (bfd_get_file_size (abfd) > 0 && i_ehdrp->e_phnum > bfd_get_file_size (abfd)) goto got_no_match; - amt = (bfd_size_type) i_ehdrp->e_phnum * sizeof (*i_phdr); - elf_tdata (abfd)->phdr = (Elf_Internal_Phdr *) bfd_alloc (abfd, amt); + elf_tdata (abfd)->phdr + = (Elf_Internal_Phdr *) bfd_alloc2 (abfd, i_ehdrp->e_phnum, + sizeof (*i_phdr)); if (elf_tdata (abfd)->phdr == NULL) goto got_no_match; if (bfd_seek (abfd, (file_ptr) i_ehdrp->e_phoff, SEEK_SET) != 0) @@ -903,7 +903,8 @@ elf_write_relocs (bfd *abfd, asection *sec, void *data) rela_hdr = elf_section_data (sec)->rel.hdr; rela_hdr->sh_size = rela_hdr->sh_entsize * sec->reloc_count; - rela_hdr->contents = (unsigned char *) bfd_alloc (abfd, rela_hdr->sh_size); + rela_hdr->contents = (unsigned char *) bfd_alloc2 (abfd, sec->reloc_count, + rela_hdr->sh_entsize); if (rela_hdr->contents == NULL) { *failedp = TRUE; @@ -1040,9 +1041,8 @@ elf_write_shdrs_and_ehdr (bfd *abfd) i_shdrp[0]->sh_link = i_ehdrp->e_shstrndx; /* at this point we've concocted all the ELF sections... */ - amt = i_ehdrp->e_shnum; - amt *= sizeof (*x_shdrp); - x_shdrp = (Elf_External_Shdr *) bfd_alloc (abfd, amt); + x_shdrp = (Elf_External_Shdr *) bfd_alloc2 (abfd, i_ehdrp->e_shnum, + sizeof (*x_shdrp)); if (!x_shdrp) return FALSE; @@ -1053,6 +1053,7 @@ elf_write_shdrs_and_ehdr (bfd *abfd) #endif elf_swap_shdr_out (abfd, *i_shdrp, x_shdrp + count); } + amt = (bfd_size_type) i_ehdrp->e_shnum * sizeof (*x_shdrp); if (bfd_seek (abfd, (file_ptr) i_ehdrp->e_shoff, SEEK_SET) != 0 || bfd_bwrite (x_shdrp, amt, abfd) != amt) return FALSE; @@ -1152,7 +1153,6 @@ elf_slurp_symbol_table (bfd *abfd, asymbol **symptrs, bfd_boolean dynamic) Elf_External_Versym *xver; Elf_External_Versym *xverbuf = NULL; const struct elf_backend_data *ebd; - bfd_size_type amt; /* Read each raw ELF symbol, converting from external ELF form to internal ELF form, and then using the information to create a @@ -1197,9 +1197,8 @@ elf_slurp_symbol_table (bfd *abfd, asymbol **symptrs, bfd_boolean dynamic) if (isymbuf == NULL) return -1; - amt = symcount; - amt *= sizeof (elf_symbol_type); - symbase = (elf_symbol_type *) bfd_zalloc (abfd, amt); + symbase = (elf_symbol_type *) bfd_zalloc2 (abfd, symcount, + sizeof (elf_symbol_type)); if (symbase == (elf_symbol_type *) NULL) goto error_return; @@ -1519,7 +1518,6 @@ elf_slurp_reloc_table (bfd *abfd, bfd_size_type reloc_count; bfd_size_type reloc_count2; arelent *relents; - bfd_size_type amt; if (asect->relocation != NULL) return TRUE; @@ -1557,8 +1555,8 @@ elf_slurp_reloc_table (bfd *abfd, reloc_count2 = 0; } - amt = (reloc_count + reloc_count2) * sizeof (arelent); - relents = (arelent *) bfd_alloc (abfd, amt); + relents = (arelent *) bfd_alloc2 (abfd, reloc_count + reloc_count2, + sizeof (arelent)); if (relents == NULL) return FALSE; @@ -1713,8 +1711,9 @@ NAME(_bfd_elf,bfd_from_remote_memory) return NULL; } - x_phdrs = (Elf_External_Phdr *) - bfd_malloc (i_ehdr.e_phnum * (sizeof *x_phdrs + sizeof *i_phdrs)); + x_phdrs + = (Elf_External_Phdr *) bfd_malloc2 (i_ehdr.e_phnum, + sizeof (*x_phdrs) + sizeof (*i_phdrs)); if (x_phdrs == NULL) return NULL; err = target_read_memory (ehdr_vma + i_ehdr.e_phoff, (bfd_byte *) x_phdrs, diff --git a/bfd/mach-o.c b/bfd/mach-o.c index 917335d..a9ca313 100644 --- a/bfd/mach-o.c +++ b/bfd/mach-o.c @@ -19,6 +19,7 @@ MA 02110-1301, USA. */ #include "sysdep.h" +#include <limits.h> #include "bfd.h" #include "libbfd.h" #include "libiberty.h" @@ -1416,12 +1417,24 @@ bfd_mach_o_write_dyld_info (bfd *abfd, bfd_mach_o_load_command *command) return TRUE; } +#if GCC_VERSION >= 4003 +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wtype-limits" +#endif long bfd_mach_o_get_reloc_upper_bound (bfd *abfd ATTRIBUTE_UNUSED, asection *asect) { - return (asect->reloc_count + 1) * sizeof (arelent *); + if (asect->reloc_count >= LONG_MAX / sizeof (arelent *)) + { + bfd_set_error (bfd_error_file_too_big); + return -1; + } + return (asect->reloc_count + 1) * sizeof (arelent *); } +#if GCC_VERSION >= 4003 +# pragma GCC diagnostic pop +#endif /* In addition to the need to byte-swap the symbol number, the bit positions of the fields in the relocation information vary per target endian-ness. */ diff --git a/bfd/pdp11.c b/bfd/pdp11.c index b16c78f..1d34047 100644 --- a/bfd/pdp11.c +++ b/bfd/pdp11.c @@ -66,6 +66,7 @@ && N_MAGIC(x) != ZMAGIC) #include "sysdep.h" +#include <limits.h> #include "bfd.h" #define external_exec pdp11_external_exec @@ -1980,6 +1981,8 @@ NAME (aout, canonicalize_reloc) (bfd *abfd, long NAME (aout, get_reloc_upper_bound) (bfd *abfd, sec_ptr asect) { + bfd_size_type count; + if (bfd_get_format (abfd) != bfd_object) { bfd_set_error (bfd_error_invalid_operation); @@ -1987,28 +1990,25 @@ NAME (aout, get_reloc_upper_bound) (bfd *abfd, sec_ptr asect) } if (asect->flags & SEC_CONSTRUCTOR) - return (sizeof (arelent *) * (asect->reloc_count + 1)); - - if (asect == obj_datasec (abfd)) - return (sizeof (arelent *) - * ((exec_hdr (abfd)->a_drsize / obj_reloc_entry_size (abfd)) - + 1)); - - if (asect == obj_textsec (abfd)) - return (sizeof (arelent *) - * ((exec_hdr (abfd)->a_trsize / obj_reloc_entry_size (abfd)) - + 1)); - - /* TODO: why are there two if statements for obj_bsssec()? */ - - if (asect == obj_bsssec (abfd)) - return sizeof (arelent *); - - if (asect == obj_bsssec (abfd)) - return 0; + count = asect->reloc_count; + else if (asect == obj_datasec (abfd)) + count = exec_hdr (abfd)->a_drsize / obj_reloc_entry_size (abfd); + else if (asect == obj_textsec (abfd)) + count = exec_hdr (abfd)->a_trsize / obj_reloc_entry_size (abfd); + else if (asect == obj_bsssec (abfd)) + count = 0; + else + { + bfd_set_error (bfd_error_invalid_operation); + return -1; + } - bfd_set_error (bfd_error_invalid_operation); - return -1; + if (count >= LONG_MAX / sizeof (arelent *)) + { + bfd_set_error (bfd_error_file_too_big); + return -1; + } + return (count + 1) * sizeof (arelent *); } diff --git a/binutils/ChangeLog b/binutils/ChangeLog index 605a7b3..d62f94a 100644 --- a/binutils/ChangeLog +++ b/binutils/ChangeLog @@ -1,3 +1,10 @@ +2019-03-12 Alan Modra <amodra@gmail.com> + + * objdump.c (load_specific_debug_section): Don't compare section + size against file size. + (dump_relocs_in_section): Don't compare reloc size against file size. + Print "failed to read relocs" on bfd_get_reloc_upper_bound error. + 2019-03-05 Nick Clifton <nickc@redhat.com> PR 24295 diff --git a/binutils/objdump.c b/binutils/objdump.c index ab091c1..3ef2716 100644 --- a/binutils/objdump.c +++ b/binutils/objdump.c @@ -2695,7 +2695,7 @@ load_specific_debug_section (enum dwarf_section_display_enum debug, section->user_data = sec; section->size = bfd_get_section_size (sec); amt = section->size + 1; - if (amt == 0 || amt > bfd_get_file_size (abfd)) + if (amt == 0) { section->start = NULL; free_debug_section (debug); @@ -3640,47 +3640,28 @@ dump_relocs_in_section (bfd *abfd, || ((section->flags & SEC_RELOC) == 0)) return; - relsize = bfd_get_reloc_upper_bound (abfd, section); - if (relsize < 0) - bfd_fatal (bfd_get_filename (abfd)); - printf ("RELOCATION RECORDS FOR [%s]:", sanitize_string (section->name)); + relsize = bfd_get_reloc_upper_bound (abfd, section); if (relsize == 0) { printf (" (none)\n\n"); return; } - if ((bfd_get_file_flags (abfd) & (BFD_IN_MEMORY | BFD_LINKER_CREATED)) == 0 - && (/* Check that the size of the relocs is reasonable. Note that some - file formats, eg aout, can have relocs whose internal size is - larger than their external size, thus we check the size divided - by four against the file size. See PR 23931 for an example of - this. */ - ((ufile_ptr) (relsize / 4) > bfd_get_file_size (abfd)) - /* Also check the section's reloc count since if this is negative - (or very large) the computation in bfd_get_reloc_upper_bound - may have resulted in returning a small, positive integer. - See PR 22508 for a reproducer. - - Note - we check against file size rather than section size as - it is possible for there to be more relocs that apply to a - section than there are bytes in that section. */ - || (section->reloc_count > bfd_get_file_size (abfd)))) + if (relsize < 0) + relcount = relsize; + else { - printf (" (too many: %#x relocs)\n", section->reloc_count); - bfd_set_error (bfd_error_file_truncated); - bfd_fatal (bfd_get_filename (abfd)); + relpp = (arelent **) xmalloc (relsize); + relcount = bfd_canonicalize_reloc (abfd, section, relpp, syms); } - relpp = (arelent **) xmalloc (relsize); - relcount = bfd_canonicalize_reloc (abfd, section, relpp, syms); - if (relcount < 0) { printf ("\n"); - non_fatal (_("failed to read relocs in: %s"), sanitize_string (bfd_get_filename (abfd))); + non_fatal (_("failed to read relocs in: %s"), + sanitize_string (bfd_get_filename (abfd))); bfd_fatal (_("error message was")); } else if (relcount == 0) |