From a043396b72d17ae87267b534aa98457a0702f5c8 Mon Sep 17 00:00:00 2001 From: Nick Clifton Date: Fri, 15 Feb 2013 14:37:39 +0000 Subject: PR binutils/15140 * ar.c (open_inarch): Fail on attempts to convert a normal archive to a thin archive or vice versa. * elfcomm.c (make_qualified_name): Handle corrupted thin archives. * readelf.c (process_archive): Likewise. * doc/binutils.texi: Clarify documentation describing thin archives. * archive.c (_bfd_get_elt_at_filepos): Prevent an infinite loop accessing a corrupt nested archive. --- binutils/ChangeLog | 11 +++++++++++ binutils/ar.c | 23 ++++++++++++++++++++--- binutils/doc/binutils.texi | 26 ++++++++++++++++---------- binutils/elfcomm.c | 28 +++++++++++++++++++++------- binutils/readelf.c | 9 +++++++++ 5 files changed, 77 insertions(+), 20 deletions(-) (limited to 'binutils') diff --git a/binutils/ChangeLog b/binutils/ChangeLog index d2e6dd0..06f5dd5 100644 --- a/binutils/ChangeLog +++ b/binutils/ChangeLog @@ -4,6 +4,17 @@ 2013-02-15 Nick Clifton + PR binutils/15140 + * ar.c (open_inarch): Fail on attempts to convert a normal archive + to a thin archive or vice versa. + * elfcomm.c (make_qualified_name): Handle corrupted thin + archives. + * readelf.c (process_archive): Likewise. + * doc/binutils.texi: Clarify documentation describing thin + archives. + +2013-02-15 Nick Clifton + PR binutils/15033 * objcopy.c (enum change_action): Delete. (struct section_list): Delete remove, copy, change_vma, change_lma diff --git a/binutils/ar.c b/binutils/ar.c index 0aa1ba3..c424038 100644 --- a/binutils/ar.c +++ b/binutils/ar.c @@ -1,7 +1,5 @@ /* ar.c - Archive modify and extract. - Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, - 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013 - Free Software Foundation, Inc. + Copyright 1991-2013 Free Software Foundation, Inc. This file is part of GNU Binutils. @@ -918,6 +916,25 @@ open_inarch (const char *archive_filename, const char *file) xexit (1); } + if ((operation == replace || operation == quick_append) + && bfd_openr_next_archived_file (arch, NULL) != NULL) + { + /* PR 15140: Catch attempts to convert a normal + archive into a thin archive or vice versa. */ + if (make_thin_archive && ! bfd_is_thin_archive (arch)) + { + fatal (_("Cannot convert existing library %s to thin format"), + bfd_get_filename (arch)); + goto bloser; + } + else if (! make_thin_archive && bfd_is_thin_archive (arch)) + { + fatal (_("Cannot convert existing thin library %s to normal format"), + bfd_get_filename (arch)); + goto bloser; + } + } + last_one = &(arch->archive_next); /* Read all the contents right away, regardless. */ for (next_one = bfd_openr_next_archived_file (arch, NULL); diff --git a/binutils/doc/binutils.texi b/binutils/doc/binutils.texi index d733fdb..0bb1d92 100644 --- a/binutils/doc/binutils.texi +++ b/binutils/doc/binutils.texi @@ -10,10 +10,7 @@ @copying @c man begin COPYRIGHT -Copyright @copyright{} 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, -1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, -2010, 2011, 2012, 2013 -Free Software Foundation, Inc. +Copyright @copyright{} 1991-2013 Free Software Foundation, Inc. Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.3 @@ -221,12 +218,21 @@ table. If an archive lacks the table, another form of @command{ar} called @cindex thin archives @sc{gnu} @command{ar} can optionally create a @emph{thin} archive, which contains a symbol index and references to the original copies -of the member files of the archives. Such an archive is useful -for building libraries for use within a local build, where the -relocatable objects are expected to remain available, and copying the -contents of each object would only waste time and space. Thin archives -are also @emph{flattened}, so that adding one or more archives to a -thin archive will add the elements of the nested archive individually. +of the member files of the archive. This is useful for building +libraries for use within a local build tree, where the relocatable +objects are expected to remain available, and copying the contents of +each object would only waste time and space. + +An archive can either be @emph{thin} or it can be normal. It cannot +be both at the same time. Once an archive is created its format +cannot be changed without first deleting it and then creating a new +archive in its place. + +Thin archives are also @emph{flattened}, so that adding one thin +archive to another thin archive does not nest it, as would happen with +a normal archive. Instead the elements of the first archive are added +individually to the second archive. + The paths to the elements of the archive are stored relative to the archive itself. diff --git a/binutils/elfcomm.c b/binutils/elfcomm.c index 64d4b213..1179a1a 100644 --- a/binutils/elfcomm.c +++ b/binutils/elfcomm.c @@ -1,6 +1,5 @@ /* elfcomm.c -- common code for ELF format file. - Copyright 2010 - Free Software Foundation, Inc. + Copyright 2010-2013 Free Software Foundation, Inc. Originally developed by Eric Youngdale Modifications by Nick Clifton @@ -690,12 +689,20 @@ make_qualified_name (struct archive_info * arch, struct archive_info * nested_arch, const char *member_name) { + const char * error_name = _(""); size_t len; char * name; len = strlen (arch->file_name) + strlen (member_name) + 3; - if (arch->is_thin_archive && arch->nested_member_origin != 0) - len += strlen (nested_arch->file_name) + 2; + if (arch->is_thin_archive + && arch->nested_member_origin != 0) + { + /* PR 15140: Allow for corrupt thin archives. */ + if (nested_arch->file_name) + len += strlen (nested_arch->file_name) + 2; + else + len += strlen (error_name) + 2; + } name = (char *) malloc (len); if (name == NULL) @@ -704,9 +711,16 @@ make_qualified_name (struct archive_info * arch, return NULL; } - if (arch->is_thin_archive && arch->nested_member_origin != 0) - snprintf (name, len, "%s[%s(%s)]", arch->file_name, - nested_arch->file_name, member_name); + if (arch->is_thin_archive + && arch->nested_member_origin != 0) + { + if (nested_arch->file_name) + snprintf (name, len, "%s[%s(%s)]", arch->file_name, + nested_arch->file_name, member_name); + else + snprintf (name, len, "%s[%s(%s)]", arch->file_name, + error_name, member_name); + } else if (arch->is_thin_archive) snprintf (name, len, "%s[%s]", arch->file_name, member_name); else diff --git a/binutils/readelf.c b/binutils/readelf.c index 7710079..c7bd05f 100644 --- a/binutils/readelf.c +++ b/binutils/readelf.c @@ -13975,6 +13975,15 @@ process_archive (char * file_name, FILE * file, bfd_boolean is_thin_archive) } else if (is_thin_archive) { + /* PR 15140: Allow for corrupt thin archives. */ + if (nested_arch.file == NULL) + { + error (_("%s: contains corrupt thin archive: %s\n"), + file_name, name); + ret = 1; + break; + } + /* This is a proxy for a member of a nested archive. */ archive_file_offset = arch.nested_member_origin + sizeof arch.arhdr; -- cgit v1.1