From: "Alejandro Colomar (man-pages)" <alx.manpages@gmail.com>
To: Jonny Grant <jg@jguk.org>
Cc: linux-man <linux-man@vger.kernel.org>,
Michael Kerrisk <mtk.manpages@gmail.com>,
Florian Weimer <fw@deneb.enyo.de>,
gcc-help@gcc.gnu.org
Subject: Re: strlen
Date: Thu, 8 Jul 2021 13:06:17 +0200 [thread overview]
Message-ID: <feb6c15d-b242-83fc-c58d-2ebfbcd4f2bd@gmail.com> (raw)
In-Reply-To: <5566b180-1333-d73b-22ee-6c6d32053921@jguk.org>
On 7/8/21 12:07 PM, Jonny Grant wrote:
> Thank you for your reply.
>
> We can't guarantee safestrlen() won't be called with NULL. So because strlen() itself doesn't check for NULL in C standard we'd need to call the wrapper so that NULL can be checked for.
>
> I'd like to avoid the compiler removing certain execution paths.
> I'd rather keep all code paths, even if they are not taken, just in case a NULL pointer creeps in due to an external device that is connected to an embedded system.
>
>
> Probably this would work:
>
> size_t __attribute__((optimize("O0"))) safestrlen(const char * s)
> {
> if (NULL == s) return 0;
> else return strlen(s);
> }
I don't think you don't need that. Unless there's a bug in GCC, it
shouldn't optimize that path unless it is 100% sure that it will never
be called.
Moreover, I recommend you to optimize as much as possible.
Even though NULL is possible in your code, I guess it's unlikely.
Also, calling a function safe is too generic.
I'd call it with the suffix null, as it act different on null.
Also, I recommend avoiding 'size_t' (and any other unsigned types, BTW).
See <https://google.github.io/styleguide/cppguide.html#Integer_Types>.
Use the POSIX type 'ssize_t'.
That also allows differentiating a length of 0 (i.e., "") from an
invalid string (i.e., NULL), by returning -1 for NULL.
Recommended implementation (requires C99 or later due to the usage of
inline):
[
// compiler.h
#define likely(x) __builtin_expect((x), 1)
#define unlikely(x) __builtin_expect((x), 0)
]
[
// strlennull.h
#include <string.h>
#include <sys/types.h>
#include "compiler.h"
[[gnu::pure]]
inline ssize_t strlennull(const char *s);
inline ssize_t strlennull(const char *s)
{
if (unlikely(!s))
return -1;
return strlen(s);
}
]
[
// strlennull.c
#include "strlennull.h"
#include <sys/types.h>
extern inline ssize_t strlennull(const char *s);
]
BTW, if the input is so untrusted that NULL may be possible, I guess it
might as well contain invalid strings (non-NUL-terminated), for which
strlen(3) would behave as bad or worse. So I recommend having a look at
strnlen(3) and maybe implement strnlennull() instead of strlennull().
Unless you _know_ there's a compiler bug that doesn't allow you to
optimize, please optimize. Otherwise, if it's just a bit of paranoia,
you could as well not optimize any code at all. Specifically not
optimizing this code by the use of pragmas or attributes is *wrong*.
Just revise the preprocessor output, the compiler output, and also try
introducing a NULL at run time, to check that everything's fine.
>
> I also use 'volatile' for reads/writes to addresses that I don't want to be optimized out.
Are you sure you don't want to optimize? Are those addresses hardware
I/O or interrupts?
Maybe you just want membarrier(2).
>
>>
>> What I recommend you to do from time to time, to make sure you don't miss any warnings, is compile the whole project first with '-O3' and then with '-O0'. If you are a bit paranoic, sporadically you can try all of them : '-Og', '-O0', '-O1', '-Os', '-O2', '-O3', '-Ofast' but I don't think that is necessary. Of course, always use '-fanalyzer' (GCC 10 and above).
>
> Yes, I am looking forward to David Malcom's -fanalyzer when Ubuntu LTS next upgrades, I'm on gcc 9.3 today. But -fanalyzer is only for C anyway.. much of of code base I work with is compiled as C++ so I can't use -fanalyzer yet.
You can install gcc-10 for Bionic: apt-get install gcc-10
I recommend it. It finds bugs very deep in the code.
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-08 11:06 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 ` strlen Alejandro Colomar (man-pages)
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 ` Alejandro Colomar (man-pages) [this message]
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=feb6c15d-b242-83fc-c58d-2ebfbcd4f2bd@gmail.com \
--to=alx.manpages@gmail.com \
--cc=fw@deneb.enyo.de \
--cc=gcc-help@gcc.gnu.org \
--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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.