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

Reply via email to