Prevent a potential use-after-fee memory corruption bug in the linker (for PE format...
authorNick Clifton <nickc@redhat.com>
Mon, 18 May 2020 09:28:52 +0000 (10:28 +0100)
committerNick Clifton <nickc@redhat.com>
Mon, 18 May 2020 09:28:52 +0000 (10:28 +0100)
PR 25993
* emultempl/pe.em (_after_open): Check for duplicate filename
pointers before renaming the dll.
* emultempl/pep.em (_after_open): Likewise.

ld/ChangeLog
ld/emultempl/pe.em
ld/emultempl/pep.em

index 5923e4ca36bc03f211f783c659851322a9470263..49c697023d8a2d4eb2b62341bc186cf139776a42 100644 (file)
@@ -1,3 +1,10 @@
+2020-05-18  Nick Clifton  <nickc@redhat.com>
+
+       PR 25993
+       * emultempl/pe.em (_after_open): Check for duplicate filename
+       pointers before renaming the dll.
+       * emultempl/pep.em (_after_open): Likewise.
+
 2020-05-13  Nick Clifton  <nickc@redhat.com>
 
        PR 25979
index 4fe195ec32abc4eab650121bc7198f1ce1f8bd75..ad5d65d024a52c349b0a95ba91abb6a5f207f3d2 100644 (file)
@@ -1655,13 +1655,27 @@ gld_${EMULATION_NAME}_after_open (void)
                else /* sentinel */
                  seq = 'c';
 
-               new_name = xmalloc (strlen (is->the_bfd->filename) + 3);
-               sprintf (new_name, "%s.%c", is->the_bfd->filename, seq);
-               bfd_set_filename (is->the_bfd, new_name);
 
-               new_name = xmalloc (strlen (is->filename) + 3);
-               sprintf (new_name, "%s.%c", is->filename, seq);
-               is->filename = new_name;
+               /* PR 25993: It is possible that is->the_bfd-filename == is->filename.
+                  In which case calling bfd_set_filename on one will free the memory
+                  pointed to by the other.  */
+               if (is->filename == is->the_bfd->filename)
+                 {
+                   new_name = xmalloc (strlen (is->filename) + 3);
+                   sprintf (new_name, "%s.%c", is->filename, seq);
+                   bfd_set_filename (is->the_bfd, new_name);
+                   is->filename = new_name;
+                 }
+               else
+                 {
+                   new_name = xmalloc (strlen (is->the_bfd->filename) + 3);
+                   sprintf (new_name, "%s.%c", is->the_bfd->filename, seq);
+                   bfd_set_filename (is->the_bfd, new_name);
+
+                   new_name = xmalloc (strlen (is->filename) + 3);
+                   sprintf (new_name, "%s.%c", is->filename, seq);
+                   is->filename = new_name;
+                 }
              }
          }
       }
index 3e03eb3a6e0f40135f67abfc3355d5aadc1fabea..aa8bac5f8163279ab31918d4aa9a0d08425b9e17 100644 (file)
@@ -1623,13 +1623,26 @@ gld_${EMULATION_NAME}_after_open (void)
                else /* sentinel */
                  seq = 'c';
 
-               new_name = xmalloc (strlen (is->the_bfd->filename) + 3);
-               sprintf (new_name, "%s.%c", is->the_bfd->filename, seq);
-               bfd_set_filename (is->the_bfd, new_name);
+               /* PR 25993: It is possible that is->the_bfd-filename == is->filename.
+                  In which case calling bfd_set_filename on one will free the memory
+                  pointed to by the other.  */
+               if (is->filename == is->the_bfd->filename)
+                 {
+                   new_name = xmalloc (strlen (is->filename) + 3);
+                   sprintf (new_name, "%s.%c", is->filename, seq);
+                   bfd_set_filename (is->the_bfd, new_name);
+                   is->filename = new_name;
+                 }
+               else
+                 {
+                   new_name = xmalloc (strlen (is->the_bfd->filename) + 3);
+                   sprintf (new_name, "%s.%c", is->the_bfd->filename, seq);
+                   bfd_set_filename (is->the_bfd, new_name);
 
-               new_name = xmalloc (strlen (is->filename) + 3);
-               sprintf (new_name, "%s.%c", is->filename, seq);
-               is->filename = new_name;
+                   new_name = xmalloc (strlen (is->filename) + 3);
+                   sprintf (new_name, "%s.%c", is->filename, seq);
+                   is->filename = new_name;
+                 }
              }
          }
       }