[clang] [clang][analyzer] Add more notes to PointerSubChecker (PR #102432)
via cfe-commits
cfe-commits at lists.llvm.org
Thu Aug 8 00:53:19 PDT 2024
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang-static-analyzer-1
Author: Balázs Kéri (balazske)
<details>
<summary>Changes</summary>
Notes appear at out-of-range array index for index value and array size.
---
Full diff: https://github.com/llvm/llvm-project/pull/102432.diff
2 Files Affected:
- (modified) clang/lib/StaticAnalyzer/Checkers/PointerSubChecker.cpp (+23-7)
- (modified) clang/test/Analysis/pointer-sub.c (+25-7)
``````````diff
diff --git a/clang/lib/StaticAnalyzer/Checkers/PointerSubChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/PointerSubChecker.cpp
index b856b0edc61514..1b215cc59c95ae 100644
--- a/clang/lib/StaticAnalyzer/Checkers/PointerSubChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/PointerSubChecker.cpp
@@ -73,31 +73,47 @@ bool PointerSubChecker::checkArrayBounds(CheckerContext &C, const Expr *E,
if (!ElemReg)
return true;
+ ProgramStateRef State = C.getState();
+ SValBuilder &SVB = C.getSValBuilder();
+
const MemRegion *SuperReg = ElemReg->getSuperRegion();
if (!isArrayVar(SuperReg))
return true;
+ DefinedOrUnknownSVal ElemCount =
+ getDynamicElementCount(State, SuperReg, SVB, ElemReg->getElementType());
+
+ const ValueDecl *SuperDecl = nullptr;
+ if (auto *DR = dyn_cast<DeclRegion>(SuperReg))
+ SuperDecl = DR->getDecl();
+ const llvm::APSInt *ElemCountKnown = SVB.getKnownValue(State, ElemCount);
+ const llvm::APSInt *IndexKnown =
+ SVB.getKnownValue(State, ElemReg->getIndex());
auto ReportBug = [&](const llvm::StringLiteral &Msg) {
if (ExplodedNode *N = C.generateNonFatalErrorNode()) {
auto R = std::make_unique<PathSensitiveBugReport>(BT, Msg, N);
R->addRange(E->getSourceRange());
+ if (SuperDecl && ElemCountKnown && SuperDecl->getType()->isArrayType()) {
+ std::string Msg =
+ llvm::formatv("Array of size {0} declared here", *ElemCountKnown);
+ R->addNote(Msg, {SuperDecl, C.getSourceManager()});
+ }
+ if (IndexKnown) {
+ std::string Msg =
+ llvm::formatv("Memory object indexed with {0}", *IndexKnown);
+ R->addNote(Msg, {E, C.getSourceManager(), C.getLocationContext()});
+ }
C.emitReport(std::move(R));
}
};
- ProgramStateRef State = C.getState();
- SValBuilder &SVB = C.getSValBuilder();
-
if (SuperReg == Reg) {
// Case like `(&x + 1) - &x`. Only 1 or 0 is allowed as index.
- if (const llvm::APSInt *I = SVB.getKnownValue(State, ElemReg->getIndex());
- I && (!I->isOne() && !I->isZero()))
+ if (IndexKnown && (!IndexKnown->isOne() && !IndexKnown->isZero()))
ReportBug(Msg_BadVarIndex);
return false;
}
- DefinedOrUnknownSVal ElemCount =
- getDynamicElementCount(State, SuperReg, SVB, ElemReg->getElementType());
auto IndexTooLarge = SVB.evalBinOp(C.getState(), BO_GT, ElemReg->getIndex(),
ElemCount, SVB.getConditionType())
.getAs<DefinedOrUnknownSVal>();
diff --git a/clang/test/Analysis/pointer-sub.c b/clang/test/Analysis/pointer-sub.c
index 194c8918899525..0ce8fe850ca0fe 100644
--- a/clang/test/Analysis/pointer-sub.c
+++ b/clang/test/Analysis/pointer-sub.c
@@ -1,7 +1,7 @@
// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.core.PointerSub -analyzer-output=text-minimal -verify %s
void f1(void) {
- int x, y, z[10];
+ int x, y, z[10]; // expected-note2{{Array of size 10 declared here}}
int d = &y - &x; // expected-warning{{Subtraction of two pointers that do not point into the same array is undefined behavior}}
d = z - &y; // expected-warning{{Subtraction of two pointers that do not point into the same array is undefined behavior}}
d = &x - &x; // no-warning (subtraction of any two identical pointers is allowed)
@@ -9,18 +9,23 @@ void f1(void) {
d = (&x + 1) - &x; // no-warning ('&x' is like a single-element array)
d = &x - (&x + 1); // no-warning
d = (&x + 0) - &x; // no-warning
- d = (&x - 1) - &x; // expected-warning{{Indexing the address of a variable with other than 1 at this place is undefined behavior}}
- d = (&x + 2) - &x; // expected-warning{{Indexing the address of a variable with other than 1 at this place is undefined behavior}}
+ d = (&x - 1) - &x; // expected-warning{{Indexing the address of a variable with other than 1 at this place is undefined behavior}} \
+ // expected-note{{Memory object indexed with -1}}
+ d = (&x + 2) - &x; // expected-warning{{Indexing the address of a variable with other than 1 at this place is undefined behavior}} \
+ // expected-note{{Memory object indexed with 2}}
d = (z + 9) - z; // no-warning (pointers to same array)
d = (z + 10) - z; // no-warning (pointer to "one after the end")
- d = (z + 11) - z; // expected-warning{{Using an array index greater than the array size at pointer subtraction is undefined behavior}}
- d = (z - 1) - z; // expected-warning{{Using a negative array index at pointer subtraction is undefined behavior}}
+ d = (z + 11) - z; // expected-warning{{Using an array index greater than the array size at pointer subtraction is undefined behavior}} \
+ // expected-note{{Memory object indexed with 11}}
+ d = (z - 1) - z; // expected-warning{{Using a negative array index at pointer subtraction is undefined behavior}} \
+ // expected-note{{Memory object indexed with -1}}
}
void f2(void) {
int a[10], b[10], c; // expected-note{{Array at the left-hand side of subtraction}} \
- // expected-note2{{Array at the right-hand side of subtraction}}
+ // expected-note2{{Array at the right-hand side of subtraction}} \
+ // expected-note{{Array of size 10 declared here}}
int *p = &a[2];
int *q = &a[8];
int d = q - p; // no-warning (pointers into the same array)
@@ -31,7 +36,8 @@ void f2(void) {
q = a + 10;
d = q - p; // no warning (use of pointer to one after the end is allowed)
q = a + 11;
- d = q - a; // expected-warning{{Using an array index greater than the array size at pointer subtraction is undefined behavior}}
+ d = q - a; // expected-warning{{Using an array index greater than the array size at pointer subtraction is undefined behavior}} \
+ // expected-note{{Memory object indexed with 11}}
d = &a[4] - a; // no-warning
d = &a[2] - p; // no-warning
@@ -154,3 +160,15 @@ int f12() {
init_S2(&s);
return s.p1 - s.p2; // no-warning (pointers are unknown)
}
+
+void f13() {
+ int a[0]; // expected-note2{{Array of size 0 declared here}}
+ int *p1 = a, *p2 = a, *p3 = a;
+ --p1;
+ ++p2;
+ int d1 = a - p1; // expected-warning{{negative array index}} \
+ // expected-note{{Memory object indexed with -1}}
+ int d2 = a - p2; // expected-warning{{array index greater}} \
+ // expected-note{{Memory object indexed with 1}}
+ int d3 = a - p3;
+}
``````````
</details>
https://github.com/llvm/llvm-project/pull/102432
More information about the cfe-commits
mailing list