From: Nick Clifton Date: Tue, 11 Nov 2014 15:34:27 +0000 (+0000) Subject: More fixes for invalid memory accesses, uncovered by valgrind and binary fuzzers. X-Git-Url: http://git.efficios.com/?a=commitdiff_plain;h=201159ecec7e17600df4153e5d4e7a145f0c7cfe;p=deliverable%2Fbinutils-gdb.git More fixes for invalid memory accesses, uncovered by valgrind and binary fuzzers. PR binutils/17512 * coffcode.h (coff_slurp_line_table): Initialise the parts of the line number cache that would not be initialised by the copy from the new line number table. (coff_classify_symbol): Allow for _bfd_coff_internal_syment_name returning NULL. * coffgen.c (coff_get_normalized_symbols): Get the external symbols before allocating space for the internal symbols, in case the get fails. * elf.c (_bfd_elf_slurp_version_tables): Only allocate a verref array if one is needed. Likewise with the verdef array. * peXXigen.c (_bfd_XXi_swap_sym_in): Replace abort()'s with error messages. (_bfd_XXi_swap_aux_in): Make sure that all fields of the aux structure are initialised. (pe_print_edata): Avoid reading off the end of the data buffer. --- diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 2e3e5a5657..9f48d57849 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,22 @@ +2014-11-11 Nick Clifton + + PR binutils/17512 + * coffcode.h (coff_slurp_line_table): Initialise the parts of the + line number cache that would not be initialised by the copy from + the new line number table. + (coff_classify_symbol): Allow for _bfd_coff_internal_syment_name + returning NULL. + * coffgen.c (coff_get_normalized_symbols): Get the external + symbols before allocating space for the internal symbols, in case + the get fails. + * elf.c (_bfd_elf_slurp_version_tables): Only allocate a verref + array if one is needed. Likewise with the verdef array. + * peXXigen.c (_bfd_XXi_swap_sym_in): Replace abort()'s with error + messages. + (_bfd_XXi_swap_aux_in): Make sure that all fields of the aux + structure are initialised. + (pe_print_edata): Avoid reading off the end of the data buffer. + 2014-11-11 Alan Modra PR binutils/17512 diff --git a/bfd/coffcode.h b/bfd/coffcode.h index f10654e3f7..4bc80bd25a 100644 --- a/bfd/coffcode.h +++ b/bfd/coffcode.h @@ -4453,11 +4453,11 @@ buy_and_read (bfd *abfd, file_ptr where, bfd_size_type size) void * area = bfd_alloc (abfd, size); if (!area) - return (NULL); + return NULL; if (bfd_seek (abfd, where, SEEK_SET) != 0 || bfd_bread (area, size, abfd) != size) - return (NULL); - return (area); + return NULL; + return area; } /* @@ -4637,13 +4637,20 @@ coff_slurp_line_table (bfd *abfd, asection *asect) /* PR binutils/17512: Point the lineno to where this entry will be after the memcpy below. */ sym->lineno = lineno_cache + (n_cache_ptr - n_lineno_cache); - /* Copy the function and line number entries. */ do *n_cache_ptr++ = *old_ptr++; while (old_ptr->line_number != 0); } - memcpy (lineno_cache, n_lineno_cache, amt); + /* PR 17521: file: 078-10659-0.004. */ + if (n_cache_ptr < n_lineno_cache + asect->lineno_count) + { + amt = n_cache_ptr - n_lineno_cache; + memcpy (lineno_cache, n_lineno_cache, amt * sizeof (alent)); + memset (lineno_cache + amt, 0, (asect->lineno_count - amt) * sizeof (alent)); + } + else + memcpy (lineno_cache, n_lineno_cache, amt); } bfd_release (abfd, func_table); } @@ -5074,13 +5081,13 @@ coff_classify_symbol (bfd *abfd, if (syment->n_value == 0) { asection *sec; - char buf[SYMNMLEN + 1]; - - sec = coff_section_from_bfd_index (abfd, syment->n_scnum); - if (sec != NULL - && (strcmp (bfd_get_section_name (abfd, sec), - _bfd_coff_internal_syment_name (abfd, syment, buf)) - == 0)) + char * name; + char buf[SYMNMLEN + 1]; + + name = _bfd_coff_internal_syment_name (abfd, syment, buf) + sec = coff_section_from_bfd_index (abfd, syment->n_scnum); + if (sec != NULL && name != NULL + && (strcmp (bfd_get_section_name (abfd, sec), name) == 0)) return COFF_SYMBOL_PE_SECTION; } #endif diff --git a/bfd/coffgen.c b/bfd/coffgen.c index 6c69902507..aab88e38f1 100644 --- a/bfd/coffgen.c +++ b/bfd/coffgen.c @@ -1758,15 +1758,15 @@ coff_get_normalized_symtab (bfd *abfd) if (obj_raw_syments (abfd) != NULL) return obj_raw_syments (abfd); + if (! _bfd_coff_get_external_symbols (abfd)) + return NULL; + size = obj_raw_syment_count (abfd) * sizeof (combined_entry_type); internal = (combined_entry_type *) bfd_zalloc (abfd, size); if (internal == NULL && size != 0) return NULL; internal_end = internal + obj_raw_syment_count (abfd); - if (! _bfd_coff_get_external_symbols (abfd)) - return NULL; - raw_src = (char *) obj_coff_external_syms (abfd); /* Mark the end of the symbols. */ diff --git a/bfd/elf.c b/bfd/elf.c index 9c4dcdf452..8b207ad872 100644 --- a/bfd/elf.c +++ b/bfd/elf.c @@ -7269,8 +7269,12 @@ _bfd_elf_slurp_version_tables (bfd *abfd, bfd_boolean default_imported_symver) hdr = &elf_tdata (abfd)->dynverref_hdr; - elf_tdata (abfd)->verref = (Elf_Internal_Verneed *) + if (hdr->sh_info) + elf_tdata (abfd)->verref = (Elf_Internal_Verneed *) bfd_zalloc2 (abfd, hdr->sh_info, sizeof (Elf_Internal_Verneed)); + else + elf_tdata (abfd)->verref = NULL; + if (elf_tdata (abfd)->verref == NULL) goto error_return; @@ -7430,8 +7434,12 @@ error_return_verref: else freeidx = ++maxidx; } - elf_tdata (abfd)->verdef = (Elf_Internal_Verdef *) + if (maxidx) + elf_tdata (abfd)->verdef = (Elf_Internal_Verdef *) bfd_zalloc2 (abfd, maxidx, sizeof (Elf_Internal_Verdef)); + else + elf_tdata (abfd)->verdef = NULL; + if (elf_tdata (abfd)->verdef == NULL) goto error_return; @@ -7572,16 +7580,12 @@ asymbol * _bfd_elf_make_empty_symbol (bfd *abfd) { elf_symbol_type *newsym; - bfd_size_type amt = sizeof (elf_symbol_type); - newsym = (elf_symbol_type *) bfd_zalloc (abfd, amt); + newsym = (elf_symbol_type *) bfd_zalloc (abfd, sizeof * newsym); if (!newsym) return NULL; - else - { - newsym->symbol.the_bfd = abfd; - return &newsym->symbol; - } + newsym->symbol.the_bfd = abfd; + return &newsym->symbol; } void diff --git a/bfd/peXXigen.c b/bfd/peXXigen.c index d1b33fd3b3..725e9f6790 100644 --- a/bfd/peXXigen.c +++ b/bfd/peXXigen.c @@ -149,8 +149,13 @@ _bfd_XXi_swap_sym_in (bfd * abfd, void * ext1, void * in1) name = _bfd_coff_internal_syment_name (abfd, in, namebuf); if (name == NULL) - /* FIXME: Return error. */ - abort (); + { + _bfd_error_handler (_("%B: unable to find name for empty section"), + abfd); + bfd_set_error (bfd_error_invalid_target); + return; + } + sec = bfd_get_section_by_name (abfd, name); if (sec != NULL) in->n_scnum = sec->target_index; @@ -170,15 +175,22 @@ _bfd_XXi_swap_sym_in (bfd * abfd, void * ext1, void * in1) { name = (const char *) bfd_alloc (abfd, strlen (namebuf) + 1); if (name == NULL) - /* FIXME: Return error. */ - abort (); + { + _bfd_error_handler (_("%B: out of memory creating name for empty section"), + abfd); + return; + } strcpy ((char *) name, namebuf); } + flags = SEC_HAS_CONTENTS | SEC_ALLOC | SEC_DATA | SEC_LOAD; sec = bfd_make_section_anyway_with_flags (abfd, name, flags); if (sec == NULL) - /* FIXME: Return error. */ - abort (); + { + _bfd_error_handler (_("%B: unable to create fake empty section"), + abfd); + return; + } sec->vma = 0; sec->lma = 0; @@ -283,6 +295,9 @@ _bfd_XXi_swap_aux_in (bfd * abfd, AUXENT *ext = (AUXENT *) ext1; union internal_auxent *in = (union internal_auxent *) in1; + /* PR 17521: Make sure that all fields in the aux structure + are initialised. */ + memset (in, 0, sizeof * in); switch (in_class) { case C_FILE: @@ -1681,7 +1696,9 @@ pe_print_edata (bfd * abfd, void * vfile) bfd_fprintf_vma (abfd, file, edt.name); if ((edt.name >= adj) && (edt.name < adj + datasize)) - fprintf (file, " %s\n", data + edt.name - adj); + fprintf (file, " %.*s\n", + (int) (datasize - (edt.name - adj)), + data + edt.name - adj); else fprintf (file, "(outside .edata section)\n");