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;
}
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;
}
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;
}
-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;
}
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;
}
free (shdrs);
-
- return 1;
+ return TRUE;
}
static Elf_Internal_Sym *
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. */
{
/* 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;
++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;
+ }
}
}
/* 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;