Follow @Openwall on Twitter for new release announcements and other news
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date: Thu, 25 May 2023 16:45:00 +0200
From: Jens Gustedt <Jens.Gustedt@...ia.fr>
To: musl@...ts.openwall.com
Subject: [C23 const 2/2] C23: change string.h and wchar.h interfaces to macros that respects the const contract

This adds a macro interfaces to those string functions that search for
a string position. This has an additional cast of the return value to
`void const*` for the case that the argument to the call was also
const-qualified. Nothing changes for the correspondin function itself,
only the identifier has to be protected with (), such that the macro
does not expand for the function declaration or definition.
---
 include/string.h     | 54 ++++++++++++++++++++++++++++++++++++++-----
 include/wchar.h      | 55 +++++++++++++++++++++++++++++++++++++++-----
 src/include/string.h |  6 +++++
 src/include/wchar.h  |  6 +++++
 src/string/memchr.c  |  2 +-
 src/string/strchr.c  |  2 +-
 src/string/strpbrk.c |  2 +-
 src/string/strrchr.c |  2 +-
 src/string/strstr.c  |  2 +-
 src/string/wcschr.c  |  2 +-
 src/string/wcspbrk.c |  2 +-
 src/string/wcsrchr.c |  2 +-
 src/string/wcsstr.c  |  2 +-
 src/string/wmemchr.c |  2 +-
 14 files changed, 119 insertions(+), 22 deletions(-)

diff --git a/include/string.h b/include/string.h
index 7df7a402..05019c03 100644
--- a/include/string.h
+++ b/include/string.h
@@ -28,7 +28,54 @@ void *memcpy (void *__restrict, const void *__restrict, size_t);
 void *memmove (void *, const void *, size_t);
 void *memset (void *, int, size_t);
 int memcmp (const void *, const void *, size_t);
-void *memchr (const void *, int, size_t);
+
+void *(memchr) (const void *, int, size_t);
+char *(strchr) (const char *, int);
+char *(strrchr) (const char *, int);
+char *(strpbrk) (const char *, const char *);
+char *(strstr) (const char *, const char *);
+#if __STDC_VERSION__ > 201112L
+# define memchr(S, C, N)                                                \
+	_Generic(                                                       \
+		/* ensure conversion to a void pointer */               \
+		1 ? (S) : (void*)1,                                     \
+		void const*: (void const*)memchr((void const*)(S), (C), (N)), \
+		/* volatile qualification of *S is an error for this call */ \
+		default:     memchr((S), (C), (N))                      \
+)
+# define strchr(S, C)                                                   \
+	_Generic(                                                       \
+		/* ensure conversion to a void pointer */               \
+		1 ? (S) : (void*)1,                                     \
+		void const*: (char const*)strchr((char const*){ (S) }, (C)), \
+		/* volatile qualification of *S is an error for this call */ \
+		default:     strchr((S), (C))                           \
+)
+# define strrchr(S, C)                                                   \
+	_Generic(                                                       \
+		/* ensure conversion to a void pointer */               \
+		1 ? (S) : (void*)1,                                     \
+		void const*: (char const*)strrchr((char const*){ (S) }, (C)), \
+		/* volatile qualification of *S is an error for this call */ \
+		default:     strrchr((S), (C))                           \
+)
+# define strpbrk(S, A)                                                  \
+	_Generic(                                                       \
+		/* ensure conversion to a void pointer */               \
+		1 ? (S) : (void*)1,                                     \
+		void const*: (char const*)strpbrk((char const*){ (S) }, (A)), \
+		/* volatile qualification of *S is an error for this call */ \
+		default:     strpbrk((S), (A))                          \
+)
+# define strstr(H, N)                                                   \
+	_Generic(                                                       \
+		/* ensure conversion to a void pointer */               \
+		1 ? (H) : (void*)1,                                     \
+		void const*: (char const*)strstr((char const*){ (H) }, (N)), \
+		/* volatile qualification of *S is an error for this call */ \
+		default:     strstr((H), (N))                           \
+)
+#endif
 
 char *strcpy (char *__restrict, const char *__restrict);
 char *strncpy (char *__restrict, const char *__restrict, size_t);
@@ -42,13 +89,8 @@ int strncmp (const char *, const char *, size_t);
 int strcoll (const char *, const char *);
 size_t strxfrm (char *__restrict, const char *__restrict, size_t);
 
-char *strchr (const char *, int);
-char *strrchr (const char *, int);
-
 size_t strcspn (const char *, const char *);
 size_t strspn (const char *, const char *);
-char *strpbrk (const char *, const char *);
-char *strstr (const char *, const char *);
 char *strtok (char *__restrict, const char *__restrict);
 
 size_t strlen (const char *);
diff --git a/include/wchar.h b/include/wchar.h
index ed5d774d..3816a7cd 100644
--- a/include/wchar.h
+++ b/include/wchar.h
@@ -61,21 +61,64 @@ int wcsncmp (const wchar_t *, const wchar_t *, size_t);
 int wcscoll(const wchar_t *, const wchar_t *);
 size_t wcsxfrm (wchar_t *__restrict, const wchar_t *__restrict, size_t);
 
-wchar_t *wcschr (const wchar_t *, wchar_t);
-wchar_t *wcsrchr (const wchar_t *, wchar_t);
-
 size_t wcscspn (const wchar_t *, const wchar_t *);
 size_t wcsspn (const wchar_t *, const wchar_t *);
-wchar_t *wcspbrk (const wchar_t *, const wchar_t *);
 
 wchar_t *wcstok (wchar_t *__restrict, const wchar_t *__restrict, wchar_t **__restrict);
 
 size_t wcslen (const wchar_t *);
 
-wchar_t *wcsstr (const wchar_t *__restrict, const wchar_t *__restrict);
 wchar_t *wcswcs (const wchar_t *, const wchar_t *);
 
-wchar_t *wmemchr (const wchar_t *, wchar_t, size_t);
+wchar_t *(wmemchr) (const wchar_t *, wchar_t, size_t);
+wchar_t *(wcschr) (const wchar_t *, wchar_t);
+wchar_t *(wcsrchr) (const wchar_t *, wchar_t);
+wchar_t *(wcspbrk) (const wchar_t *, const wchar_t *);
+wchar_t *(wcsstr) (const wchar_t *__restrict, const wchar_t *__restrict);
+#if __STDC_VERSION__ > 201112L
+# define wmemchr(S, C, N)                                               \
+	_Generic(                                                       \
+		/* ensure conversion to a void pointer */               \
+		1 ? (S) : (void*)1,                                     \
+		void const*: (wchar_t const*)wmemchr((wchar_t const*){ (S) }, (C), (N)), \
+		/* volatile qualification of *S is an error for this call */ \
+		default:     wmemchr((S), (C), (N))                     \
+)
+# define wcschr(S, C)                                                   \
+	_Generic(                                                       \
+		/* ensure conversion to a void pointer */               \
+		1 ? (S) : (void*)1,                                     \
+		void const*: (wchar_t const*)wcschr((wchar_t const*){ (S) }, (C)), \
+		/* volatile qualification of *S is an error for this call */ \
+		default:     wcschr((S), (C))                           \
+)
+# define wcsrchr(S, C)                                                  \
+	_Generic(                                                       \
+		/* ensure conversion to a void pointer */               \
+		1 ? (S) : (void*)1,                                     \
+		void const*: (wchar_t const*)wcsrchr((wchar_t const*){ (S) }, (C)), \
+		/* volatile qualification of *S is an error for this call */ \
+		default:     wcsrchr((S), (C))                          \
+)
+# define wcspbrk(S, A)                                                  \
+	_Generic(                                                       \
+		/* ensure conversion to a void pointer */               \
+		1 ? (S) : (void*)1,                                     \
+		void const*: (wchar_t const*)wcspbrk((wchar_t const*){ (S) }, (A)), \
+		/* volatile qualification of *S is an error for this call */ \
+		default:     wcspbrk((S), (A))                          \
+)
+# define wcsstr(H, N)                                                   \
+	_Generic(                                                       \
+		/* ensure conversion to a void pointer */               \
+		1 ? (H) : (void*)1,                                     \
+		void const*: (wchar_t const*)wcsstr((wchar_t const*){ (H) }, (N)), \
+		/* volatile qualification of *S is an error for this call */ \
+		default:     wcsstr((H), (N))                           \
+)
+#endif
+
+
 int wmemcmp (const wchar_t *, const wchar_t *, size_t);
 wchar_t *wmemcpy (wchar_t *__restrict, const wchar_t *__restrict, size_t);
 wchar_t *wmemmove (wchar_t *, const wchar_t *, size_t);
diff --git a/src/include/string.h b/src/include/string.h
index 2133b5c1..f536c26b 100644
--- a/src/include/string.h
+++ b/src/include/string.h
@@ -8,4 +8,10 @@ hidden char *__stpcpy(char *, const char *);
 hidden char *__stpncpy(char *, const char *, size_t);
 hidden char *__strchrnul(const char *, int);
 
+#undef memchr
+#undef strchr
+#undef strrchr
+#undef strpbrk
+#undef strstr
+
 #endif
diff --git a/src/include/wchar.h b/src/include/wchar.h
index 79f5d0e7..dcd1cce1 100644
--- a/src/include/wchar.h
+++ b/src/include/wchar.h
@@ -5,5 +5,11 @@
 
 #include "../../include/wchar.h"
 
+#undef wmemchr
+#undef wcschr
+#undef wcsrchr
+#undef wcspbrk
+#undef wcsstr
+
 #endif
 
diff --git a/src/string/memchr.c b/src/string/memchr.c
index 65f0d789..f11c0573 100644
--- a/src/string/memchr.c
+++ b/src/string/memchr.c
@@ -8,7 +8,7 @@
 #define HIGHS (ONES * (UCHAR_MAX/2+1))
 #define HASZERO(x) ((x)-ONES & ~(x) & HIGHS)
 
-void *memchr(const void *src, int c, size_t n)
+void *(memchr)(const void *src, int c, size_t n)
 {
 	const unsigned char *s = src;
 	c = (unsigned char)c;
diff --git a/src/string/strchr.c b/src/string/strchr.c
index 3cbc828b..3a86beeb 100644
--- a/src/string/strchr.c
+++ b/src/string/strchr.c
@@ -1,6 +1,6 @@
 #include <string.h>
 
-char *strchr(const char *s, int c)
+char *(strchr)(const char *s, int c)
 {
 	char *r = __strchrnul(s, c);
 	return *(unsigned char *)r == (unsigned char)c ? r : 0;
diff --git a/src/string/strpbrk.c b/src/string/strpbrk.c
index 55947c64..0941fc51 100644
--- a/src/string/strpbrk.c
+++ b/src/string/strpbrk.c
@@ -1,6 +1,6 @@
 #include <string.h>
 
-char *strpbrk(const char *s, const char *b)
+char *(strpbrk)(const char *s, const char *b)
 {
 	s += strcspn(s, b);
 	return *s ? (char *)s : 0;
diff --git a/src/string/strrchr.c b/src/string/strrchr.c
index 98ad1b04..908fd8d4 100644
--- a/src/string/strrchr.c
+++ b/src/string/strrchr.c
@@ -1,6 +1,6 @@
 #include <string.h>
 
-char *strrchr(const char *s, int c)
+char *(strrchr)(const char *s, int c)
 {
 	return __memrchr(s, c, strlen(s) + 1);
 }
diff --git a/src/string/strstr.c b/src/string/strstr.c
index 96657bc2..5c622a82 100644
--- a/src/string/strstr.c
+++ b/src/string/strstr.c
@@ -135,7 +135,7 @@ static char *twoway_strstr(const unsigned char *h, const unsigned char *n)
 	}
 }
 
-char *strstr(const char *h, const char *n)
+char *(strstr)(const char *h, const char *n)
 {
 	/* Return immediately on empty needle */
 	if (!n[0]) return (char *)h;
diff --git a/src/string/wcschr.c b/src/string/wcschr.c
index 8dfc2f31..2bf7a111 100644
--- a/src/string/wcschr.c
+++ b/src/string/wcschr.c
@@ -1,6 +1,6 @@
 #include <wchar.h>
 
-wchar_t *wcschr(const wchar_t *s, wchar_t c)
+wchar_t *(wcschr)(const wchar_t *s, wchar_t c)
 {
 	if (!c) return (wchar_t *)s + wcslen(s);
 	for (; *s && *s != c; s++);
diff --git a/src/string/wcspbrk.c b/src/string/wcspbrk.c
index 0c72c197..eb76b5ff 100644
--- a/src/string/wcspbrk.c
+++ b/src/string/wcspbrk.c
@@ -1,6 +1,6 @@
 #include <wchar.h>
 
-wchar_t *wcspbrk(const wchar_t *s, const wchar_t *b)
+wchar_t *(wcspbrk)(const wchar_t *s, const wchar_t *b)
 {
 	s += wcscspn(s, b);
 	return *s ? (wchar_t *)s : NULL;
diff --git a/src/string/wcsrchr.c b/src/string/wcsrchr.c
index 8961b9e2..889303f3 100644
--- a/src/string/wcsrchr.c
+++ b/src/string/wcsrchr.c
@@ -1,6 +1,6 @@
 #include <wchar.h>
 
-wchar_t *wcsrchr(const wchar_t *s, wchar_t c)
+wchar_t *(wcsrchr)(const wchar_t *s, wchar_t c)
 {
 	const wchar_t *p;
 	for (p=s+wcslen(s); p>=s && *p!=c; p--);
diff --git a/src/string/wcsstr.c b/src/string/wcsstr.c
index 4caaef3c..8f27dbea 100644
--- a/src/string/wcsstr.c
+++ b/src/string/wcsstr.c
@@ -90,7 +90,7 @@ static wchar_t *twoway_wcsstr(const wchar_t *h, const wchar_t *n)
 	}
 }
 
-wchar_t *wcsstr(const wchar_t *restrict h, const wchar_t *restrict n)
+wchar_t *(wcsstr)(const wchar_t *restrict h, const wchar_t *restrict n)
 {
 	/* Return immediately on empty needle or haystack */
 	if (!n[0]) return (wchar_t *)h;
diff --git a/src/string/wmemchr.c b/src/string/wmemchr.c
index 2bc2c270..3d761488 100644
--- a/src/string/wmemchr.c
+++ b/src/string/wmemchr.c
@@ -1,6 +1,6 @@
 #include <wchar.h>
 
-wchar_t *wmemchr(const wchar_t *s, wchar_t c, size_t n)
+wchar_t *(wmemchr)(const wchar_t *s, wchar_t c, size_t n)
 {
 	for (; n && *s != c; n--, s++);
 	return n ? (wchar_t *)s : 0;
-- 
2.34.1

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.