From 463ec189fe9eca199edf87cda2c31efbe850390d Mon Sep 17 00:00:00 2001
From: Nick Clifton <nickc@redhat.com>
Date: Wed, 3 Jun 2020 15:16:48 +0100
Subject: [PATCH] Prevent a potential use-after-fee memory corruption bug in
 the linker (for PE format files).

	PR 25993
	* emultempl/pe.em (_after_open): Check for duplicate filename
	pointers before renaming the dll.
	* emultempl/pep.em (_after_open): Likewise.
---
 ld/emultempl/pe.em  | 25 +++++++++++++++++++------
 ld/emultempl/pep.em | 25 +++++++++++++++++++------
 3 files changed, 48 insertions(+), 12 deletions(-)

diff --git a/ld/emultempl/pe.em b/ld/emultempl/pe.em
index 97fb1468aa..26fa7465c0 100644
--- a/ld/emultempl/pe.em
+++ b/ld/emultempl/pe.em
@@ -1652,13 +1652,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;
+		  }
 	      }
 	  }
       }
diff --git a/ld/emultempl/pep.em b/ld/emultempl/pep.em
index e8f5ca503f..ef23221c03 100644
--- a/ld/emultempl/pep.em
+++ b/ld/emultempl/pep.em
@@ -1620,13 +1620,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;
+		  }
 	      }
 	  }
       }
-- 
2.27.0