PR binutils/15140
authorNick Clifton <nickc@redhat.com>
Fri, 15 Feb 2013 14:37:39 +0000 (14:37 +0000)
committerNick Clifton <nickc@redhat.com>
Fri, 15 Feb 2013 14:37:39 +0000 (14:37 +0000)
* 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.

bfd/ChangeLog
bfd/archive.c
binutils/ChangeLog
binutils/ar.c
binutils/doc/binutils.texi
binutils/elfcomm.c
binutils/readelf.c

index 21c9396..b65b234 100644 (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.
index e4183ea..4b6a81c 100644 (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))
     {
index d2e6dd0..06f5dd5 100644 (file)
@@ -4,6 +4,17 @@
 
 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
        * objcopy.c (enum change_action): Delete.
        (struct section_list): Delete remove, copy, change_vma, change_lma
index 0aa1ba3..c424038 100644 (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);
index d733fdb..0bb1d92 100644 (file)
 
 @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.
 
index 64d4b21..1179a1a 100644 (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
index 7710079..c7bd05f 100644 (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;