From ca1c292d2ee6bcb06be71400d25ae37e9dc2c1aa Mon Sep 17 00:00:00 2001 From: Rasmus Villemoes Date: Tue, 21 Apr 2026 09:54:31 +0200 Subject: string: fix prototype of memdup() It doesn't make sense to restrict memdup() to only return char* pointers, especially when it is already defined to accept void*. This makes it uglier to use to e.g. duplicate a struct. Make it return void*, just as kmemdup() does in the kernel (and which our kmemdup() in fact also does). While in here, make a small optimization: memcpy() is defined to return the destination register, so we write this in a way that the compiler may do a tail call. Reviewed-by: Simon Glass Signed-off-by: Rasmus Villemoes --- include/linux/string.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include/linux') diff --git a/include/linux/string.h b/include/linux/string.h index d943fcce690..9e47fe01c16 100644 --- a/include/linux/string.h +++ b/include/linux/string.h @@ -142,7 +142,7 @@ void *memchr_inv(const void *, int, size_t); * memory is available * */ -char *memdup(const void *src, size_t len); +void *memdup(const void *src, size_t len); unsigned long ustrtoul(const char *cp, char **endp, unsigned int base); unsigned long long ustrtoull(const char *cp, char **endp, unsigned int base); -- cgit v1.3.1 From 349d148f16d83da3b1e3475be0e43bfda4f4ab71 Mon Sep 17 00:00:00 2001 From: Rasmus Villemoes Date: Tue, 21 Apr 2026 09:54:33 +0200 Subject: lib/string.c: drop pointless __HAVE_ARCH_STRDUP There has never been an arch-specific optimized implementation of str[n]dup, nor is there likely to ever be one, because unlike their cousins strlen(), strcpy() and similar that simply read/write the src/dst, the dup functions by definition involve memory allocation. So drop this irrelevant cpp guard. Reviewed-by: Simon Glass Signed-off-by: Rasmus Villemoes --- include/linux/string.h | 3 +-- lib/string.c | 2 -- 2 files changed, 1 insertion(+), 4 deletions(-) (limited to 'include/linux') diff --git a/include/linux/string.h b/include/linux/string.h index 9e47fe01c16..a28150fa578 100644 --- a/include/linux/string.h +++ b/include/linux/string.h @@ -101,10 +101,9 @@ size_t strcspn(const char *s, const char *reject); # define strndup sandbox_strndup #endif -#ifndef __HAVE_ARCH_STRDUP extern char * strdup(const char *); extern char * strndup(const char *, size_t); -#endif + #ifndef __HAVE_ARCH_STRSWAB extern char * strswab(const char *); #endif diff --git a/lib/string.c b/lib/string.c index c2813e0f854..2c1baa568b9 100644 --- a/lib/string.c +++ b/lib/string.c @@ -343,7 +343,6 @@ size_t strcspn(const char *s, const char *reject) } #endif -#ifndef __HAVE_ARCH_STRDUP char * strdup(const char *s) { char *new; @@ -379,7 +378,6 @@ char * strndup(const char *s, size_t n) return new; } -#endif #ifndef __HAVE_ARCH_STRSPN /** -- cgit v1.3.1 From 8c664d2135723a110a60b792a8614c4864ad82a3 Mon Sep 17 00:00:00 2001 From: Rasmus Villemoes Date: Tue, 21 Apr 2026 09:54:34 +0200 Subject: lib/string.c: introduce memdup_nul() helper This is completely analogous to the linux kernel's kmemdup_nul() helper, apart from the lack of the gfp_t argument: Allocate a buffer of size {len}+1, copy {len} bytes from the given buffer, and add a final nul byte. This pattern exists in a number of places, so this helper can reduce some boilerplate code. Reviewed-by: Simon Glass Signed-off-by: Rasmus Villemoes --- include/linux/string.h | 13 +++++++++++++ lib/string.c | 15 +++++++++++++++ 2 files changed, 28 insertions(+) (limited to 'include/linux') diff --git a/include/linux/string.h b/include/linux/string.h index a28150fa578..b2e38ecf26e 100644 --- a/include/linux/string.h +++ b/include/linux/string.h @@ -143,6 +143,19 @@ void *memchr_inv(const void *, int, size_t); */ void *memdup(const void *src, size_t len); +/** + * memdup_nul() - allocate a buffer and copy in the contents, appending a nul byte + * + * Note that this returns a valid pointer even if @len is 0 + * + * @src: data to copy in + * @len: number of bytes to copy + * Return: allocated buffer with the copied contents and an extra nul byte, + * or NULL if not enough memory is available + * + */ +void *memdup_nul(const void *src, size_t len); + unsigned long ustrtoul(const char *cp, char **endp, unsigned int base); unsigned long long ustrtoull(const char *cp, char **endp, unsigned int base); diff --git a/lib/string.c b/lib/string.c index 2c1baa568b9..3923cce5561 100644 --- a/lib/string.c +++ b/lib/string.c @@ -343,6 +343,21 @@ size_t strcspn(const char *s, const char *reject) } #endif +void *memdup_nul(const void *src, size_t len) +{ + char *dst; + + if (len + 1 < len) + return NULL; + + dst = malloc(len + 1); + if (!dst) + return NULL; + + dst[len] = '\0'; + return memcpy(dst, src, len); +} + char * strdup(const char *s) { char *new; -- cgit v1.3.1