[v2,1/2] libc: Make string.h POSIX.1-2024 compliant

Message ID 20251114232625.1788701-2-simon.barth@gmx.de
State New
Headers
Series Improve POSIX.1-2024 conformity and docs |

Commit Message

Simon Barth Nov. 14, 2025, 11:26 p.m. UTC
  POSIX.1-2024 added strlcpy, strlcat, and memmem to strings.h. Previously
these functions were only available as parts of BSD or GNU extensions.

Fix the header so that the symbol are visible for either the right
extensions, or for POSIX.1-2024.
---
 newlib/libc/include/string.h | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)
  

Comments

John Scott Nov. 16, 2025, 3:46 a.m. UTC | #1
Simon Barth wrote:
> POSIX.1-2024 added strlcpy, strlcat, and memmem to strings.h. Previously these functions were only available as parts of BSD or GNU extensions.
> Fix the header so that the symbol are visible for either the right extensions, or for POSIX.1-2024.

This is a pedantic comment, but technically these functions do not have to be guarded behind feature test macros at all. Functions beginning with 'str' or 'mem' in <string.h> are in implementation-reserved namespace. I believe this provision goes back to C89.
You can see it in a C17 draft at https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2310.pdf#nameddest=subsection.7.31.13
POSIX has always done the same: https://pubs.opengroup.org/onlinepubs/9799919799/functions/V2_chap02.html#tag_16_02_02

As an example, POSIX provides that Annex K's string functions need not be guarded behind the __STDC_WANT_LIB_EXT1__ feature test macro.
  
Simon Barth Nov. 19, 2025, 5:01 a.m. UTC | #2
Hi,

On Sun, Nov 16, 2025 at 03:46:34AM +0000, John Scott wrote:
> Simon Barth wrote:
> > POSIX.1-2024 added strlcpy, strlcat, and memmem to strings.h. Previously these functions were only available as parts of BSD or GNU extensions.
> > Fix the header so that the symbol are visible for either the right extensions, or for POSIX.1-2024.
> 
> This is a pedantic comment, but technically these functions do not have to be guarded behind feature test macros at all. Functions beginning with 'str' or 'mem' in <string.h> are in implementation-reserved namespace. I believe this provision goes back to C89.
> You can see it in a C17 draft at https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2310.pdf#nameddest=subsection.7.31.13
> POSIX has always done the same: https://pubs.opengroup.org/onlinepubs/9799919799/functions/V2_chap02.html#tag_16_02_02
> 
> As an example, POSIX provides that Annex K's string functions need not be guarded behind the __STDC_WANT_LIB_EXT1__ feature test macro.

I understand that according to this, an implementation of the C library
is free to add functions with any of the prefixes 'str' or 'mem' to
<string.h>.

Are you proposing to _unguard_  all functions in <string.h>
that match those criteria?

Cheers,

Simon
  
Brian Inglis Nov. 19, 2025, 7:37 a.m. UTC | #3
On 2025-11-15 20:46, John Scott wrote:
> Simon Barth wrote:
>> POSIX.1-2024 added strlcpy, strlcat, and memmem to strings.h. Previously these functions were only available as parts of BSD or GNU extensions.
>> Fix the header so that the symbol are visible for either the right extensions, or for POSIX.1-2024.
> 
> This is a pedantic comment, but technically these functions do not have to be guarded behind feature test macros at all. Functions beginning with 'str' or 'mem' in <string.h> are in implementation-reserved namespace. I believe this provision goes back to C89.
> You can see it in a C17 draft at https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2310.pdf#nameddest=subsection.7.31.13

This is qualified in the WD derived from C2023 (which adds prefix "wcs"):

	https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3685.pdf#page=511

"7.35.18 String handling <string.h>

1 Function names that begin with str, mem, or wcs and a lowercase letter are 
potentially reserved identifiers and may be added to the declarations in the 
<string.h> header.

2 Suppressing the macro definitions of memchr, strchr, strpbrk, strrchr, or 
strstr to access the corresponding actual function is an obsolescent feature."

> POSIX has always done the same:
>	https://pubs.opengroup.org/onlinepubs/9799919799/functions/V2_chap02.html#tag_16_02_02

"2.2.2 The Name Space

All identifiers in this volume of POSIX.1-2024, except environ, are defined in 
at least one of the headers, as shown in XBD 14. Headers.
When [XSI] _XOPEN_SOURCE or _POSIX_C_SOURCE is defined, each header defines or 
declares some identifiers, potentially conflicting with identifiers used by the 
application.
The set of identifiers visible to the application consists of precisely those 
identifiers from the header pages of the included headers, as well as additional 
identifiers reserved for the implementation.
In addition, some headers may make visible identifiers from other headers as 
indicated on the relevant header pages.
...
Implementations may add symbols to the headers shown in the following table, 
provided the identifiers for those symbols either:

	1. Begin with the corresponding reserved prefixes in the table, or
...
Header		Prefix				Suffix		Complete Name
...
<string.h>	str[a-z], mem[a-z], wcs[a-z]"

excludes unguarded (str|mem|wcs)[^a-z] and may be extended by any header which 
is defined to, or as implemented, includes <string.h>.

> As an example, POSIX provides that Annex K's string functions need not be guarded behind the __STDC_WANT_LIB_EXT1__ feature test macro.
  
Corinna Vinschen Nov. 19, 2025, 11:11 a.m. UTC | #4
On Nov 15 00:26, Simon Barth wrote:
> POSIX.1-2024 added strlcpy, strlcat, and memmem to strings.h. Previously
> these functions were only available as parts of BSD or GNU extensions.
> 
> Fix the header so that the symbol are visible for either the right
> extensions, or for POSIX.1-2024.
> ---
>  newlib/libc/include/string.h | 6 ++++--
>  1 file changed, 4 insertions(+), 2 deletions(-)
> 
> diff --git a/newlib/libc/include/string.h b/newlib/libc/include/string.h
> index 32199c027..3e66ec3dd 100644
> --- a/newlib/libc/include/string.h
> +++ b/newlib/libc/include/string.h
> @@ -68,10 +68,12 @@ void *	 memccpy (void *__restrict, const void *__restrict, int, size_t);
>  #endif
>  #if __GNU_VISIBLE
>  void *	 mempcpy (void *, const void *, size_t);
> -void *	 memmem (const void *, size_t, const void *, size_t);
>  void *	 memrchr (const void *, int, size_t);
>  void *	 rawmemchr (const void *, int);
>  #endif
> +#if __GNU_VISIBLE || __POSIX_VISIBLE >= 202405
> +void *	 memmem (const void *, size_t, const void *, size_t);
> +#endif
>  #if __POSIX_VISIBLE >= 200809
>  char 	*stpcpy (char *__restrict, const char *__restrict);
>  char 	*stpncpy (char *__restrict, const char *__restrict, size_t);
> @@ -111,7 +113,7 @@ int	__xpg_strerror_r (int, char *, size_t);
>  /* Reentrant version of strerror.  */
>  char *	_strerror_r (struct _reent *, int, int, int *);
>  
> -#if __BSD_VISIBLE
> +#if __BSD_VISIBLE || __POSIX_VISIBLE >= 202405L
>  size_t	strlcat (char *, const char *, size_t);
>  size_t	strlcpy (char *, const char *, size_t);
>  #endif
> -- 
> 2.51.2

I pushed this patch as is, but if you follow up with another patch
removing the guards, that would be fine.

Thanks,
Corinna
  

Patch

diff --git a/newlib/libc/include/string.h b/newlib/libc/include/string.h
index 32199c027..3e66ec3dd 100644
--- a/newlib/libc/include/string.h
+++ b/newlib/libc/include/string.h
@@ -68,10 +68,12 @@  void *	 memccpy (void *__restrict, const void *__restrict, int, size_t);
 #endif
 #if __GNU_VISIBLE
 void *	 mempcpy (void *, const void *, size_t);
-void *	 memmem (const void *, size_t, const void *, size_t);
 void *	 memrchr (const void *, int, size_t);
 void *	 rawmemchr (const void *, int);
 #endif
+#if __GNU_VISIBLE || __POSIX_VISIBLE >= 202405
+void *	 memmem (const void *, size_t, const void *, size_t);
+#endif
 #if __POSIX_VISIBLE >= 200809
 char 	*stpcpy (char *__restrict, const char *__restrict);
 char 	*stpncpy (char *__restrict, const char *__restrict, size_t);
@@ -111,7 +113,7 @@  int	__xpg_strerror_r (int, char *, size_t);
 /* Reentrant version of strerror.  */
 char *	_strerror_r (struct _reent *, int, int, int *);
 
-#if __BSD_VISIBLE
+#if __BSD_VISIBLE || __POSIX_VISIBLE >= 202405L
 size_t	strlcat (char *, const char *, size_t);
 size_t	strlcpy (char *, const char *, size_t);
 #endif