Fix access violation when parsing a corrupt IEEE binary.
authorNick Clifton <nickc@redhat.com>
Mon, 19 Jun 2017 13:06:53 +0000 (14:06 +0100)
committerNick Clifton <nickc@redhat.com>
Mon, 19 Jun 2017 13:06:53 +0000 (14:06 +0100)
PR binutils/21612
* libieee.h (struct common_header_type): Add end_p field.
* ieee.c (this_byte_and_next): Do not advance input_p beyond
end_p.
(read_id): Check for a length that exceeds the remaining bytes in
the input buffer.
(ieee_seek): Initialise end_p.
(ieee_archive_p): Likewise.
(ieee_object_p): Likewise.

bfd/ChangeLog
bfd/ieee.c
bfd/libieee.h

index 6aa4c9099f7f56aa2a14e25bf1039cbd3d237906..e7185172c1db6a4caf7c9a4f5219d1a7c58dbc5c 100644 (file)
@@ -1,3 +1,15 @@
+2017-06-19  Nick Clifton  <nickc@redhat.com>
+
+       PR binutils/21612
+       * libieee.h (struct common_header_type): Add end_p field.
+       * ieee.c (this_byte_and_next): Do not advance input_p beyond
+       end_p.
+       (read_id): Check for a length that exceeds the remaining bytes in
+       the input buffer.
+       (ieee_seek): Initialise end_p.
+       (ieee_archive_p): Likewise.
+       (ieee_object_p): Likewise.
+
 2017-06-19  Nick Clifton  <nickc@redhat.com>
 
        PR binutils/21611
index d5220b6ab1551a8e8f533b534586d3147ea64929..08d08d4eecbe1c27ab982bd37f92f07693136fa9 100644 (file)
@@ -170,7 +170,7 @@ ieee_write_id (bfd *abfd, const char *id)
    standard requires.  */
 
 #define this_byte(ieee)           *((ieee)->input_p)
-#define this_byte_and_next(ieee) (*((ieee)->input_p++))
+#define this_byte_and_next(ieee) ((ieee)->input_p < (ieee)->end_p ? *((ieee)->input_p++) : 0)
 
 static bfd_boolean
 next_byte (common_header_type * ieee)
@@ -220,6 +220,15 @@ read_id (common_header_type *ieee)
       length = (length * 256) + this_byte_and_next (ieee);
     }
 
+  /* PR 21612: Check for an invalid length.  */
+  if (ieee->input_p + length >= ieee->end_p)
+    {
+      _bfd_error_handler (_("IEEE parser: string length: %#lx longer than buffer: %#lx"),
+                         length, (long) (ieee->end_p - ieee->input_p));
+      bfd_set_error (bfd_error_invalid_operation);
+      return NULL;
+    }
+
   /* Buy memory and read string.  */
   string = bfd_alloc (ieee->abfd, (bfd_size_type) length + 1);
   if (!string)
@@ -699,12 +708,12 @@ ieee_seek (ieee_data_type * ieee, file_ptr offset)
   if (offset < 0 || (bfd_size_type) offset >= ieee->h.total_amt)
     {
       ieee->h.input_p = ieee->h.first_byte + ieee->h.total_amt;
-      ieee->h.last_byte = ieee->h.input_p;
+      ieee->h.end_p = ieee->h.last_byte = ieee->h.input_p;
       return FALSE;
     }
 
   ieee->h.input_p = ieee->h.first_byte + offset;
-  ieee->h.last_byte = (ieee->h.first_byte + ieee_part_after (ieee, offset));
+  ieee->h.end_p = ieee->h.last_byte = (ieee->h.first_byte + ieee_part_after (ieee, offset));
   return TRUE;
 }
 
@@ -1375,6 +1384,8 @@ ieee_archive_p (bfd *abfd)
 
   ieee->h.first_byte = buffer;
   ieee->h.input_p = buffer;
+  ieee->h.total_amt = sizeof (buffer);
+  ieee->h.end_p = buffer + sizeof (buffer);
 
   ieee->h.abfd = abfd;
 
@@ -1442,6 +1453,8 @@ ieee_archive_p (bfd *abfd)
          bfd_bread ((void *) buffer, (bfd_size_type) sizeof (buffer), abfd);
          ieee->h.first_byte = buffer;
          ieee->h.input_p = buffer;
+         ieee->h.total_amt = sizeof (buffer);
+         ieee->h.end_p = buffer + sizeof (buffer);
        }
     }
 
@@ -1465,6 +1478,8 @@ ieee_archive_p (bfd *abfd)
       bfd_bread ((void *) buffer, (bfd_size_type) sizeof (buffer), abfd);
       ieee->h.first_byte = buffer;
       ieee->h.input_p = buffer;
+      ieee->h.total_amt = sizeof (buffer);
+      ieee->h.end_p = buffer + sizeof (buffer);
 
       (void) next_byte (&(ieee->h));   /* Drop F8.  */
       if (! next_byte (&(ieee->h)))    /* Drop 14.  */
@@ -1890,6 +1905,8 @@ ieee_object_p (bfd *abfd)
 
   ieee->h.input_p = buffer;
   ieee->h.total_amt = sizeof (buffer);
+  ieee->h.end_p = buffer + sizeof (buffer);
+
   if (this_byte_and_next (&(ieee->h)) != Module_Beginning)
     goto got_wrong_format;
 
index ace4ed3f8890d3007878921141ce78e97c414226..8a07248304a60855473dd4b386543435210c1ca8 100644 (file)
@@ -64,6 +64,7 @@ typedef struct ieee_per_section
 
 typedef struct {
   unsigned char *input_p;
+  unsigned char *end_p;
   unsigned char *first_byte;
   unsigned char *last_byte;
   bfd_size_type total_amt;