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