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 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).