Limit bogus archive parsed_size
authorAlan Modra <amodra@gmail.com>
Tue, 25 Feb 2020 02:18:43 +0000 (12:48 +1030)
committerAlan Modra <amodra@gmail.com>
Wed, 26 Feb 2020 00:07:13 +0000 (10:37 +1030)
Archive element size is given by data in the archive, and thus is
subject to attack by fuzzers.  The only harm this allows is allocation
of huge amounts of memory, but some systems don't handle that well.
So limit archive element size to archive file size.

* bfdio.c (bfd_get_file_size): Ignore bogus archive element sizes.

bfd/ChangeLog
bfd/bfdio.c

index 7e8e454632ce6bb2802ec19f7698798044ba4f50..5855df7c6b32bda879bf85553ef5a88f11ef760b 100644 (file)
@@ -1,3 +1,7 @@
+2020-02-26  Alan Modra  <amodra@gmail.com>
+
+       * bfdio.c (bfd_get_file_size): Ignore bogus archive element sizes.
+
 2020-02-25  H.J. Lu  <hongjiu.lu@intel.com>
 
        PR binutils/25584
index 49e09585264daeb43512a5cc16f02a9f1c434a0c..71ac17ec51515e157214769d8efb5fc45971d3df 100644 (file)
@@ -25,6 +25,7 @@
 #include <limits.h>
 #include "bfd.h"
 #include "libbfd.h"
+#include "aout/ar.h"
 
 #ifndef S_IXUSR
 #define S_IXUSR 0100    /* Execute by owner.  */
@@ -460,11 +461,24 @@ DESCRIPTION
 ufile_ptr
 bfd_get_file_size (bfd *abfd)
 {
+  ufile_ptr file_size, archive_size = (ufile_ptr) -1;
+
   if (abfd->my_archive != NULL
       && !bfd_is_thin_archive (abfd->my_archive))
-    return arelt_size (abfd);
+    {
+      struct areltdata *adata = (struct areltdata *) abfd->arelt_data;
+      archive_size = adata->parsed_size;
+      /* If the archive is compressed we can't compare against file size.  */
+      if (memcmp (((struct ar_hdr *) adata->arch_header)->ar_fmag,
+                 "Z\012", 2) == 0)
+       return archive_size;
+      abfd = abfd->my_archive;
+    }
 
-  return bfd_get_size (abfd);
+  file_size = bfd_get_size (abfd);
+  if (archive_size < file_size)
+    return archive_size;
+  return file_size;
 }
 
 /*