@@ -96,10 +96,14 @@ class BuiltinFunctionChecker : public Checker<eval::Call> {
9696 void handleOverflowBuiltin (const CallEvent &Call, CheckerContext &C,
9797 BinaryOperator::Opcode Op,
9898 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 ;
103107 std::pair<bool , bool > checkOverflow (CheckerContext &C, SVal RetVal,
104108 QualType Res) const ;
105109
@@ -121,30 +125,24 @@ class BuiltinFunctionChecker : public Checker<eval::Call> {
121125
122126} // namespace
123127
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) {
129132 if (!BR.isInteresting (Result))
130133 return ;
131134
132- // Propagate interestingness to input argumets if result is interesting.
135+ // Propagate interestingness to input arguments if result is interesting.
133136 BR.markInteresting (Arg1);
134137 BR.markInteresting (Arg2);
135138
136- if (BothFeasible)
139+ if (overflow)
140+ OS << " Assuming overflow" ;
141+ else
137142 OS << " Assuming no overflow" ;
138143 });
139144}
140145
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-
148146std::pair<bool , bool >
149147BuiltinFunctionChecker::checkOverflow (CheckerContext &C, SVal RetVal,
150148 QualType Res) const {
@@ -174,6 +172,29 @@ BuiltinFunctionChecker::checkOverflow(CheckerContext &C, SVal RetVal,
174172 return {MayOverflow || MayUnderflow, MayNotOverflow && MayNotUnderflow};
175173}
176174
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+
177198void BuiltinFunctionChecker::handleOverflowBuiltin (const CallEvent &Call,
178199 CheckerContext &C,
179200 BinaryOperator::Opcode Op,
@@ -183,8 +204,6 @@ void BuiltinFunctionChecker::handleOverflowBuiltin(const CallEvent &Call,
183204
184205 ProgramStateRef State = C.getState ();
185206 SValBuilder &SVB = C.getSValBuilder ();
186- const Expr *CE = Call.getOriginExpr ();
187- auto BoolTy = C.getASTContext ().BoolTy ;
188207
189208 SVal Arg1 = Call.getArgSVal (0 );
190209 SVal Arg2 = Call.getArgSVal (1 );
@@ -194,29 +213,20 @@ void BuiltinFunctionChecker::handleOverflowBuiltin(const CallEvent &Call,
194213 SVal RetVal = SVB.evalBinOp (State, Op, Arg1, Arg2, ResultType);
195214
196215 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 ());
204216
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 );
209220
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));
214223 }
215224
216225 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));
220230 }
221231}
222232
0 commit comments