Nick Clifton 1212c9
--- binutils.orig/binutils/readelf.c	2018-05-31 10:14:28.019641872 +0100
Nick Clifton 1212c9
+++ binutils-2.29/binutils/readelf.c	2018-05-31 10:57:28.912460915 +0100
Nick Clifton 1212c9
@@ -10154,9 +10154,8 @@ process_version_sections (FILE * file)
Nick Clifton 1212c9
 	case SHT_GNU_verdef:
Nick Clifton 1212c9
 	  {
Nick Clifton 1212c9
 	    Elf_External_Verdef * edefs;
Nick Clifton 1212c9
-	    unsigned int idx;
Nick Clifton 1212c9
-	    unsigned int cnt;
Nick Clifton 1212c9
-	    unsigned int end;
Nick Clifton 1212c9
+	    unsigned long idx;
Nick Clifton 1212c9
+	    unsigned long cnt;
Nick Clifton 1212c9
 	    char * endbuf;
Nick Clifton 1212c9
 
Nick Clifton 1212c9
 	    found = TRUE;
Nick Clifton 1212c9
@@ -10178,23 +10177,16 @@ process_version_sections (FILE * file)
Nick Clifton 1212c9
 	      break;
Nick Clifton 1212c9
 	    endbuf = (char *) edefs + section->sh_size;
Nick Clifton 1212c9
 
Nick Clifton 1212c9
-	    /* PR 17531: file: id:000001,src:000172+005151,op:splice,rep:2.  */
Nick Clifton 1212c9
-	    end = (section->sh_info < section->sh_size
Nick Clifton 1212c9
-		   ? section->sh_info : section->sh_size);
Nick Clifton 1212c9
-	    for (idx = cnt = 0; cnt < end; ++cnt)
Nick Clifton 1212c9
+	    for (idx = cnt = 0; cnt < section->sh_info; ++cnt)
Nick Clifton 1212c9
 	      {
Nick Clifton 1212c9
 		char * vstart;
Nick Clifton 1212c9
 		Elf_External_Verdef * edef;
Nick Clifton 1212c9
 		Elf_Internal_Verdef ent;
Nick Clifton 1212c9
 		Elf_External_Verdaux * eaux;
Nick Clifton 1212c9
 		Elf_Internal_Verdaux aux;
Nick Clifton 1212c9
-		unsigned int isum;
Nick Clifton 1212c9
+		unsigned long isum;
Nick Clifton 1212c9
 		int j;
Nick Clifton 1212c9
 
Nick Clifton 1212c9
-		/* Check for very large indices.  */
Nick Clifton 1212c9
-		if (idx > (size_t) (endbuf - (char *) edefs))
Nick Clifton 1212c9
-		  break;
Nick Clifton 1212c9
-
Nick Clifton 1212c9
 		vstart = ((char *) edefs) + idx;
Nick Clifton 1212c9
 		if (vstart + sizeof (*edef) > endbuf)
Nick Clifton 1212c9
 		  break;
Nick Clifton 1212c9
@@ -10209,19 +10201,20 @@ process_version_sections (FILE * file)
Nick Clifton 1212c9
 		ent.vd_aux     = BYTE_GET (edef->vd_aux);
Nick Clifton 1212c9
 		ent.vd_next    = BYTE_GET (edef->vd_next);
Nick Clifton 1212c9
 
Nick Clifton 1212c9
-		printf (_("  %#06x: Rev: %d  Flags: %s"),
Nick Clifton 1212c9
+		printf (_("  %#06lx: Rev: %d  Flags: %s"),
Nick Clifton 1212c9
 			idx, ent.vd_version, get_ver_flags (ent.vd_flags));
Nick Clifton 1212c9
 
Nick Clifton 1212c9
 		printf (_("  Index: %d  Cnt: %d  "),
Nick Clifton 1212c9
 			ent.vd_ndx, ent.vd_cnt);
Nick Clifton 1212c9
 
Nick Clifton 1212c9
-		/* Check for overflow and underflow.  */
Nick Clifton 1212c9
-		if (ent.vd_aux + sizeof (* eaux) > (size_t) (endbuf - vstart)
Nick Clifton 1212c9
-		    || (vstart + ent.vd_aux < vstart))
Nick Clifton 1212c9
+		/* Check for overflow.  */
Nick Clifton 1212c9
+		if (ent.vd_aux > (size_t) (endbuf - vstart))
Nick Clifton 1212c9
 		  break;
Nick Clifton 1212c9
 
Nick Clifton 1212c9
 		vstart += ent.vd_aux;
Nick Clifton 1212c9
 
Nick Clifton 1212c9
+		if (vstart + sizeof (*eaux) > endbuf)
Nick Clifton 1212c9
+		  break;
Nick Clifton 1212c9
 		eaux = (Elf_External_Verdaux *) vstart;
Nick Clifton 1212c9
 
Nick Clifton 1212c9
 		aux.vda_name = BYTE_GET (eaux->vda_name);
Nick Clifton 1212c9
@@ -10236,6 +10229,14 @@ process_version_sections (FILE * file)
Nick Clifton 1212c9
 
Nick Clifton 1212c9
 		for (j = 1; j < ent.vd_cnt; j++)
Nick Clifton 1212c9
 		  {
Nick Clifton 1212c9
+		    if (aux.vda_next < sizeof (*eaux)
Nick Clifton 1212c9
+			&& !(j == ent.vd_cnt - 1 && aux.vda_next == 0))
Nick Clifton 1212c9
+		      {
Nick Clifton 1212c9
+			warn (_("Invalid vda_next field of %lx\n"),
Nick Clifton 1212c9
+			      aux.vda_next);
Nick Clifton 1212c9
+			j = ent.vd_cnt;
Nick Clifton 1212c9
+			break;
Nick Clifton 1212c9
+		      }
Nick Clifton 1212c9
 		    /* Check for overflow.  */
Nick Clifton 1212c9
 		    if (aux.vda_next > (size_t) (endbuf - vstart))
Nick Clifton 1212c9
 		      break;
Nick Clifton 1212c9
@@ -10243,18 +10244,18 @@ process_version_sections (FILE * file)
Nick Clifton 1212c9
 		    isum   += aux.vda_next;
Nick Clifton 1212c9
 		    vstart += aux.vda_next;
Nick Clifton 1212c9
 
Nick Clifton 1212c9
-		    eaux = (Elf_External_Verdaux *) vstart;
Nick Clifton 1212c9
 		    if (vstart + sizeof (*eaux) > endbuf)
Nick Clifton 1212c9
 		      break;
Nick Clifton 1212c9
+		    eaux = (Elf_External_Verdaux *) vstart;
Nick Clifton 1212c9
 
Nick Clifton 1212c9
 		    aux.vda_name = BYTE_GET (eaux->vda_name);
Nick Clifton 1212c9
 		    aux.vda_next = BYTE_GET (eaux->vda_next);
Nick Clifton 1212c9
 
Nick Clifton 1212c9
 		    if (VALID_DYNAMIC_NAME (aux.vda_name))
Nick Clifton 1212c9
-		      printf (_("  %#06x: Parent %d: %s\n"),
Nick Clifton 1212c9
+		      printf (_("  %#06lx: Parent %d: %s\n"),
Nick Clifton 1212c9
 			      isum, j, GET_DYNAMIC_NAME (aux.vda_name));
Nick Clifton 1212c9
 		    else
Nick Clifton 1212c9
-		      printf (_("  %#06x: Parent %d, name index: %ld\n"),
Nick Clifton 1212c9
+		      printf (_("  %#06lx: Parent %d, name index: %ld\n"),
Nick Clifton 1212c9
 			      isum, j, aux.vda_name);
Nick Clifton 1212c9
 		  }
Nick Clifton 1212c9
 
Nick Clifton 1212c9
@@ -10263,7 +10264,14 @@ process_version_sections (FILE * file)
Nick Clifton 1212c9
 
Nick Clifton 1212c9
 		/* PR 17531:
Nick Clifton 1212c9
 		   file: id:000001,src:000172+005151,op:splice,rep:2.  */
Nick Clifton 1212c9
-		if (idx + ent.vd_next < idx)
Nick Clifton 1212c9
+		if (ent.vd_next < sizeof (*edef)
Nick Clifton 1212c9
+		    && !(cnt == section->sh_info - 1 && ent.vd_next == 0))
Nick Clifton 1212c9
+		  {
Nick Clifton 1212c9
+		    warn (_("Invalid vd_next field of %lx\n"), ent.vd_next);
Nick Clifton 1212c9
+		    cnt = section->sh_info;
Nick Clifton 1212c9
+		    break;
Nick Clifton 1212c9
+		  }
Nick Clifton 1212c9
+		if (ent.vd_next > (size_t) (endbuf - ((char *) edefs + idx)))
Nick Clifton 1212c9
 		  break;
Nick Clifton 1212c9
 
Nick Clifton 1212c9
 		idx += ent.vd_next;
Nick Clifton 1212c9
@@ -10279,8 +10287,8 @@ process_version_sections (FILE * file)
Nick Clifton 1212c9
 	case SHT_GNU_verneed:
Nick Clifton 1212c9
 	  {
Nick Clifton 1212c9
 	    Elf_External_Verneed * eneed;
Nick Clifton 1212c9
-	    unsigned int idx;
Nick Clifton 1212c9
-	    unsigned int cnt;
Nick Clifton 1212c9
+	    unsigned long idx;
Nick Clifton 1212c9
+	    unsigned long cnt;
Nick Clifton 1212c9
 	    char * endbuf;
Nick Clifton 1212c9
 
Nick Clifton 1212c9
 	    found = TRUE;
Nick Clifton 1212c9
@@ -10306,13 +10314,10 @@ process_version_sections (FILE * file)
Nick Clifton 1212c9
 	      {
Nick Clifton 1212c9
 		Elf_External_Verneed * entry;
Nick Clifton 1212c9
 		Elf_Internal_Verneed ent;
Nick Clifton 1212c9
-		unsigned int isum;
Nick Clifton 1212c9
+		unsigned long isum;
Nick Clifton 1212c9
 		int j;
Nick Clifton 1212c9
 		char * vstart;
Nick Clifton 1212c9
 
Nick Clifton 1212c9
-		if (idx > (size_t) (endbuf - (char *) eneed))
Nick Clifton 1212c9
-		  break;
Nick Clifton 1212c9
-
Nick Clifton 1212c9
 		vstart = ((char *) eneed) + idx;
Nick Clifton 1212c9
 		if (vstart + sizeof (*entry) > endbuf)
Nick Clifton 1212c9
 		  break;
Nick Clifton 1212c9
@@ -10325,7 +10330,7 @@ process_version_sections (FILE * file)
Nick Clifton 1212c9
 		ent.vn_aux     = BYTE_GET (entry->vn_aux);
Nick Clifton 1212c9
 		ent.vn_next    = BYTE_GET (entry->vn_next);
Nick Clifton 1212c9
 
Nick Clifton 1212c9
-		printf (_("  %#06x: Version: %d"), idx, ent.vn_version);
Nick Clifton 1212c9
+		printf (_("  %#06lx: Version: %d"), idx, ent.vn_version);
Nick Clifton 1212c9
 
Nick Clifton 1212c9
 		if (VALID_DYNAMIC_NAME (ent.vn_file))
Nick Clifton 1212c9
 		  printf (_("  File: %s"), GET_DYNAMIC_NAME (ent.vn_file));
Nick Clifton 1212c9
@@ -10355,24 +10360,26 @@ process_version_sections (FILE * file)
Nick Clifton 1212c9
 		    aux.vna_next  = BYTE_GET (eaux->vna_next);
Nick Clifton 1212c9
 
Nick Clifton 1212c9
 		    if (VALID_DYNAMIC_NAME (aux.vna_name))
Nick Clifton 1212c9
-		      printf (_("  %#06x:   Name: %s"),
Nick Clifton 1212c9
+		      printf (_("  %#06lx:   Name: %s"),
Nick Clifton 1212c9
 			      isum, GET_DYNAMIC_NAME (aux.vna_name));
Nick Clifton 1212c9
 		    else
Nick Clifton 1212c9
-		      printf (_("  %#06x:   Name index: %lx"),
Nick Clifton 1212c9
+		      printf (_("  %#06lx:   Name index: %lx"),
Nick Clifton 1212c9
 			      isum, aux.vna_name);
Nick Clifton 1212c9
 
Nick Clifton 1212c9
 		    printf (_("  Flags: %s  Version: %d\n"),
Nick Clifton 1212c9
 			    get_ver_flags (aux.vna_flags), aux.vna_other);
Nick Clifton 1212c9
 
Nick Clifton 1212c9
-		    /* Check for overflow.  */
Nick Clifton 1212c9
-		    if (aux.vna_next > (size_t) (endbuf - vstart)
Nick Clifton 1212c9
-			|| (aux.vna_next == 0 && j < ent.vn_cnt - 1))
Nick Clifton 1212c9
+		    if (aux.vna_next < sizeof (*eaux)
Nick Clifton 1212c9
+			&& !(j == ent.vn_cnt - 1 && aux.vna_next == 0))
Nick Clifton 1212c9
 		      {
Nick Clifton 1212c9
 			warn (_("Invalid vna_next field of %lx\n"),
Nick Clifton 1212c9
 			      aux.vna_next);
Nick Clifton 1212c9
 			j = ent.vn_cnt;
Nick Clifton 1212c9
 			break;
Nick Clifton 1212c9
 		      }
Nick Clifton 1212c9
+		    /* Check for overflow.  */
Nick Clifton 1212c9
+		    if (aux.vna_next > (size_t) (endbuf - vstart))
Nick Clifton 1212c9
+		      break;
Nick Clifton 1212c9
 		    isum   += aux.vna_next;
Nick Clifton 1212c9
 		    vstart += aux.vna_next;
Nick Clifton 1212c9
 		  }
Nick Clifton 1212c9
@@ -10380,12 +10387,15 @@ process_version_sections (FILE * file)
Nick Clifton 1212c9
 		if (j < ent.vn_cnt)
Nick Clifton 1212c9
 		  warn (_("Missing Version Needs auxillary information\n"));
Nick Clifton 1212c9
 
Nick Clifton 1212c9
-		if (ent.vn_next == 0 && cnt < section->sh_info - 1)
Nick Clifton 1212c9
+		if (ent.vn_next < sizeof (*entry)
Nick Clifton 1212c9
+		    && !(cnt == section->sh_info - 1 && ent.vn_next == 0))
Nick Clifton 1212c9
 		  {
Nick Clifton 1212c9
-		    warn (_("Corrupt Version Needs structure - offset to next structure is zero with entries still left to be processed\n"));
Nick Clifton 1212c9
+		    warn (_("Invalid vn_next field of %lx\n"), ent.vn_next);
Nick Clifton 1212c9
 		    cnt = section->sh_info;
Nick Clifton 1212c9
 		    break;
Nick Clifton 1212c9
 		  }
Nick Clifton 1212c9
+		if (ent.vn_next > (size_t) (endbuf - ((char *) eneed + idx)))
Nick Clifton 1212c9
+		  break;
Nick Clifton 1212c9
 		idx += ent.vn_next;
Nick Clifton 1212c9
 	      }
Nick Clifton 1212c9
 
Nick Clifton 1212c9
@@ -12859,7 +12869,9 @@ dump_section_as_strings (Elf_Internal_Sh
Nick Clifton 1212c9
   real_start = start = (unsigned char *) get_section_contents (section,
Nick Clifton 1212c9
 							       file);
Nick Clifton 1212c9
   if (start == NULL)
Nick Clifton 1212c9
-    return FALSE;
Nick Clifton 1212c9
+    /* PR 21820: Do not fail if the section was empty.  */
Nick Clifton 1212c9
+    return (section->sh_size == 0 || section->sh_type == SHT_NOBITS) ? TRUE : FALSE;
Nick Clifton 1212c9
+
Nick Clifton 1212c9
   num_bytes = section->sh_size;
Nick Clifton 1212c9
 
Nick Clifton 1212c9
   printf (_("\nString dump of section '%s':\n"), printable_section_name (section));
Nick Clifton 1212c9
@@ -13005,7 +13017,8 @@ dump_section_as_bytes (Elf_Internal_Shdr
Nick Clifton 1212c9
 
Nick Clifton 1212c9
   real_start = start = (unsigned char *) get_section_contents (section, file);
Nick Clifton 1212c9
   if (start == NULL)
Nick Clifton 1212c9
-    return FALSE;
Nick Clifton 1212c9
+    /* PR 21820: Do not fail if the section was empty.  */
Nick Clifton 1212c9
+    return (section->sh_size == 0 || section->sh_type == SHT_NOBITS) ? TRUE : FALSE;
Nick Clifton 1212c9
 
Nick Clifton 1212c9
   section_size = section->sh_size;
Nick Clifton 1212c9