@@ -97,10 +97,14 @@ class BuiltinFunctionChecker : public Checker<eval::Call> {
9797 void handleOverflowBuiltin (const CallEvent &Call, CheckerContext &C,
9898 BinaryOperator::Opcode Op,
9999 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 ;
104108 std::pair<bool , bool > checkOverflow (CheckerContext &C, SVal RetVal,
105109 QualType Res) const ;
106110
@@ -122,30 +126,24 @@ class BuiltinFunctionChecker : public Checker<eval::Call> {
122126
123127} // namespace
124128
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) {
130133 if (!BR.isInteresting (Result))
131134 return ;
132135
133- // Propagate interestingness to input argumets if result is interesting.
136+ // Propagate interestingness to input arguments if result is interesting.
134137 BR.markInteresting (Arg1);
135138 BR.markInteresting (Arg2);
136139
137- if (BothFeasible)
140+ if (overflow)
141+ OS << " Assuming overflow" ;
142+ else
138143 OS << " Assuming no overflow" ;
139144 });
140145}
141146
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-
149147std::pair<bool , bool >
150148BuiltinFunctionChecker::checkOverflow (CheckerContext &C, SVal RetVal,
151149 QualType Res) const {
@@ -175,6 +173,29 @@ BuiltinFunctionChecker::checkOverflow(CheckerContext &C, SVal RetVal,
175173 return {MayOverflow || MayUnderflow, MayNotOverflow && MayNotUnderflow};
176174}
177175
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+
178199void BuiltinFunctionChecker::handleOverflowBuiltin (const CallEvent &Call,
179200 CheckerContext &C,
180201 BinaryOperator::Opcode Op,
@@ -184,8 +205,6 @@ void BuiltinFunctionChecker::handleOverflowBuiltin(const CallEvent &Call,
184205
185206 ProgramStateRef State = C.getState ();
186207 SValBuilder &SVB = C.getSValBuilder ();
187- const Expr *CE = Call.getOriginExpr ();
188- auto BoolTy = C.getASTContext ().BoolTy ;
189208
190209 SVal Arg1 = Call.getArgSVal (0 );
191210 SVal Arg2 = Call.getArgSVal (1 );
@@ -195,29 +214,20 @@ void BuiltinFunctionChecker::handleOverflowBuiltin(const CallEvent &Call,
195214 SVal RetVal = SVB.evalBinOp (State, Op, Arg1, Arg2, ResultType);
196215
197216 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 ());
205217
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 );
210221
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));
215224 }
216225
217226 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));
221231 }
222232}
223233
0 commit comments