On 6/26/24 07:57, Bruno Haible wrote:
Po Lu wrote:
I believe that the semantics of the POSIX specification of this GNU
function omit the implied guarantee that strnlen will never examine
bytes beyond the first null byte
There is no such guarantee, not even implied.
There seems to be some confusion here. Here's what POSIX.1-2024 says:
"The strnlen() function shall compute the smaller of the number of bytes
in the array to which s points, not including any terminating NUL
character, or the value of the maxlen argument. The strnlen() function
shall never examine more than maxlen bytes of the array pointed to by s."
This means it's OK to call strnlen ("", SIZE_MAX), because the second
arg of strnlen can be larger than the number of bytes in the byte array
that the first arg points to, so long as that array contains a null
byte. strnlen is unusual in this sense.
In contrast, it's not OK to call memchr ("", 0, SIZE_MAX).
(libc)String Length:
If the array S of size MAXLEN contains a null byte, the ‘strnlen’
^^^^^^^^^^^^^^^^^^^^^^^^^^
That's a bug in the glibc manual, which I just now fixed as noted here:
https://sourceware.org/pipermail/libc-alpha/2024-June/157798.html
Android's strnlen [1] is not incorrect, because the same requirements
that hold for memchr also hold for strnlen.
[1] https://android.googlesource.com/platform/bionic.git/+/refs/heads/main/libc/bionic/strnlen.cpp
Actually it's not incorrect because Android's memchr no longer has
undefined behavior with calls like memchr ("", 0, SIZE_MAX); it reliably
returns its first argument in that particular example. Although this
goes beyond what C and POSIX require for memchr, it's OK for Android
memchr to do that as an extension, and it's OK for Android's strnlen to
rely on Android's extensions to memchr.
I installed the attached patch to document the Android 5.0 glitch. Since
Android 5.0 is no longer supported I hope we don't need to worry about
this in Gnulib. That being said, if it's important for free software to
run on these old unsupported platforms and if someone wants to update
the Gnulib strnlen module to work around this Android 5.0 bug, I would
think that'd be OK.
From b79238db4ac7b8e710c8cab4307ce6cb1c3937d8 Mon Sep 17 00:00:00 2001
From: Paul Eggert <egg...@cs.ucla.edu>
Date: Wed, 26 Jun 2024 16:14:26 +0100
Subject: [COMMITTED] Fix strnlen doc re array size
* manual/string.texi: For strnlen (s, maxlen), do not say that s must
be of size maxlen, as it can be smaller if it is null-terminated.
This should help avoid confusion such as seen in
<https://lists.gnu.org/r/bug-gnulib/2024-06/msg00280.html>.
Mention that strnlen and wcsnlen have been in POSIX since
POSIX.1-2008.
---
manual/string.texi | 17 ++++++++++-------
1 file changed, 10 insertions(+), 7 deletions(-)
diff --git a/manual/string.texi b/manual/string.texi
index b91299fd6a..0b667bd3fb 100644
--- a/manual/string.texi
+++ b/manual/string.texi
@@ -309,12 +309,12 @@ This function was introduced in @w{Amendment 1} to @w{ISO C90}.
@end deftypefun
@deftypefun size_t strnlen (const char *@var{s}, size_t @var{maxlen})
-@standards{GNU, string.h}
+@standards{POSIX.1, string.h}
@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}}
-If the array @var{s} of size @var{maxlen} contains a null byte,
-the @code{strnlen} function returns the length of the string @var{s} in
-bytes. Otherwise it
-returns @var{maxlen}. Therefore this function is equivalent to
+This returns the offset of the first null byte in the array @var{s},
+except that it returns @var{maxlen} if the first @var{maxlen} bytes
+are all non-null.
+Therefore this function is equivalent to
@code{(strlen (@var{s}) < @var{maxlen} ? strlen (@var{s}) : @var{maxlen})}
but it
is more efficient and works even if @var{s} is not null-terminated so
@@ -328,7 +328,9 @@ strnlen (string, 5)
@result{} 5
@end smallexample
-This function is a GNU extension and is declared in @file{string.h}.
+This function is part of POSIX.1-2008 and later editions, but was
+available in @theglibc{} and other systems as an extension long before
+it was standardized. It is declared in @file{string.h}.
@end deftypefun
@deftypefun size_t wcsnlen (const wchar_t *@var{ws}, size_t @var{maxlen})
@@ -337,7 +339,8 @@ This function is a GNU extension and is declared in @file{string.h}.
@code{wcsnlen} is the wide character equivalent to @code{strnlen}. The
@var{maxlen} parameter specifies the maximum number of wide characters.
-This function is a GNU extension and is declared in @file{wchar.h}.
+This function is part of POSIX.1-2008 and later editions, and is
+declared in @file{wchar.h}.
@end deftypefun
@node Copying Strings and Arrays
--
2.45.2