This is the mail archive of the
libc-alpha@sourceware.org
mailing list for the glibc project.
Re: [review] manual: Clarify strnlen, wcsnlen, strndup null termination behavior
- From: Szabolcs Nagy <Szabolcs dot Nagy at arm dot com>
- To: Rich Felker <dalias at libc dot org>, Carlos O'Donell <codonell at redhat dot com>
- Cc: nd <nd at arm dot com>, Florian Weimer <fw at deneb dot enyo dot de>, "libc-alpha at sourceware dot org" <libc-alpha at sourceware dot org>, Martin Sebor <msebor at gmail dot com>
- Date: Thu, 28 Nov 2019 18:38:19 +0000
- Subject: Re: [review] manual: Clarify strnlen, wcsnlen, strndup null termination behavior
- Arc-authentication-results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=arm.com; dmarc=pass action=none header.from=arm.com; dkim=pass header.d=arm.com; arc=none
- Arc-message-signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=ix1M8rzG203VMTWp/C/t7gli4UX/2dJQWOrvMoWi6vE=; b=oWEqA0UKc9kHVMMhAbIe9rR8+oTp+/hz1DkYNDPRtgHfaQV48QPsNDuHuxlucr4UfGbfBwi2adMjuf1VjU50+Ke9vU4dOdoqL9Vj7tHFT4h1FqiegITM+4j29+msrZMAnZjKGbknlRohArA10dkMv48wQqBF2CsZEbqPS5TPwcBoZ0NA3SlwImd/VqarEabzaR6MdZdrJqzyELFVXaHh6JvSyeAvIzZkoG8I4qScP5NACjzAuPkN2EEjowY5xsrJsoJsdtAtf6s/NZ5PqYCuLYe+ZAES/si6ybmjeqGhw8+OeeBRlRFMG+5eK0R4/KBCYpUI/JoMtl/uG8k+kOXJYg==
- Arc-seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=lgwvo0GJvpU2+1qoE9bsMcfndp2vwQNi/HfA43f0e7dkHG7cUgsx0FmKgiS4bzzPnwVpzLCgNQZrL6Cv8Rzlp5KN3eNPnkPyyTNhrm2+yX2WZAtpnyOO5LO2cztxlsOr8XGJYvMejdE2m6ix1xskARVshKRdX44YmGaQChzygeu3Z3ICk0cXHoqfY7GmlnrrU+9KXF1Iv5DtxqZT2P7onsHIFVZbZv+XfQs8WaOPNWgbMfsKpk7Q62qPZ3olPAwtasyTwRZVsjE+SHO7ec0VO+Ul8VVTGIV/eQY/sTPWKQJGSE2SXtv1dYBRbRVRZHzNy1F4M86GLw656McPL/+OFA==
- Original-authentication-results: spf=none (sender IP is ) smtp.mailfrom=Szabolcs dot Nagy at arm dot com;
- References: <gerrit.1572431114000.Ia3e68bc2d4d7e967df141702fb2f600cbd4a6432@gnutoolchain-gerrit.osci.io> <gerrit.1572431114000.Ia3e68bc2d4d7e967df141702fb2f600cbd4a6432@gnutoolchain-gerrit.osci.io> <mvmd0eeh5sb.fsf@suse.de> <87a79i33kt.fsf@oldenburg2.str.redhat.com> <mvm8sp2h51r.fsf@suse.de> <875zk6337v.fsf@oldenburg2.str.redhat.com> <87wobk8hew.fsf@mid.deneb.enyo.de> <0373aed6-d865-14ef-d106-a1c2b4d06c8c@redhat.com> <4312fc25-9b4c-9fab-25b1-495a618ab132@redhat.com> <20191128182251.GM16318@brightrain.aerifal.cx>
On 28/11/2019 18:22, Rich Felker wrote:
> On Thu, Nov 28, 2019 at 10:58:13AM -0500, Carlos O'Donell wrote:
>> On 11/28/19 10:56 AM, Carlos O'Donell wrote:
>>> On 11/28/19 4:43 AM, Florian Weimer wrote:
>>>> * Florian Weimer:
>>>>
>>>>> * Andreas Schwab:
>>>>>
>>>>>> On Okt 30 2019, Florian Weimer wrote:
>>>>>>
>>>>>>> * Andreas Schwab:
>>>>>>>
>>>>>>>> On Okt 30 2019, Florian Weimer (Code Review) wrote:
>>>>>>>>
>>>>>>>>> +Note that @var{s} must be an array of at least @var{maxlen} bytes. It
>>>>>>>>> +is undefined to call @code{strnlen} on a shorter array, even if it is
>>>>>>>>> +known that the shorter array contains a null terminator.
>>>>>>>>
>>>>>>>> This is not true. strnlen _always_ stops before the null byte.
>>>>>>>
>>>>>>> This is not how it is specified in POSIX.
>>>>>>
>>>>>> Yes, it is.
>>>>>>
>>>>>> The strnlen() function shall return the number of bytes preceding
>>>>>> the first null byte in the array to which s points, if s contains a
>>>>>> null byte within the first maxlen bytes; otherwise, it shall return
>>>>>> maxlen.
>>>>>>
>>>>>> There is nothing undefined here. Your interpretation would be
>>>>>> completely useless anyway.
>>>>>
>>>>> It says “array”, which implies a length. Admittedly, it does not say
>>>>> that maxlen corresponds to the arrray length. POSIX also says this:
>>>>>
>>>>> | The strnlen() function shall never examine more than maxlen bytes of
>>>>> | the array pointed to by s.
>>>>>
>>>>> But it does NOT say that reading stops after the first null terminator.
>>>>
>>>> I have built glibc with --disable-multi-arch and this patch on x86-64:
>>>>
>>>> diff --git a/string/strnlen.c b/string/strnlen.c
>>>> index 0b3a12e8b1..d5781dbb6f 100644
>>>> --- a/string/strnlen.c
>>>> +++ b/string/strnlen.c
>>>> @@ -33,6 +33,10 @@
>>>> size_t
>>>> __strnlen (const char *str, size_t maxlen)
>>>> {
>>>> + /* Assert that the entire input is readable. */
>>>> + for (size_t i = 0; i < maxlen; ++i)
>>>> + asm volatile ("" :: "r" (str[i]));
>>>> +
>>>> const char *char_ptr, *end_ptr = str + maxlen;
>>>> const unsigned long int *longword_ptr;
>>>> unsigned long int longword, himagic, lomagic;
>>>> diff --git a/sysdeps/x86_64/strnlen.S b/sysdeps/x86_64/strnlen.S
>>>> deleted file mode 100644
>>>> index d3c43ac482..0000000000
>>>> --- a/sysdeps/x86_64/strnlen.S
>>>> +++ /dev/null
>>>> @@ -1,6 +0,0 @@
>>>> -#define AS_STRNLEN
>>>> -#define strlen __strnlen
>>>> -#include "strlen.S"
>>>> -
>>>> -weak_alias (__strnlen, strnlen);
>>>> -libc_hidden_builtin_def (strnlen)
>>>> diff --git a/wcsmbs/wcsnlen.c b/wcsmbs/wcsnlen.c
>>>> index 17e004dcc0..0d3709ac91 100644
>>>> --- a/wcsmbs/wcsnlen.c
>>>> +++ b/wcsmbs/wcsnlen.c
>>>> @@ -26,6 +26,10 @@
>>>> size_t
>>>> __wcsnlen (const wchar_t *s, size_t maxlen)
>>>> {
>>>> + /* Assert that the entire input is readable. */
>>>> + for (size_t i = 0; i < maxlen; ++i)
>>>> + asm volatile ("" :: "r" (s[i]));
>>>> +
>>>> const wchar_t *ret = __wmemchr (s, L'\0', maxlen);
>>>> if (ret)
>>>> maxlen = ret - s;
>>>>
>>>> The resulting crashes demonstrate that the test suite verifies that we
>>>> do not treat the input as an array (to some degree; there might be
>>>> scopes in coverage).
>>>>
>>>> I think we should document this as a GNU extension. Thoughts?
>>>
>>> We should absolutely document this. It's an implementation-dependent detail
>>> that we choose to interpret the standard in this way.
>>>
>>
>> I also think we should get changes into the linux man page project to call
>> this out so that nobody thinks about changing this again and so the
>> implementation is clear.
>>
>> Have we asked Rich what musl does and what he thinks on the topic?
>
> I missed this whole thread, and haven't had time to look back through
> it yet. Is the claim that strnlen, etc. require a pointer to at least
> n bytes? I do not think that matches the intent of these interfaces at
> all. The language in POSIX is sloppy ("the number of bytes in the
> array to which s points"?! I think they were just trying to avoid
> saying "string" here because it's not necessarily a string, but they
> botched it) but a function like this that requires a large array is
> utterly useless. The whole point of strnlen is to be a bounded-time
> strlen when lengths >n will be treated as errors (or otherwise
> specially) after it returns.
if there is something wrong with the posix wording then
maybe the c2x proposal of strnlen should be updated too?
(cc Martin)
http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2351.htm