@@ -43,8 +43,6 @@ class PointerSubChecker
4343 bool checkArrayBounds (CheckerContext &C, const Expr *E,
4444 const ElementRegion *ElemReg,
4545 const MemRegion *Reg) const ;
46- void reportBug (CheckerContext &C, const Expr *E,
47- const llvm::StringLiteral &Msg) const ;
4846
4947public:
5048 void checkPreStmt (const BinaryOperator *B, CheckerContext &C) const ;
@@ -57,14 +55,22 @@ bool PointerSubChecker::checkArrayBounds(CheckerContext &C, const Expr *E,
5755 if (!ElemReg)
5856 return true ;
5957
58+ auto ReportBug = [&](const llvm::StringLiteral &Msg) {
59+ if (ExplodedNode *N = C.generateNonFatalErrorNode ()) {
60+ auto R = std::make_unique<PathSensitiveBugReport>(BT, Msg, N);
61+ R->addRange (E->getSourceRange ());
62+ C.emitReport (std::move (R));
63+ }
64+ };
65+
6066 ProgramStateRef State = C.getState ();
6167 const MemRegion *SuperReg = ElemReg->getSuperRegion ();
6268 SValBuilder &SVB = C.getSValBuilder ();
6369
6470 if (SuperReg == Reg) {
6571 if (const llvm::APSInt *I = SVB.getKnownValue (State, ElemReg->getIndex ());
6672 I && (!I->isOne () && !I->isZero ()))
67- reportBug (C, E, Msg_BadVarIndex);
73+ ReportBug ( Msg_BadVarIndex);
6874 return false ;
6975 }
7076
@@ -77,7 +83,7 @@ bool PointerSubChecker::checkArrayBounds(CheckerContext &C, const Expr *E,
7783 ProgramStateRef S1, S2;
7884 std::tie (S1, S2) = C.getState ()->assume (*IndexTooLarge);
7985 if (S1 && !S2) {
80- reportBug (C, E, Msg_LargeArrayIndex);
86+ ReportBug ( Msg_LargeArrayIndex);
8187 return false ;
8288 }
8389 }
@@ -89,22 +95,13 @@ bool PointerSubChecker::checkArrayBounds(CheckerContext &C, const Expr *E,
8995 ProgramStateRef S1, S2;
9096 std::tie (S1, S2) = State->assume (*IndexTooSmall);
9197 if (S1 && !S2) {
92- reportBug (C, E, Msg_NegativeArrayIndex);
98+ ReportBug ( Msg_NegativeArrayIndex);
9399 return false ;
94100 }
95101 }
96102 return true ;
97103}
98104
99- void PointerSubChecker::reportBug (CheckerContext &C, const Expr *E,
100- const llvm::StringLiteral &Msg) const {
101- if (ExplodedNode *N = C.generateNonFatalErrorNode ()) {
102- auto R = std::make_unique<PathSensitiveBugReport>(BT, Msg, N);
103- R->addRange (E->getSourceRange ());
104- C.emitReport (std::move (R));
105- }
106- }
107-
108105void PointerSubChecker::checkPreStmt (const BinaryOperator *B,
109106 CheckerContext &C) const {
110107 // When doing pointer subtraction, if the two pointers do not point to the
@@ -136,6 +133,9 @@ void PointerSubChecker::checkPreStmt(const BinaryOperator *B,
136133 if (!checkArrayBounds (C, B->getRHS (), ElemRR, LR))
137134 return ;
138135
136+ const ValueDecl *DiffDeclL = nullptr ;
137+ const ValueDecl *DiffDeclR = nullptr ;
138+
139139 if (ElemLR && ElemRR) {
140140 const MemRegion *SuperLR = ElemLR->getSuperRegion ();
141141 const MemRegion *SuperRR = ElemRR->getSuperRegion ();
@@ -144,9 +144,30 @@ void PointerSubChecker::checkPreStmt(const BinaryOperator *B,
144144 // Allow arithmetic on different symbolic regions.
145145 if (isa<SymbolicRegion>(SuperLR) || isa<SymbolicRegion>(SuperRR))
146146 return ;
147+ if (const auto *SuperDLR = dyn_cast<DeclRegion>(SuperLR))
148+ DiffDeclL = SuperDLR->getDecl ();
149+ if (const auto *SuperDRR = dyn_cast<DeclRegion>(SuperRR))
150+ DiffDeclR = SuperDRR->getDecl ();
147151 }
148152
149- reportBug (C, B, Msg_MemRegionDifferent);
153+ if (ExplodedNode *N = C.generateNonFatalErrorNode ()) {
154+ auto R =
155+ std::make_unique<PathSensitiveBugReport>(BT, Msg_MemRegionDifferent, N);
156+ R->addRange (B->getSourceRange ());
157+ // The declarations may be identical even if the regions are different:
158+ // struct { int array[10]; } a, b;
159+ // do_something(&a.array[5] - &b.array[5]);
160+ // In this case don't emit notes.
161+ if (DiffDeclL != DiffDeclR) {
162+ if (DiffDeclL)
163+ R->addNote (" Array at the left-hand side of subtraction" ,
164+ {DiffDeclL, C.getSourceManager ()});
165+ if (DiffDeclR)
166+ R->addNote (" Array at the right-hand side of subtraction" ,
167+ {DiffDeclR, C.getSourceManager ()});
168+ }
169+ C.emitReport (std::move (R));
170+ }
150171}
151172
152173void ento::registerPointerSubChecker (CheckerManager &mgr) {
0 commit comments