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.
This commit is contained in:
Nick Clifton 2014-11-11 15:34:27 +00:00
parent 015de6884f
commit 201159ecec
5 changed files with 78 additions and 31 deletions

View File

@ -1,3 +1,22 @@
2014-11-11 Nick Clifton <nickc@redhat.com>
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 <amodra@gmail.com>
PR binutils/17512

View File

@ -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,12 +4637,19 @@ 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);
}
/* 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 * 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
&& (strcmp (bfd_get_section_name (abfd, sec),
_bfd_coff_internal_syment_name (abfd, syment, buf))
== 0))
if (sec != NULL && name != NULL
&& (strcmp (bfd_get_section_name (abfd, sec), name) == 0))
return COFF_SYMBOL_PE_SECTION;
}
#endif

View File

@ -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. */

View File

@ -7269,8 +7269,12 @@ _bfd_elf_slurp_version_tables (bfd *abfd, bfd_boolean default_imported_symver)
hdr = &elf_tdata (abfd)->dynverref_hdr;
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;
}
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;
}
}
void

View File

@ -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");