zsh-workers
 help / color / mirror / code / Atom feed
* [PATCH v2] prefer memcpy() over strcpy()
@ 2024-03-18  7:11 James Tirta Halim
  2024-03-26  0:42 ` Oliver Kiddle
  0 siblings, 1 reply; 5+ messages in thread
From: James Tirta Halim @ 2024-03-18  7:11 UTC (permalink / raw)
  To: zsh-workers; +Cc: James Tirta Halim

Add zmemcpyz(), a memcpy() that nul-terminates the destination string.
This is meant to be used when we have the strlen() of the string.

We should prefer memcpy() when we know the length because it most libc
implementations provide an assembly implementation of memcpy but maybe
not strcpy(). Even if it is implemented in assembly, memcpy() is likely
to be faster than strcpy() since as the loop condition strcpy() needs
to check for zeros in SRC, whereas memcpy() can just decrement the size.

---
 Src/string.c | 56 +++++++++++++++++++++++++++++-----------------------
 Src/zsh.h    | 10 ++++++++++
 2 files changed, 41 insertions(+), 25 deletions(-)

diff --git a/Src/string.c b/Src/string.c
index 5f439926e..12da19f72 100644
--- a/Src/string.c
+++ b/Src/string.c
@@ -33,11 +33,13 @@ mod_export char *
 dupstring(const char *s)
 {
     char *t;
+    size_t l;
 
     if (!s)
 	return NULL;
-    t = (char *) zhalloc(strlen((char *)s) + 1);
-    strcpy(t, s);
+    l = strlen((char *)s);
+    t = (char *) zhalloc(l + 1);
+    zmemcpyz(t, s, l);
     return t;
 }
 
@@ -68,7 +70,7 @@ dupstring_glen(const char *s, unsigned *len_ret)
     if (!s)
 	return NULL;
     t = (char *) zhalloc((*len_ret = strlen((char *)s)) + 1);
-    strcpy(t, s);
+    zmemcpyz(t, s, *len_ret);
     return t;
 }
 
@@ -77,11 +79,13 @@ mod_export char *
 ztrdup(const char *s)
 {
     char *t;
+    size_t l;
 
     if (!s)
 	return NULL;
-    t = (char *)zalloc(strlen((char *)s) + 1);
-    strcpy(t, s);
+    l = strlen((char *)s);
+    t = (char *)zalloc(l + 1);
+    zmemcpyz(t, s, l);
     return t;
 }
 
@@ -116,11 +120,12 @@ tricat(char const *s1, char const *s2, char const *s3)
     char *ptr;
     size_t l1 = strlen(s1);
     size_t l2 = strlen(s2);
+    size_t l3 = strlen(s3);
 
-    ptr = (char *)zalloc(l1 + l2 + strlen(s3) + 1);
-    strcpy(ptr, s1);
-    strcpy(ptr + l1, s2);
-    strcpy(ptr + l1 + l2, s3);
+    ptr = (char *)zalloc(l1 + l2 + l3 + 1);
+    memcpy(ptr, s1, l1);
+    memcpy(ptr + l1, s2, l2);
+    zmemcpyz(ptr + l1 + l2, s3, l3);
     return ptr;
 }
 
@@ -131,11 +136,12 @@ zhtricat(char const *s1, char const *s2, char const *s3)
     char *ptr;
     size_t l1 = strlen(s1);
     size_t l2 = strlen(s2);
+    size_t l3 = strlen(s3);
 
     ptr = (char *)zhalloc(l1 + l2 + strlen(s3) + 1);
-    strcpy(ptr, s1);
-    strcpy(ptr + l1, s2);
-    strcpy(ptr + l1 + l2, s3);
+    memcpy(ptr, s1, l1);
+    memcpy(ptr + l1, s2, l2);
+    zmemcpyz(ptr + l1 + l2, s3, l3);
     return ptr;
 }
 
@@ -148,10 +154,11 @@ dyncat(const char *s1, const char *s2)
     /* This version always uses space from the current heap. */
     char *ptr;
     size_t l1 = strlen(s1);
+    size_t l2 = strlen(s2);
 
-    ptr = (char *)zhalloc(l1 + strlen(s2) + 1);
-    strcpy(ptr, s1);
-    strcpy(ptr + l1, s2);
+    ptr = (char *)zhalloc(l1 + l2 + 1);
+    memcpy(ptr, s1, l1);
+    zmemcpyz(ptr + l1, s2, l2);
     return ptr;
 }
 
@@ -162,10 +169,11 @@ bicat(const char *s1, const char *s2)
     /* This version always uses permanently-allocated space. */
     char *ptr;
     size_t l1 = strlen(s1);
+    size_t l2 = strlen(s2);
 
-    ptr = (char *)zalloc(l1 + strlen(s2) + 1);
-    strcpy(ptr, s1);
-    strcpy(ptr + l1, s2);
+    ptr = (char *)zalloc(l1 + l2 + 1);
+    memcpy(ptr, s1, l1);
+    zmemcpyz(ptr + l1, s2, l2);
     return ptr;
 }
 
@@ -177,9 +185,7 @@ dupstrpfx(const char *s, int len)
 {
     char *r = zhalloc(len + 1);
 
-    memcpy(r, s, len);
-    r[len] = '\0';
-    return r;
+    return zmemcpyz(r, s, len);
 }
 
 /**/
@@ -189,9 +195,7 @@ ztrduppfx(const char *s, int len)
     /* This version always uses permanently-allocated space. */
     char *r = zalloc(len + 1);
 
-    memcpy(r, s, len);
-    r[len] = '\0';
-    return r;
+    return zmemcpyz(r, s, len);
 }
 
 /* Append a string to an allocated string, reallocating to make room. */
@@ -200,7 +204,9 @@ ztrduppfx(const char *s, int len)
 mod_export char *
 appstr(char *base, char const *append)
 {
-    return strcat(realloc(base, strlen(base) + strlen(append) + 1), append);
+    size_t bl = strlen(base);
+    size_t al = strlen(append);
+    return zmemcpyz((char *)realloc(base, bl + al + 1) + bl, append, al);
 }
 
 /* Return a pointer to the last character of a string,
diff --git a/Src/zsh.h b/Src/zsh.h
index fae62b8d0..b10705356 100644
--- a/Src/zsh.h
+++ b/Src/zsh.h
@@ -3367,3 +3367,13 @@ typedef int convchar_t;
 #define ZWS(s)	s
 
 #endif /* MULTIBYTE_SUPPORT */
+
+#include <stddef.h>
+#include <string.h>
+
+/* memcpy that nul-terminates DST. SRC need not be nul-terminated. */
+static inline char *zmemcpyz(char *dst, const char *src, size_t n)
+{
+    *((char *)memcpy(dst, src, n) + n) = '\0';
+    return dst;
+}
-- 
2.44.0



^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2024-03-26  2:34 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-03-18  7:11 [PATCH v2] prefer memcpy() over strcpy() James Tirta Halim
2024-03-26  0:42 ` Oliver Kiddle
2024-03-26  2:18   ` James
2024-03-26  2:26     ` Bart Schaefer
2024-03-26  2:33       ` James

Code repositories for project(s) associated with this public inbox

	https://git.vuxu.org/mirror/zsh/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).