[PATCH 0/2] Some static checker fixes
We already had a couple of places we were working around clang-tidy
issue 58992, and the flow table series adds more. I got sick of ugly
inlines every time we used a syscall which returns a socket address,
so wrote a patch to consolidate the workarounds in one place.
However, that patch added an include of
A classic gotcha of the standard C library is that its unwise to call any
variable 'index' because it will shadow the standard string library
function index(3). This can cause warnings from cppcheck amongst others,
and it also means that if the variable is removed you tend to get confusing
type errors (or sometimes nothing at all) instead of a nice simple "name is
not defined" error.
Strictly speaking this only occurs if
On Fri, 15 Sep 2023 16:43:36 +1000
David Gibson
A classic gotcha of the standard C library is that its unwise to call any variable 'index' because it will shadow the standard string library function index(3). This can cause warnings from cppcheck amongst others, and it also means that if the variable is removed you tend to get confusing type errors (or sometimes nothing at all) instead of a nice simple "name is not defined" error.
Strictly speaking this only occurs if
is included, but that is so common that as a rule it's best to just avoid it always. We have a few places in packet.[ch] which hit this trap so rename the variables to avoid it. Signed-off-by: David Gibson
--- packet.c | 28 ++++++++++++++-------------- packet.h | 10 +++++----- 2 files changed, 19 insertions(+), 19 deletions(-) diff --git a/packet.c b/packet.c index ce807e2..8e3a87c 100644 --- a/packet.c +++ b/packet.c @@ -33,11 +33,11 @@ void packet_add_do(struct pool *p, size_t len, const char *start, const char *func, int line) { - size_t index = p->count; + size_t idx = p->count;
- if (index >= p->size) { + if (idx >= p->size) { trace("add packet index %lu to pool with size %lu, %s:%i", - index, p->size, func, line); + idx, p->size, func, line); return; }
@@ -66,8 +66,8 @@ void packet_add_do(struct pool *p, size_t len, const char *start, } #endif
- p->pkt[index].offset = start - p->buf; - p->pkt[index].len = len; + p->pkt[idx].offset = start - p->buf; + p->pkt[idx].len = len;
p->count++; } @@ -84,13 +84,13 @@ void packet_add_do(struct pool *p, size_t len, const char *start, * * Return: pointer to start of data range, NULL on invalid range or descriptor */ -void *packet_get_do(const struct pool *p, size_t index, size_t offset, +void *packet_get_do(const struct pool *p, size_t idx, size_t offset,
Really minor, but... the comment about @index should be updated as well. -- Stefano
On Mon, Sep 18, 2023 at 10:16:00AM +0200, Stefano Brivio wrote:
On Fri, 15 Sep 2023 16:43:36 +1000 David Gibson
wrote: A classic gotcha of the standard C library is that its unwise to call any variable 'index' because it will shadow the standard string library function index(3). This can cause warnings from cppcheck amongst others, and it also means that if the variable is removed you tend to get confusing type errors (or sometimes nothing at all) instead of a nice simple "name is not defined" error.
Strictly speaking this only occurs if
is included, but that is so common that as a rule it's best to just avoid it always. We have a few places in packet.[ch] which hit this trap so rename the variables to avoid it. Signed-off-by: David Gibson
--- packet.c | 28 ++++++++++++++-------------- packet.h | 10 +++++----- 2 files changed, 19 insertions(+), 19 deletions(-) diff --git a/packet.c b/packet.c index ce807e2..8e3a87c 100644 --- a/packet.c +++ b/packet.c @@ -33,11 +33,11 @@ void packet_add_do(struct pool *p, size_t len, const char *start, const char *func, int line) { - size_t index = p->count; + size_t idx = p->count;
- if (index >= p->size) { + if (idx >= p->size) { trace("add packet index %lu to pool with size %lu, %s:%i", - index, p->size, func, line); + idx, p->size, func, line); return; }
@@ -66,8 +66,8 @@ void packet_add_do(struct pool *p, size_t len, const char *start, } #endif
- p->pkt[index].offset = start - p->buf; - p->pkt[index].len = len; + p->pkt[idx].offset = start - p->buf; + p->pkt[idx].len = len;
p->count++; } @@ -84,13 +84,13 @@ void packet_add_do(struct pool *p, size_t len, const char *start, * * Return: pointer to start of data range, NULL on invalid range or descriptor */ -void *packet_get_do(const struct pool *p, size_t index, size_t offset, +void *packet_get_do(const struct pool *p, size_t idx, size_t offset,
Really minor, but... the comment about @index should be updated as well.
Oops, yes. Fixed. -- David Gibson | I'll have my music baroque, and my code david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_ | _way_ _around_! http://www.ozlabs.org/~dgibson
We have several workarounds for a clang-tidy bug where the checker doesn't
recognize that a number of system calls write to - and therefore initialise
- a socket address. We can't neatly use a suppression, because the bogus
warning shows up some time after the actual system call, when we access
a field of the socket address which clang-tidy erroneously thinks is
uninitialised.
Consolidate these workarounds into one place by using macros to implement
wrappers around affected system calls which add a memset() of the sockaddr
to silence clang-tidy. This removes the need for the individual memset()
workarounds at the callers - and the somewhat longwinded explanatory
comments.
We can then use a #define to not include the hack in "real" builds, but
only consider it for clang-tidy.
Signed-off-by: David Gibson
On Fri, 15 Sep 2023 16:43:37 +1000
David Gibson
We have several workarounds for a clang-tidy bug where the checker doesn't recognize that a number of system calls write to - and therefore initialise - a socket address. We can't neatly use a suppression, because the bogus warning shows up some time after the actual system call, when we access a field of the socket address which clang-tidy erroneously thinks is uninitialised.
Consolidate these workarounds into one place by using macros to implement wrappers around affected system calls which add a memset() of the sockaddr to silence clang-tidy. This removes the need for the individual memset() workarounds at the callers - and the somewhat longwinded explanatory comments.
We can then use a #define to not include the hack in "real" builds, but only consider it for clang-tidy.
I'm probably missing something, but wouldn't it be more obvious to conditionally define the wrapper itself? That is, #ifdef CLANG_TIDY_58992 # define recvfrom(s, buf, len, flags, src, addrlen) \ wrap_recvfrom((s), (buf), (len), (flags), (src), (addrlen)) #endif instead of doing that in sa_init()? -- Stefano
On Mon, Sep 18, 2023 at 10:16:08AM +0200, Stefano Brivio wrote:
On Fri, 15 Sep 2023 16:43:37 +1000 David Gibson
wrote: We have several workarounds for a clang-tidy bug where the checker doesn't recognize that a number of system calls write to - and therefore initialise - a socket address. We can't neatly use a suppression, because the bogus warning shows up some time after the actual system call, when we access a field of the socket address which clang-tidy erroneously thinks is uninitialised.
Consolidate these workarounds into one place by using macros to implement wrappers around affected system calls which add a memset() of the sockaddr to silence clang-tidy. This removes the need for the individual memset() workarounds at the callers - and the somewhat longwinded explanatory comments.
We can then use a #define to not include the hack in "real" builds, but only consider it for clang-tidy.
I'm probably missing something, but wouldn't it be more obvious to conditionally define the wrapper itself? That is,
#ifdef CLANG_TIDY_58992 # define recvfrom(s, buf, len, flags, src, addrlen) \ wrap_recvfrom((s), (buf), (len), (flags), (src), (addrlen)) #endif
instead of doing that in sa_init()?
Eh.. maybe? I was going for minimal differences in the preprocessed code between the two cases, to reduce the chances of missing some unrelated real problem due to the fact we're kind of lying to our static checker. I don't feel that strongly about it though, so whichever you'd prefer is fine. -- David Gibson | I'll have my music baroque, and my code david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_ | _way_ _around_! http://www.ozlabs.org/~dgibson
On Tue, 19 Sep 2023 11:08:51 +1000
David Gibson
On Mon, Sep 18, 2023 at 10:16:08AM +0200, Stefano Brivio wrote:
On Fri, 15 Sep 2023 16:43:37 +1000 David Gibson
wrote: We have several workarounds for a clang-tidy bug where the checker doesn't recognize that a number of system calls write to - and therefore initialise - a socket address. We can't neatly use a suppression, because the bogus warning shows up some time after the actual system call, when we access a field of the socket address which clang-tidy erroneously thinks is uninitialised.
Consolidate these workarounds into one place by using macros to implement wrappers around affected system calls which add a memset() of the sockaddr to silence clang-tidy. This removes the need for the individual memset() workarounds at the callers - and the somewhat longwinded explanatory comments.
We can then use a #define to not include the hack in "real" builds, but only consider it for clang-tidy.
I'm probably missing something, but wouldn't it be more obvious to conditionally define the wrapper itself? That is,
#ifdef CLANG_TIDY_58992 # define recvfrom(s, buf, len, flags, src, addrlen) \ wrap_recvfrom((s), (buf), (len), (flags), (src), (addrlen)) #endif
instead of doing that in sa_init()?
Eh.. maybe? I was going for minimal differences in the preprocessed code between the two cases, to reduce the chances of missing some unrelated real problem due to the fact we're kind of lying to our static checker.
Ah, okay, I see your point -- in both cases we'd call a function (even though one is going to be inlined, the other one not necessarily)... sure, it makes sense. -- Stefano
participants (2)
-
David Gibson
-
Stefano Brivio