This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
Commit: Add checks for overflowing 4Gb archive symbol table limit
- From: Nick Clifton <nickc at redhat dot com>
- To: binutils at sourceware dot org
- Date: Tue, 03 Jul 2012 16:19:14 +0100
- Subject: 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);
}
}