PR24236, Heap buffer overflow in _bfd_archive_64_bit_slurp_armap
authorAlan Modra <amodra@gmail.com>
Tue, 19 Feb 2019 21:51:24 +0000 (08:21 +1030)
committerAlan Modra <amodra@gmail.com>
Wed, 20 Feb 2019 01:20:07 +0000 (11:50 +1030)
PR 24236
* archive64.c (_bfd_archive_64_bit_slurp_armap): Move code adding
sentinel NUL to string buffer nearer to loop where it is used.
Don't go past sentinel when scanning strings, and don't write
NUL again.
* archive.c (do_slurp_coff_armap): Simplify string handling to
archive64.c style.

bfd/ChangeLog
bfd/archive.c
bfd/archive64.c

index 72c87c78a29a4d5fb4dc4ee6f78e1c3b1b0c6f42..e39bb1264cb9e550bea1620d1114094905f07c6c 100644 (file)
@@ -1,3 +1,13 @@
+2019-02-20  Alan Modra  <amodra@gmail.com>
+
+       PR 24236
+       * archive64.c (_bfd_archive_64_bit_slurp_armap): Move code adding
+       sentinel NUL to string buffer nearer to loop where it is used.
+       Don't go past sentinel when scanning strings, and don't write
+       NUL again.
+       * archive.c (do_slurp_coff_armap): Simplify string handling to
+       archive64.c style.
+
 2019-02-19  Alan Modra  <amodra@gmail.com>
 
        PR 24235
index d2d9b728d845ffbbe110aa911fb636b053fe68f1..68a92a3e36314959661ae44bfcf6e2cc3bf2fb64 100644 (file)
@@ -1012,6 +1012,7 @@ do_slurp_coff_armap (bfd *abfd)
   int *raw_armap, *rawptr;
   struct artdata *ardata = bfd_ardata (abfd);
   char *stringbase;
+  char *stringend;
   bfd_size_type stringsize;
   bfd_size_type parsed_size;
   carsym *carsyms;
@@ -1071,22 +1072,18 @@ do_slurp_coff_armap (bfd *abfd)
     }
 
   /* OK, build the carsyms.  */
-  for (i = 0; i < nsymz && stringsize > 0; i++)
+  stringend = stringbase + stringsize;
+  *stringend = 0;
+  for (i = 0; i < nsymz; i++)
     {
-      bfd_size_type len;
-
       rawptr = raw_armap + i;
       carsyms->file_offset = swap ((bfd_byte *) rawptr);
       carsyms->name = stringbase;
-      /* PR 17512: file: 4a1d50c1.  */
-      len = strnlen (stringbase, stringsize);
-      if (len < stringsize)
-       len ++;
-      stringbase += len;
-      stringsize -= len;
+      stringbase += strlen (stringbase);
+      if (stringbase != stringend)
+       ++stringbase;
       carsyms++;
     }
-  *stringbase = 0;
 
   ardata->symdef_count = nsymz;
   ardata->first_file_filepos = bfd_tell (abfd);
index 312bf823ebe907401c1c9ea251ca4492918e29cd..42f6ed92f095fb5cc404801b9d897bc7669bab41 100644 (file)
@@ -100,8 +100,6 @@ _bfd_archive_64_bit_slurp_armap (bfd *abfd)
     return FALSE;
   carsyms = ardata->symdefs;
   stringbase = ((char *) ardata->symdefs) + carsym_size;
-  stringbase[stringsize] = 0;
-  stringend = stringbase + stringsize;
 
   raw_armap = (bfd_byte *) bfd_alloc (abfd, ptrsize);
   if (raw_armap == NULL)
@@ -115,15 +113,17 @@ _bfd_archive_64_bit_slurp_armap (bfd *abfd)
       goto release_raw_armap;
     }
 
+  stringend = stringbase + stringsize;
+  *stringend = 0;
   for (i = 0; i < nsymz; i++)
     {
       carsyms->file_offset = bfd_getb64 (raw_armap + i * 8);
       carsyms->name = stringbase;
-      if (stringbase < stringend)
-       stringbase += strlen (stringbase) + 1;
+      stringbase += strlen (stringbase);
+      if (stringbase != stringend)
+       ++stringbase;
       ++carsyms;
     }
-  *stringbase = '\0';
 
   ardata->symdef_count = nsymz;
   ardata->first_file_filepos = bfd_tell (abfd);