From f38a1951764a834024cbcee9a65f3d6759e63f65 Mon Sep 17 00:00:00 2001 From: Nick Clifton Date: Fri, 20 Jan 2012 14:42:56 +0000 Subject: [PATCH] PR binutils/13534 * archive.c (_bfd_ar_sizepad): New function. Correctly install and pad the size field in an archive header. (_bfd_generic_read_ar_hdr_mag): Use the correct type and scan function for the archive size field. (bfd_generic_openr_next_archived_file): Likewise. (do_slurp_coff_armap): Likewise. (_bfd_write_archive_contents): Likewise. (_bfd_bsd44_write_ar_hdr): Use the new function. (bfd_ar_hdr_from_filesystem): Likewise. (_bfd_write_archive_contents): Likewise. (bsd_write_armap): Likewise. (coff_write_armap): Likewise. * archive64.c (bfd_elf64_archive_write_armap): Likewise. * bfdio.c (bfd_bread): Use correct type for archive element sizes. * ar.c (open_inarch): Likewise. (extract_file): Likewise. * libbfd-in.h (struct areltdata): Use correct types for parsed_size and extra_size fields. Prototype _bfd_ar_sizepad function. * libbfd.h: Regenerate. --- bfd/ChangeLog | 25 +++++++++++++++++++++++ bfd/archive.c | 63 +++++++++++++++++++++++++++++++++++++++++---------------- bfd/archive64.c | 6 +++--- bfd/bfdio.c | 3 ++- bfd/libbfd-in.h | 32 ++++++++++++++++------------- bfd/libbfd.h | 32 ++++++++++++++++------------- 6 files changed, 112 insertions(+), 49 deletions(-) diff --git a/bfd/ChangeLog b/bfd/ChangeLog index ab9cde148..994a1ce2d 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,28 @@ +2012-01-20 Francois Gouget + + PR binutils/13534 + * archive.c (_bfd_ar_sizepad): New function. Correctly install and + pad the size field in an archive header. + (_bfd_generic_read_ar_hdr_mag): Use the correct type and scan + function for the archive size field. + (bfd_generic_openr_next_archived_file): Likewise. + (do_slurp_coff_armap): Likewise. + (_bfd_write_archive_contents): Likewise. + (_bfd_bsd44_write_ar_hdr): Use the new function. + (bfd_ar_hdr_from_filesystem): Likewise. + (_bfd_write_archive_contents): Likewise. + (bsd_write_armap): Likewise. + (coff_write_armap): Likewise. + * archive64.c (bfd_elf64_archive_write_armap): Likewise. + * bfdio.c (bfd_bread): Use correct type for archive element + sizes. + * ar.c (open_inarch): Likewise. + (extract_file): Likewise. + * libbfd-in.h (struct areltdata): Use correct types for + parsed_size and extra_size fields. + Prototype _bfd_ar_sizepad function. + * libbfd.h: Regenerate. + 2012-01-20 Ulrich Weigand * elf.c (elfcore_write_prpsinfo): Provide unconditionally. diff --git a/bfd/archive.c b/bfd/archive.c index ac2be3e00..86c62a5f7 100644 --- a/bfd/archive.c +++ b/bfd/archive.c @@ -1,7 +1,7 @@ /* BFD back-end for archive files (libraries). Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, - 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, + 2012 Free Software Foundation, Inc. Written by Cygnus Support. Mostly Gumby Henkel-Wallace's fault. This file is part of BFD, the Binary File Descriptor library. @@ -178,6 +178,29 @@ _bfd_ar_spacepad (char *p, size_t n, const char *fmt, long val) else memcpy (p, buf, n); } + +bfd_boolean +_bfd_ar_sizepad (char *p, size_t n, bfd_size_type size) +{ + static char buf[21]; + size_t len; + + snprintf (buf, sizeof (buf), "%-10" BFD_VMA_FMT "u", size); + len = strlen (buf); + if (len > n) + { + bfd_set_error (bfd_error_file_too_big); + return FALSE; + } + if (len < n) + { + memcpy (p, buf, len); + memset (p + len, ' ', n - len); + } + else + memcpy (p, buf, n); + return TRUE; +} bfd_boolean _bfd_generic_mkarchive (bfd *abfd) @@ -424,7 +447,7 @@ _bfd_generic_read_ar_hdr_mag (bfd *abfd, const char *mag) { struct ar_hdr hdr; char *hdrp = (char *) &hdr; - size_t parsed_size; + bfd_size_type parsed_size; struct areltdata *ared; char *filename = NULL; bfd_size_type namelen = 0; @@ -448,8 +471,7 @@ _bfd_generic_read_ar_hdr_mag (bfd *abfd, const char *mag) } errno = 0; - parsed_size = strtol (hdr.ar_size, NULL, 10); - if (errno != 0) + if (sscanf (hdr.ar_size, "%" BFD_VMA_FMT "u", &parsed_size) != 1) { bfd_set_error (bfd_error_malformed_archive); return NULL; @@ -721,7 +743,7 @@ bfd_generic_openr_next_archived_file (bfd *archive, bfd *last_file) filestart = bfd_ardata (archive)->first_file_filepos; else { - unsigned int size = arelt_size (last_file); + bfd_size_type size = arelt_size (last_file); filestart = last_file->proxy_origin; if (! bfd_is_thin_archive (archive)) @@ -917,7 +939,7 @@ do_slurp_coff_armap (bfd *abfd) struct artdata *ardata = bfd_ardata (abfd); char *stringbase; bfd_size_type stringsize; - unsigned int parsed_size; + bfd_size_type parsed_size; carsym *carsyms; bfd_size_type nsymz; /* Number of symbols in armap. */ bfd_vma (*swap) (const void *); @@ -1762,14 +1784,16 @@ _bfd_bsd44_write_ar_hdr (bfd *archive, bfd *abfd) BFD_ASSERT (padded_len == arch_eltdata (abfd)->extra_size); - _bfd_ar_spacepad (hdr->ar_size, sizeof (hdr->ar_size), "%-10ld", - arch_eltdata (abfd)->parsed_size + padded_len); + if (!_bfd_ar_sizepad (hdr->ar_size, sizeof (hdr->ar_size), + arch_eltdata (abfd)->parsed_size + padded_len)) + return FALSE; if (bfd_bwrite (hdr, sizeof (*hdr), archive) != sizeof (*hdr)) return FALSE; if (bfd_bwrite (fullname, len, archive) != len) return FALSE; + if (len & 3) { static const char pad[3] = { 0, 0, 0 }; @@ -1883,8 +1907,11 @@ bfd_ar_hdr_from_filesystem (bfd *abfd, const char *filename, bfd *member) status.st_gid); _bfd_ar_spacepad (hdr->ar_mode, sizeof (hdr->ar_mode), "%-8lo", status.st_mode); - _bfd_ar_spacepad (hdr->ar_size, sizeof (hdr->ar_size), "%-10ld", - status.st_size); + if (!_bfd_ar_sizepad (hdr->ar_size, sizeof (hdr->ar_size), status.st_size)) + { + free (ared); + return NULL; + } memcpy (hdr->ar_fmag, ARFMAG, 2); ared->parsed_size = status.st_size; ared->arch_header = (char *) hdr; @@ -2124,8 +2151,9 @@ _bfd_write_archive_contents (bfd *arch) memset (&hdr, ' ', sizeof (struct ar_hdr)); memcpy (hdr.ar_name, ename, strlen (ename)); /* Round size up to even number in archive header. */ - _bfd_ar_spacepad (hdr.ar_size, sizeof (hdr.ar_size), "%-10ld", - (elength + 1) & ~(bfd_size_type) 1); + if (!_bfd_ar_sizepad (hdr.ar_size, sizeof (hdr.ar_size), + (elength + 1) & ~(bfd_size_type) 1)) + return FALSE; memcpy (hdr.ar_fmag, ARFMAG, 2); if ((bfd_bwrite (&hdr, sizeof (struct ar_hdr), arch) != sizeof (struct ar_hdr)) @@ -2143,7 +2171,7 @@ _bfd_write_archive_contents (bfd *arch) current = current->archive_next) { char buffer[DEFAULT_BUFFERSIZE]; - unsigned int remaining = arelt_size (current); + bfd_size_type remaining = arelt_size (current); /* Write ar header. */ if (!_bfd_write_ar_hdr (arch, current)) @@ -2401,7 +2429,8 @@ bsd_write_armap (bfd *arch, bfd_ardata (arch)->armap_timestamp); _bfd_ar_spacepad (hdr.ar_uid, sizeof (hdr.ar_uid), "%ld", uid); _bfd_ar_spacepad (hdr.ar_gid, sizeof (hdr.ar_gid), "%ld", gid); - _bfd_ar_spacepad (hdr.ar_size, sizeof (hdr.ar_size), "%-10ld", mapsize); + if (!_bfd_ar_sizepad (hdr.ar_size, sizeof (hdr.ar_size), mapsize)) + return FALSE; memcpy (hdr.ar_fmag, ARFMAG, 2); if (bfd_bwrite (&hdr, sizeof (struct ar_hdr), arch) != sizeof (struct ar_hdr)) @@ -2556,8 +2585,8 @@ coff_write_armap (bfd *arch, memset (&hdr, ' ', sizeof (struct ar_hdr)); hdr.ar_name[0] = '/'; - _bfd_ar_spacepad (hdr.ar_size, sizeof (hdr.ar_size), "%-10ld", - mapsize); + if (!_bfd_ar_sizepad (hdr.ar_size, sizeof (hdr.ar_size), mapsize)) + return FALSE; _bfd_ar_spacepad (hdr.ar_date, sizeof (hdr.ar_date), "%ld", ((arch->flags & BFD_DETERMINISTIC_OUTPUT) == 0 ? time (NULL) : 0)); diff --git a/bfd/archive64.c b/bfd/archive64.c index bbc4c3f72..f3a13d341 100644 --- a/bfd/archive64.c +++ b/bfd/archive64.c @@ -1,6 +1,6 @@ /* MIPS-specific support for 64-bit ELF Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2005, 2006, 2007, - 2010 Free Software Foundation, Inc. + 2010, 2012 Free Software Foundation, Inc. Ian Lance Taylor, Cygnus Support Linker support added by Mark Mitchell, CodeSourcery, LLC. @@ -169,8 +169,8 @@ bfd_elf64_archive_write_armap (bfd *arch, memset (&hdr, ' ', sizeof (struct ar_hdr)); memcpy (hdr.ar_name, "/SYM64/", strlen ("/SYM64/")); - _bfd_ar_spacepad (hdr.ar_size, sizeof (hdr.ar_size), "%-10ld", - mapsize); + if (!_bfd_ar_sizepad (hdr.ar_size, sizeof (hdr.ar_size), mapsize)) + return FALSE; _bfd_ar_spacepad (hdr.ar_date, sizeof (hdr.ar_date), "%ld", time (NULL)); /* This, at least, is what Intel coff sets the values to.: */ diff --git a/bfd/bfdio.c b/bfd/bfdio.c index c142c179c..6f8a7c9b8 100644 --- a/bfd/bfdio.c +++ b/bfd/bfdio.c @@ -185,7 +185,8 @@ bfd_bread (void *ptr, bfd_size_type size, bfd *abfd) this element. */ if (abfd->arelt_data != NULL) { - size_t maxbytes = arelt_size (abfd); + bfd_size_type maxbytes = arelt_size (abfd); + if (abfd->where + size > maxbytes) { if (abfd->where >= maxbytes) diff --git a/bfd/libbfd-in.h b/bfd/libbfd-in.h index f7a9e21bf..640768ee8 100644 --- a/bfd/libbfd-in.h +++ b/bfd/libbfd-in.h @@ -3,7 +3,7 @@ Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, - 2010, 2011 + 2010, 2011, 2012 Free Software Foundation, Inc. Written by Cygnus Support. @@ -64,16 +64,17 @@ struct section_hash_entry /* tdata for an archive. For an input archive, cache needs to be free()'d. For an output archive, symdefs do. */ -struct artdata { +struct artdata +{ file_ptr first_file_filepos; /* Speed up searching the armap */ htab_t cache; - bfd *archive_head; /* Only interesting in output routines */ - carsym *symdefs; /* the symdef entries */ - symindex symdef_count; /* how many there are */ - char *extended_names; /* clever intel extension */ - bfd_size_type extended_names_size; /* Size of extended names */ - /* when more compilers are standard C, this can be a time_t */ + bfd *archive_head; /* Only interesting in output routines. */ + carsym *symdefs; /* The symdef entries. */ + symindex symdef_count; /* How many there are. */ + char *extended_names; /* Clever intel extension. */ + bfd_size_type extended_names_size; /* Size of extended names. */ + /* When more compilers are standard C, this can be a time_t. */ long armap_timestamp; /* Timestamp value written into armap. This is used for BSD archives to check that the timestamp is recent enough @@ -88,12 +89,13 @@ struct artdata { #define bfd_ardata(bfd) ((bfd)->tdata.aout_ar_data) /* Goes in bfd's arelt_data slot */ -struct areltdata { - char * arch_header; /* it's actually a string */ - unsigned int parsed_size; /* octets of filesize not including ar_hdr */ - unsigned int extra_size; /* BSD4.4: extra bytes after the header. */ - char *filename; /* null-terminated */ - file_ptr origin; /* for element of a thin archive */ +struct areltdata +{ + char * arch_header; /* It's actually a string. */ + bfd_size_type parsed_size; /* Octets of filesize not including ar_hdr. */ + bfd_size_type extra_size; /* BSD4.4: extra bytes after the header. */ + char *filename; /* Null-terminated. */ + file_ptr origin; /* For element of a thin archive. */ }; #define arelt_size(bfd) (((struct areltdata *)((bfd)->arelt_data))->parsed_size) @@ -203,6 +205,8 @@ extern void *_bfd_generic_read_ar_hdr (bfd *); extern void _bfd_ar_spacepad (char *, size_t, const char *, long); +extern bfd_boolean _bfd_ar_sizepad + (char *, size_t, bfd_size_type); extern void *_bfd_generic_read_ar_hdr_mag (bfd *, const char *); diff --git a/bfd/libbfd.h b/bfd/libbfd.h index a10a651e7..5e1cfe095 100644 --- a/bfd/libbfd.h +++ b/bfd/libbfd.h @@ -8,7 +8,7 @@ Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, - 2010, 2011 + 2010, 2011, 2012 Free Software Foundation, Inc. Written by Cygnus Support. @@ -69,16 +69,17 @@ struct section_hash_entry /* tdata for an archive. For an input archive, cache needs to be free()'d. For an output archive, symdefs do. */ -struct artdata { +struct artdata +{ file_ptr first_file_filepos; /* Speed up searching the armap */ htab_t cache; - bfd *archive_head; /* Only interesting in output routines */ - carsym *symdefs; /* the symdef entries */ - symindex symdef_count; /* how many there are */ - char *extended_names; /* clever intel extension */ - bfd_size_type extended_names_size; /* Size of extended names */ - /* when more compilers are standard C, this can be a time_t */ + bfd *archive_head; /* Only interesting in output routines. */ + carsym *symdefs; /* The symdef entries. */ + symindex symdef_count; /* How many there are. */ + char *extended_names; /* Clever intel extension. */ + bfd_size_type extended_names_size; /* Size of extended names. */ + /* When more compilers are standard C, this can be a time_t. */ long armap_timestamp; /* Timestamp value written into armap. This is used for BSD archives to check that the timestamp is recent enough @@ -93,12 +94,13 @@ struct artdata { #define bfd_ardata(bfd) ((bfd)->tdata.aout_ar_data) /* Goes in bfd's arelt_data slot */ -struct areltdata { - char * arch_header; /* it's actually a string */ - unsigned int parsed_size; /* octets of filesize not including ar_hdr */ - unsigned int extra_size; /* BSD4.4: extra bytes after the header. */ - char *filename; /* null-terminated */ - file_ptr origin; /* for element of a thin archive */ +struct areltdata +{ + char * arch_header; /* It's actually a string. */ + bfd_size_type parsed_size; /* Octets of filesize not including ar_hdr. */ + bfd_size_type extra_size; /* BSD4.4: extra bytes after the header. */ + char *filename; /* Null-terminated. */ + file_ptr origin; /* For element of a thin archive. */ }; #define arelt_size(bfd) (((struct areltdata *)((bfd)->arelt_data))->parsed_size) @@ -208,6 +210,8 @@ extern void *_bfd_generic_read_ar_hdr (bfd *); extern void _bfd_ar_spacepad (char *, size_t, const char *, long); +extern bfd_boolean _bfd_ar_sizepad + (char *, size_t, bfd_size_type); extern void *_bfd_generic_read_ar_hdr_mag (bfd *, const char *); -- 2.11.4.GIT