Fix address violations when reading corrupt VMS records.
authorNick Clifton <nickc@redhat.com>
Mon, 19 Jun 2017 13:52:36 +0000 (14:52 +0100)
committerNick Clifton <nickc@redhat.com>
Mon, 19 Jun 2017 13:52:36 +0000 (14:52 +0100)
PR binutils/21618
* vms-alpha.c (evax_bfd_print_emh): Check for insufficient record
length.
(evax_bfd_print_eeom): Likewise.
(evax_bfd_print_egsd): Check for an overlarge record length.
(evax_bfd_print_etir): Likewise.

bfd/ChangeLog
bfd/vms-alpha.c

index e718517..5177bc7 100644 (file)
@@ -1,5 +1,14 @@
 2017-06-19  Nick Clifton  <nickc@redhat.com>
 
+       PR binutils/21618
+       * vms-alpha.c (evax_bfd_print_emh): Check for insufficient record
+       length.
+       (evax_bfd_print_eeom): Likewise.
+       (evax_bfd_print_egsd): Check for an overlarge record length.
+       (evax_bfd_print_etir): Likewise.
+
+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
index 73f6976..8569868 100644 (file)
@@ -5634,6 +5634,13 @@ evax_bfd_print_emh (FILE *file, unsigned char *rec, unsigned int rec_len)
   /* xgettext:c-format */
   fprintf (file, _("  EMH %u (len=%u): "), subtype, rec_len);
 
+  /* PR 21618: Check for invalid lengths.  */
+  if (rec_len < sizeof (* emh))
+    {
+      fprintf (file, _("   Error: The length is less than the length of an EMH record\n"));
+      return;
+    }
+  
   switch (subtype)
     {
     case EMH__C_MHD:
@@ -5697,6 +5704,14 @@ evax_bfd_print_eeom (FILE *file, unsigned char *rec, unsigned int rec_len)
   struct vms_eeom *eeom = (struct vms_eeom *)rec;
 
   fprintf (file, _("  EEOM (len=%u):\n"), rec_len);
+
+  /* PR 21618: Check for invalid lengths.  */
+  if (rec_len < sizeof (* eeom))
+    {
+      fprintf (file, _("   Error: The length is less than the length of an EEOM record\n"));
+      return;
+    }
+  
   fprintf (file, _("   number of cond linkage pairs: %u\n"),
            (unsigned)bfd_getl32 (eeom->total_lps));
   fprintf (file, _("   completion code: %u\n"),
@@ -5786,6 +5801,12 @@ evax_bfd_print_egsd (FILE *file, unsigned char *rec, unsigned int rec_len)
                n, type, len);
       n++;
 
+      if (off + len > rec_len || off + len < off)
+       {
+         fprintf (file, _("   Error: length larger than remaining space in record\n"));
+         return;
+       }
+
       switch (type)
         {
         case EGSD__C_PSC:
@@ -6031,6 +6052,12 @@ evax_bfd_print_etir (FILE *file, const char *name,
       size = bfd_getl16 (etir->size);
       buf = rec + off + sizeof (struct vms_etir);
 
+      if (off + size > rec_len || off + size < off)
+       {
+         fprintf (file, _("   Error: length larger than remaining space in record\n"));
+         return;
+       }
+
       /* xgettext:c-format */
       fprintf (file, _("   (type: %3u, size: 4+%3u): "), type, size - 4);
       switch (type)