Fix invalid memory access attempting to read the compression header of a too-small...
authorNick Clifton <nickc@redhat.com>
Mon, 13 Feb 2017 14:52:48 +0000 (14:52 +0000)
committerNick Clifton <nickc@redhat.com>
Mon, 13 Feb 2017 14:52:48 +0000 (14:52 +0000)
PR binutils/21149
* readelf.c (get_compression_header): Add size parameter.  Check
size against sizeof compression header before attempting to
extract the header.
(process_section_headers): Pass size to get_compression_header.
(dump_section_as_strings): Likewise.
(dump_section_as_bytes): Likewise.
(load_specific_debug_section): Likewise.

binutils/ChangeLog
binutils/readelf.c

index ebaedccf7cbc4e51a0e64b8ee96b9997de131c8b..10140c204e51a44116e6a38a3a48b1b19a73cad2 100644 (file)
@@ -1,3 +1,14 @@
+2017-02-13  Nick Clifton  <nickc@redhat.com>
+
+       PR binutils/21149
+       * readelf.c (get_compression_header): Add size parameter.  Check
+       size against sizeof compression header before attempting to
+       extract the header.
+       (process_section_headers): Pass size to get_compression_header.
+       (dump_section_as_strings): Likewise.
+       (dump_section_as_bytes): Likewise.
+       (load_specific_debug_section): Likewise.
+
 2017-02-13  Nick Clifton  <nickc@redhat.com>
 
        PR binutils/21148
index a61befef3fbd92a8e392b81618d496f068433087..e6f48b424c61ff103375a952b3ee6ecd972a2c17 100644 (file)
@@ -5715,12 +5715,18 @@ get_elf_section_flags (bfd_vma sh_flags)
 }
 
 static unsigned int
-get_compression_header (Elf_Internal_Chdr *chdr, unsigned char *buf)
+get_compression_header (Elf_Internal_Chdr *chdr, unsigned char *buf, bfd_size_type size)
 {
   if (is_32bit_elf)
     {
       Elf32_External_Chdr *echdr = (Elf32_External_Chdr *) buf;
 
+      if (size < sizeof (* echdr))
+       {
+         error (_("Compressed section is too small even for a compression header\n"));
+         return 0;
+       }
+
       chdr->ch_type = BYTE_GET (echdr->ch_type);
       chdr->ch_size = BYTE_GET (echdr->ch_size);
       chdr->ch_addralign = BYTE_GET (echdr->ch_addralign);
@@ -5730,6 +5736,12 @@ get_compression_header (Elf_Internal_Chdr *chdr, unsigned char *buf)
     {
       Elf64_External_Chdr *echdr = (Elf64_External_Chdr *) buf;
 
+      if (size < sizeof (* echdr))
+       {
+         error (_("Compressed section is too small even for a compression header\n"));
+         return 0;
+       }
+
       chdr->ch_type = BYTE_GET (echdr->ch_type);
       chdr->ch_size = BYTE_GET (echdr->ch_size);
       chdr->ch_addralign = BYTE_GET (echdr->ch_addralign);
@@ -6311,7 +6323,7 @@ process_section_headers (FILE * file)
                {
                  Elf_Internal_Chdr chdr;
 
-                 (void) get_compression_header (&chdr, buf);
+                 (void) get_compression_header (&chdr, buf, sizeof (buf));
 
                  if (chdr.ch_type == ELFCOMPRESS_ZLIB)
                    printf ("       ZLIB, ");
@@ -12643,7 +12655,8 @@ dump_section_as_strings (Elf_Internal_Shdr * section, FILE * file)
        {
          Elf_Internal_Chdr chdr;
          unsigned int compression_header_size
-           = get_compression_header (& chdr, (unsigned char *) start);
+           = get_compression_header (& chdr, (unsigned char *) start,
+                                     num_bytes);
 
          if (chdr.ch_type != ELFCOMPRESS_ZLIB)
            {
@@ -12777,7 +12790,7 @@ dump_section_as_bytes (Elf_Internal_Shdr * section,
        {
          Elf_Internal_Chdr chdr;
          unsigned int compression_header_size
-           = get_compression_header (& chdr, start);
+           = get_compression_header (& chdr, start, section_size);
 
          if (chdr.ch_type != ELFCOMPRESS_ZLIB)
            {
@@ -12930,7 +12943,7 @@ load_specific_debug_section (enum dwarf_section_display_enum debug,
              return 0;
            }
 
-         compression_header_size = get_compression_header (&chdr, start);
+         compression_header_size = get_compression_header (&chdr, start, size);
 
          if (chdr.ch_type != ELFCOMPRESS_ZLIB)
            {