llvm / llvm-project

The LLVM Project is a collection of modular and reusable compiler and toolchain technologies.
http://llvm.org
Other
28.28k stars 11.68k forks source link

track linear constraints #4922

Open llvmbot opened 15 years ago

llvmbot commented 15 years ago
Bugzilla Link 4550
Version trunk
OS FreeBSD
Blocks llvm/llvm-bugzilla-archive#5780 llvm/llvm-bugzilla-archive#5976
Attachments snipped from FreeBSD sh(1)'s expand.c
Reporter LLVM Bugzilla Contributor
CC @devincoughlin,@loskutov,@kirillbobyrev,@tkremenek

Extended Description

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.

edwintorok commented 2 years ago

mentioned in issue llvm/llvm-bugzilla-archive#5976

llvmbot commented 2 years ago

mentioned in issue llvm/llvm-bugzilla-archive#5780

2cebcbff-deb3-4f85-8491-d6b0a69d170c commented 5 years ago

The issue still reproduces with recent builds.

$ cat test.c

include

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

devincoughlin commented 8 years ago

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

include

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); }

kirillbobyrev commented 8 years ago

The bug is not reproducible anymore using clang 3.7/3.8.

tkremenek commented 15 years ago

This is related to PR 2695.

tkremenek commented 15 years ago

The analyzer does track a range constraint for 'len'. What is lost is the linear constraint that 'half = len / 2'.

llvmbot commented 15 years ago

assigned to @tkremenek