$OpenBSD: patch-gettext-runtime_intl_dcigettext_c,v 1.10 2020/08/20 21:03:25 naddy Exp $
Index: gettext-runtime/intl/dcigettext.c
--- gettext-runtime/intl/dcigettext.c.orig
+++ gettext-runtime/intl/dcigettext.c
@@ -494,6 +494,7 @@ DCIGETTEXT (const char *domainname, const char *msgid1
   const char *localename;
 #endif
   size_t domainname_len;
+  size_t xdomainname_len;
 
   /* If no real MSGID is given return NULL.  */
   if (msgid1 == NULL)
@@ -685,6 +686,7 @@ DCIGETTEXT (const char *domainname, const char *msgid1
 	  /* We have a relative path.  Make it absolute now.  */
 	  size_t dirname_len = strlen (dirname) + 1;
 	  size_t path_max;
+	  size_t resolved_dirname_len;
 	  char *resolved_dirname;
 	  char *ret;
 
@@ -693,7 +695,8 @@ DCIGETTEXT (const char *domainname, const char *msgid1
 
 	  for (;;)
 	    {
-	      resolved_dirname = (char *) alloca (path_max + dirname_len);
+	      resolved_dirname_len = path_max + dirname_len;
+	      resolved_dirname = (char *) alloca (resolved_dirname_len);
 	      ADD_BLOCK (block_list, resolved_dirname);
 
 	      __set_errno (0);
@@ -710,7 +713,8 @@ DCIGETTEXT (const char *domainname, const char *msgid1
 	       error but simply return the default string.  */
 	    goto return_untranslated;
 
-	  stpcpy (stpcpy (strchr (resolved_dirname, '\0'), "/"), dirname);
+	  strlcat (resolved_dirname, "/", resolved_dirname_len);
+	  strlcat (resolved_dirname, dirname, resolved_dirname_len);
 	  dirname = resolved_dirname;
 	}
 #endif
@@ -729,13 +733,14 @@ DCIGETTEXT (const char *domainname, const char *msgid1
 #endif
 
   domainname_len = strlen (domainname);
-  xdomainname = (char *) alloca (strlen (categoryname)
-				 + domainname_len + 5);
+  xdomainname_len = strlen (categoryname) + domainname_len + 5;
+  xdomainname = (char *) alloca (xdomainname_len);
   ADD_BLOCK (block_list, xdomainname);
 
-  stpcpy ((char *) mempcpy (stpcpy (stpcpy (xdomainname, categoryname), "/"),
-			    domainname, domainname_len),
-	  ".mo");
+  strlcpy (xdomainname, categoryname, xdomainname_len);
+  strlcat (xdomainname, "/", xdomainname_len);
+  strlcat (xdomainname, domainname, xdomainname_len);
+  strlcat (xdomainname, ".mo", xdomainname_len);
 
   /* Creating working area.  */
   single_locale = (char *) alloca (strlen (categoryvalue) + 1);
@@ -837,13 +842,17 @@ DCIGETTEXT (const char *domainname, const char *msgid1
 		  /* Create a new entry and add it to the search tree.  */
 		  size_t msgid_len;
 		  size_t size;
+#ifdef HAVE_PER_THREAD_LOCALE
+		  size_t localename_len;
+#endif
 		  struct known_translation_t *newp;
 
 		  msgid_len = strlen (msgid1) + 1;
 		  size = offsetof (struct known_translation_t, msgid)
 			 + msgid_len + domainname_len + 1;
 #ifdef HAVE_PER_THREAD_LOCALE
-		  size += strlen (localename) + 1;
+		  localename_len = strlen (localename);
+		  size += localename_len + 1;
 #endif
 		  newp = (struct known_translation_t *) malloc (size);
 		  if (newp != NULL)
@@ -859,7 +868,7 @@ DCIGETTEXT (const char *domainname, const char *msgid1
 		      memcpy (new_domainname, domainname, domainname_len + 1);
 #ifdef HAVE_PER_THREAD_LOCALE
 		      new_localename = new_domainname + domainname_len + 1;
-		      strcpy (new_localename, localename);
+		      memcpy (new_localename, localename, localename_len + 1);
 #endif
 		      newp->domainname = new_domainname;
 		      newp->category = category;
