Package: cppcheck
Version: 2.3-1
Severity: normal
Thank you for packaging cppcheck 2.3! I'm pleased to confirm that the
bugs that I reported in #943463 were indeed fixed in that release.
Unfortunately, it appears to have introduced a few more false positives
in this general area. Here is a minimized test case:
#include <stdint.h>
#include <some-header.h>
int
test_a(void)
{
uint32_t pag;
struct some_struct foo;
pag = (uint32_t) -1;
/* The bug disappears if &pag is not cast to void *. */
foo.pag = (void *) &pag;
foo.pag_size = sizeof(pag);
result = some_call(&foo);
if (result == 0)
return pag != (uint32_t) -1;
}
int
test_b(void)
{
char **string = NULL;
/* The bug disappears if retval is not included in the check. */
retval = some_other_call(&string);
if (retval && string && string[0])
return 0;
return -1;
}
void
test_c(void)
{
some_type *foo = NULL;
other_type blah;
retval = call_a(&foo);
if (retval != 0)
goto done;
blah.flag = foo->flag;
call_b(&blah);
done:
if (foo != NULL)
free_foo(foo);
}
And here is the output from cppcheck:
% cppcheck --enable=warning,style foo.c
Checking foo.c ...
foo.c:16:20: style: Condition 'pag!=(uint32_t)-1' is always false
[knownConditionTrueFalse]
return pag != (uint32_t) -1;
^
foo.c:10:11: note: Assignment 'pag=(uint32_t)-1', assigned value is 4294967295
pag = (uint32_t) -1;
^
foo.c:16:20: note: Condition 'pag!=(uint32_t)-1' is always false
return pag != (uint32_t) -1;
^
foo.c:22:12: warning: Either the condition 'retval&&string' is redundant or
there is possible null pointer dereference: string. [nullPointerRedundantCheck]
char **string = NULL;
^
foo.c:26:16: note: Assuming that condition 'retval&&string' is not redundant
if (retval && string && string[0])
^
foo.c:22:12: note: Null pointer dereference
char **string = NULL;
^
foo.c:40:17: warning: Either the condition 'foo!=NULL' is redundant or there is
possible null pointer dereference: foo. [nullPointerRedundantCheck]
blah.flag = foo->flag;
^
foo.c:44:13: note: Assuming that condition 'foo!=NULL' is not redundant
if (foo != NULL)
^
foo.c:40:17: note: Null pointer dereference
blah.flag = foo->flag;
^
The common theme in all three cases is that a variable is passed by
address to another function (via adding its address to a struct or
just directly), and cppcheck loses track of the fact that function may
have changed its value.
In the first case, I think the (void *) cast is the key. If it's
removed, cppcheck understands the code correctly. (But this is sometimes
required by badly-designed APIs.)
In the second case, something about adding retval to the test messes up
its understanding of the data flow.
The third case seems similar to the previous set of bugs, although note
that it only happens with assignment. If that line is instead replaced
with something like call_c(foo->flag), there is no error.
(Apologies, I haven't reported these upstream since they want bug
reporters to catch them on IRC to get a Trac account created.)
-- System Information:
Debian Release: bullseye/sid
APT prefers unstable
APT policy: (990, 'unstable'), (500, 'unstable-debug'), (1, 'experimental')
Architecture: amd64 (x86_64)
Kernel: Linux 5.9.0-4-amd64 (SMP w/8 CPU threads)
Kernel taint flags: TAINT_PROPRIETARY_MODULE, TAINT_OOT_MODULE,
TAINT_UNSIGNED_MODULE
Locale: LANG=en_US.UTF-8, LC_CTYPE=en_US.UTF-8 (charmap=UTF-8), LANGUAGE not set
Shell: /bin/sh linked to /bin/dash
Init: systemd (via /run/systemd/system)
LSM: AppArmor: enabled
Versions of packages cppcheck depends on:
ii libc6 2.31-5
ii libgcc-s1 10.2.1-1
ii libpcre3 2:8.39-13
ii libstdc++6 10.2.1-1
ii libtinyxml2-8 8.0.0+dfsg-2
ii libz3-4 4.8.9-1
ii python3 3.9.0-4
ii python3-pygments 2.7.1+dfsg-1
cppcheck recommends no packages.
Versions of packages cppcheck suggests:
ii clang 1:11.0-51
pn clang-tidy <none>
pn cppcheck-gui <none>
-- no debconf information