Open Quuxplusone opened 15 years ago
Attached clang-expand.c
(347 bytes, text/plain): snipped from FreeBSD sh(1)'s expand.c
The analyzer does track a range constraint for 'len'. What is lost is the linear constraint that 'half = len / 2'.
This is related to PR 2695.
The bug is not reproducible anymore using clang 3.7/3.8.
Reopening because the static analyzer still does not track linear constraints.
The attached example (reproduced below) no longer shows a false positive in
more recent clangs because the analyzer changed its heuristics about when to
analyze functions at the top level, without context.
With these changed heuristics, the analyzer doesn't analyze msort() as a top-
level function but rather only in context (inlining) for the three calls in
main(). If you were to comment out main, the analysis would analyze msort() at
the top-level (making no assumptions about len) and show the false positive
again: "Dereference of null pointer (loaded from variable 'q')".
#include <stdlib.h>
#include <stdio.h>
static int dummy = 42;
void
msort(int len)
{
int *p, *q = NULL;
int half, n;
if (len <= 1)
return;
half = len >> 1;
p = &dummy;
for (n = half; --n >= 0; ) {
q = p;
}
printf("%d\n", *q); // <-- False positive here.
}
int
main(int argc, char **argv)
{
msort(1);
msort(2);
msort(3);
return (0);
}
The issue still reproduces with recent builds.
$ cat test.c
void foo(int i) { if (i != 0) { if (-i == 0) { (void) strlen(NULL); } } } $ clang-tidy-9 test.c Error while trying to load a compilation database: Could not auto-detect compilation database for file "test.c" No compilation database found in /tmp or any parent directory fixed-compilation-database: Error while opening fixed database: No such file or directory json-compilation-database: Error while opening JSON database: No such file or directory Running without flags. 2 warnings generated. /tmp/test.c:6:20: warning: Null pointer passed as an argument to a 'nonnull' parameter [clang-analyzer-core.NonNullParamChecker] (void) strlen(NULL); ^ /tmp/test.c:4:9: note: Assuming 'i' is not equal to 0 if (i != 0) { ^ /tmp/test.c:4:5: note: Taking true branch if (i != 0) { ^ /tmp/test.c:5:9: note: Taking true branch if (-i == 0) { ^ /tmp/test.c:6:20: note: Null pointer passed as an argument to a 'nonnull' parameter (void) strlen(NULL); ^ /tmp/test.c:6:31: warning: null passed to a callee that requires a non-null argument [clang-diagnostic-nonnull] (void) strlen(NULL); ^
Obviously, -i == 0
is false assuming i is not equal to 0
clang-expand.c
(347 bytes, text/plain)Hi, I'm not sure ccc-analyzer is already smart enough to avoid these false positives, but there is a pretty small function in FreeBSD's sh(1) where it fails. The real example can be seen at: https://www.spoerlein.net/scan-build/2009-07-04-1/report-STEwrs.html#EndPath
I'll attach a minimal test case showing the problem. The loop condition in that example can never be false, but is flagged as such.