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.

Upstream-Status: Backport

CVE: CVE-2017-12449_12455_12457
Signed-off-by: Thiruvadi Rajaraman <trajaraman@mvista.com>

Index: git/bfd/mach-o.c
===================================================================
--- git.orig/bfd/mach-o.c	2017-08-30 17:21:59.684671218 +0530
+++ git/bfd/mach-o.c	2017-08-30 17:22:19.136813620 +0530
@@ -3739,6 +3739,9 @@
     }
   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;
Index: git/bfd/nlmcode.h
===================================================================
--- git.orig/bfd/nlmcode.h	2017-08-30 17:21:59.688671247 +0530
+++ git/bfd/nlmcode.h	2017-08-30 17:22:19.140813649 +0530
@@ -351,7 +351,9 @@
 	      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)
Index: git/bfd/section.c
===================================================================
--- git.orig/bfd/section.c	2017-08-30 17:21:59.708671392 +0530
+++ git/bfd/section.c	2017-08-30 17:22:19.140813649 +0530
@@ -1240,7 +1240,7 @@
   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;
Index: git/bfd/vms-alpha.c
===================================================================
--- git.orig/bfd/vms-alpha.c	2017-08-30 17:22:19.080813209 +0530
+++ git/bfd/vms-alpha.c	2017-08-30 17:22:19.140813649 +0530
@@ -5562,8 +5562,9 @@
 {
   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);
 
   fprintf (file, _("  EMH %u (len=%u): "), subtype, rec_len);
 
@@ -5573,58 +5574,82 @@
       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;
Index: git/bfd/vms-misc.c
===================================================================
--- git.orig/bfd/vms-misc.c	2017-08-30 17:21:59.716671451 +0530
+++ git/bfd/vms-misc.c	2017-08-30 17:22:19.140813649 +0530
@@ -135,8 +135,8 @@
 #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, int size)
@@ -151,8 +151,8 @@
   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)
Index: git/bfd/ChangeLog
===================================================================
--- git.orig/bfd/ChangeLog	2017-08-30 17:22:19.080813209 +0530
+++ git/bfd/ChangeLog	2017-08-30 17:23:51.069502425 +0530
@@ -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-19  Nick Clifton  <nickc@redhat.com>
 
        PR 21787
