Prevent looping in archives
authorAlan Modra <amodra@gmail.com>
Wed, 18 Nov 2015 11:42:23 +0000 (22:12 +1030)
committerAlan Modra <amodra@gmail.com>
Wed, 18 Nov 2015 11:46:24 +0000 (22:16 +1030)
PR 19256
* archive.c (bfd_generic_openr_next_archived_file): Don't allow
backward file movement via "negative" sizes.
* coff-alpha.c (alpha_ecoff_openr_next_archived_file): Likewise.

bfd/ChangeLog
bfd/archive.c
bfd/coff-alpha.c

index 46a2cafdc827fe13dc13a3ba3d70637af9497bbf..b70456dceefc3a7f2e634dd33da40de5ff15192e 100644 (file)
@@ -1,3 +1,10 @@
+2015-11-18  Alan Modra  <amodra@gmail.com>
+
+       PR 19256
+       * archive.c (bfd_generic_openr_next_archived_file): Don't allow
+       backward file movement via "negative" sizes.
+       * coff-alpha.c (alpha_ecoff_openr_next_archived_file): Likewise.
+
 2015-11-18  Tristan Gingold  <gingold@adacore.com>
 
        * mach-o.h (struct mach_o_data_struct): Add hdr_offset field.
index 1715474ea6cecd9bcdb8378bdf933036139843d6..b3d03d36daf62ddfa40d33fd9bb489172c29c630 100644 (file)
@@ -786,21 +786,29 @@ bfd_openr_next_archived_file (bfd *archive, bfd *last_file)
 bfd *
 bfd_generic_openr_next_archived_file (bfd *archive, bfd *last_file)
 {
-  file_ptr filestart;
+  ufile_ptr filestart;
 
   if (!last_file)
     filestart = bfd_ardata (archive)->first_file_filepos;
   else
     {
-      bfd_size_type size = arelt_size (last_file);
-
       filestart = last_file->proxy_origin;
       if (! bfd_is_thin_archive (archive))
-       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.  */
-      filestart += filestart % 2;
+       {
+         bfd_size_type size = arelt_size (last_file);
+
+         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.  */
+         filestart += filestart % 2;
+         if (filestart <= last_file->proxy_origin)
+           {
+             /* Prevent looping.  See PR19256.  */
+             bfd_set_error (bfd_error_malformed_archive);
+             return NULL;
+           }
+       }
     }
 
   return _bfd_get_elt_at_filepos (archive, filestart);
index 58d4e1d1fbe536db2255cd811baa24d0e4ddef70..7478f2f320d39a81f2d390de36ce44b42fd756ba 100644 (file)
@@ -2187,7 +2187,7 @@ alpha_ecoff_get_elt_at_filepos (bfd *archive, file_ptr filepos)
 static bfd *
 alpha_ecoff_openr_next_archived_file (bfd *archive, bfd *last_file)
 {
-  file_ptr filestart;
+  ufile_ptr filestart;
 
   if (last_file == NULL)
     filestart = bfd_ardata (archive)->first_file_filepos;
@@ -2208,6 +2208,12 @@ alpha_ecoff_openr_next_archived_file (bfd *archive, bfd *last_file)
         BSD-4.4-style element with a long odd size.  */
       filestart = last_file->proxy_origin + size;
       filestart += filestart % 2;
+      if (filestart <= last_file->proxy_origin)
+       {
+         /* Prevent looping.  See PR19256.  */
+         bfd_set_error (bfd_error_malformed_archive);
+         return NULL;
+       }
     }
 
   return alpha_ecoff_get_elt_at_filepos (archive, filestart);