Follow @Openwall on Twitter for new release announcements and other news
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <5cd6a28148eab3fff4af4ef2197ed0788f141f52.1764107117.git.alx@kernel.org>
Date: Tue, 25 Nov 2025 22:49:29 +0100
From: Alejandro Colomar <alx@...nel.org>
To: musl@...ts.openwall.com
Cc: Alejandro Colomar <alx@...nel.org>
Subject: [PATCH v2 1/1] include/string.h: Implement QChar wrappers
 standardized in C23

I used compound literals instead of casts because they're less
dangerous.  They only allow conversions that would be legal implicitly.

The register storage-class specifier is used because compound literals
are lvalues.  register makes sure one can't take the address of them.
That is, it rejects:

	&strchr(s, c);

Signed-off-by: Alejandro Colomar <alx@...nel.org>
---
 include/string.h | 21 +++++++++++++++++++++
 1 file changed, 21 insertions(+)

diff --git a/include/string.h b/include/string.h
index 83e2b946..c492698a 100644
--- a/include/string.h
+++ b/include/string.h
@@ -24,6 +24,16 @@ extern "C" {
 
 #include <bits/alltypes.h>
 
+#define __QCharof(s)  typeof                                            \
+(                                                                     \
+	_Generic(s,                                                   \
+		const char *:  (const char){},                        \
+		const void *:  (const char){},                        \
+		char *:        (char){},                              \
+		void *:        (char){}                               \
+	)                                                             \
+)
+
 void *memcpy (void *__restrict, const void *__restrict, size_t);
 void *memmove (void *, const void *, size_t);
 void *memset (void *, int, size_t);
@@ -55,6 +65,13 @@ size_t strlen (const char *);
 
 char *strerror (int);
 
+#if __STDC_VERSION__ >= 202311L
+# define strchr(s, ...)   ((register __QCharof(s) *){ strchr(s, __VA_ARGS__)})
+# define strrchr(s, ...)  ((register __QCharof(s) *){strrchr(s, __VA_ARGS__)})
+# define strpbrk(s, ...)  ((register __QCharof(s) *){strpbrk(s, __VA_ARGS__)})
+# define strstr(s, ...)   ((register __QCharof(s) *){ strstr(s, __VA_ARGS__)})
+#endif
+
 #if defined(_BSD_SOURCE) || defined(_GNU_SOURCE)
 #include <strings.h>
 #endif
@@ -95,6 +112,10 @@ char *strchrnul(const char *, int);
 char *strcasestr(const char *, const char *);
 void *memrchr(const void *, int, size_t);
 void *mempcpy(void *, const void *, size_t);
+# if __STDC_VERSION__ >= 202311L
+#  define strchrnul(s, ...)   ((register __QCharof(s) *){ strchrnul(s, __VA_ARGS__)})
+#  define strcasestr(s, ...)  ((register __QCharof(s) *){strcasestr(s, __VA_ARGS__)})
+# endif
 #endif
 
 #ifdef __cplusplus
-- 
2.51.0

Powered by blists - more mailing lists

Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.