@@ -96,10 +96,14 @@ class BuiltinFunctionChecker : public Checker<eval::Call> {
96
96
void handleOverflowBuiltin (const CallEvent &Call, CheckerContext &C,
97
97
BinaryOperator::Opcode Op,
98
98
QualType ResultType) const ;
99
- const NoteTag *createBuiltinNoOverflowNoteTag (CheckerContext &C,
100
- bool BothFeasible, SVal Arg1,
101
- SVal Arg2, SVal Result) const ;
102
- const NoteTag *createBuiltinOverflowNoteTag (CheckerContext &C) const ;
99
+ const NoteTag *createBuiltinOverflowNoteTag (CheckerContext &C,
100
+ bool BothFeasible, SVal Arg1,
101
+ SVal Arg2, SVal Result) const ;
102
+ ProgramStateRef initStateAftetBuiltinOverflow (CheckerContext &C,
103
+ ProgramStateRef State,
104
+ const CallEvent &Call,
105
+ SVal RetCal,
106
+ bool IsOverflow) const ;
103
107
std::pair<bool , bool > checkOverflow (CheckerContext &C, SVal RetVal,
104
108
QualType Res) const ;
105
109
@@ -121,30 +125,24 @@ class BuiltinFunctionChecker : public Checker<eval::Call> {
121
125
122
126
} // namespace
123
127
124
- const NoteTag *BuiltinFunctionChecker::createBuiltinNoOverflowNoteTag (
125
- CheckerContext &C, bool BothFeasible, SVal Arg1, SVal Arg2,
126
- SVal Result) const {
127
- return C.getNoteTag ([Result, Arg1, Arg2, BothFeasible](
128
- PathSensitiveBugReport &BR, llvm::raw_ostream &OS) {
128
+ const NoteTag *BuiltinFunctionChecker::createBuiltinOverflowNoteTag (
129
+ CheckerContext &C, bool overflow, SVal Arg1, SVal Arg2, SVal Result) const {
130
+ return C.getNoteTag ([Result, Arg1, Arg2, overflow](PathSensitiveBugReport &BR,
131
+ llvm::raw_ostream &OS) {
129
132
if (!BR.isInteresting (Result))
130
133
return ;
131
134
132
- // Propagate interestingness to input argumets if result is interesting.
135
+ // Propagate interestingness to input arguments if result is interesting.
133
136
BR.markInteresting (Arg1);
134
137
BR.markInteresting (Arg2);
135
138
136
- if (BothFeasible)
139
+ if (overflow)
140
+ OS << " Assuming overflow" ;
141
+ else
137
142
OS << " Assuming no overflow" ;
138
143
});
139
144
}
140
145
141
- const NoteTag *
142
- BuiltinFunctionChecker::createBuiltinOverflowNoteTag (CheckerContext &C) const {
143
- return C.getNoteTag ([](PathSensitiveBugReport &BR,
144
- llvm::raw_ostream &OS) { OS << " Assuming overflow" ; },
145
- /* isPrunable=*/ true );
146
- }
147
-
148
146
std::pair<bool , bool >
149
147
BuiltinFunctionChecker::checkOverflow (CheckerContext &C, SVal RetVal,
150
148
QualType Res) const {
@@ -174,6 +172,29 @@ BuiltinFunctionChecker::checkOverflow(CheckerContext &C, SVal RetVal,
174
172
return {MayOverflow || MayUnderflow, MayNotOverflow && MayNotUnderflow};
175
173
}
176
174
175
+ ProgramStateRef BuiltinFunctionChecker::initStateAftetBuiltinOverflow (
176
+ CheckerContext &C, ProgramStateRef State, const CallEvent &Call,
177
+ SVal RetVal, bool IsOverflow) const {
178
+ SValBuilder &SVB = C.getSValBuilder ();
179
+ SVal Arg1 = Call.getArgSVal (0 );
180
+ SVal Arg2 = Call.getArgSVal (1 );
181
+ auto BoolTy = C.getASTContext ().BoolTy ;
182
+
183
+ ProgramStateRef NewState =
184
+ State->BindExpr (Call.getOriginExpr (), C.getLocationContext (),
185
+ SVB.makeTruthVal (IsOverflow, BoolTy));
186
+
187
+ if (auto L = Call.getArgSVal (2 ).getAs <Loc>()) {
188
+ NewState = NewState->bindLoc (*L, RetVal, C.getLocationContext ());
189
+
190
+ // Propagate taint if any of the arguments were tainted
191
+ if (isTainted (State, Arg1) || isTainted (State, Arg2))
192
+ NewState = addTaint (NewState, *L);
193
+ }
194
+
195
+ return NewState;
196
+ }
197
+
177
198
void BuiltinFunctionChecker::handleOverflowBuiltin (const CallEvent &Call,
178
199
CheckerContext &C,
179
200
BinaryOperator::Opcode Op,
@@ -183,8 +204,6 @@ void BuiltinFunctionChecker::handleOverflowBuiltin(const CallEvent &Call,
183
204
184
205
ProgramStateRef State = C.getState ();
185
206
SValBuilder &SVB = C.getSValBuilder ();
186
- const Expr *CE = Call.getOriginExpr ();
187
- auto BoolTy = C.getASTContext ().BoolTy ;
188
207
189
208
SVal Arg1 = Call.getArgSVal (0 );
190
209
SVal Arg2 = Call.getArgSVal (1 );
@@ -194,29 +213,20 @@ void BuiltinFunctionChecker::handleOverflowBuiltin(const CallEvent &Call,
194
213
SVal RetVal = SVB.evalBinOp (State, Op, Arg1, Arg2, ResultType);
195
214
196
215
auto [Overflow, NotOverflow] = checkOverflow (C, RetValMax, ResultType);
197
- if (NotOverflow) {
198
- ProgramStateRef StateNoOverflow = State->BindExpr (
199
- CE, C.getLocationContext (), SVB.makeTruthVal (false , BoolTy));
200
-
201
- if (auto L = Call.getArgSVal (2 ).getAs <Loc>()) {
202
- StateNoOverflow =
203
- StateNoOverflow->bindLoc (*L, RetVal, C.getLocationContext ());
204
216
205
- // Propagate taint if any of the argumets were tainted
206
- if (isTainted (State, Arg1) || isTainted (State, Arg2))
207
- StateNoOverflow = addTaint (StateNoOverflow, *L);
208
- }
217
+ if (NotOverflow) {
218
+ auto NewState =
219
+ initStateAftetBuiltinOverflow (C, State, Call, RetVal, false );
209
220
210
- C.addTransition (
211
- StateNoOverflow,
212
- createBuiltinNoOverflowNoteTag (
213
- C, /* BothFeasible=*/ NotOverflow && Overflow, Arg1, Arg2, RetVal));
221
+ C.addTransition (NewState, createBuiltinOverflowNoteTag (
222
+ C, /* overflow=*/ false , Arg1, Arg2, RetVal));
214
223
}
215
224
216
225
if (Overflow) {
217
- C.addTransition (State->BindExpr (CE, C.getLocationContext (),
218
- SVB.makeTruthVal (true , BoolTy)),
219
- createBuiltinOverflowNoteTag (C));
226
+ auto NewState = initStateAftetBuiltinOverflow (C, State, Call, RetVal, true );
227
+
228
+ C.addTransition (NewState, createBuiltinOverflowNoteTag (C, /* overflow=*/ true ,
229
+ Arg1, Arg2, RetVal));
220
230
}
221
231
}
222
232
0 commit comments