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.k...@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.k...@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.k...@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')}} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits