aboutsummaryrefslogtreecommitdiff
path: root/bfd/mach-o.c
diff options
context:
space:
mode:
authorNick Clifton <nickc@redhat.com>2015-01-05 23:13:50 +0000
committerNick Clifton <nickc@redhat.com>2015-01-05 23:13:50 +0000
commit896ca0981329171639b1fe0b934393a79ef4fdfb (patch)
treeac6f2a1d6ab8084254dac309ba83173eb962d5c2 /bfd/mach-o.c
parent82b1b41bcdc6d01fdbd94b246e24a8a8f8c2bddd (diff)
downloadgdb-896ca0981329171639b1fe0b934393a79ef4fdfb.zip
gdb-896ca0981329171639b1fe0b934393a79ef4fdfb.tar.gz
gdb-896ca0981329171639b1fe0b934393a79ef4fdfb.tar.bz2
More fixes for invalid memory accesses triggered by fuzzed binaries.
PR binutils/17512 * nm.c (print_symbol): Add 'is_synthetic' parameter. Use it to help initialize the info.elfinfo field. (print_size_symbols): Add 'synth_count' parameter. Use it to set the is_synthetic parameter when calling print_symbol. (print_symbols): Likewise. (display_rel_file): Pass synth_count to printing function. (display_archive): Break loop if the last archive displayed matches the current archive. * size.c (display_archive): Likewise. * archive.c (do_slurp_bsd_armap): Make sure that the parsed sized is at least big enough for the header to be read. * elf32-i386.c (elf_i386_get_plt_sym_val): Skip unknown relocs. * mach-o.c (bfd_mach_o_get_synthetic_symtab): Add range checks. (bfd_mach_o_read_command): Prevetn duplicate error messages about unrecognized commands. * syms.c (_bfd_stab_section_find_nearest_line): Add range checks when indexing into the string table.
Diffstat (limited to 'bfd/mach-o.c')
-rw-r--r--bfd/mach-o.c61
1 files changed, 49 insertions, 12 deletions
diff --git a/bfd/mach-o.c b/bfd/mach-o.c
index 14d6276..5dd6250 100644
--- a/bfd/mach-o.c
+++ b/bfd/mach-o.c
@@ -790,18 +790,19 @@ bfd_mach_o_get_synthetic_symtab (bfd *abfd,
bfd_mach_o_dysymtab_command *dysymtab = mdata->dysymtab;
bfd_mach_o_symtab_command *symtab = mdata->symtab;
asymbol *s;
+ char * s_start;
+ char * s_end;
unsigned long count, i, j, n;
size_t size;
char *names;
char *nul_name;
+ const char stub [] = "$stub";
*ret = NULL;
/* Stop now if no symbols or no indirect symbols. */
- if (dysymtab == NULL || symtab == NULL || symtab->symbols == NULL)
- return 0;
-
- if (dysymtab->nindirectsyms == 0)
+ if (dysymtab == NULL || dysymtab->nindirectsyms == 0
+ || symtab == NULL || symtab->symbols == NULL)
return 0;
/* We need to allocate a bfd symbol for every indirect symbol and to
@@ -811,19 +812,23 @@ bfd_mach_o_get_synthetic_symtab (bfd *abfd,
for (j = 0; j < count; j++)
{
+ const char * strng;
unsigned int isym = dysymtab->indirect_syms[j];
/* Some indirect symbols are anonymous. */
- if (isym < symtab->nsyms && symtab->symbols[isym].symbol.name)
- size += strlen (symtab->symbols[isym].symbol.name) + sizeof ("$stub");
+ if (isym < symtab->nsyms && (strng = symtab->symbols[isym].symbol.name))
+ /* PR 17512: file: f5b8eeba. */
+ size += strnlen (strng, symtab->strsize - (strng - symtab->strtab)) + sizeof (stub);
}
- s = *ret = (asymbol *) bfd_malloc (size);
+ s_start = bfd_malloc (size);
+ s = *ret = (asymbol *) s_start;
if (s == NULL)
return -1;
names = (char *) (s + count);
nul_name = names;
*names++ = 0;
+ s_end = s_start + size;
n = 0;
for (i = 0; i < mdata->nsects; i++)
@@ -843,10 +848,19 @@ bfd_mach_o_get_synthetic_symtab (bfd *abfd,
last = first + bfd_mach_o_section_get_nbr_indirect (abfd, sec);
addr = sec->addr;
entry_size = bfd_mach_o_section_get_entry_size (abfd, sec);
+
+ /* PR 17512: file: 08e15eec. */
+ if (first >= count || last >= count || first > last)
+ goto fail;
+
for (j = first; j < last; j++)
{
unsigned int isym = dysymtab->indirect_syms[j];
+ /* PR 17512: file: 04d64d9b. */
+ if (((char *) s) + sizeof (* s) > s_end)
+ goto fail;
+
s->flags = BSF_GLOBAL | BSF_SYNTHETIC;
s->section = sec->bfdsection;
s->value = addr - sec->addr;
@@ -860,10 +874,16 @@ bfd_mach_o_get_synthetic_symtab (bfd *abfd,
s->name = names;
len = strlen (sym);
+ /* PR 17512: file: 47dfd4d2. */
+ if (names + len >= s_end)
+ goto fail;
memcpy (names, sym, len);
names += len;
- memcpy (names, "$stub", sizeof ("$stub"));
- names += sizeof ("$stub");
+ /* PR 17512: file: 18f340a4. */
+ if (names + sizeof (stub) >= s_end)
+ goto fail;
+ memcpy (names, stub, sizeof (stub));
+ names += sizeof (stub);
}
else
s->name = nul_name;
@@ -879,6 +899,11 @@ bfd_mach_o_get_synthetic_symtab (bfd *abfd,
}
return n;
+
+ fail:
+ free (s_start);
+ * ret = NULL;
+ return -1;
}
void
@@ -4660,9 +4685,21 @@ bfd_mach_o_read_command (bfd *abfd, bfd_mach_o_load_command *command)
return FALSE;
break;
default:
- (*_bfd_error_handler)(_("%B: unknown load command 0x%lx"),
- abfd, (unsigned long) command->type);
- break;
+ {
+ static bfd_boolean unknown_set = FALSE;
+ static unsigned long unknown_command = 0;
+
+ /* Prevent reams of error messages when parsing corrupt binaries. */
+ if (!unknown_set)
+ unknown_set = TRUE;
+ else if (command->type == unknown_command)
+ break;
+ unknown_command = command->type;
+
+ (*_bfd_error_handler)(_("%B: unknown load command 0x%lx"),
+ abfd, (unsigned long) command->type);
+ break;
+ }
}
return TRUE;