@@ -43,8 +43,6 @@ class PointerSubChecker
43
43
bool checkArrayBounds (CheckerContext &C, const Expr *E,
44
44
const ElementRegion *ElemReg,
45
45
const MemRegion *Reg) const ;
46
- void reportBug (CheckerContext &C, const Expr *E,
47
- const llvm::StringLiteral &Msg) const ;
48
46
49
47
public:
50
48
void checkPreStmt (const BinaryOperator *B, CheckerContext &C) const ;
@@ -57,14 +55,22 @@ bool PointerSubChecker::checkArrayBounds(CheckerContext &C, const Expr *E,
57
55
if (!ElemReg)
58
56
return true ;
59
57
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
+
60
66
ProgramStateRef State = C.getState ();
61
67
const MemRegion *SuperReg = ElemReg->getSuperRegion ();
62
68
SValBuilder &SVB = C.getSValBuilder ();
63
69
64
70
if (SuperReg == Reg) {
65
71
if (const llvm::APSInt *I = SVB.getKnownValue (State, ElemReg->getIndex ());
66
72
I && (!I->isOne () && !I->isZero ()))
67
- reportBug (C, E, Msg_BadVarIndex);
73
+ ReportBug ( Msg_BadVarIndex);
68
74
return false ;
69
75
}
70
76
@@ -77,7 +83,7 @@ bool PointerSubChecker::checkArrayBounds(CheckerContext &C, const Expr *E,
77
83
ProgramStateRef S1, S2;
78
84
std::tie (S1, S2) = C.getState ()->assume (*IndexTooLarge);
79
85
if (S1 && !S2) {
80
- reportBug (C, E, Msg_LargeArrayIndex);
86
+ ReportBug ( Msg_LargeArrayIndex);
81
87
return false ;
82
88
}
83
89
}
@@ -89,22 +95,13 @@ bool PointerSubChecker::checkArrayBounds(CheckerContext &C, const Expr *E,
89
95
ProgramStateRef S1, S2;
90
96
std::tie (S1, S2) = State->assume (*IndexTooSmall);
91
97
if (S1 && !S2) {
92
- reportBug (C, E, Msg_NegativeArrayIndex);
98
+ ReportBug ( Msg_NegativeArrayIndex);
93
99
return false ;
94
100
}
95
101
}
96
102
return true ;
97
103
}
98
104
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
-
108
105
void PointerSubChecker::checkPreStmt (const BinaryOperator *B,
109
106
CheckerContext &C) const {
110
107
// When doing pointer subtraction, if the two pointers do not point to the
@@ -136,6 +133,9 @@ void PointerSubChecker::checkPreStmt(const BinaryOperator *B,
136
133
if (!checkArrayBounds (C, B->getRHS (), ElemRR, LR))
137
134
return ;
138
135
136
+ const ValueDecl *DiffDeclL = nullptr ;
137
+ const ValueDecl *DiffDeclR = nullptr ;
138
+
139
139
if (ElemLR && ElemRR) {
140
140
const MemRegion *SuperLR = ElemLR->getSuperRegion ();
141
141
const MemRegion *SuperRR = ElemRR->getSuperRegion ();
@@ -144,9 +144,30 @@ void PointerSubChecker::checkPreStmt(const BinaryOperator *B,
144
144
// Allow arithmetic on different symbolic regions.
145
145
if (isa<SymbolicRegion>(SuperLR) || isa<SymbolicRegion>(SuperRR))
146
146
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 ();
147
151
}
148
152
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
+ }
150
171
}
151
172
152
173
void ento::registerPointerSubChecker (CheckerManager &mgr) {
0 commit comments