From eaf1fa5ac5972efe5041c835c3ac9fec3c6aa06c Mon Sep 17 00:00:00 2001
From: Alan Modra <amodra@gmail.com>
Date: Thu, 3 Aug 2023 08:40:12 +0930
Subject: ld: sprintf sanitizer null destination pointer

	* configure.ac (stpcpy): AC_CHECK_DECLS.
	* sysdep.h (stpcpy): Add fallback declaraion.
	* config.in: Regenerate.
	* configure: Regenerate.
	* emultempl/pe.em (open_dynamic_archive): Use
	stpcpy rather than sprintf plus strlen.
	* emultempl/pep.em (open_dynamic_archive): Likewise.
	* emultempl/xtensaelf.em (elf_xtensa_before_allocation): Use
	auto rather than malloc'd buffer.  Use sprintf count.
	* ldelf.c (ldelf_search_needed): Use memcpy in place of sprintf.
	* pe-dll.c (pe_process_import_defs): Use string already formed
	for alias match rather than recreating.
---
 ld/config.in              |  4 ++++
 ld/configure              | 10 ++++++++++
 ld/configure.ac           |  2 +-
 ld/emultempl/pe.em        |  4 ++--
 ld/emultempl/pep.em       |  4 ++--
 ld/emultempl/xtensaelf.em | 10 ++++------
 ld/ldelf.c                | 11 +++++++----
 ld/pe-dll.c               | 18 ++++++++----------
 ld/sysdep.h               |  4 ++++
 9 files changed, 42 insertions(+), 25 deletions(-)

(limited to 'ld')

diff --git a/ld/config.in b/ld/config.in
index ad0dc6a..a453c7f 100644
--- a/ld/config.in
+++ b/ld/config.in
@@ -78,6 +78,10 @@
 /* Is the prototype for getopt in <unistd.h> in the expected format? */
 #undef HAVE_DECL_GETOPT
 
+/* Define to 1 if you have the declaration of `stpcpy', and to 0 if you don't.
+   */
+#undef HAVE_DECL_STPCPY
+
 /* Define to 1 if you have the <dlfcn.h> header file. */
 #undef HAVE_DLFCN_H
 
diff --git a/ld/configure b/ld/configure
index 33e09fc..a4fcb9b 100755
--- a/ld/configure
+++ b/ld/configure
@@ -16771,6 +16771,16 @@ fi
 cat >>confdefs.h <<_ACEOF
 #define HAVE_DECL_ENVIRON $ac_have_decl
 _ACEOF
+ac_fn_c_check_decl "$LINENO" "stpcpy" "ac_cv_have_decl_stpcpy" "$ac_includes_default"
+if test "x$ac_cv_have_decl_stpcpy" = xyes; then :
+  ac_have_decl=1
+else
+  ac_have_decl=0
+fi
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_DECL_STPCPY $ac_have_decl
+_ACEOF
 
 
 
diff --git a/ld/configure.ac b/ld/configure.ac
index 217ef7b..14628e5 100644
--- a/ld/configure.ac
+++ b/ld/configure.ac
@@ -371,7 +371,7 @@ AC_CHECK_FUNCS(close glob lseek mkstemp open realpath waitpid)
 
 BFD_BINARY_FOPEN
 
-AC_CHECK_DECLS([asprintf, environ])
+AC_CHECK_DECLS([asprintf, environ, stpcpy])
 
 AC_FUNC_MMAP
 
diff --git a/ld/emultempl/pe.em b/ld/emultempl/pe.em
index cd2abe4..a583b02 100644
--- a/ld/emultempl/pe.em
+++ b/ld/emultempl/pe.em
@@ -2464,8 +2464,8 @@ gld${EMULATION_NAME}_open_dynamic_archive
 			    search->name and the start of the format string.  */
 			 + 2);
 
-  sprintf (full_string, "%s/", search->name);
-  base_string = full_string + strlen (full_string);
+  base_string = stpcpy (full_string, search->name);
+  *base_string++ = '/';
 
   for (i = 0; libname_fmt[i].format; i++)
     {
diff --git a/ld/emultempl/pep.em b/ld/emultempl/pep.em
index 28d8c8d..516d2af 100644
--- a/ld/emultempl/pep.em
+++ b/ld/emultempl/pep.em
@@ -2295,8 +2295,8 @@ gld${EMULATION_NAME}_open_dynamic_archive
 			    search->name and the start of the format string.  */
 			 + 2);
 
-  sprintf (full_string, "%s/", search->name);
-  base_string = full_string + strlen (full_string);
+  base_string = stpcpy (full_string, search->name);
+  *base_string++ = '/';
 
   for (i = 0; libname_fmt[i].format; i++)
     {
diff --git a/ld/emultempl/xtensaelf.em b/ld/emultempl/xtensaelf.em
index 4cb9bda..f2d10b5 100644
--- a/ld/emultempl/xtensaelf.em
+++ b/ld/emultempl/xtensaelf.em
@@ -490,15 +490,14 @@ elf_xtensa_before_allocation (void)
   if (info_sec)
     {
       int xtensa_info_size;
-      char *data;
+      char data[100];
 
       info_sec->flags &= ~SEC_EXCLUDE;
       info_sec->flags |= SEC_IN_MEMORY;
 
-      data = xmalloc (100);
-      sprintf (data, "USE_ABSOLUTE_LITERALS=%d\nABI=%d\n",
-	       XSHAL_USE_ABSOLUTE_LITERALS, xtensa_abi_choice ());
-      xtensa_info_size = strlen (data) + 1;
+      xtensa_info_size
+	= 1 + sprintf (data, "USE_ABSOLUTE_LITERALS=%d\nABI=%d\n",
+		       XSHAL_USE_ABSOLUTE_LITERALS, xtensa_abi_choice ());
 
       /* Add enough null terminators to pad to a word boundary.  */
       do
@@ -512,7 +511,6 @@ elf_xtensa_before_allocation (void)
       bfd_put_32 (info_sec->owner, XTINFO_TYPE, info_sec->contents + 8);
       memcpy (info_sec->contents + 12, XTINFO_NAME, XTINFO_NAMESZ);
       memcpy (info_sec->contents + 12 + XTINFO_NAMESZ, data, xtensa_info_size);
-      free (data);
     }
 
   /* Enable relaxation by default if the "--no-relax" option was not
diff --git a/ld/ldelf.c b/ld/ldelf.c
index f9a6819..23a014d 100644
--- a/ld/ldelf.c
+++ b/ld/ldelf.c
@@ -524,10 +524,13 @@ ldelf_search_needed (const char *path, struct dt_needed *n, int force,
 		      else
 			{
 			  char * current_dir = getpwd ();
-
-			  freeme = xmalloc (strlen (replacement)
-					    + strlen (current_dir) + 2);
-			  sprintf (freeme, "%s/%s", current_dir, replacement);
+			  size_t cdir_len = strlen (current_dir);
+			  size_t rep_len = strlen (replacement);
+			  freeme = xmalloc (cdir_len + rep_len + 2);
+			  memcpy (freeme, current_dir, cdir_len);
+			  freeme[cdir_len] = '/';
+			  memcpy (freeme + cdir_len + 1,
+				  replacement, rep_len + 1);
 			}
 
 		      replacement = freeme;
diff --git a/ld/pe-dll.c b/ld/pe-dll.c
index a95b85c..b45c530 100644
--- a/ld/pe-dll.c
+++ b/ld/pe-dll.c
@@ -3340,6 +3340,14 @@ pe_process_import_defs (bfd *output_bfd, struct bfd_link_info *linfo)
 					       false, false, false);
 		  if (blhe)
 		    is_undef = (blhe->type == bfd_link_hash_undefined);
+
+		  if (is_cdecl && (!blhe || !is_undef))
+		    {
+		      blhe = pe_find_cdecl_alias_match (linfo, name + 6);
+		      include_jmp_stub = true;
+		      if (blhe)
+			is_undef = (blhe->type == bfd_link_hash_undefined);
+		    }
 		}
 	      else
 		{
@@ -3347,16 +3355,6 @@ pe_process_import_defs (bfd *output_bfd, struct bfd_link_info *linfo)
 		  is_undef = (blhe->type == bfd_link_hash_undefined);
 		}
 
-	      if (is_cdecl
-		  && (!blhe || (blhe && blhe->type != bfd_link_hash_undefined)))
-		{
-		  sprintf (name, "%s%s",U (""), imp[i].internal_name);
-		  blhe = pe_find_cdecl_alias_match (linfo, name);
-		  include_jmp_stub = true;
-		  if (blhe)
-		    is_undef = (blhe->type == bfd_link_hash_undefined);
-		}
-
 	      free (name);
 
 	      if (is_undef)
diff --git a/ld/sysdep.h b/ld/sysdep.h
index 3601a59..1573d5e 100644
--- a/ld/sysdep.h
+++ b/ld/sysdep.h
@@ -92,6 +92,10 @@
 extern char **environ;
 #endif
 
+#if !HAVE_DECL_STPCPY
+extern char *stpcpy (char *__dest, const char *__src);
+#endif
+
 #define POISON_BFD_BOOLEAN 1
 
 #endif /* ! defined (LD_SYSDEP_H) */
-- 
cgit v1.1