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.
This commit is contained in:
Nick Clifton 2013-02-15 14:37:39 +00:00
parent 76d8cf45bb
commit a043396b72
7 changed files with 92 additions and 23 deletions

View File

@ -1,3 +1,9 @@
2013-02-15 Nick Clifton <nickc@redhat.com>
PR binutils/15140
* archive.c (_bfd_get_elt_at_filepos): Prevent an infinite loop
accessing a corrupt nested archive.
2013-02-13 Richard Sandiford <rdsandiford@googlemail.com>
* elfxx-mips.c (mips_got_page_ref): New structure.

View File

@ -1,7 +1,5 @@
/* 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,
2012 Free Software Foundation, Inc.
Copyright 1990-2013 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.
@ -619,6 +617,7 @@ _bfd_append_relative_path (bfd *arch, char *elt_name)
bfd *
_bfd_get_elt_at_filepos (bfd *archive, file_ptr filepos)
{
static file_ptr prev_filepos;
struct areltdata *new_areldata;
bfd *n_nfd;
char *filename;
@ -626,6 +625,12 @@ _bfd_get_elt_at_filepos (bfd *archive, file_ptr filepos)
n_nfd = _bfd_look_for_bfd_in_cache (archive, filepos);
if (n_nfd)
return n_nfd;
/* PR15140: Prevent an inifnite recursion scanning a malformed nested archive. */
if (filepos == prev_filepos)
{
bfd_set_error (bfd_error_malformed_archive);
return NULL;
}
if (0 > bfd_seek (archive, filepos, SEEK_SET))
return NULL;
@ -634,6 +639,7 @@ _bfd_get_elt_at_filepos (bfd *archive, file_ptr filepos)
return NULL;
filename = new_areldata->filename;
prev_filepos = filepos;
if (bfd_is_thin_archive (archive))
{

View File

@ -2,6 +2,17 @@
* objcopy.c (copy_main): Initialize context variable.
2013-02-15 Nick Clifton <nickc@redhat.com>
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 <nickc@redhat.com>
PR binutils/15033

View File

@ -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);

View File

@ -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.

View File

@ -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 <eric@andante.jic.com>
Modifications by Nick Clifton <nickc@redhat.com>
@ -690,12 +689,20 @@ make_qualified_name (struct archive_info * arch,
struct archive_info * nested_arch,
const char *member_name)
{
const char * error_name = _("<corrupt>");
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

View File

@ -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;