Fix seg-faults when running readelf on fuzzed binaries.
authorNick Clifton <nickc@redhat.com>
Mon, 8 Aug 2016 12:20:04 +0000 (13:20 +0100)
committerNick Clifton <nickc@redhat.com>
Mon, 8 Aug 2016 12:20:04 +0000 (13:20 +0100)
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.

binutils/ChangeLog
binutils/dwarf.c
binutils/readelf.c

index 2ba1bbdf0e18a7968595a23f63e0f2c250e56853..d21c299fac89975918f0c9a0e8bd8d0ba0d37e65 100644 (file)
@@ -1,5 +1,14 @@
 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
        * dwarf.c (display_debug_lines_decoded): Check directory and file
        indicies before using them to access directory and file tables.
index 2f2d8aea780897cdb1238aa1197feda0f82e84b5..e07f66142016bec3cb65b7a10c89b0767342bf51 100644 (file)
@@ -3252,16 +3252,32 @@ display_debug_lines_decoded (struct dwarf_section *section,
 
          /* Traverse the Directory table just to count entries.  */
          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)
            {
              unsigned char *ptr_directory_table = data;
 
-             while (*data != 0)
+             while (data < end && *data != 0)
                {
                  data += strnlen ((char *) data, end - data) + 1;
                  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.  */
              directory_table = (unsigned char **)
                xmalloc (n_directories * sizeof (unsigned char *));
@@ -3279,11 +3295,11 @@ display_debug_lines_decoded (struct dwarf_section *section,
          data++;
 
          /* 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;
 
-             while (*data != 0)
+             while (data < end && *data != 0)
                {
                  unsigned int bytes_read;
 
@@ -3300,6 +3316,13 @@ display_debug_lines_decoded (struct dwarf_section *section,
                  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.  */
              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;
   char tmp[100];
 
-  if (*max_regs < fc->ncols)
+  if (*max_regs != fc->ncols)
     *max_regs = fc->ncols;
 
   if (*need_col_headers)
index 4c7ad4c99c3e0e6dd1fa4849a3fceb1c53367211..e6674c2f5fcd85d2cf55a64a99b85bce441d2cd3 100644 (file)
@@ -5622,6 +5622,7 @@ get_compression_header (Elf_Internal_Chdr *chdr, unsigned char *buf)
   if (is_32bit_elf)
     {
       Elf32_External_Chdr *echdr = (Elf32_External_Chdr *) buf;
+
       chdr->ch_type = BYTE_GET (echdr->ch_type);
       chdr->ch_size = BYTE_GET (echdr->ch_size);
       chdr->ch_addralign = BYTE_GET (echdr->ch_addralign);
@@ -5630,6 +5631,7 @@ get_compression_header (Elf_Internal_Chdr *chdr, unsigned char *buf)
   else
     {
       Elf64_External_Chdr *echdr = (Elf64_External_Chdr *) buf;
+
       chdr->ch_type = BYTE_GET (echdr->ch_type);
       chdr->ch_size = BYTE_GET (echdr->ch_size);
       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
                 header + 12 bytes for compressed data header.  */
              unsigned char buf[24];
+
              assert (sizeof (buf) >= sizeof (Elf64_External_Chdr));
              if (get_data (&buf, (FILE *) file, section->sh_offset, 1,
                            sizeof (buf), _("compression header")))
                {
                  Elf_Internal_Chdr chdr;
-                 get_compression_header (&chdr, buf);
+
+                 (void) get_compression_header (&chdr, buf);
+
                  if (chdr.ch_type == ELFCOMPRESS_ZLIB)
                    printf ("       ZLIB, ");
                  else
@@ -12573,8 +12578,17 @@ load_specific_debug_section (enum dwarf_section_display_enum debug,
       if ((sec->sh_flags & SHF_COMPRESSED) != 0)
        {
          Elf_Internal_Chdr chdr;
-         unsigned int compression_header_size
-           = get_compression_header (&chdr, start);
+         unsigned int compression_header_size;
+
+         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)
            {
              warn (_("section '%s' has unsupported compress type: %d\n"),
This page took 0.056342 seconds and 4 git commands to generate.