aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bfd/ChangeLog25
-rw-r--r--bfd/archive.c63
-rw-r--r--bfd/archive64.c6
-rw-r--r--bfd/bfdio.c3
-rw-r--r--bfd/libbfd-in.h32
-rw-r--r--bfd/libbfd.h32
6 files changed, 112 insertions, 49 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index ab9cde1..994a1ce 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,3 +1,28 @@
+2012-01-20 Francois Gouget <fgouget@codeweavers.com>
+
+ 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 <ulrich.weigand@linaro.org>
* elf.c (elfcore_write_prpsinfo): Provide unconditionally.
diff --git a/bfd/archive.c b/bfd/archive.c
index ac2be3e..86c62a5 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 bbc4c3f..f3a13d3 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.
<mark@codesourcery.com>
@@ -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 c142c17..6f8a7c9 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 f7a9e21..640768e 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 a10a651..5e1cfe0 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 *);