Fixes for crashes running readelf.
PR binutils/17531 * readelf.c (get_data): If the reason parameter is null, do not print any error messages. (get_32bit_section_headers): Verify section header entry size before reading in the section headers. (get_64bit_section_headers): Likewise. (process_section_headers): Pass FALSE to get_section_headers. (get_file_header): Pass TRUE to get_section_headers. (process_dynamic_section): Change an assert to an error message. (process_symbol_table): Handle corrupt histograms.
This commit is contained in:
parent
e0f52461c2
commit
049b0c3a24
2 changed files with 96 additions and 33 deletions
|
@ -1,3 +1,16 @@
|
|||
2014-11-04 Nick Clifton <nickc@redhat.com>
|
||||
|
||||
PR binutils/17531
|
||||
* readelf.c (get_data): If the reason parameter is null, do not
|
||||
print any error messages.
|
||||
(get_32bit_section_headers): Verify section header entry size
|
||||
before reading in the section headers.
|
||||
(get_64bit_section_headers): Likewise.
|
||||
(process_section_headers): Pass FALSE to get_section_headers.
|
||||
(get_file_header): Pass TRUE to get_section_headers.
|
||||
(process_dynamic_section): Change an assert to an error message.
|
||||
(process_symbol_table): Handle corrupt histograms.
|
||||
|
||||
2014-11-03 Nick Clifton <nickc@redhat.com>
|
||||
|
||||
PR binutils/17512
|
||||
|
|
|
@ -316,8 +316,9 @@ get_data (void * var, FILE * file, long offset, size_t size, size_t nmemb,
|
|||
|
||||
if (fseek (file, archive_file_offset + offset, SEEK_SET))
|
||||
{
|
||||
error (_("Unable to seek to 0x%lx for %s\n"),
|
||||
(unsigned long) archive_file_offset + offset, reason);
|
||||
if (reason)
|
||||
error (_("Unable to seek to 0x%lx for %s\n"),
|
||||
(unsigned long) archive_file_offset + offset, reason);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -331,8 +332,9 @@ get_data (void * var, FILE * file, long offset, size_t size, size_t nmemb,
|
|||
|
||||
if (mvar == NULL)
|
||||
{
|
||||
error (_("Out of memory allocating 0x%lx bytes for %s\n"),
|
||||
(unsigned long)(size * nmemb), reason);
|
||||
if (reason)
|
||||
error (_("Out of memory allocating 0x%lx bytes for %s\n"),
|
||||
(unsigned long)(size * nmemb), reason);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -341,8 +343,9 @@ get_data (void * var, FILE * file, long offset, size_t size, size_t nmemb,
|
|||
|
||||
if (fread (mvar, size, nmemb, file) != nmemb)
|
||||
{
|
||||
error (_("Unable to read in 0x%lx bytes of %s\n"),
|
||||
(unsigned long)(size * nmemb), reason);
|
||||
if (reason)
|
||||
error (_("Unable to read in 0x%lx bytes of %s\n"),
|
||||
(unsigned long)(size * nmemb), reason);
|
||||
if (mvar != var)
|
||||
free (mvar);
|
||||
return NULL;
|
||||
|
@ -4482,26 +4485,46 @@ offset_from_vma (FILE * file, bfd_vma vma, bfd_size_type size)
|
|||
}
|
||||
|
||||
|
||||
static int
|
||||
get_32bit_section_headers (FILE * file, unsigned int num)
|
||||
/* Allocate memory and load the sections headers into the global pointer
|
||||
SECTION_HEADERS. If PROBE is true, this is just a probe and we do not
|
||||
generate any error messages if the load fails. */
|
||||
|
||||
static bfd_boolean
|
||||
get_32bit_section_headers (FILE * file, bfd_boolean probe)
|
||||
{
|
||||
Elf32_External_Shdr * shdrs;
|
||||
Elf_Internal_Shdr * internal;
|
||||
unsigned int i;
|
||||
unsigned int size = elf_header.e_shentsize;
|
||||
unsigned int num = probe ? 1 : elf_header.e_shnum;
|
||||
|
||||
/* PR binutils/17531: Cope with unexpected section header sizes. */
|
||||
if (size == 0 || num == 0)
|
||||
return FALSE;
|
||||
if (size < sizeof * shdrs)
|
||||
{
|
||||
if (! probe)
|
||||
error (_("The e_shentsize field in the ELF header is less than the size of an ELF section header\n"));
|
||||
return FALSE;
|
||||
}
|
||||
if (!probe && size > sizeof * shdrs)
|
||||
warn (_("The e_shentsize field in the ELF header is larger than the size of an ELF section header\n"));
|
||||
|
||||
shdrs = (Elf32_External_Shdr *) get_data (NULL, file, elf_header.e_shoff,
|
||||
elf_header.e_shentsize, num,
|
||||
_("section headers"));
|
||||
if (!shdrs)
|
||||
return 0;
|
||||
size, num,
|
||||
probe ? NULL : _("section headers"));
|
||||
if (shdrs == NULL)
|
||||
return FALSE;
|
||||
|
||||
if (section_headers != NULL)
|
||||
free (section_headers);
|
||||
section_headers = (Elf_Internal_Shdr *) cmalloc (num,
|
||||
sizeof (Elf_Internal_Shdr));
|
||||
|
||||
if (section_headers == NULL)
|
||||
{
|
||||
error (_("Out of memory\n"));
|
||||
return 0;
|
||||
if (!probe)
|
||||
error (_("Out of memory\n"));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
for (i = 0, internal = section_headers;
|
||||
|
@ -4521,30 +4544,45 @@ get_32bit_section_headers (FILE * file, unsigned int num)
|
|||
}
|
||||
|
||||
free (shdrs);
|
||||
|
||||
return 1;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static int
|
||||
get_64bit_section_headers (FILE * file, unsigned int num)
|
||||
static bfd_boolean
|
||||
get_64bit_section_headers (FILE * file, bfd_boolean probe)
|
||||
{
|
||||
Elf64_External_Shdr * shdrs;
|
||||
Elf_Internal_Shdr * internal;
|
||||
unsigned int i;
|
||||
unsigned int size = elf_header.e_shentsize;
|
||||
unsigned int num = probe ? 1 : elf_header.e_shnum;
|
||||
|
||||
/* PR binutils/17531: Cope with unexpected section header sizes. */
|
||||
if (size == 0 || num == 0)
|
||||
return FALSE;
|
||||
if (size < sizeof * shdrs)
|
||||
{
|
||||
if (! probe)
|
||||
error (_("The e_shentsize field in the ELF header is less than the size of an ELF section header\n"));
|
||||
return FALSE;
|
||||
}
|
||||
if (! probe && size > sizeof * shdrs)
|
||||
warn (_("The e_shentsize field in the ELF header is larger than the size of an ELF section header\n"));
|
||||
|
||||
shdrs = (Elf64_External_Shdr *) get_data (NULL, file, elf_header.e_shoff,
|
||||
elf_header.e_shentsize, num,
|
||||
_("section headers"));
|
||||
if (!shdrs)
|
||||
return 0;
|
||||
size, num,
|
||||
probe ? NULL : _("section headers"));
|
||||
if (shdrs == NULL)
|
||||
return FALSE;
|
||||
|
||||
if (section_headers != NULL)
|
||||
free (section_headers);
|
||||
section_headers = (Elf_Internal_Shdr *) cmalloc (num,
|
||||
sizeof (Elf_Internal_Shdr));
|
||||
|
||||
if (section_headers == NULL)
|
||||
{
|
||||
error (_("Out of memory\n"));
|
||||
return 0;
|
||||
if (! probe)
|
||||
error (_("Out of memory\n"));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
for (i = 0, internal = section_headers;
|
||||
|
@ -4564,8 +4602,7 @@ get_64bit_section_headers (FILE * file, unsigned int num)
|
|||
}
|
||||
|
||||
free (shdrs);
|
||||
|
||||
return 1;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static Elf_Internal_Sym *
|
||||
|
@ -4998,10 +5035,10 @@ process_section_headers (FILE * file)
|
|||
|
||||
if (is_32bit_elf)
|
||||
{
|
||||
if (! get_32bit_section_headers (file, elf_header.e_shnum))
|
||||
if (! get_32bit_section_headers (file, FALSE))
|
||||
return 0;
|
||||
}
|
||||
else if (! get_64bit_section_headers (file, elf_header.e_shnum))
|
||||
else if (! get_64bit_section_headers (file, FALSE))
|
||||
return 0;
|
||||
|
||||
/* Read in the string table, so that we have names to display. */
|
||||
|
@ -8236,7 +8273,11 @@ process_dynamic_section (FILE * file)
|
|||
{
|
||||
/* Note: these braces are necessary to avoid a syntax
|
||||
error from the SunOS4 C compiler. */
|
||||
assert (sizeof (Elf_External_Syminfo) == entry->d_un.d_val);
|
||||
/* PR binutils/17531: A corrupt file can trigger this test.
|
||||
So do not use an assert, instead generate an error message. */
|
||||
if (sizeof (Elf_External_Syminfo) != entry->d_un.d_val)
|
||||
error (_("Bad value (%d) for SYMINENT entry"),
|
||||
(int) entry->d_un.d_val);
|
||||
}
|
||||
else if (entry->d_tag == DT_SYMINSZ)
|
||||
syminsz = entry->d_un.d_val;
|
||||
|
@ -10133,6 +10174,15 @@ process_symbol_table (FILE * file)
|
|||
++nsyms;
|
||||
if (maxlength < ++lengths[hn])
|
||||
++maxlength;
|
||||
|
||||
/* PR binutils/17531: A corrupt binary could contain broken
|
||||
histogram data. Do not go into an infinite loop trying
|
||||
to process it. */
|
||||
if (chains[si] == si)
|
||||
{
|
||||
error (_("histogram chain links to itself\n"));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -14466,9 +14516,9 @@ get_file_header (FILE * file)
|
|||
/* There may be some extensions in the first section header. Don't
|
||||
bomb if we can't read it. */
|
||||
if (is_32bit_elf)
|
||||
get_32bit_section_headers (file, 1);
|
||||
get_32bit_section_headers (file, TRUE);
|
||||
else
|
||||
get_64bit_section_headers (file, 1);
|
||||
get_64bit_section_headers (file, TRUE);
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
|
Loading…
Reference in a new issue