From: "Alejandro Colomar (man-pages)" <alx.manpages@gmail.com>
To: Jonny Grant <jg@jguk.org>, Florian Weimer <fw@deneb.enyo.de>
Cc: linux-man <linux-man@vger.kernel.org>,
Michael Kerrisk <mtk.manpages@gmail.com>
Subject: Re: strlen
Date: Wed, 7 Jul 2021 14:22:55 +0200 [thread overview]
Message-ID: <53b3666b-d200-ef97-b050-cc38669c61cd@gmail.com> (raw)
In-Reply-To: <23679a28-5986-0af2-4d98-7de68ed0deec@jguk.org>
Hello Jonny,
On 7/7/21 1:36 PM, Jonny Grant wrote:
>
>
> On 06/07/2021 23:11, Florian Weimer wrote:
>> * Jonny Grant:
>>
>>> The reason it does not crash appears to be because of this warning
>>> which removes the call to strlen due to the return not being
>>> checked?
>>
>> GCC uses the information that the argument to strlen cannot be null on
>> that particular path.
>
> It's a shame GCC doesn't give a warning
>
> It may be GCC is using '__builtin_strlen'
>
> <string.h> marks the param as nonnull. However, I am surprised this does not trigger the GCC warning -Werror=nonnull
[[gnu::nunnull]], aka __attribute__((nonnull)), is only triggered by
compile time NULL. That is: passing NULL (either hardcoded or through a
macro)
If after optimizations the compiler realizes that an argument is NULL at
compile time, it may (but also may not) trigger the warning. However,
if you optimize too much, the expression may vanish, and the warning be
silenced again. The -fanalyzer option of GCC may (but also may not)
realize of more NULL cases.
I managed to trigger the following, but only with '-O0 -fanalyzer':
[[
<source>:17:20: error: use of NULL 's' where non-null expected [CWE-476]
[-Werror=analyzer-null-argument]
17 | int x = strlen (s);
| ~~~~~~~^~~
'void f(const char*)': events 1-2
|
| 16 | const char *s = NULL;
| | ^
| | |
| | (1) 's' is NULL
| 17 | int x = strlen(s);
| | ~~~~~~~~~~
| | |
| | (2) argument 1 ('s') NULL where non-null
expected
|
In file included from <source>:4:
/usr/include/string.h:385:15: note: argument 1 of 'size_t strlen(const
char*)' must be non-null
385 | extern size_t strlen (const char *__s)
| ^~~~~~
]]
It is undefined behavior to pass NULL to a nonnull parameter, and it is
a problem that the caller should check before the call. The compiler
may warn you of the most obvious ones, but in the end, the
responsibility is on the programmer.
See
<https://stackoverflow.com/questions/42035769/how-to-generate-warning-of-non-null-argument-for-my-custom-function>.
>
> /* Return the length of S. */
> extern size_t strlen (const char *__s)
> __THROW __attribute_pure__ __nonnull ((1));
>
> Perhaps that is just a macro that is not actually used......
It _is_ being used:
/usr/include$ grep -rn 'define __nonnull' -B3 -A1
x86_64-linux-gnu/sys/cdefs.h-290-/* The nonull function attribute allows
to mark pointer parameters which
x86_64-linux-gnu/sys/cdefs.h-291- must not be NULL. */
x86_64-linux-gnu/sys/cdefs.h-292-#if __GNUC_PREREQ (3,3)
x86_64-linux-gnu/sys/cdefs.h:293:# define __nonnull(params)
__attribute__ ((__nonnull__ params))
x86_64-linux-gnu/sys/cdefs.h-294-#else
x86_64-linux-gnu/sys/cdefs.h:295:# define __nonnull(params)
x86_64-linux-gnu/sys/cdefs.h-296-#endif
>
> If I add another function -Werror=nonnull does give a warning
> void test(const char * const p) __attribute__((nonnull));
>
> https://godbolt.org/z/x37sbfWaG
>
> <source>:15:9: error: argument 1 null where non-null expected [-Werror=nonnull]
> 15 | test(NULL);
>
>>
>>> strlen.c:11:3: warning: statement with no effect [-Wunused-value]
>>> 11 | strlen (str);
>>> | ^~~~~~~~~~~~
>>>
>>> https://godbolt.org/z/caoes5nGa
>>
>> That site probably uses different library headers.
>>
>> As posted, with Debian's GCC 8.3, I get this for the main function:
>>
>> main:
>> xorl %eax, %eax
>> ret
>>
>
>
> In that case maybe https://man7.org/linux/man-pages/man3/strlen.3.html should have a "NOTES" section stating something similar to your wording ?
>
> NOTES
>
> The behavior of strlen(NULL) is depends on different things. It may cause a SEGV exception, or the compiler may optimize and remove the code path handling NULL.
>
I disagree with this. It is likely that the behavior is that, given the
current implementation of Linux/GCC/glibc. But it is undefined
behavior, and anything can happen. You should just try harder to avoid
it, and not rely on any possible outcome of it. GCC people may decide
tomorrow to change the behavior to do some more agresive optimizations,
and the documentation shouldn't preclude such a thing, as long as it's
legal according to the relevant standards, and sane.
Cheers,
Alex
--
Alejandro Colomar
Linux man-pages comaintainer; https://www.kernel.org/doc/man-pages/
http://www.alejandro-colomar.es/
next prev parent reply other threads:[~2021-07-07 12:25 UTC|newest]
Thread overview: 32+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-09-04 18:01 strlen Jonny Grant
2020-09-04 19:21 ` strlen Florian Weimer
2020-09-04 23:14 ` strlen Jonny Grant
2020-09-05 7:12 ` strlen Florian Weimer
2021-07-06 20:30 ` strlen Jonny Grant
2021-07-06 22:11 ` strlen Florian Weimer
2021-07-07 11:36 ` strlen Jonny Grant
2021-07-07 12:22 ` Alejandro Colomar (man-pages) [this message]
2021-07-07 12:31 ` strlen Alejandro Colomar (man-pages)
2021-07-07 13:31 ` strlen Jonny Grant
2021-07-07 16:57 ` strlen Alejandro Colomar (man-pages)
2021-07-07 17:23 ` strlen Alejandro Colomar (man-pages)
2021-07-07 17:33 ` strlen Alejandro Colomar (man-pages)
2021-07-09 13:48 ` strlen Jonny Grant
2021-07-08 10:07 ` strlen Jonny Grant
2021-07-08 11:06 ` strlen Alejandro Colomar (man-pages)
2021-07-08 12:13 ` strlen Xi Ruoyao
2021-07-08 23:49 ` strlen Segher Boessenkool
2021-07-09 13:54 ` strlen Jonny Grant
2021-07-09 14:17 ` strlen Alejandro Colomar (man-pages)
2021-07-09 16:11 ` strlen Xi Ruoyao
2021-07-10 1:00 ` strlen Segher Boessenkool
2021-07-09 10:50 ` strlen Jonny Grant
2021-07-09 11:27 ` strlen Alejandro Colomar (man-pages)
2021-07-09 11:43 ` strlen Alejandro Colomar (man-pages)
[not found] ` <1627912755.3783669.1625745946723@mail.yahoo.com>
[not found] ` <59a70222-a46f-1e65-c9db-6c9e577c8adc@126.com>
2021-07-09 17:26 ` strlen Martin Sebor
2021-07-09 20:19 ` strlen Alejandro Colomar (man-pages)
2021-07-09 20:44 ` strlen Jonny Grant
2021-07-10 18:37 ` strlen Alejandro Colomar (man-pages)
2021-07-10 20:49 ` strlen Jonny Grant
2021-07-10 21:36 ` strlen Alejandro Colomar (man-pages)
2021-07-12 21:16 ` strlen Jonny Grant
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=53b3666b-d200-ef97-b050-cc38669c61cd@gmail.com \
--to=alx.manpages@gmail.com \
--cc=fw@deneb.enyo.de \
--cc=jg@jguk.org \
--cc=linux-man@vger.kernel.org \
--cc=mtk.manpages@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).