https://github.com/balazske created https://github.com/llvm/llvm-project/pull/95899
Notes are added to indicate the array declarations of the arrays in a found invalid pointer subtraction. From 1eb6e7ebde0e97e1cd077dc27ffd3ebd6ed0e93d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bal=C3=A1zs=20K=C3=A9ri?= <balazs.k...@ericsson.com> Date: Tue, 18 Jun 2024 10:09:24 +0200 Subject: [PATCH] [clang][analyzer] Add notes to PointerSubChecker Notes are added to indicate the array declarations of the arrays in a found invalid pointer subtraction. --- .../Checkers/PointerSubChecker.cpp | 45 ++++++++++++------- clang/test/Analysis/pointer-sub-notes.c | 34 ++++++++++++++ 2 files changed, 64 insertions(+), 15 deletions(-) create mode 100644 clang/test/Analysis/pointer-sub-notes.c diff --git a/clang/lib/StaticAnalyzer/Checkers/PointerSubChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/PointerSubChecker.cpp index b73534136fdf0..a983e66df0818 100644 --- a/clang/lib/StaticAnalyzer/Checkers/PointerSubChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/PointerSubChecker.cpp @@ -43,8 +43,6 @@ class PointerSubChecker bool checkArrayBounds(CheckerContext &C, const Expr *E, const ElementRegion *ElemReg, const MemRegion *Reg) const; - void reportBug(CheckerContext &C, const Expr *E, - const llvm::StringLiteral &Msg) const; public: void checkPreStmt(const BinaryOperator *B, CheckerContext &C) const; @@ -57,6 +55,14 @@ bool PointerSubChecker::checkArrayBounds(CheckerContext &C, const Expr *E, if (!ElemReg) return true; + auto ReportBug = [&](const llvm::StringLiteral &Msg) { + if (ExplodedNode *N = C.generateNonFatalErrorNode()) { + auto R = std::make_unique<PathSensitiveBugReport>(BT, Msg, N); + R->addRange(E->getSourceRange()); + C.emitReport(std::move(R)); + } + }; + ProgramStateRef State = C.getState(); const MemRegion *SuperReg = ElemReg->getSuperRegion(); SValBuilder &SVB = C.getSValBuilder(); @@ -64,7 +70,7 @@ bool PointerSubChecker::checkArrayBounds(CheckerContext &C, const Expr *E, if (SuperReg == Reg) { if (const llvm::APSInt *I = SVB.getKnownValue(State, ElemReg->getIndex()); I && (!I->isOne() && !I->isZero())) - reportBug(C, E, Msg_BadVarIndex); + ReportBug(Msg_BadVarIndex); return false; } @@ -77,7 +83,7 @@ bool PointerSubChecker::checkArrayBounds(CheckerContext &C, const Expr *E, ProgramStateRef S1, S2; std::tie(S1, S2) = C.getState()->assume(*IndexTooLarge); if (S1 && !S2) { - reportBug(C, E, Msg_LargeArrayIndex); + ReportBug(Msg_LargeArrayIndex); return false; } } @@ -89,22 +95,13 @@ bool PointerSubChecker::checkArrayBounds(CheckerContext &C, const Expr *E, ProgramStateRef S1, S2; std::tie(S1, S2) = State->assume(*IndexTooSmall); if (S1 && !S2) { - reportBug(C, E, Msg_NegativeArrayIndex); + ReportBug(Msg_NegativeArrayIndex); return false; } } return true; } -void PointerSubChecker::reportBug(CheckerContext &C, const Expr *E, - const llvm::StringLiteral &Msg) const { - if (ExplodedNode *N = C.generateNonFatalErrorNode()) { - auto R = std::make_unique<PathSensitiveBugReport>(BT, Msg, N); - R->addRange(E->getSourceRange()); - C.emitReport(std::move(R)); - } -} - void PointerSubChecker::checkPreStmt(const BinaryOperator *B, CheckerContext &C) const { // When doing pointer subtraction, if the two pointers do not point to the @@ -136,6 +133,9 @@ void PointerSubChecker::checkPreStmt(const BinaryOperator *B, if (!checkArrayBounds(C, B->getRHS(), ElemRR, LR)) return; + const ValueDecl *DiffDeclL = nullptr; + const ValueDecl *DiffDeclR = nullptr; + if (ElemLR && ElemRR) { const MemRegion *SuperLR = ElemLR->getSuperRegion(); const MemRegion *SuperRR = ElemRR->getSuperRegion(); @@ -144,9 +144,24 @@ void PointerSubChecker::checkPreStmt(const BinaryOperator *B, // Allow arithmetic on different symbolic regions. if (isa<SymbolicRegion>(SuperLR) || isa<SymbolicRegion>(SuperRR)) return; + if (const auto *SuperDLR = dyn_cast<DeclRegion>(SuperLR)) + DiffDeclL = SuperDLR->getDecl(); + if (const auto *SuperDRR = dyn_cast<DeclRegion>(SuperRR)) + DiffDeclR = SuperDRR->getDecl(); } - reportBug(C, B, Msg_MemRegionDifferent); + if (ExplodedNode *N = C.generateNonFatalErrorNode()) { + auto R = + std::make_unique<PathSensitiveBugReport>(BT, Msg_MemRegionDifferent, N); + R->addRange(B->getSourceRange()); + if (DiffDeclL) + R->addNote("Array at the left-hand side of subtraction", + {DiffDeclL, C.getSourceManager()}); + if (DiffDeclR) + R->addNote("Array at the right-hand side of subtraction", + {DiffDeclR, C.getSourceManager()}); + C.emitReport(std::move(R)); + } } void ento::registerPointerSubChecker(CheckerManager &mgr) { diff --git a/clang/test/Analysis/pointer-sub-notes.c b/clang/test/Analysis/pointer-sub-notes.c new file mode 100644 index 0000000000000..dfdace3a58deb --- /dev/null +++ b/clang/test/Analysis/pointer-sub-notes.c @@ -0,0 +1,34 @@ +// RUN: %clang_analyze_cc1 -analyzer-checker=alpha.core.PointerSub -analyzer-output=text -verify %s + +void negative_1() { + int a[3]; + int x = -1; + // FIXME: should indicate that 'x' is -1 + int d = &a[x] - &a[0]; // expected-warning{{Using a negative array index at pointer subtraction is undefined behavior}} \ + // expected-note{{Using a negative array index at pointer subtraction is undefined behavior}} +} + +void negative_2() { + int a[3]; + int *p1 = a, *p2 = a; + --p2; + // FIXME: should indicate that 'p2' is negative + int d = p1 - p2; // expected-warning{{Using a negative array index at pointer subtraction is undefined behavior}} \ + // expected-note{{Using a negative array index at pointer subtraction is undefined behavior}} +} + +void different_1() { + int a[3]; // expected-note{{Array at the left-hand side of subtraction}} + int b[3]; // expected-note{{Array at the right-hand side of subtraction}} + int d = &a[2] - &b[0]; // expected-warning{{Subtraction of two pointers that do not point into the same array is undefined behavior}} \ + // expected-note{{Subtraction of two pointers that do not point into the same array is undefined behavior}} +} + +void different_2() { + int a[3]; // expected-note{{Array at the right-hand side of subtraction}} + int b[3]; // expected-note{{Array at the left-hand side of subtraction}} + int *p1 = a + 1; + int *p2 = b; + int d = p2 - p1; // expected-warning{{Subtraction of two pointers that do not point into the same array is undefined behavior}} \ + // expected-note{{Subtraction of two pointers that do not point into the same array is undefined behavior}} +} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits