From 5f8ebec53d47aacc4dc1d67f3c9b0117539b2468 Mon Sep 17 00:00:00 2001 From: Nick Clifton Date: Tue, 3 Jul 2012 16:25:17 +0000 Subject: * archive.c (bsd_write_armap): Catch attempts to create an archive with indicies bigger than 4Gb. (coff_write_armap): Likewise. * readelf.c (process_archive): Display member indicies when dumping index. --- bfd/ChangeLog | 6 ++++++ bfd/archive.c | 24 ++++++++++++++++++++++-- 2 files changed, 28 insertions(+), 2 deletions(-) (limited to 'bfd') diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 5ab8525..f6d368e 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,9 @@ +2012-07-03 Nick Clifton + + * archive.c (bsd_write_armap): Catch attempts to create an archive + with indicies bigger than 4Gb. + (coff_write_armap): Likewise. + 2012-07-03 H.J. Lu PR binutils/14319 diff --git a/bfd/archive.c b/bfd/archive.c index 0620452..f56e99e 100644 --- a/bfd/archive.c +++ b/bfd/archive.c @@ -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++; } -- cgit v1.1