This is the mail archive of the binutils@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]

Commit: Add checks for overflowing 4Gb archive symbol table limit


Hi Guys,

  I am applying the patch below to catch a problem with ar creating
  invalid archives (because the file offsets in the symbol table overflow
  the 32-bits that are available to them).  This is not just a
  theoretical problem - it has now started happening with real libraries
  in real production systems.

  As a side effect of the patch I have also extended readelf's dumping
  of archive symbol tables to include the file offset to the member
  containing the symbols.  This is useful to help track down problems
  like the file offsets overflowing 32-bits.

Cheers
  Nick

bfd/ChangeLog
2012-07-03  Nick Clifton  <nickc@redhat.com>

	* archive.c (bsd_write_armap): Catch attempts to create an archive
	with indicies bigger than 4Gb.
	(coff_write_armap): Likewise.

binutils/ChangeLog
2012-07-03  Nick Clifton  <nickc@redhat.com>

	* readelf.c (process_archive): Display member indicies when
	dumping index.

Index: bfd/archive.c
===================================================================
RCS file: /cvs/src/src/bfd/archive.c,v
retrieving revision 1.85
diff -u -3 -p -r1.85 archive.c
--- bfd/archive.c	29 Jun 2012 17:36:21 -0000	1.85
+++ bfd/archive.c	3 Jul 2012 14:28:56 -0000
@@ -2405,6 +2405,9 @@ bsd_write_armap (bfd *arch,
   unsigned int count;
   struct ar_hdr hdr;
   long uid, gid;
+  file_ptr max_first_real = 1;
+
+  max_first_real <<= 31;
 
   firstreal = mapsize + elength + sizeof (struct ar_hdr) + SARMAG;
 
@@ -2463,6 +2466,15 @@ bsd_write_armap (bfd *arch,
 	  while (current != map[count].u.abfd);
 	}
 
+      /* The archive file format only has 4 bytes to store the offset
+	 of the member.  Check to make sure that firstreal has not grown
+	 too big.  */
+      if (firstreal >= max_first_real)
+	{
+	  bfd_set_error (bfd_error_file_truncated);
+	  return FALSE;
+	}
+      
       last_elt = current;
       H_PUT_32 (arch, map[count].namidx, buf);
       H_PUT_32 (arch, firstreal, buf + BSD_SYMDEF_OFFSET_SIZE);
@@ -2574,7 +2586,7 @@ coff_write_armap (bfd *arch,
   unsigned int ranlibsize = (symbol_count * 4) + 4;
   unsigned int stringsize = stridx;
   unsigned int mapsize = stringsize + ranlibsize;
-  unsigned int archive_member_file_ptr;
+  file_ptr archive_member_file_ptr;
   bfd *current = arch->archive_head;
   unsigned int count;
   struct ar_hdr hdr;
@@ -2625,7 +2637,15 @@ coff_write_armap (bfd *arch,
 
       while (count < symbol_count && map[count].u.abfd == current)
 	{
-	  if (!bfd_write_bigendian_4byte_int (arch, archive_member_file_ptr))
+	  unsigned int offset = (unsigned int) archive_member_file_ptr;
+
+	  /* Catch an attempt to grow an archive past its 4Gb limit.  */
+	  if (archive_member_file_ptr != (file_ptr) offset)
+	    {
+	      bfd_set_error (bfd_error_file_truncated);
+	      return FALSE;
+	    }
+	  if (!bfd_write_bigendian_4byte_int (arch, offset))
 	    return FALSE;
 	  count++;
 	}
Index: binutils/readelf.c
===================================================================
RCS file: /cvs/src/src/binutils/readelf.c,v
retrieving revision 1.576
diff -u -3 -p -r1.576 readelf.c
--- binutils/readelf.c	29 Jun 2012 07:02:36 -0000	1.576
+++ binutils/readelf.c	3 Jul 2012 14:28:58 -0000
@@ -13459,7 +13459,8 @@ process_archive (char * file_name, FILE 
 
                       if (qualified_name != NULL)
                         {
-		          printf (_("Binary %s contains:\n"), qualified_name);
+		          printf (_("Binary %s at offset 0x%lx contains:\n"),
+				  qualified_name, arch.index_array[i]);
 		          free (qualified_name);
 		        }
 		    }


  


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