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> 2013-02-13 Richard Sandiford <rdsandiford@googlemail.com>
* elfxx-mips.c (mips_got_page_ref): New structure. * elfxx-mips.c (mips_got_page_ref): New structure.

View File

@ -1,7 +1,5 @@
/* BFD back-end for archive files (libraries). /* BFD back-end for archive files (libraries).
Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, Copyright 1990-2013 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. Written by Cygnus Support. Mostly Gumby Henkel-Wallace's fault.
This file is part of BFD, the Binary File Descriptor library. 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 *
_bfd_get_elt_at_filepos (bfd *archive, file_ptr filepos) _bfd_get_elt_at_filepos (bfd *archive, file_ptr filepos)
{ {
static file_ptr prev_filepos;
struct areltdata *new_areldata; struct areltdata *new_areldata;
bfd *n_nfd; bfd *n_nfd;
char *filename; 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); n_nfd = _bfd_look_for_bfd_in_cache (archive, filepos);
if (n_nfd) if (n_nfd)
return 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)) if (0 > bfd_seek (archive, filepos, SEEK_SET))
return NULL; return NULL;
@ -634,6 +639,7 @@ _bfd_get_elt_at_filepos (bfd *archive, file_ptr filepos)
return NULL; return NULL;
filename = new_areldata->filename; filename = new_areldata->filename;
prev_filepos = filepos;
if (bfd_is_thin_archive (archive)) if (bfd_is_thin_archive (archive))
{ {

View File

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

View File

@ -1,7 +1,5 @@
/* ar.c - Archive modify and extract. /* ar.c - Archive modify and extract.
Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, Copyright 1991-2013 Free Software Foundation, Inc.
2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013
Free Software Foundation, Inc.
This file is part of GNU Binutils. This file is part of GNU Binutils.
@ -918,6 +916,25 @@ open_inarch (const char *archive_filename, const char *file)
xexit (1); 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); last_one = &(arch->archive_next);
/* Read all the contents right away, regardless. */ /* Read all the contents right away, regardless. */
for (next_one = bfd_openr_next_archived_file (arch, NULL); for (next_one = bfd_openr_next_archived_file (arch, NULL);

View File

@ -10,10 +10,7 @@
@copying @copying
@c man begin COPYRIGHT @c man begin COPYRIGHT
Copyright @copyright{} 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, Copyright @copyright{} 1991-2013 Free Software Foundation, Inc.
1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
2010, 2011, 2012, 2013
Free Software Foundation, Inc.
Permission is granted to copy, distribute and/or modify this document Permission is granted to copy, distribute and/or modify this document
under the terms of the GNU Free Documentation License, Version 1.3 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 @cindex thin archives
@sc{gnu} @command{ar} can optionally create a @emph{thin} archive, @sc{gnu} @command{ar} can optionally create a @emph{thin} archive,
which contains a symbol index and references to the original copies which contains a symbol index and references to the original copies
of the member files of the archives. Such an archive is useful of the member files of the archive. This is useful for building
for building libraries for use within a local build, where the libraries for use within a local build tree, where the relocatable
relocatable objects are expected to remain available, and copying the objects are expected to remain available, and copying the contents of
contents of each object would only waste time and space. Thin archives each object would only waste time and space.
are also @emph{flattened}, so that adding one or more archives to a
thin archive will add the elements of the nested archive individually. 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 The paths to the elements of the archive are stored relative to the
archive itself. archive itself.

View File

@ -1,6 +1,5 @@
/* elfcomm.c -- common code for ELF format file. /* elfcomm.c -- common code for ELF format file.
Copyright 2010 Copyright 2010-2013 Free Software Foundation, Inc.
Free Software Foundation, Inc.
Originally developed by Eric Youngdale <eric@andante.jic.com> Originally developed by Eric Youngdale <eric@andante.jic.com>
Modifications by Nick Clifton <nickc@redhat.com> Modifications by Nick Clifton <nickc@redhat.com>
@ -690,12 +689,20 @@ make_qualified_name (struct archive_info * arch,
struct archive_info * nested_arch, struct archive_info * nested_arch,
const char *member_name) const char *member_name)
{ {
const char * error_name = _("<corrupt>");
size_t len; size_t len;
char * name; char * name;
len = strlen (arch->file_name) + strlen (member_name) + 3; len = strlen (arch->file_name) + strlen (member_name) + 3;
if (arch->is_thin_archive && arch->nested_member_origin != 0) 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; len += strlen (nested_arch->file_name) + 2;
else
len += strlen (error_name) + 2;
}
name = (char *) malloc (len); name = (char *) malloc (len);
if (name == NULL) if (name == NULL)
@ -704,9 +711,16 @@ make_qualified_name (struct archive_info * arch,
return NULL; return NULL;
} }
if (arch->is_thin_archive && arch->nested_member_origin != 0) if (arch->is_thin_archive
&& arch->nested_member_origin != 0)
{
if (nested_arch->file_name)
snprintf (name, len, "%s[%s(%s)]", arch->file_name, snprintf (name, len, "%s[%s(%s)]", arch->file_name,
nested_arch->file_name, member_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) else if (arch->is_thin_archive)
snprintf (name, len, "%s[%s]", arch->file_name, member_name); snprintf (name, len, "%s[%s]", arch->file_name, member_name);
else else

View File

@ -13975,6 +13975,15 @@ process_archive (char * file_name, FILE * file, bfd_boolean is_thin_archive)
} }
else if (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. */ /* This is a proxy for a member of a nested archive. */
archive_file_offset = arch.nested_member_origin + sizeof arch.arhdr; archive_file_offset = arch.nested_member_origin + sizeof arch.arhdr;