This is the mail archive of the binutils-cvs@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[binutils-gdb] Fix address violation issues encountered when parsing corrupt binaries.


https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=8bdf0be19d2777565a8b1c88347f65d6a4b8c5fc

commit 8bdf0be19d2777565a8b1c88347f65d6a4b8c5fc
Author: Nick Clifton <nickc@redhat.com>
Date:   Thu Jul 27 12:04:50 2017 +0100

    Fix address violation issues encountered when parsing corrupt binaries.
    
    	PR 21840
    	* mach-o.c (bfd_mach_o_read_symtab_strtab): Fail if the symtab
    	size is -1.
    	* nlmcode.h (nlm_swap_auxiliary_headers_in): Replace assertion
    	with error return.
    	* section.c (bfd_make_section_with_flags): Fail if the name or bfd
    	are NULL.
    	* vms-alpha.c (bfd_make_section_with_flags): Correct computation
    	of end pointer.
    	(evax_bfd_print_emh): Check for invalid string lengths.

Diff:
---
 bfd/ChangeLog   | 13 +++++++++
 bfd/mach-o.c    |  3 ++
 bfd/nlmcode.h   |  4 ++-
 bfd/section.c   |  2 +-
 bfd/vms-alpha.c | 91 ++++++++++++++++++++++++++++++++++++---------------------
 bfd/vms-misc.c  |  8 ++---
 6 files changed, 82 insertions(+), 39 deletions(-)

diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index bd50ac5..0a4c852 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,3 +1,16 @@
+2017-07-27  Nick Clifton  <nickc@redhat.com>
+
+	PR 21840
+	* mach-o.c (bfd_mach_o_read_symtab_strtab): Fail if the symtab
+	size is -1.
+	* nlmcode.h (nlm_swap_auxiliary_headers_in): Replace assertion
+	with error return.
+	* section.c (bfd_make_section_with_flags): Fail if the name or bfd
+	are NULL.
+	* vms-alpha.c (bfd_make_section_with_flags): Correct computation
+	of end pointer.
+	(evax_bfd_print_emh): Check for invalid string lengths.
+
 2017-07-25  Nick Clifton  <nickc@redhat.com>
 
 	* po/fr.po: Updated French translation.
diff --git a/bfd/mach-o.c b/bfd/mach-o.c
index 1807391..9fe6326 100644
--- a/bfd/mach-o.c
+++ b/bfd/mach-o.c
@@ -3749,6 +3749,9 @@ bfd_mach_o_read_symtab_strtab (bfd *abfd)
     }
   else
     {
+      /* See PR 21840 for a reproducer.  */
+      if ((sym->strsize + 1) == 0)
+	return FALSE;
       sym->strtab = bfd_alloc (abfd, sym->strsize + 1);
       if (sym->strtab == NULL)
         return FALSE;
diff --git a/bfd/nlmcode.h b/bfd/nlmcode.h
index 6d6aed0..350c83e 100644
--- a/bfd/nlmcode.h
+++ b/bfd/nlmcode.h
@@ -351,7 +351,9 @@ nlm_swap_auxiliary_headers_in (bfd *abfd)
 	      bfd_byte *contents;
 	      bfd_byte *p, *pend;
 
-	      BFD_ASSERT (hdrLength == 0 && hdr == NULL);
+	      /* See PR 21840 for a reproducer.  */
+	      if (hdrLength != 0 || hdr != NULL)
+		return FALSE;
 
 	      pos = bfd_tell (abfd);
 	      if (bfd_seek (abfd, dataOffset, SEEK_SET) != 0)
diff --git a/bfd/section.c b/bfd/section.c
index 28eee7f..811d42a 100644
--- a/bfd/section.c
+++ b/bfd/section.c
@@ -1240,7 +1240,7 @@ bfd_make_section_with_flags (bfd *abfd, const char *name,
   struct section_hash_entry *sh;
   asection *newsect;
 
-  if (abfd->output_has_begun)
+  if (abfd == NULL || name == NULL || abfd->output_has_begun)
     {
       bfd_set_error (bfd_error_invalid_operation);
       return NULL;
diff --git a/bfd/vms-alpha.c b/bfd/vms-alpha.c
index 610b034..5595b61 100644
--- a/bfd/vms-alpha.c
+++ b/bfd/vms-alpha.c
@@ -903,7 +903,7 @@ _bfd_vms_slurp_ehdr (bfd *abfd)
 
   vms_rec = PRIV (recrd.rec);
   /* PR 17512: file: 62736583.  */
-  end = vms_rec + PRIV (recrd.buf_size);
+  end = PRIV (recrd.buf) + PRIV (recrd.buf_size);
 
   vms_debug2 ((2, "HDR/EMH\n"));
 
@@ -5737,8 +5737,9 @@ evax_bfd_print_emh (FILE *file, unsigned char *rec, unsigned int rec_len)
 {
   struct vms_emh_common *emh = (struct vms_emh_common *)rec;
   unsigned int subtype;
+  int extra;
 
-  subtype = (unsigned)bfd_getl16 (emh->subtyp);
+  subtype = (unsigned) bfd_getl16 (emh->subtyp);
 
   /* xgettext:c-format */
   fprintf (file, _("  EMH %u (len=%u): "), subtype, rec_len);
@@ -5749,58 +5750,82 @@ evax_bfd_print_emh (FILE *file, unsigned char *rec, unsigned int rec_len)
       fprintf (file, _("   Error: The length is less than the length of an EMH record\n"));
       return;
     }
-  
+  extra = rec_len - sizeof (struct vms_emh_common);
+
   switch (subtype)
     {
     case EMH__C_MHD:
       {
-        struct vms_emh_mhd *mhd = (struct vms_emh_mhd *)rec;
-        const char *name;
+        struct vms_emh_mhd *mhd = (struct vms_emh_mhd *) rec;
+        const char * name;
+	const char * nextname;
+	const char * maxname;
 
+	/* PR 21840: Check for invalid lengths.  */
+	if (rec_len < sizeof (* mhd))
+	  {
+	    fprintf (file, _("   Error: The record length is less than the size of an EMH_MHD record\n"));
+	    return;
+	  }
         fprintf (file, _("Module header\n"));
         fprintf (file, _("   structure level: %u\n"), mhd->strlvl);
         fprintf (file, _("   max record size: %u\n"),
-                 (unsigned)bfd_getl32 (mhd->recsiz));
+                 (unsigned) bfd_getl32 (mhd->recsiz));
         name = (char *)(mhd + 1);
+	maxname = (char *) rec + rec_len;
+	if (name > maxname - 2)
+	  {
+	    fprintf (file, _("   Error: The module name is missing\n"));
+	    return;
+	  }
+	nextname = name + name[0] + 1;
+	if (nextname >= maxname)
+	  {
+	    fprintf (file, _("   Error: The module name is too long\n"));
+	    return;
+	  }
         fprintf (file, _("   module name    : %.*s\n"), name[0], name + 1);
-        name += name[0] + 1;
+        name = nextname;
+	if (name > maxname - 2)
+	  {
+	    fprintf (file, _("   Error: The module version is missing\n"));
+	    return;
+	  }
+	nextname = name + name[0] + 1;
+	if (nextname >= maxname)
+	  {
+	    fprintf (file, _("   Error: The module version is too long\n"));
+	    return;
+	  }
         fprintf (file, _("   module version : %.*s\n"), name[0], name + 1);
-        name += name[0] + 1;
-        fprintf (file, _("   compile date   : %.17s\n"), name);
+        name = nextname;
+	if ((maxname - name) < 17 && maxname[-1] != 0)
+	  fprintf (file, _("   Error: The compile date is truncated\n"));
+	else
+	  fprintf (file, _("   compile date   : %.17s\n"), name);
       }
       break;
+
     case EMH__C_LNM:
-      {
-        fprintf (file, _("Language Processor Name\n"));
-        fprintf (file, _("   language name: %.*s\n"),
-                 (int)(rec_len - sizeof (struct vms_emh_common)),
-                 (char *)rec + sizeof (struct vms_emh_common));
-      }
+      fprintf (file, _("Language Processor Name\n"));
+      fprintf (file, _("   language name: %.*s\n"), extra, (char *)(emh + 1));
       break;
+
     case EMH__C_SRC:
-      {
-        fprintf (file, _("Source Files Header\n"));
-        fprintf (file, _("   file: %.*s\n"),
-                 (int)(rec_len - sizeof (struct vms_emh_common)),
-                 (char *)rec + sizeof (struct vms_emh_common));
-      }
+      fprintf (file, _("Source Files Header\n"));
+      fprintf (file, _("   file: %.*s\n"), extra, (char *)(emh + 1));
       break;
+
     case EMH__C_TTL:
-      {
-        fprintf (file, _("Title Text Header\n"));
-        fprintf (file, _("   title: %.*s\n"),
-                 (int)(rec_len - sizeof (struct vms_emh_common)),
-                 (char *)rec + sizeof (struct vms_emh_common));
-      }
+      fprintf (file, _("Title Text Header\n"));
+      fprintf (file, _("   title: %.*s\n"), extra, (char *)(emh + 1));
       break;
+
     case EMH__C_CPR:
-      {
-        fprintf (file, _("Copyright Header\n"));
-        fprintf (file, _("   copyright: %.*s\n"),
-                 (int)(rec_len - sizeof (struct vms_emh_common)),
-                 (char *)rec + sizeof (struct vms_emh_common));
-      }
+      fprintf (file, _("Copyright Header\n"));
+      fprintf (file, _("   copyright: %.*s\n"), extra, (char *)(emh + 1));
       break;
+
     default:
       fprintf (file, _("unhandled emh subtype %u\n"), subtype);
       break;
diff --git a/bfd/vms-misc.c b/bfd/vms-misc.c
index 7497f02..91e2ec7 100644
--- a/bfd/vms-misc.c
+++ b/bfd/vms-misc.c
@@ -135,8 +135,8 @@ _bfd_hexdump (int level, unsigned char *ptr, int size, int offset)
 #endif
 
 
-/* Copy sized string (string with fixed size) to new allocated area
-   size is string size (size of record)  */
+/* Copy sized string (string with fixed size) to new allocated area.
+   Size is string size (size of record).  */
 
 char *
 _bfd_vms_save_sized_string (unsigned char *str, unsigned int size)
@@ -151,8 +151,8 @@ _bfd_vms_save_sized_string (unsigned char *str, unsigned int size)
   return newstr;
 }
 
-/* Copy counted string (string with size at first byte) to new allocated area
-   ptr points to size byte on entry  */
+/* Copy counted string (string with size at first byte) to new allocated area.
+   PTR points to size byte on entry.  */
 
 char *
 _bfd_vms_save_counted_string (unsigned char *ptr, unsigned int maxlen)


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]