[clang] [clang][analyzer] Add BugReporterVisitor messages for non-null fixed pointer (PR #129557)

Balázs Kéri via cfe-commits cfe-commits at lists.llvm.org
Thu Mar 6 08:56:53 PST 2025


https://github.com/balazske updated https://github.com/llvm/llvm-project/pull/129557

>From 8006fde8ad615dffcaf38bc017b58d6bbed59ae2 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bal=C3=A1zs=20K=C3=A9ri?= <balazs.keri at ericsson.com>
Date: Mon, 3 Mar 2025 17:57:19 +0100
Subject: [PATCH 1/3] [clang][analyzer] Add BugReporterVisitor messages for
 non-null fixed pointer

---
 .../Core/BugReporterVisitors.cpp              | 60 ++++++++++++++++---
 clang/test/Analysis/fixed-address-notes.c     | 52 ++++++++++++++++
 2 files changed, 103 insertions(+), 9 deletions(-)
 create mode 100644 clang/test/Analysis/fixed-address-notes.c

diff --git a/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp b/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
index f638cb23302c0..fe9f39e6b66c5 100644
--- a/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
+++ b/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
@@ -1223,6 +1223,28 @@ static bool isObjCPointer(const ValueDecl *D) {
   return D->getType()->isObjCObjectPointerType();
 }
 
+static std::string getDestTypeValueStr(const StoreInfo &SI,
+                                       loc::ConcreteInt CV) {
+  std::string Ret;
+  if (auto *TyR = SI.Dest->getAs<TypedRegion>()) {
+    QualType LocTy = TyR->getLocationType();
+    if (!LocTy.isNull()) {
+      if (auto *PtrTy = LocTy->getAs<PointerType>()) {
+        std::string PStr = PtrTy->getPointeeType().getAsString();
+        if (!PStr.empty()) {
+          Ret.append("(");
+          Ret.append(PStr);
+          Ret.append(")");
+        }
+      }
+    }
+  }
+  SmallString<16> ValStr;
+  CV.getValue()->toString(ValStr, 10, true);
+  Ret.append(ValStr.c_str());
+  return Ret;
+}
+
 /// Show diagnostics for initializing or declaring a region \p R with a bad value.
 static void showBRDiagnostics(llvm::raw_svector_ostream &OS, StoreInfo SI) {
   const bool HasPrefix = SI.Dest->canPrintPretty();
@@ -1245,8 +1267,11 @@ static void showBRDiagnostics(llvm::raw_svector_ostream &OS, StoreInfo SI) {
     llvm_unreachable("Unexpected store kind");
   }
 
-  if (isa<loc::ConcreteInt>(SI.Value)) {
-    OS << Action << (isObjCPointer(SI.Dest) ? "nil" : "a null pointer value");
+  if (auto CVal = SI.Value.getAs<loc::ConcreteInt>()) {
+    if (!*CVal->getValue())
+      OS << Action << (isObjCPointer(SI.Dest) ? "nil" : "a null pointer value");
+    else
+      OS << Action << getDestTypeValueStr(SI, *CVal);
 
   } else if (auto CVal = SI.Value.getAs<nonloc::ConcreteInt>()) {
     OS << Action << CVal->getValue();
@@ -1288,8 +1313,12 @@ static void showBRParamDiagnostics(llvm::raw_svector_ostream &OS,
 
   OS << "Passing ";
 
-  if (isa<loc::ConcreteInt>(SI.Value)) {
-    OS << (isObjCPointer(D) ? "nil object reference" : "null pointer value");
+  if (auto CI = SI.Value.getAs<loc::ConcreteInt>()) {
+    if (!*CI->getValue())
+      OS << (isObjCPointer(D) ? "nil object reference" : "null pointer value");
+    else
+      OS << (isObjCPointer(D) ? "object reference of value " : "pointer value ")
+         << getDestTypeValueStr(SI, *CI);
 
   } else if (SI.Value.isUndef()) {
     OS << "uninitialized value";
@@ -1324,11 +1353,24 @@ static void showBRDefaultDiagnostics(llvm::raw_svector_ostream &OS,
                                      StoreInfo SI) {
   const bool HasSuffix = SI.Dest->canPrintPretty();
 
-  if (isa<loc::ConcreteInt>(SI.Value)) {
-    OS << (isObjCPointer(SI.Dest) ? "nil object reference stored"
-                                  : (HasSuffix ? "Null pointer value stored"
-                                               : "Storing null pointer value"));
-
+  if (auto CV = SI.Value.getAs<loc::ConcreteInt>()) {
+    APSIntPtr V = CV->getValue();
+    if (!*V)
+      OS << (isObjCPointer(SI.Dest)
+                 ? "nil object reference stored"
+                 : (HasSuffix ? "Null pointer value stored"
+                              : "Storing null pointer value"));
+    else {
+      std::string TVStr = getDestTypeValueStr(SI, *CV);
+      if (isObjCPointer(SI.Dest)) {
+        OS << "object reference of value " << TVStr << " stored";
+      } else {
+        if (HasSuffix)
+          OS << "Pointer value of " << TVStr << " stored";
+        else
+          OS << "Storing pointer value of " << TVStr;
+      }
+    }
   } else if (SI.Value.isUndef()) {
     OS << (HasSuffix ? "Uninitialized value stored"
                      : "Storing uninitialized value");
diff --git a/clang/test/Analysis/fixed-address-notes.c b/clang/test/Analysis/fixed-address-notes.c
new file mode 100644
index 0000000000000..d1797bf2c7830
--- /dev/null
+++ b/clang/test/Analysis/fixed-address-notes.c
@@ -0,0 +1,52 @@
+// RUN: %clang_analyze_cc1 -analyzer-checker=core -analyzer-output=text -verify %s
+
+extern char *something();
+
+void test1() {
+  int *p;
+  p = (int *)22; // expected-note{{Pointer value of (int *)22 stored to 'p'}}
+  *p = 2; // expected-warning{{Dereference of a fixed address (loaded from variable 'p')}} \
+          // expected-note{{Dereference of a fixed address (loaded from variable 'p')}}
+}
+
+void test2_1(int *p) {
+  *p = 1; // expected-warning{{Dereference of a fixed address (loaded from variable 'p')}} \
+          // expected-note{{Dereference of a fixed address (loaded from variable 'p')}}
+}
+
+void test2() {
+  int *p = (int *)11; // expected-note{{'p' initialized to (int *)11}}
+  test2_1(p); // expected-note{{Passing pointer value (int *)11 via 1st parameter 'p'}} \
+              // expected-note{{Calling 'test2_1'}}
+}
+
+struct test3_s {
+  int a;
+};
+
+
+void test3() {
+  struct test3_s *x;
+  unsigned long val = 1111111; // expected-note{{'val' initialized to 1111111}}
+  x = (struct test3_s *)val; // expected-note{{Pointer value of (struct test3_s *)1111111 stored to 'x'}}
+  x->a = 3; // expected-warning{{Access to field 'a' results in a dereference of a fixed address (loaded from variable 'x')}} \
+            // expected-note{{Access to field 'a' results in a dereference of a fixed address (loaded from variable 'x')}}
+}
+
+char *test4_1() {
+  char *ret;
+  ret = something(); // expected-note{{Value assigned to 'ret'}}
+  if (ret == (char *)-1) // expected-note{{Assuming the condition is true}} \
+                         // expected-note{{Taking true branch}}
+    return ret; // expected-note{{Returning pointer (loaded from 'ret')}}
+  return 0;
+}
+
+void test4() {
+  char *x;
+  x = test4_1(); // expected-note{{Calling 'test4_1'}} \
+                 // expected-note{{Returning from 'test4_1'}} \
+                 // expected-note{{Pointer value of (char *)-1 stored to 'x'}}
+  *x = 3; // expected-warning{{Dereference of a fixed address (loaded from variable 'x')}} \
+          // expected-note{{Dereference of a fixed address (loaded from variable 'x')}}
+}

>From a45b3b0ae7eb5b8c2de756d6accba0085d5e91cf Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bal=C3=A1zs=20K=C3=A9ri?= <balazs.keri at ericsson.com>
Date: Tue, 4 Mar 2025 09:14:32 +0100
Subject: [PATCH 2/3] fixed test

---
 clang/test/Analysis/fixed-address-notes.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/clang/test/Analysis/fixed-address-notes.c b/clang/test/Analysis/fixed-address-notes.c
index d1797bf2c7830..41e21c1fd1ee9 100644
--- a/clang/test/Analysis/fixed-address-notes.c
+++ b/clang/test/Analysis/fixed-address-notes.c
@@ -1,4 +1,4 @@
-// RUN: %clang_analyze_cc1 -analyzer-checker=core -analyzer-output=text -verify %s
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.core.FixedAddressDereference -analyzer-output=text -verify %s
 
 extern char *something();
 

>From bb5cf239dd6cff2829e043462a8b43e7ccc0664b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bal=C3=A1zs=20K=C3=A9ri?= <balazs.keri at ericsson.com>
Date: Thu, 6 Mar 2025 17:56:15 +0100
Subject: [PATCH 3/3] fixed test (Windows x64)

---
 clang/test/Analysis/fixed-address-notes.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/clang/test/Analysis/fixed-address-notes.c b/clang/test/Analysis/fixed-address-notes.c
index 41e21c1fd1ee9..fd7baf7fc14cb 100644
--- a/clang/test/Analysis/fixed-address-notes.c
+++ b/clang/test/Analysis/fixed-address-notes.c
@@ -27,7 +27,7 @@ struct test3_s {
 
 void test3() {
   struct test3_s *x;
-  unsigned long val = 1111111; // expected-note{{'val' initialized to 1111111}}
+  unsigned long long val = 1111111; // expected-note{{'val' initialized to 1111111}}
   x = (struct test3_s *)val; // expected-note{{Pointer value of (struct test3_s *)1111111 stored to 'x'}}
   x->a = 3; // expected-warning{{Access to field 'a' results in a dereference of a fixed address (loaded from variable 'x')}} \
             // expected-note{{Access to field 'a' results in a dereference of a fixed address (loaded from variable 'x')}}



More information about the cfe-commits mailing list