aboutsummaryrefslogtreecommitdiff
path: root/bfd
diff options
context:
space:
mode:
authorNick Clifton <nickc@redhat.com>2014-11-11 15:34:27 +0000
committerNick Clifton <nickc@redhat.com>2014-11-11 15:34:27 +0000
commit201159ecec7e17600df4153e5d4e7a145f0c7cfe (patch)
tree328d0499e8bedc423bb8907ad53e30f7647f2df1 /bfd
parent015de6884f6fdebaffd4b7d4c7f14fb4d5fc0bb1 (diff)
downloadgdb-201159ecec7e17600df4153e5d4e7a145f0c7cfe.zip
gdb-201159ecec7e17600df4153e5d4e7a145f0c7cfe.tar.gz
gdb-201159ecec7e17600df4153e5d4e7a145f0c7cfe.tar.bz2
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.
Diffstat (limited to 'bfd')
-rw-r--r--bfd/ChangeLog19
-rw-r--r--bfd/coffcode.h31
-rw-r--r--bfd/coffgen.c6
-rw-r--r--bfd/elf.c22
-rw-r--r--bfd/peXXigen.c31
5 files changed, 78 insertions, 31 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index 2e3e5a5..9f48d57 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -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
diff --git a/bfd/coffcode.h b/bfd/coffcode.h
index f10654e..4bc80bd 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 6c69902..aab88e3 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 9c4dcdf..8b207ad 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 d1b33fd..725e9f6 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");