Overlarge allocation in _bfd_generic_read_ar_hdr_mag
authorAlan Modra <amodra@gmail.com>
Tue, 24 Mar 2020 06:56:40 +0000 (17:26 +1030)
committerAlan Modra <amodra@gmail.com>
Tue, 24 Mar 2020 08:30:35 +0000 (19:00 +1030)
* archive.c (_bfd_generic_read_ar_hdr_mag): Sanity check extended
name size.  Use bfd_malloc rather than bfd_zmalloc, clearing just
struct areltdata.

bfd/ChangeLog
bfd/archive.c

index b5e0f2822e0207d8faecfefede7e31c5046c3a2a..da8e05894f07729454a083374043a3edd8bce452 100644 (file)
@@ -1,3 +1,9 @@
+2020-03-24  Alan Modra  <amodra@gmail.com>
+
+       * archive.c (_bfd_generic_read_ar_hdr_mag): Sanity check extended
+       name size.  Use bfd_malloc rather than bfd_zmalloc, clearing just
+       struct areltdata.
+
 2020-03-23  Sebastian Huber  <sebastian.huber@embedded-brains.de>
 
        * elflink.c (_bfd_elf_tls_setup): Mention .tdata in comment.
index 0c009f10de876b8374141d84b6540252b1f93e3c..3423a336956a211eb707d0f2bff724e52ca6b12c 100644 (file)
@@ -488,6 +488,7 @@ _bfd_generic_read_ar_hdr_mag (bfd *abfd, const char *mag)
   bfd_size_type parsed_size;
   struct areltdata *ared;
   char *filename = NULL;
+  ufile_ptr filesize;
   bfd_size_type namelen = 0;
   bfd_size_type allocsize = sizeof (struct areltdata) + sizeof (struct ar_hdr);
   char *allocptr = 0;
@@ -538,11 +539,19 @@ _bfd_generic_read_ar_hdr_mag (bfd *abfd, const char *mag)
     {
       /* BSD-4.4 extended name */
       namelen = atoi (&hdr.ar_name[3]);
+      filesize = bfd_get_file_size (abfd);
+      if (namelen > parsed_size
+         || namelen > -allocsize - 2
+         || (filesize != 0 && namelen > filesize))
+       {
+         bfd_set_error (bfd_error_malformed_archive);
+         return NULL;
+       }
       allocsize += namelen + 1;
       parsed_size -= namelen;
       extra_size = namelen;
 
-      allocptr = (char *) bfd_zmalloc (allocsize);
+      allocptr = (char *) bfd_malloc (allocsize);
       if (allocptr == NULL)
        return NULL;
       filename = (allocptr
@@ -586,13 +595,13 @@ _bfd_generic_read_ar_hdr_mag (bfd *abfd, const char *mag)
 
   if (!allocptr)
     {
-      allocptr = (char *) bfd_zmalloc (allocsize);
+      allocptr = (char *) bfd_malloc (allocsize);
       if (allocptr == NULL)
        return NULL;
     }
 
+  memset (allocptr, 0, sizeof (struct areltdata));
   ared = (struct areltdata *) allocptr;
-
   ared->arch_header = allocptr + sizeof (struct areltdata);
   memcpy (ared->arch_header, &hdr, sizeof (struct ar_hdr));
   ared->parsed_size = parsed_size;