Index: bfd/archive.c |
diff --git a/bfd/archive.c b/bfd/archive.c |
index 3e333c7e8949870614233df0ab310760caff1c2f..fe57755770bbbfc43be705fb5c437dd8619dff7d 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. |
@@ -147,7 +147,8 @@ extern int errno; |
it's generally short enough to search linearly. |
Note that the pointers here point to the front of the ar_hdr, not |
to the front of the contents! */ |
-struct ar_cache { |
+struct ar_cache |
+{ |
file_ptr ptr; |
bfd *arbfd; |
}; |
@@ -168,6 +169,7 @@ _bfd_ar_spacepad (char *p, size_t n, const char *fmt, long val) |
{ |
static char buf[20]; |
size_t len; |
+ |
snprintf (buf, sizeof (buf), fmt, val); |
len = strlen (buf); |
if (len < n) |
@@ -178,6 +180,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) |
@@ -273,6 +298,7 @@ _bfd_look_for_bfd_in_cache (bfd *arch_bfd, file_ptr filepos) |
{ |
htab_t hash_table = bfd_ardata (arch_bfd)->cache; |
struct ar_cache m; |
+ |
m.ptr = filepos; |
if (hash_table) |
@@ -288,7 +314,7 @@ _bfd_look_for_bfd_in_cache (bfd *arch_bfd, file_ptr filepos) |
} |
static hashval_t |
-hash_file_ptr (const PTR p) |
+hash_file_ptr (const void * p) |
{ |
return (hashval_t) (((struct ar_cache *) p)->ptr); |
} |
@@ -296,7 +322,7 @@ hash_file_ptr (const PTR p) |
/* Returns non-zero if P1 and P2 are equal. */ |
static int |
-eq_file_ptr (const PTR p1, const PTR p2) |
+eq_file_ptr (const void * p1, const void * p2) |
{ |
struct ar_cache *arc1 = (struct ar_cache *) p1; |
struct ar_cache *arc2 = (struct ar_cache *) p2; |
@@ -350,7 +376,7 @@ _bfd_find_nested_archive (bfd *arch_bfd, const char *filename) |
abfd = abfd->archive_next) |
{ |
if (filename_cmp (filename, abfd->filename) == 0) |
- return abfd; |
+ return abfd; |
} |
target = NULL; |
if (!arch_bfd->target_defaulted) |
@@ -390,10 +416,10 @@ get_extended_arelt_filename (bfd *arch, const char *name, file_ptr *originp) |
file_ptr origin = strtol (endp + 1, NULL, 10); |
if (errno != 0) |
- { |
- bfd_set_error (bfd_error_malformed_archive); |
- return NULL; |
- } |
+ { |
+ bfd_set_error (bfd_error_malformed_archive); |
+ return NULL; |
+ } |
*originp = origin; |
} |
else |
@@ -424,7 +450,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; |
@@ -432,6 +458,8 @@ _bfd_generic_read_ar_hdr_mag (bfd *abfd, const char *mag) |
char *allocptr = 0; |
file_ptr origin = 0; |
unsigned int extra_size = 0; |
+ char fmag_save; |
+ int scan; |
if (bfd_bread (hdrp, sizeof (struct ar_hdr), abfd) != sizeof (struct ar_hdr)) |
{ |
@@ -448,8 +476,11 @@ _bfd_generic_read_ar_hdr_mag (bfd *abfd, const char *mag) |
} |
errno = 0; |
- parsed_size = strtol (hdr.ar_size, NULL, 10); |
- if (errno != 0) |
+ fmag_save = hdr.ar_fmag[0]; |
+ hdr.ar_fmag[0] = 0; |
+ scan = sscanf (hdr.ar_size, "%" BFD_VMA_FMT "u", &parsed_size); |
+ hdr.ar_fmag[0] = fmag_save; |
+ if (scan != 1) |
{ |
bfd_set_error (bfd_error_malformed_archive); |
return NULL; |
@@ -581,12 +612,6 @@ _bfd_get_elt_at_filepos (bfd *archive, file_ptr filepos) |
bfd *n_nfd; |
char *filename; |
- if (archive->my_archive) |
- { |
- filepos += archive->origin; |
- archive = archive->my_archive; |
- } |
- |
n_nfd = _bfd_look_for_bfd_in_cache (archive, filepos); |
if (n_nfd) |
return n_nfd; |
@@ -605,35 +630,35 @@ _bfd_get_elt_at_filepos (bfd *archive, file_ptr filepos) |
/* This is a proxy entry for an external file. */ |
if (! IS_ABSOLUTE_PATH (filename)) |
- { |
- filename = _bfd_append_relative_path (archive, filename); |
- if (filename == NULL) |
- return NULL; |
- } |
+ { |
+ filename = _bfd_append_relative_path (archive, filename); |
+ if (filename == NULL) |
+ return NULL; |
+ } |
if (new_areldata->origin > 0) |
- { |
- /* This proxy entry refers to an element of a nested archive. |
- Locate the member of that archive and return a bfd for it. */ |
- bfd *ext_arch = _bfd_find_nested_archive (archive, filename); |
- |
- if (ext_arch == NULL |
- || ! bfd_check_format (ext_arch, bfd_archive)) |
- { |
- bfd_release (archive, new_areldata); |
- return NULL; |
- } |
- n_nfd = _bfd_get_elt_at_filepos (ext_arch, new_areldata->origin); |
- if (n_nfd == NULL) |
- { |
- bfd_release (archive, new_areldata); |
- return NULL; |
- } |
- n_nfd->proxy_origin = bfd_tell (archive); |
- return n_nfd; |
- } |
+ { |
+ /* This proxy entry refers to an element of a nested archive. |
+ Locate the member of that archive and return a bfd for it. */ |
+ bfd *ext_arch = _bfd_find_nested_archive (archive, filename); |
+ |
+ if (ext_arch == NULL |
+ || ! bfd_check_format (ext_arch, bfd_archive)) |
+ { |
+ bfd_release (archive, new_areldata); |
+ return NULL; |
+ } |
+ n_nfd = _bfd_get_elt_at_filepos (ext_arch, new_areldata->origin); |
+ if (n_nfd == NULL) |
+ { |
+ bfd_release (archive, new_areldata); |
+ return NULL; |
+ } |
+ n_nfd->proxy_origin = bfd_tell (archive); |
+ return n_nfd; |
+ } |
/* It's not an element of a nested archive; |
- open the external file as a bfd. */ |
+ open the external file as a bfd. */ |
target = NULL; |
if (!archive->target_defaulted) |
target = archive->xvec->name; |
@@ -727,13 +752,11 @@ 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)) |
- filestart += size; |
- if (archive->my_archive) |
- filestart -= archive->origin; |
+ filestart += size; |
/* Pad to an even boundary... |
Note that last_file->origin can be odd in the case of |
BSD-4.4-style element with a long odd size. */ |
@@ -925,7 +948,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 *); |
@@ -979,7 +1002,7 @@ do_slurp_coff_armap (bfd *abfd) |
return FALSE; |
ardata->symdefs = (struct carsym *) bfd_zalloc (abfd, |
- carsym_size + stringsize + 1); |
+ carsym_size + stringsize + 1); |
if (ardata->symdefs == NULL) |
return FALSE; |
carsyms = ardata->symdefs; |
@@ -1079,21 +1102,21 @@ bfd_slurp_armap (bfd *abfd) |
else if (CONST_STRNEQ (nextname, "#1/20 ")) |
{ |
/* Mach-O has a special name for armap when the map is sorted by name. |
- However because this name has a space it is slightly more difficult |
- to check it. */ |
+ However because this name has a space it is slightly more difficult |
+ to check it. */ |
struct ar_hdr hdr; |
char extname[21]; |
if (bfd_bread (&hdr, sizeof (hdr), abfd) != sizeof (hdr)) |
- return FALSE; |
+ return FALSE; |
/* Read the extended name. We know its length. */ |
if (bfd_bread (extname, 20, abfd) != 20) |
- return FALSE; |
- if (bfd_seek (abfd, (file_ptr) -(sizeof (hdr) + 20), SEEK_CUR) != 0) |
- return FALSE; |
+ return FALSE; |
+ if (bfd_seek (abfd, -(file_ptr) (sizeof (hdr) + 20), SEEK_CUR) != 0) |
+ return FALSE; |
if (CONST_STRNEQ (extname, "__.SYMDEF SORTED") |
- || CONST_STRNEQ (extname, "__.SYMDEF")) |
- return do_slurp_bsd_armap (abfd); |
+ || CONST_STRNEQ (extname, "__.SYMDEF")) |
+ return do_slurp_bsd_armap (abfd); |
} |
bfd_has_map (abfd) = FALSE; |
@@ -1250,7 +1273,7 @@ _bfd_slurp_extended_name_table (bfd *abfd) |
amt = namedata->parsed_size; |
if (amt + 1 == 0) |
- goto byebye; |
+ goto byebye; |
bfd_ardata (abfd)->extended_names_size = amt; |
bfd_ardata (abfd)->extended_names = (char *) bfd_zalloc (abfd, amt + 1); |
@@ -1276,7 +1299,7 @@ _bfd_slurp_extended_name_table (bfd *abfd) |
trailing '/'. DOS/NT created archive often have \ in them |
We'll fix all problems here.. */ |
{ |
- char *ext_names = bfd_ardata (abfd)->extended_names; |
+ char *ext_names = bfd_ardata (abfd)->extended_names; |
char *temp = ext_names; |
char *limit = temp + namedata->parsed_size; |
for (; temp < limit; ++temp) |
@@ -1366,7 +1389,7 @@ normalize (bfd *abfd ATTRIBUTE_UNUSED, const char *file) |
the autogenerated bfd.h header... |
Note - the string is returned in a static buffer. */ |
- |
+ |
static const char * |
adjust_relative_path (const char * path, const char * ref_path) |
{ |
@@ -1389,7 +1412,7 @@ adjust_relative_path (const char * path, const char * ref_path) |
rpath = lrealpath (ref_path); |
refp = rpath == NULL ? ref_path : rpath; |
- |
+ |
/* Remove common leading path elements. */ |
for (;;) |
{ |
@@ -1415,7 +1438,7 @@ adjust_relative_path (const char * path, const char * ref_path) |
{ |
/* PR 12710: If the path element is "../" then instead of |
inserting "../" we need to insert the name of the directory |
- at the current level. */ |
+ at the current level. */ |
if (refp > ref_path + 1 |
&& refp[-1] == '.' |
&& refp[-2] == '.') |
@@ -1426,7 +1449,7 @@ adjust_relative_path (const char * path, const char * ref_path) |
/* If the lrealpath calls above succeeded then we should never |
see dir_up and dir_down both being non-zero. */ |
- |
+ |
len += 3 * dir_up; |
if (dir_down) |
@@ -1531,40 +1554,40 @@ _bfd_construct_extended_name_table (bfd *abfd, |
unsigned int thislen; |
if (bfd_is_thin_archive (abfd)) |
- { |
- const char *filename = current->filename; |
- |
- /* If the element being added is a member of another archive |
- (i.e., we are flattening), use the containing archive's name. */ |
- if (current->my_archive |
- && ! bfd_is_thin_archive (current->my_archive)) |
- filename = current->my_archive->filename; |
- |
- /* If the path is the same as the previous path seen, |
- reuse it. This can happen when flattening a thin |
- archive that contains other archives. */ |
- if (last_filename && filename_cmp (last_filename, filename) == 0) |
- continue; |
- |
- last_filename = filename; |
- |
- /* If the path is relative, adjust it relative to |
- the containing archive. */ |
- if (! IS_ABSOLUTE_PATH (filename) |
- && ! IS_ABSOLUTE_PATH (abfd->filename)) |
- normal = adjust_relative_path (filename, abfd->filename); |
- else |
- normal = filename; |
- |
- /* In a thin archive, always store the full pathname |
- in the extended name table. */ |
- total_namelen += strlen (normal) + 1; |
+ { |
+ const char *filename = current->filename; |
+ |
+ /* If the element being added is a member of another archive |
+ (i.e., we are flattening), use the containing archive's name. */ |
+ if (current->my_archive |
+ && ! bfd_is_thin_archive (current->my_archive)) |
+ filename = current->my_archive->filename; |
+ |
+ /* If the path is the same as the previous path seen, |
+ reuse it. This can happen when flattening a thin |
+ archive that contains other archives. */ |
+ if (last_filename && filename_cmp (last_filename, filename) == 0) |
+ continue; |
+ |
+ last_filename = filename; |
+ |
+ /* If the path is relative, adjust it relative to |
+ the containing archive. */ |
+ if (! IS_ABSOLUTE_PATH (filename) |
+ && ! IS_ABSOLUTE_PATH (abfd->filename)) |
+ normal = adjust_relative_path (filename, abfd->filename); |
+ else |
+ normal = filename; |
+ |
+ /* In a thin archive, always store the full pathname |
+ in the extended name table. */ |
+ total_namelen += strlen (normal) + 1; |
if (trailing_slash) |
/* Leave room for trailing slash. */ |
++total_namelen; |
- continue; |
- } |
+ continue; |
+ } |
normal = normalize (current, current->filename); |
if (normal == NULL) |
@@ -1594,7 +1617,7 @@ _bfd_construct_extended_name_table (bfd *abfd, |
&& hdr->ar_name[thislen] != ar_padchar (current))) |
{ |
/* Must have been using extended format even though it |
- didn't need to. Fix it to use normal format. */ |
+ didn't need to. Fix it to use normal format. */ |
memcpy (hdr->ar_name, normal, thislen); |
if (thislen < maxname |
|| (thislen == maxname && thislen < sizeof hdr->ar_name)) |
@@ -1626,31 +1649,31 @@ _bfd_construct_extended_name_table (bfd *abfd, |
const char *filename = current->filename; |
if (bfd_is_thin_archive (abfd)) |
- { |
- /* If the element being added is a member of another archive |
- (i.e., we are flattening), use the containing archive's name. */ |
- if (current->my_archive |
- && ! bfd_is_thin_archive (current->my_archive)) |
- filename = current->my_archive->filename; |
- /* If the path is the same as the previous path seen, |
- reuse it. This can happen when flattening a thin |
- archive that contains other archives. |
- If the path is relative, adjust it relative to |
- the containing archive. */ |
- if (last_filename && filename_cmp (last_filename, filename) == 0) |
- normal = last_filename; |
- else if (! IS_ABSOLUTE_PATH (filename) |
- && ! IS_ABSOLUTE_PATH (abfd->filename)) |
- normal = adjust_relative_path (filename, abfd->filename); |
- else |
- normal = filename; |
- } |
+ { |
+ /* If the element being added is a member of another archive |
+ (i.e., we are flattening), use the containing archive's name. */ |
+ if (current->my_archive |
+ && ! bfd_is_thin_archive (current->my_archive)) |
+ filename = current->my_archive->filename; |
+ /* If the path is the same as the previous path seen, |
+ reuse it. This can happen when flattening a thin |
+ archive that contains other archives. |
+ If the path is relative, adjust it relative to |
+ the containing archive. */ |
+ if (last_filename && filename_cmp (last_filename, filename) == 0) |
+ normal = last_filename; |
+ else if (! IS_ABSOLUTE_PATH (filename) |
+ && ! IS_ABSOLUTE_PATH (abfd->filename)) |
+ normal = adjust_relative_path (filename, abfd->filename); |
+ else |
+ normal = filename; |
+ } |
else |
- { |
- normal = normalize (current, filename); |
- if (normal == NULL) |
- return FALSE; |
- } |
+ { |
+ normal = normalize (current, filename); |
+ if (normal == NULL) |
+ return FALSE; |
+ } |
thislen = strlen (normal); |
if (thislen > maxname || bfd_is_thin_archive (abfd)) |
@@ -1661,16 +1684,16 @@ _bfd_construct_extended_name_table (bfd *abfd, |
struct ar_hdr *hdr = arch_hdr (current); |
if (normal == last_filename) |
stroff = last_stroff; |
- else |
- { |
+ else |
+ { |
strcpy (strptr, normal); |
if (! trailing_slash) |
- strptr[thislen] = ARFMAG[1]; |
+ strptr[thislen] = ARFMAG[1]; |
else |
- { |
- strptr[thislen] = '/'; |
- strptr[thislen + 1] = ARFMAG[1]; |
- } |
+ { |
+ strptr[thislen] = '/'; |
+ strptr[thislen + 1] = ARFMAG[1]; |
+ } |
stroff = strptr - *tabloc; |
last_stroff = stroff; |
} |
@@ -1678,19 +1701,19 @@ _bfd_construct_extended_name_table (bfd *abfd, |
if (bfd_is_thin_archive (abfd) && current->origin > 0) |
{ |
int len = snprintf (hdr->ar_name + 1, maxname - 1, "%-ld:", |
- stroff); |
+ stroff); |
_bfd_ar_spacepad (hdr->ar_name + 1 + len, maxname - 1 - len, |
- "%-ld", |
- current->origin - sizeof (struct ar_hdr)); |
+ "%-ld", |
+ current->origin - sizeof (struct ar_hdr)); |
} |
else |
- _bfd_ar_spacepad (hdr->ar_name + 1, maxname - 1, "%-ld", stroff); |
- if (normal != last_filename) |
- { |
+ _bfd_ar_spacepad (hdr->ar_name + 1, maxname - 1, "%-ld", stroff); |
+ if (normal != last_filename) |
+ { |
strptr += thislen + 1; |
if (trailing_slash) |
- ++strptr; |
- last_filename = filename; |
+ ++strptr; |
+ last_filename = filename; |
} |
} |
} |
@@ -1703,9 +1726,9 @@ _bfd_construct_extended_name_table (bfd *abfd, |
bfd_boolean |
_bfd_archive_bsd44_construct_extended_name_table (bfd *abfd, |
- char **tabloc, |
- bfd_size_type *tablen, |
- const char **name) |
+ char **tabloc, |
+ bfd_size_type *tablen, |
+ const char **name) |
{ |
unsigned int maxname = ar_maxnamelen (abfd); |
bfd *current; |
@@ -1726,16 +1749,16 @@ _bfd_archive_bsd44_construct_extended_name_table (bfd *abfd, |
return FALSE; |
for (len = 0; normal[len]; len++) |
- if (normal[len] == ' ') |
- has_space = 1; |
+ if (normal[len] == ' ') |
+ has_space = 1; |
if (len > maxname || has_space) |
{ |
- struct ar_hdr *hdr = arch_hdr (current); |
+ struct ar_hdr *hdr = arch_hdr (current); |
- len = (len + 3) & ~3; |
- arch_eltdata (current)->extra_size = len; |
- _bfd_ar_spacepad (hdr->ar_name, maxname, "#1/%lu", len); |
+ len = (len + 3) & ~3; |
+ arch_eltdata (current)->extra_size = len; |
+ _bfd_ar_spacepad (hdr->ar_name, maxname, "#1/%lu", len); |
} |
} |
@@ -1770,27 +1793,29 @@ _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; |
+ return FALSE; |
if (bfd_bwrite (fullname, len, archive) != len) |
- return FALSE; |
+ return FALSE; |
+ |
if (len & 3) |
- { |
- static const char pad[3] = { 0, 0, 0 }; |
+ { |
+ static const char pad[3] = { 0, 0, 0 }; |
- len = 4 - (len & 3); |
- if (bfd_bwrite (pad, len, archive) != len) |
- return FALSE; |
- } |
+ len = 4 - (len & 3); |
+ if (bfd_bwrite (pad, len, archive) != len) |
+ return FALSE; |
+ } |
} |
else |
{ |
if (bfd_bwrite (hdr, sizeof (*hdr), archive) != sizeof (*hdr)) |
- return FALSE; |
+ return FALSE; |
} |
return TRUE; |
} |
@@ -1870,7 +1895,7 @@ bfd_ar_hdr_from_filesystem (bfd *abfd, const char *filename, bfd *member) |
memset (hdr, ' ', sizeof (struct ar_hdr)); |
_bfd_ar_spacepad (hdr->ar_date, sizeof (hdr->ar_date), "%-12ld", |
- status.st_mtime); |
+ status.st_mtime); |
#ifdef HPUX_LARGE_AR_IDS |
/* HP has a very "special" way to handle UID/GID's with numeric values |
> 99999. */ |
@@ -1879,7 +1904,7 @@ bfd_ar_hdr_from_filesystem (bfd *abfd, const char *filename, bfd *member) |
else |
#endif |
_bfd_ar_spacepad (hdr->ar_uid, sizeof (hdr->ar_uid), "%ld", |
- status.st_uid); |
+ status.st_uid); |
#ifdef HPUX_LARGE_AR_IDS |
/* HP has a very "special" way to handle UID/GID's with numeric values |
> 99999. */ |
@@ -1888,11 +1913,14 @@ bfd_ar_hdr_from_filesystem (bfd *abfd, const char *filename, bfd *member) |
else |
#endif |
_bfd_ar_spacepad (hdr->ar_gid, sizeof (hdr->ar_gid), "%ld", |
- status.st_gid); |
+ 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); |
+ status.st_mode); |
+ 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; |
@@ -2132,8 +2160,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)) |
@@ -2151,13 +2180,13 @@ _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)) |
- return FALSE; |
+ return FALSE; |
if (bfd_is_thin_archive (arch)) |
- continue; |
+ continue; |
if (bfd_seek (current, (file_ptr) 0, SEEK_SET) != 0) |
goto input_err; |
@@ -2282,16 +2311,16 @@ _bfd_compute_and_write_armap (bfd *arch, unsigned int elength) |
goto error_return; |
/* Now map over all the symbols, picking out the ones we |
- want. */ |
+ want. */ |
for (src_count = 0; src_count < symcount; src_count++) |
{ |
flagword flags = (syms[src_count])->flags; |
asection *sec = syms[src_count]->section; |
- if ((flags & BSF_GLOBAL |
- || flags & BSF_WEAK |
- || flags & BSF_INDIRECT |
- || flags & BSF_GNU_UNIQUE |
+ if (((flags & (BSF_GLOBAL |
+ | BSF_WEAK |
+ | BSF_INDIRECT |
+ | BSF_GNU_UNIQUE)) != 0 |
|| bfd_is_com_section (sec)) |
&& ! bfd_is_und_section (sec)) |
{ |
@@ -2316,7 +2345,7 @@ _bfd_compute_and_write_armap (bfd *arch, unsigned int elength) |
if (map[orl_count].name == NULL) |
goto error_return; |
*(map[orl_count].name) = (char *) bfd_alloc (arch, |
- namelen + 1); |
+ namelen + 1); |
if (*(map[orl_count].name) == NULL) |
goto error_return; |
strcpy (*(map[orl_count].name), syms[src_count]->name); |
@@ -2379,6 +2408,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; |
@@ -2406,10 +2438,11 @@ bsd_write_armap (bfd *arch, |
bfd_ardata (arch)->armap_datepos = (SARMAG |
+ offsetof (struct ar_hdr, ar_date[0])); |
_bfd_ar_spacepad (hdr.ar_date, sizeof (hdr.ar_date), "%ld", |
- bfd_ardata (arch)->armap_timestamp); |
+ 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)) |
@@ -2426,16 +2459,25 @@ bsd_write_armap (bfd *arch, |
{ |
do |
{ |
- struct areltdata *ared = arch_eltdata (current); |
+ struct areltdata *ared = arch_eltdata (current); |
firstreal += (ared->parsed_size + ared->extra_size |
- + sizeof (struct ar_hdr)); |
+ + sizeof (struct ar_hdr)); |
firstreal += firstreal % 2; |
current = current->archive_next; |
} |
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); |
@@ -2503,7 +2545,7 @@ _bfd_archive_bsd_update_armap_timestamp (bfd *arch) |
/* Prepare an ASCII version suitable for writing. */ |
memset (hdr.ar_date, ' ', sizeof (hdr.ar_date)); |
_bfd_ar_spacepad (hdr.ar_date, sizeof (hdr.ar_date), "%ld", |
- bfd_ardata (arch)->armap_timestamp); |
+ bfd_ardata (arch)->armap_timestamp); |
/* Write it into the file. */ |
bfd_ardata (arch)->armap_datepos = (SARMAG |
@@ -2547,7 +2589,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; |
@@ -2564,11 +2606,11 @@ 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)); |
+ ((arch->flags & BFD_DETERMINISTIC_OUTPUT) == 0 |
+ ? time (NULL) : 0)); |
/* This, at least, is what Intel coff sets the values to. */ |
_bfd_ar_spacepad (hdr.ar_uid, sizeof (hdr.ar_uid), "%ld", 0); |
_bfd_ar_spacepad (hdr.ar_gid, sizeof (hdr.ar_gid), "%ld", 0); |
@@ -2598,18 +2640,26 @@ 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++; |
} |
archive_member_file_ptr += sizeof (struct ar_hdr); |
if (! bfd_is_thin_archive (arch)) |
- { |
- /* Add size of this archive entry. */ |
- archive_member_file_ptr += arelt_size (current); |
- /* Remember about the even alignment. */ |
- archive_member_file_ptr += archive_member_file_ptr % 2; |
- } |
+ { |
+ /* Add size of this archive entry. */ |
+ archive_member_file_ptr += arelt_size (current); |
+ /* Remember about the even alignment. */ |
+ archive_member_file_ptr += archive_member_file_ptr % 2; |
+ } |
current = current->archive_next; |
} |