Yet another out-of-memory fuzzed object
authorAlan Modra <amodra@gmail.com>
Wed, 19 Apr 2023 13:02:15 +0000 (22:32 +0930)
committerAlan Modra <amodra@gmail.com>
Wed, 19 Apr 2023 23:33:53 +0000 (09:03 +0930)
Do I care about out of memory conditions triggered by fuzzers?  Not
much.  Your operating system ought to be able to handle it by killing
the memory hog.  Oh well, this one was an element of a coff-alpha
archive that said it was a little less that 2**64 in size.  The
coff-alpha compression scheme expands at most 8 times, so we can do
better in bfd_get_file_size.

* bfdio.c (bfd_get_file_size): Assume elements in compressed
archive can only expand a maximum of eight times.
* coffgen.c (_bfd_coff_get_external_symbols): Sanity check
size of symbol table agains file size.

bfd/bfdio.c
bfd/coffgen.c

index 337d4a10b66aa121e459a342f1967ce1ffaf6700..990d349d4284049f8db55c40e082b548b85c6a86 100644 (file)
@@ -524,6 +524,7 @@ ufile_ptr
 bfd_get_file_size (bfd *abfd)
 {
   ufile_ptr file_size, archive_size = (ufile_ptr) -1;
+  unsigned int compression_p2 = 0;
 
   if (abfd->my_archive != NULL
       && !bfd_is_thin_archive (abfd->my_archive))
@@ -532,17 +533,17 @@ bfd_get_file_size (bfd *abfd)
       if (adata != NULL)
        {
          archive_size = adata->parsed_size;
-         /* If the archive is compressed we can't compare against
-            file size.  */
+         /* If the archive is compressed, assume an element won't
+            expand more than eight times file size.  */
          if (adata->arch_header != NULL
              && memcmp (((struct ar_hdr *) adata->arch_header)->ar_fmag,
                         "Z\012", 2) == 0)
-           return archive_size;
+           compression_p2 = 3;
          abfd = abfd->my_archive;
        }
     }
 
-  file_size = bfd_get_size (abfd);
+  file_size = bfd_get_size (abfd) << compression_p2;
   if (archive_size < file_size)
     return archive_size;
   return file_size;
index 4725406b5aeb3c2a1feb8fc0137fbafa1affef5d..05f2640abe2e82e7b80d41ac4cc3808c0a78c905 100644 (file)
@@ -1551,6 +1551,7 @@ _bfd_coff_get_external_symbols (bfd *abfd)
   size_t symesz;
   size_t size;
   void * syms;
+  ufile_ptr filesize;
 
   if (obj_coff_external_syms (abfd) != NULL)
     return true;
@@ -1565,6 +1566,15 @@ _bfd_coff_get_external_symbols (bfd *abfd)
   if (size == 0)
     return true;
 
+  filesize = bfd_get_file_size (abfd);
+  if (filesize != 0
+      && ((ufile_ptr) obj_sym_filepos (abfd) > filesize
+         || size > filesize - obj_sym_filepos (abfd)))
+    {
+      bfd_set_error (bfd_error_file_truncated);
+      return false;
+    }
+
   if (bfd_seek (abfd, obj_sym_filepos (abfd), SEEK_SET) != 0)
     return false;
   syms = _bfd_malloc_and_read (abfd, size, size);