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

Reply via email to