https://github.com/balazske created https://github.com/llvm/llvm-project/pull/102432
Notes appear at out-of-range array index for index value and array size. From b9753a79654b1428f753a2fad865eacdf0250ac5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bal=C3=A1zs=20K=C3=A9ri?= <balazs.k...@ericsson.com> Date: Thu, 8 Aug 2024 09:45:14 +0200 Subject: [PATCH] [clang][analyzer] Add more notes to PointerSubChecker Notes appear at out-of-range array index for index value and array size. --- .../Checkers/PointerSubChecker.cpp | 30 +++++++++++++---- clang/test/Analysis/pointer-sub.c | 32 +++++++++++++++---- 2 files changed, 48 insertions(+), 14 deletions(-) diff --git a/clang/lib/StaticAnalyzer/Checkers/PointerSubChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/PointerSubChecker.cpp index b856b0edc6151..1b215cc59c95a 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 194c891889952..0ce8fe850ca0f 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; +} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits