zsh-workers
 help / color / mirror / code / Atom feed
From: James Tirta Halim <tirtajames45@gmail.com>
To: zsh-workers@zsh.org
Cc: James Tirta Halim <tirtajames45@gmail.com>
Subject: [PATCH v2] prefer memcpy() over strcpy()
Date: Mon, 18 Mar 2024 14:11:48 +0700	[thread overview]
Message-ID: <20240318071148.135833-1-tirtajames45@gmail.com> (raw)

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



             reply	other threads:[~2024-03-18  7:15 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-03-18  7:11 James Tirta Halim [this message]
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

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20240318071148.135833-1-tirtajames45@gmail.com \
    --to=tirtajames45@gmail.com \
    --cc=zsh-workers@zsh.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).