llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clang Author: Radovan Božić (bozicrHT) <details> <summary>Changes</summary> `castRegion()` returns `nullopt` for `ElementRegion`s with symbolic indices, causing pointer casts to become `UnknownVal` and lose nullness information. Preserve the original region as a zero-offset view of the destination type, while stripping redundant cast views. Update tests for symbolic pointer casts. Fixes #<!-- -->220281 --- Full diff: https://github.com/llvm/llvm-project/pull/221213.diff 3 Files Affected: - (modified) clang/lib/StaticAnalyzer/Core/Store.cpp (+7-4) - (modified) clang/test/Analysis/pr22954.c (+3-2) - (added) clang/test/Analysis/symbolic-pointer-cast.c (+42) ``````````diff diff --git a/clang/lib/StaticAnalyzer/Core/Store.cpp b/clang/lib/StaticAnalyzer/Core/Store.cpp index 3b56dde1b56d6..0a91b452ee11d 100644 --- a/clang/lib/StaticAnalyzer/Core/Store.cpp +++ b/clang/lib/StaticAnalyzer/Core/Store.cpp @@ -175,10 +175,13 @@ std::optional<const MemRegion *> StoreManager::castRegion(const MemRegion *R, const RegionRawOffset &rawOff = elementR->getAsArrayOffset(); const MemRegion *baseR = rawOff.getRegion(); - // If we cannot compute a raw offset, throw up our hands and return - // a NULL MemRegion*. - if (!baseR) - return std::nullopt; + if (!baseR) { + const MemRegion *uncastedR = elementR->StripCasts(false); + if (IsSameRegionType(uncastedR, CanonPointeeTy)) + return uncastedR; + + return MakeElementRegion(cast<SubRegion>(uncastedR), PointeeTy); + } CharUnits off = rawOff.getOffset(); diff --git a/clang/test/Analysis/pr22954.c b/clang/test/Analysis/pr22954.c index b3910da6c70ab..1a14d83ca2ae9 100644 --- a/clang/test/Analysis/pr22954.c +++ b/clang/test/Analysis/pr22954.c @@ -615,7 +615,8 @@ int f29(int i, int j, int k, int l, int m) { l29->s1[m] = 2; char input[] = {'a', 'b', 'c', 'd'}; memcpy(l29->s1, input, 4); - clang_analyzer_eval(m29[0].s3[0] == 1); // expected-warning{{UNKNOWN}} + clang_analyzer_eval(m29[0].s3[0] == 1); // expected-warning{{UNKNOWN}}\ + expected-warning{{Potential leak of memory pointed to by field 's4'}} clang_analyzer_eval(m29[0].s3[1] == 1); // expected-warning{{UNKNOWN}} clang_analyzer_eval(m29[0].s3[2] == 1); // expected-warning{{UNKNOWN}} clang_analyzer_eval(m29[0].s3[3] == 1); // expected-warning{{UNKNOWN}} @@ -627,7 +628,7 @@ int f29(int i, int j, int k, int l, int m) { clang_analyzer_eval(m29[i].s3[1] == 1); // expected-warning{{UNKNOWN}} clang_analyzer_eval(m29[i].s3[2] == 1); // expected-warning{{UNKNOWN}} clang_analyzer_eval(m29[i].s3[3] == 1); // expected-warning{{UNKNOWN}} - clang_analyzer_eval(m29[j].s3[k] == 1); // expected-warning{{TRUE}} + clang_analyzer_eval(m29[j].s3[k] == 1); // expected-warning{{UNKNOWN}} clang_analyzer_eval(l29->s1[m] == 2); // expected-warning{{UNKNOWN}} // FIXME: Should warn that m29[i].s4 leaks. But not on the previous line, // because l29 and m29 alias. diff --git a/clang/test/Analysis/symbolic-pointer-cast.c b/clang/test/Analysis/symbolic-pointer-cast.c new file mode 100644 index 0000000000000..9804254808343 --- /dev/null +++ b/clang/test/Analysis/symbolic-pointer-cast.c @@ -0,0 +1,42 @@ +// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -verify %s + +void clang_analyzer_eval(int); + +void symbolic_offset_pointer_cast_preserves_nonnull(_Bool i) { + unsigned char a[2]; + unsigned char *q = a + i; + char *r = (char *)q; + + clang_analyzer_eval(q != 0); // expected-warning{{TRUE}} + clang_analyzer_eval(r != 0); // expected-warning{{TRUE}} + + if (!r) + *r = 0; // no-warning +} + +void differently_sized_symbolic_offset_pointer_cast_preserves_nonnull(_Bool i) { + int a[2]; + int *q = a + i; + char *r = (char *)q; + int *s = (int *)r; + + clang_analyzer_eval(r != 0); // expected-warning{{TRUE}} + clang_analyzer_eval(s == q); // expected-warning{{TRUE}} + + if (!r) + *r = 0; // no-warning +} + +void symbolic_base_pointer_cast_preserves_nonnull(int *p, _Bool i) { + if (!p) + return; + + int *q = p + i; + char *r = (char *)q; + + clang_analyzer_eval(q != 0); // expected-warning{{TRUE}} + clang_analyzer_eval(r != 0); // expected-warning{{TRUE}} + + if (!r) + *r = 0; // no-warning +} `````````` </details> https://github.com/llvm/llvm-project/pull/221213 _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
