macho-o archive sanity checks
authorAlan Modra <amodra@gmail.com>
Mon, 1 Nov 2021 08:25:19 +0000 (18:55 +1030)
committerAlan Modra <amodra@gmail.com>
Mon, 1 Nov 2021 12:00:33 +0000 (22:30 +1030)
Anti-fuzzing checks.

* mach-o.c (bfd_mach_o_fat_archive_p): Sanity check entry offset
and size against file size.

bfd/mach-o.c

index 31a109b17a8b7dd0503c13665e605d00864f8705..1f0d47008110a78a74ab86faef11ae696a86791e 100644 (file)
@@ -5509,6 +5509,7 @@ bfd_mach_o_fat_archive_p (bfd *abfd)
   struct mach_o_fat_header_external hdr;
   unsigned long i;
   size_t amt;
+  ufile_ptr filesize;
 
   if (bfd_seek (abfd, 0, SEEK_SET) != 0
       || bfd_bread (&hdr, sizeof (hdr), abfd) != sizeof (hdr))
@@ -5538,6 +5539,7 @@ bfd_mach_o_fat_archive_p (bfd *abfd)
   if (adata->archentries == NULL)
     goto error;
 
+  filesize = bfd_get_file_size (abfd);
   for (i = 0; i < adata->nfat_arch; i++)
     {
       struct mach_o_fat_arch_external arch;
@@ -5548,6 +5550,15 @@ bfd_mach_o_fat_archive_p (bfd *abfd)
       adata->archentries[i].offset = bfd_getb32 (arch.offset);
       adata->archentries[i].size = bfd_getb32 (arch.size);
       adata->archentries[i].align = bfd_getb32 (arch.align);
+      if (filesize != 0
+         && (adata->archentries[i].offset > filesize
+             || (adata->archentries[i].size
+                 > filesize - adata->archentries[i].offset)))
+       {
+         bfd_release (abfd, adata);
+         bfd_set_error (bfd_error_malformed_archive);
+         return NULL;
+       }
     }
 
   abfd->tdata.mach_o_fat_data = adata;