diff --git a/clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp index 63ebfaf90dc82c..bfb788c24e2412 100644 --- a/clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp @@ -195,9 +195,29 @@ ProgramStateRef bindInt(uint64_t Value, ProgramStateRef State, class StreamChecker : public Checker { - mutable std::unique_ptr BT_nullfp, BT_illegalwhence, - BT_UseAfterClose, BT_UseAfterOpenFailed, BT_ResourceLeak, BT_StreamEof, - BT_IndeterminatePosition; + BuiltinBug BT_FileNull{this, "NULL stream pointer", + "Stream pointer might be NULL."}; + BuiltinBug BT_UseAfterClose{ + this, "Closed stream", + "Stream might be already closed. Causes undefined behaviour."}; + BuiltinBug BT_UseAfterOpenFailed{this, "Invalid stream", + "Stream might be invalid after " + "(re-)opening it has failed. " + "Can cause undefined behaviour."}; + BuiltinBug BT_IndeterminatePosition{ + this, "Invalid stream state", + "File position of the stream might be 'indeterminate' " + "after a failed operation. " + "Can cause undefined behavior."}; + BuiltinBug BT_IllegalWhence{this, "Illegal whence argument", + "The whence argument to fseek() should be " + "SEEK_SET, SEEK_END, or SEEK_CUR."}; + BuiltinBug BT_StreamEof{this, "Stream already in EOF", + "Read function called when stream is in EOF state. " + "Function has no effect."}; + BuiltinBug BT_ResourceLeak{ + this, "Resource Leak", + "Opened File never closed. Potential Resource leak."}; public: void checkPreCall(const CallEvent &Call, CheckerContext &C) const; @@ -755,11 +775,8 @@ StreamChecker::ensureStreamNonNull(SVal StreamVal, CheckerContext &C, if (!StateNotNull && StateNull) { if (ExplodedNode *N = C.generateErrorNode(StateNull)) { - if (!BT_nullfp) - BT_nullfp.reset(new BuiltinBug(this, "NULL stream pointer", - "Stream pointer might be NULL.")); C.emitReport(std::make_unique( - *BT_nullfp, BT_nullfp->getDescription(), N)); + BT_FileNull, BT_FileNull.getDescription(), N)); } return nullptr; } @@ -783,12 +800,8 @@ ProgramStateRef StreamChecker::ensureStreamOpened(SVal StreamVal, // according to cppreference.com . ExplodedNode *N = C.generateErrorNode(); if (N) { - if (!BT_UseAfterClose) - BT_UseAfterClose.reset(new BuiltinBug(this, "Closed stream", - "Stream might be already closed. " - "Causes undefined behaviour.")); C.emitReport(std::make_unique( - *BT_UseAfterClose, BT_UseAfterClose->getDescription(), N)); + BT_UseAfterClose, BT_UseAfterClose.getDescription(), N)); return nullptr; } @@ -802,14 +815,8 @@ ProgramStateRef StreamChecker::ensureStreamOpened(SVal StreamVal, // failed to open. ExplodedNode *N = C.generateErrorNode(); if (N) { - if (!BT_UseAfterOpenFailed) - BT_UseAfterOpenFailed.reset( - new BuiltinBug(this, "Invalid stream", - "Stream might be invalid after " - "(re-)opening it has failed. " - "Can cause undefined behaviour.")); C.emitReport(std::make_unique( - *BT_UseAfterOpenFailed, BT_UseAfterOpenFailed->getDescription(), N)); + BT_UseAfterOpenFailed, BT_UseAfterOpenFailed.getDescription(), N)); return nullptr; } return State; @@ -831,13 +838,6 @@ ProgramStateRef StreamChecker::ensureNoFilePositionIndeterminate( assert(SS->isOpened() && "First ensure that stream is opened."); if (SS->FilePositionIndeterminate) { - if (!BT_IndeterminatePosition) - BT_IndeterminatePosition.reset( - new BuiltinBug(this, "Invalid stream state", - "File position of the stream might be 'indeterminate' " - "after a failed operation. " - "Can cause undefined behavior.")); - if (SS->ErrorState & ErrorFEof) { // The error is unknown but may be FEOF. // Continue analysis with the FEOF error state. @@ -847,7 +847,7 @@ ProgramStateRef StreamChecker::ensureNoFilePositionIndeterminate( return nullptr; C.emitReport(std::make_unique( - *BT_IndeterminatePosition, BT_IndeterminatePosition->getDescription(), + BT_IndeterminatePosition, BT_IndeterminatePosition.getDescription(), N)); return State->set( Sym, StreamState::getOpened(SS->LastOperation, ErrorFEof, false)); @@ -858,7 +858,7 @@ ProgramStateRef StreamChecker::ensureNoFilePositionIndeterminate( ExplodedNode *N = C.generateErrorNode(State); if (N) C.emitReport(std::make_unique( - *BT_IndeterminatePosition, BT_IndeterminatePosition->getDescription(), + BT_IndeterminatePosition, BT_IndeterminatePosition.getDescription(), N)); return nullptr; @@ -879,13 +879,8 @@ StreamChecker::ensureFseekWhenceCorrect(SVal WhenceVal, CheckerContext &C, return State; if (ExplodedNode *N = C.generateNonFatalErrorNode(State)) { - if (!BT_illegalwhence) - BT_illegalwhence.reset( - new BuiltinBug(this, "Illegal whence argument", - "The whence argument to fseek() should be " - "SEEK_SET, SEEK_END, or SEEK_CUR.")); C.emitReport(std::make_unique( - *BT_illegalwhence, BT_illegalwhence->getDescription(), N)); + BT_IllegalWhence, BT_IllegalWhence.getDescription(), N)); return nullptr; } @@ -895,13 +890,8 @@ StreamChecker::ensureFseekWhenceCorrect(SVal WhenceVal, CheckerContext &C, void StreamChecker::reportFEofWarning(CheckerContext &C, ProgramStateRef State) const { if (ExplodedNode *N = C.generateNonFatalErrorNode(State)) { - if (!BT_StreamEof) - BT_StreamEof.reset( - new BuiltinBug(this, "Stream already in EOF", - "Read function called when stream is in EOF state. " - "Function has no effect.")); C.emitReport(std::make_unique( - *BT_StreamEof, BT_StreamEof->getDescription(), N)); + BT_StreamEof, BT_StreamEof.getDescription(), N)); return; } C.addTransition(State); @@ -923,12 +913,8 @@ void StreamChecker::checkDeadSymbols(SymbolReaper &SymReaper, if (!N) continue; - if (!BT_ResourceLeak) - BT_ResourceLeak.reset( - new BuiltinBug(this, "Resource Leak", - "Opened File never closed. Potential Resource leak.")); C.emitReport(std::make_unique( - *BT_ResourceLeak, BT_ResourceLeak->getDescription(), N)); + BT_ResourceLeak, BT_ResourceLeak.getDescription(), N)); } }