Fix seg-faults when running readelf on fuzzed binaries.
PR binutils/20440 * dwarf.c (display_debug_lines_decoded): Add checks for running off the end of the section when populating the directory table and file table. (frame_display_row): Set max_regs equal to ncols. (load_specific_debug_section): If the section is compressed, but it is not big enough to hold a compression header then warn and return 0.
This commit is contained in:
parent
8a286b6345
commit
d8024a9189
|
@ -1,5 +1,14 @@
|
||||||
2016-08-08 Nick Clifton <nickc@redhat.com>
|
2016-08-08 Nick Clifton <nickc@redhat.com>
|
||||||
|
|
||||||
|
PR binutils/20440
|
||||||
|
* dwarf.c (display_debug_lines_decoded): Add checks for running
|
||||||
|
off the end of the section when populating the directory table and
|
||||||
|
file table.
|
||||||
|
(frame_display_row): Set max_regs equal to ncols.
|
||||||
|
(load_specific_debug_section): If the section is compressed, but
|
||||||
|
it is not big enough to hold a compression header then warn and
|
||||||
|
return 0.
|
||||||
|
|
||||||
PR binutils/20439
|
PR binutils/20439
|
||||||
* dwarf.c (display_debug_lines_decoded): Check directory and file
|
* dwarf.c (display_debug_lines_decoded): Check directory and file
|
||||||
indicies before using them to access directory and file tables.
|
indicies before using them to access directory and file tables.
|
||||||
|
|
|
@ -3252,16 +3252,32 @@ display_debug_lines_decoded (struct dwarf_section *section,
|
||||||
|
|
||||||
/* Traverse the Directory table just to count entries. */
|
/* Traverse the Directory table just to count entries. */
|
||||||
data = standard_opcodes + linfo.li_opcode_base - 1;
|
data = standard_opcodes + linfo.li_opcode_base - 1;
|
||||||
|
/* PR 20440 */
|
||||||
|
if (data >= end)
|
||||||
|
{
|
||||||
|
warn (_("opcode base of %d extends beyond end of section\n"),
|
||||||
|
linfo.li_opcode_base);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (*data != 0)
|
if (*data != 0)
|
||||||
{
|
{
|
||||||
unsigned char *ptr_directory_table = data;
|
unsigned char *ptr_directory_table = data;
|
||||||
|
|
||||||
while (*data != 0)
|
while (data < end && *data != 0)
|
||||||
{
|
{
|
||||||
data += strnlen ((char *) data, end - data) + 1;
|
data += strnlen ((char *) data, end - data) + 1;
|
||||||
n_directories++;
|
n_directories++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* PR 20440 */
|
||||||
|
if (data >= end)
|
||||||
|
{
|
||||||
|
warn (_("directory table ends unexpectedly\n"));
|
||||||
|
n_directories = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
/* Go through the directory table again to save the directories. */
|
/* Go through the directory table again to save the directories. */
|
||||||
directory_table = (unsigned char **)
|
directory_table = (unsigned char **)
|
||||||
xmalloc (n_directories * sizeof (unsigned char *));
|
xmalloc (n_directories * sizeof (unsigned char *));
|
||||||
|
@ -3279,11 +3295,11 @@ display_debug_lines_decoded (struct dwarf_section *section,
|
||||||
data++;
|
data++;
|
||||||
|
|
||||||
/* Traverse the File Name table just to count the entries. */
|
/* Traverse the File Name table just to count the entries. */
|
||||||
if (*data != 0)
|
if (data < end && *data != 0)
|
||||||
{
|
{
|
||||||
unsigned char *ptr_file_name_table = data;
|
unsigned char *ptr_file_name_table = data;
|
||||||
|
|
||||||
while (*data != 0)
|
while (data < end && *data != 0)
|
||||||
{
|
{
|
||||||
unsigned int bytes_read;
|
unsigned int bytes_read;
|
||||||
|
|
||||||
|
@ -3300,6 +3316,13 @@ display_debug_lines_decoded (struct dwarf_section *section,
|
||||||
n_files++;
|
n_files++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (data >= end)
|
||||||
|
{
|
||||||
|
warn (_("file table ends unexpectedly\n"));
|
||||||
|
n_files = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
/* Go through the file table again to save the strings. */
|
/* Go through the file table again to save the strings. */
|
||||||
file_table = (File_Entry *) xmalloc (n_files * sizeof (File_Entry));
|
file_table = (File_Entry *) xmalloc (n_files * sizeof (File_Entry));
|
||||||
|
|
||||||
|
@ -5582,7 +5605,7 @@ frame_display_row (Frame_Chunk *fc, int *need_col_headers, unsigned int *max_reg
|
||||||
unsigned int r;
|
unsigned int r;
|
||||||
char tmp[100];
|
char tmp[100];
|
||||||
|
|
||||||
if (*max_regs < fc->ncols)
|
if (*max_regs != fc->ncols)
|
||||||
*max_regs = fc->ncols;
|
*max_regs = fc->ncols;
|
||||||
|
|
||||||
if (*need_col_headers)
|
if (*need_col_headers)
|
||||||
|
|
|
@ -5622,6 +5622,7 @@ get_compression_header (Elf_Internal_Chdr *chdr, unsigned char *buf)
|
||||||
if (is_32bit_elf)
|
if (is_32bit_elf)
|
||||||
{
|
{
|
||||||
Elf32_External_Chdr *echdr = (Elf32_External_Chdr *) buf;
|
Elf32_External_Chdr *echdr = (Elf32_External_Chdr *) buf;
|
||||||
|
|
||||||
chdr->ch_type = BYTE_GET (echdr->ch_type);
|
chdr->ch_type = BYTE_GET (echdr->ch_type);
|
||||||
chdr->ch_size = BYTE_GET (echdr->ch_size);
|
chdr->ch_size = BYTE_GET (echdr->ch_size);
|
||||||
chdr->ch_addralign = BYTE_GET (echdr->ch_addralign);
|
chdr->ch_addralign = BYTE_GET (echdr->ch_addralign);
|
||||||
|
@ -5630,6 +5631,7 @@ get_compression_header (Elf_Internal_Chdr *chdr, unsigned char *buf)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Elf64_External_Chdr *echdr = (Elf64_External_Chdr *) buf;
|
Elf64_External_Chdr *echdr = (Elf64_External_Chdr *) buf;
|
||||||
|
|
||||||
chdr->ch_type = BYTE_GET (echdr->ch_type);
|
chdr->ch_type = BYTE_GET (echdr->ch_type);
|
||||||
chdr->ch_size = BYTE_GET (echdr->ch_size);
|
chdr->ch_size = BYTE_GET (echdr->ch_size);
|
||||||
chdr->ch_addralign = BYTE_GET (echdr->ch_addralign);
|
chdr->ch_addralign = BYTE_GET (echdr->ch_addralign);
|
||||||
|
@ -6086,12 +6088,15 @@ process_section_headers (FILE * file)
|
||||||
/* Minimum section size is 12 bytes for 32-bit compression
|
/* Minimum section size is 12 bytes for 32-bit compression
|
||||||
header + 12 bytes for compressed data header. */
|
header + 12 bytes for compressed data header. */
|
||||||
unsigned char buf[24];
|
unsigned char buf[24];
|
||||||
|
|
||||||
assert (sizeof (buf) >= sizeof (Elf64_External_Chdr));
|
assert (sizeof (buf) >= sizeof (Elf64_External_Chdr));
|
||||||
if (get_data (&buf, (FILE *) file, section->sh_offset, 1,
|
if (get_data (&buf, (FILE *) file, section->sh_offset, 1,
|
||||||
sizeof (buf), _("compression header")))
|
sizeof (buf), _("compression header")))
|
||||||
{
|
{
|
||||||
Elf_Internal_Chdr chdr;
|
Elf_Internal_Chdr chdr;
|
||||||
get_compression_header (&chdr, buf);
|
|
||||||
|
(void) get_compression_header (&chdr, buf);
|
||||||
|
|
||||||
if (chdr.ch_type == ELFCOMPRESS_ZLIB)
|
if (chdr.ch_type == ELFCOMPRESS_ZLIB)
|
||||||
printf (" ZLIB, ");
|
printf (" ZLIB, ");
|
||||||
else
|
else
|
||||||
|
@ -12573,8 +12578,17 @@ load_specific_debug_section (enum dwarf_section_display_enum debug,
|
||||||
if ((sec->sh_flags & SHF_COMPRESSED) != 0)
|
if ((sec->sh_flags & SHF_COMPRESSED) != 0)
|
||||||
{
|
{
|
||||||
Elf_Internal_Chdr chdr;
|
Elf_Internal_Chdr chdr;
|
||||||
unsigned int compression_header_size
|
unsigned int compression_header_size;
|
||||||
= get_compression_header (&chdr, start);
|
|
||||||
|
if (size < sizeof chdr)
|
||||||
|
{
|
||||||
|
warn (_("compressed section %s is too small to contain a compression header"),
|
||||||
|
section->name);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
compression_header_size = get_compression_header (&chdr, start);
|
||||||
|
|
||||||
if (chdr.ch_type != ELFCOMPRESS_ZLIB)
|
if (chdr.ch_type != ELFCOMPRESS_ZLIB)
|
||||||
{
|
{
|
||||||
warn (_("section '%s' has unsupported compress type: %d\n"),
|
warn (_("section '%s' has unsupported compress type: %d\n"),
|
||||||
|
|
Loading…
Reference in New Issue