/* Support for the generic parts of COFF, for BFD.
- Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
- 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
- Free Software Foundation, Inc.
+ Copyright (C) 1990-2014 Free Software Foundation, Inc.
Written by Cygnus Support.
This file is part of BFD, the Binary File Descriptor library.
strings = _bfd_coff_read_string_table (abfd);
if (strings == NULL)
return FALSE;
- /* FIXME: For extra safety, we should make sure that
- strindex does not run us past the end, but right now we
- don't know the length of the string table. */
+ if ((bfd_size_type)(strindex + 2) >= obj_coff_strings_len (abfd))
+ return FALSE;
strings += strindex;
name = (char *) bfd_alloc (abfd,
(bfd_size_type) strlen (strings) + 1 + 1);
/* Read in a COFF object and make it into a BFD. This is used by
ECOFF as well. */
-
-static const bfd_target *
+const bfd_target *
+coff_real_object_p (bfd *,
+ unsigned,
+ struct internal_filehdr *,
+ struct internal_aouthdr *);
+const bfd_target *
coff_real_object_p (bfd *abfd,
unsigned nscns,
struct internal_filehdr *internal_f,
if (strings == NULL)
return NULL;
}
+ if (sym->_n._n_n._n_offset >= obj_coff_strings_len (abfd))
+ return NULL;
return strings + sym->_n._n_n._n_offset;
}
}
struct internal_syment *syment)
{
/* Normalize the symbol flags. */
- if (coff_symbol_ptr->symbol.section
+ if (coff_symbol_ptr->symbol.section
&& bfd_is_com_section (coff_symbol_ptr->symbol.section))
{
/* A common symbol is undefined with a value. */
/* Otherwise patch up. */
#define N_TMASK coff_data (abfd)->local_n_tmask
#define N_BTSHFT coff_data (abfd)->local_n_btshft
-
+
if ((ISFCN (type) || ISTAG (n_sclass) || n_sclass == C_BLOCK
|| n_sclass == C_FCN)
&& auxent->u.auxent.x_sym.x_fcnary.x_fcn.x_endndx.l > 0)
we didn't want to go to the trouble until someone needed it. */
static char *
-build_debug_section (bfd *abfd)
+build_debug_section (bfd *abfd, asection ** sect_return)
{
char *debug_section;
file_ptr position;
|| bfd_bread (debug_section, sec_size, abfd) != sec_size
|| bfd_seek (abfd, position, SEEK_SET) != 0)
return NULL;
+
+ * sect_return = sect;
return debug_section;
}
if (size == 0)
return TRUE;
+ /* PR binutils/17512: Do not even try to load
+ a symbol table bigger than the entire file... */
+ if (size >= (bfd_size_type) bfd_get_size (abfd))
+ return FALSE;
+
syms = bfd_malloc (size);
if (syms == NULL)
return FALSE;
/* Read in the external strings. The strings are not loaded until
they are needed. This is because we have no simple way of
- detecting a missing string table in an archive. */
+ detecting a missing string table in an archive. If the strings
+ are loaded then the STRINGS and STRINGS_LEN fields in the
+ coff_tdata structure will be set. */
const char *
_bfd_coff_read_string_table (bfd *abfd)
}
obj_coff_strings (abfd) = strings;
+ obj_coff_strings_len (abfd) = strsize;
return strings;
}
{
free (obj_coff_strings (abfd));
obj_coff_strings (abfd) = NULL;
+ obj_coff_strings_len (abfd) = 0;
}
return TRUE;
}
char *raw_src;
char *raw_end;
const char *string_table = NULL;
- char *debug_section = NULL;
+ asection * debug_sec = NULL;
+ char *debug_sec_data = NULL;
bfd_size_type size;
if (obj_raw_syments (abfd) != NULL)
return obj_raw_syments (abfd);
- size = obj_raw_syment_count (abfd) * sizeof (combined_entry_type);
+ size = obj_raw_syment_count (abfd);
+ if (size == 0)
+ return NULL;
+ /* PR binutils/17512: Do not even try to load
+ a symbol table bigger than the entire file... */
+ if (size >= (bfd_size_type) bfd_get_size (abfd))
+ return NULL;
+
+ size *= 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 < raw_end;
raw_src += symesz, internal_ptr++)
{
-
unsigned int i;
+
bfd_coff_swap_sym_in (abfd, (void *) raw_src,
(void *) & internal_ptr->u.syment);
symbol_ptr = internal_ptr;
i++)
{
internal_ptr++;
+ /* PR 17512: Prevent buffer overrun. */
+ if (internal_ptr >= internal_end)
+ return NULL;
+
raw_src += symesz;
bfd_coff_swap_aux_in (abfd, (void *) raw_src,
symbol_ptr->u.syment.n_type,
if (string_table == NULL)
return NULL;
}
-
- internal_ptr->u.syment._n._n_n._n_offset =
- ((bfd_hostptr_t)
- (string_table
- + (internal_ptr + 1)->u.auxent.x_file.x_n.x_offset));
+ if ((bfd_size_type)((internal_ptr + 1)->u.auxent.x_file.x_n.x_offset)
+ >= obj_coff_strings_len (abfd))
+ internal_ptr->u.syment._n._n_n._n_offset = (bfd_hostptr_t) _("<corrupt>");
+ else
+ internal_ptr->u.syment._n._n_n._n_offset =
+ ((bfd_hostptr_t)
+ (string_table
+ + (internal_ptr + 1)->u.auxent.x_file.x_n.x_offset));
}
else
{
if (string_table == NULL)
return NULL;
}
- internal_ptr->u.syment._n._n_n._n_offset =
- ((bfd_hostptr_t)
- (string_table
- + internal_ptr->u.syment._n._n_n._n_offset));
+ if (internal_ptr->u.syment._n._n_n._n_offset >= obj_coff_strings_len (abfd))
+ internal_ptr->u.syment._n._n_n._n_offset = (bfd_hostptr_t) _("<corrupt>");
+ else
+ internal_ptr->u.syment._n._n_n._n_offset =
+ ((bfd_hostptr_t)
+ (string_table
+ + internal_ptr->u.syment._n._n_n._n_offset));
}
else
{
/* Long name in debug section. Very similar. */
- if (debug_section == NULL)
- debug_section = build_debug_section (abfd);
- internal_ptr->u.syment._n._n_n._n_offset = (bfd_hostptr_t)
- (debug_section + internal_ptr->u.syment._n._n_n._n_offset);
+ if (debug_sec_data == NULL)
+ debug_sec_data = build_debug_section (abfd, & debug_sec);
+ if (debug_sec_data != NULL)
+ {
+ BFD_ASSERT (debug_sec != NULL);
+ /* PR binutils/17512: Catch out of range offsets into the debug data. */
+ if (internal_ptr->u.syment._n._n_n._n_offset > debug_sec->size)
+ internal_ptr->u.syment._n._n_n._n_offset = (bfd_hostptr_t) _("<corrupt>");
+ else
+ internal_ptr->u.syment._n._n_n._n_offset = (bfd_hostptr_t)
+ (debug_sec_data + internal_ptr->u.syment._n._n_n._n_offset);
+ }
+ else
+ internal_ptr->u.syment._n._n_n._n_offset = (bfd_hostptr_t) "";
}
}
internal_ptr += internal_ptr->u.syment.n_numaux;
new_symbol->lineno = NULL;
new_symbol->done_lineno = FALSE;
new_symbol->symbol.the_bfd = abfd;
-
+
return & new_symbol->symbol;
}
bfd_boolean
coff_find_nearest_line_with_names (bfd *abfd,
- const struct dwarf_debug_section *debug_sections,
- asection *section,
asymbol **symbols,
+ asection *section,
bfd_vma offset,
const char **filename_ptr,
const char **functionname_ptr,
- unsigned int *line_ptr)
+ unsigned int *line_ptr,
+ const struct dwarf_debug_section *debug_sections)
{
bfd_boolean found;
unsigned int i;
return TRUE;
/* Also try examining DWARF2 debugging information. */
- if (_bfd_dwarf2_find_nearest_line (abfd, debug_sections,
- section, symbols, offset,
+ if (_bfd_dwarf2_find_nearest_line (abfd, symbols, NULL, section, offset,
filename_ptr, functionname_ptr,
- line_ptr, NULL, 0,
+ line_ptr, NULL, debug_sections, 0,
&coff_data(abfd)->dwarf2_find_line_info))
return TRUE;
bfd_boolean
coff_find_nearest_line (bfd *abfd,
- asection *section,
asymbol **symbols,
+ asection *section,
bfd_vma offset,
const char **filename_ptr,
const char **functionname_ptr,
- unsigned int *line_ptr)
-{
- return coff_find_nearest_line_with_names (abfd, dwarf_debug_sections,
- section, symbols, offset,
- filename_ptr, functionname_ptr,
- line_ptr);
-}
-
-bfd_boolean
-coff_find_nearest_line_discriminator (bfd *abfd,
- asection *section,
- asymbol **symbols,
- bfd_vma offset,
- const char **filename_ptr,
- const char **functionname_ptr,
- unsigned int *line_ptr,
- unsigned int *discriminator)
+ unsigned int *line_ptr,
+ unsigned int *discriminator_ptr)
{
- *discriminator = 0;
- return coff_find_nearest_line_with_names (abfd, dwarf_debug_sections,
- section, symbols, offset,
+ if (discriminator_ptr)
+ *discriminator_ptr = 0;
+ return coff_find_nearest_line_with_names (abfd, symbols, section, offset,
filename_ptr, functionname_ptr,
- line_ptr);
+ line_ptr, dwarf_debug_sections);
}
-
bfd_boolean
coff_find_inliner_info (bfd *abfd,
const char **filename_ptr,