[clang] fd41f1b - [clang][analyzer] Add BugReporterVisitor messages for non-null fixed pointer (#129557)
via cfe-commits
cfe-commits at lists.llvm.org
Mon Mar 17 01:47:01 PDT 2025
Author: Balázs Kéri
Date: 2025-03-17T09:46:58+01:00
New Revision: fd41f1b0ce1e7d4eb2d51da82418b3e41dbb59ba
URL: https://github.com/llvm/llvm-project/commit/fd41f1b0ce1e7d4eb2d51da82418b3e41dbb59ba
DIFF: https://github.com/llvm/llvm-project/commit/fd41f1b0ce1e7d4eb2d51da82418b3e41dbb59ba.diff
LOG: [clang][analyzer] Add BugReporterVisitor messages for non-null fixed pointer (#129557)
Added:
clang/test/Analysis/fixed-address-notes.c
Modified:
clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
Removed:
################################################################################
diff --git a/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp b/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
index f638cb23302c0..6e7aba65c94ea 100644
--- a/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
+++ b/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
@@ -1223,6 +1223,27 @@ static bool isObjCPointer(const ValueDecl *D) {
return D->getType()->isObjCObjectPointerType();
}
+namespace {
+using DestTypeValue = std::pair<const StoreInfo &, loc::ConcreteInt>;
+
+llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const DestTypeValue &Val) {
+ if (auto *TyR = Val.first.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())
+ OS << "(" << PStr << ")";
+ }
+ }
+ }
+ SmallString<16> ValStr;
+ Val.second.getValue()->toString(ValStr, 10, true);
+ OS << ValStr;
+ return OS;
+}
+} // namespace
+
/// 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 +1266,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 << DestTypeValue(SI, *CVal);
} else if (auto CVal = SI.Value.getAs<nonloc::ConcreteInt>()) {
OS << Action << CVal->getValue();
@@ -1288,8 +1312,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 ")
+ << DestTypeValue(SI, *CI);
} else if (SI.Value.isUndef()) {
OS << "uninitialized value";
@@ -1324,11 +1352,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 {
+ if (isObjCPointer(SI.Dest)) {
+ OS << "object reference of value " << DestTypeValue(SI, *CV)
+ << " stored";
+ } else {
+ if (HasSuffix)
+ OS << "Pointer value of " << DestTypeValue(SI, *CV) << " stored";
+ else
+ OS << "Storing pointer value of " << DestTypeValue(SI, *CV);
+ }
+ }
} 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..fd7baf7fc14cb
--- /dev/null
+++ b/clang/test/Analysis/fixed-address-notes.c
@@ -0,0 +1,52 @@
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.core.FixedAddressDereference -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 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')}}
+}
More information about the cfe-commits
mailing list