aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm-project/clang/lib/StaticAnalyzer/Checkers/SimpleStreamChecker.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm-project/clang/lib/StaticAnalyzer/Checkers/SimpleStreamChecker.cpp')
-rw-r--r--contrib/llvm-project/clang/lib/StaticAnalyzer/Checkers/SimpleStreamChecker.cpp58
1 files changed, 14 insertions, 44 deletions
diff --git a/contrib/llvm-project/clang/lib/StaticAnalyzer/Checkers/SimpleStreamChecker.cpp b/contrib/llvm-project/clang/lib/StaticAnalyzer/Checkers/SimpleStreamChecker.cpp
index 8d380ed1b93d..7cbe271dfbf9 100644
--- a/contrib/llvm-project/clang/lib/StaticAnalyzer/Checkers/SimpleStreamChecker.cpp
+++ b/contrib/llvm-project/clang/lib/StaticAnalyzer/Checkers/SimpleStreamChecker.cpp
@@ -17,6 +17,7 @@
#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
#include "clang/StaticAnalyzer/Core/Checker.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CallDescription.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
#include <utility>
@@ -51,10 +52,13 @@ class SimpleStreamChecker : public Checker<check::PostCall,
check::PreCall,
check::DeadSymbols,
check::PointerEscape> {
- CallDescription OpenFn, CloseFn;
+ const CallDescription OpenFn{{"fopen"}, 2};
+ const CallDescription CloseFn{{"fclose"}, 1};
- std::unique_ptr<BugType> DoubleCloseBugType;
- std::unique_ptr<BugType> LeakBugType;
+ const BugType DoubleCloseBugType{this, "Double fclose",
+ "Unix Stream API Error"};
+ const BugType LeakBugType{this, "Resource Leak", "Unix Stream API Error",
+ /*SuppressOnSink=*/true};
void reportDoubleClose(SymbolRef FileDescSym,
const CallEvent &Call,
@@ -66,8 +70,6 @@ class SimpleStreamChecker : public Checker<check::PostCall,
bool guaranteedNotToCloseFile(const CallEvent &Call) const;
public:
- SimpleStreamChecker();
-
/// Process fopen.
void checkPostCall(const CallEvent &Call, CheckerContext &C) const;
/// Process fclose.
@@ -88,38 +90,12 @@ public:
/// state. Let's store it in the ProgramState.
REGISTER_MAP_WITH_PROGRAMSTATE(StreamMap, SymbolRef, StreamState)
-namespace {
-class StopTrackingCallback final : public SymbolVisitor {
- ProgramStateRef state;
-public:
- StopTrackingCallback(ProgramStateRef st) : state(std::move(st)) {}
- ProgramStateRef getState() const { return state; }
-
- bool VisitSymbol(SymbolRef sym) override {
- state = state->remove<StreamMap>(sym);
- return true;
- }
-};
-} // end anonymous namespace
-
-SimpleStreamChecker::SimpleStreamChecker()
- : OpenFn("fopen"), CloseFn("fclose", 1) {
- // Initialize the bug types.
- DoubleCloseBugType.reset(
- new BugType(this, "Double fclose", "Unix Stream API Error"));
-
- // Sinks are higher importance bugs as well as calls to assert() or exit(0).
- LeakBugType.reset(
- new BugType(this, "Resource Leak", "Unix Stream API Error",
- /*SuppressOnSink=*/true));
-}
-
void SimpleStreamChecker::checkPostCall(const CallEvent &Call,
CheckerContext &C) const {
if (!Call.isGlobalCFunction())
return;
- if (!Call.isCalled(OpenFn))
+ if (!OpenFn.matches(Call))
return;
// Get the symbolic value corresponding to the file handle.
@@ -138,7 +114,7 @@ void SimpleStreamChecker::checkPreCall(const CallEvent &Call,
if (!Call.isGlobalCFunction())
return;
- if (!Call.isCalled(CloseFn))
+ if (!CloseFn.matches(Call))
return;
// Get the symbolic value corresponding to the file handle.
@@ -176,13 +152,11 @@ void SimpleStreamChecker::checkDeadSymbols(SymbolReaper &SymReaper,
ProgramStateRef State = C.getState();
SymbolVector LeakedStreams;
StreamMapTy TrackedStreams = State->get<StreamMap>();
- for (StreamMapTy::iterator I = TrackedStreams.begin(),
- E = TrackedStreams.end(); I != E; ++I) {
- SymbolRef Sym = I->first;
+ for (auto [Sym, StreamStatus] : TrackedStreams) {
bool IsSymDead = SymReaper.isDead(Sym);
// Collect leaked symbols.
- if (isLeaked(Sym, I->second, IsSymDead, State))
+ if (isLeaked(Sym, StreamStatus, IsSymDead, State))
LeakedStreams.push_back(Sym);
// Remove the dead symbol from the streams map.
@@ -207,7 +181,7 @@ void SimpleStreamChecker::reportDoubleClose(SymbolRef FileDescSym,
// Generate the report.
auto R = std::make_unique<PathSensitiveBugReport>(
- *DoubleCloseBugType, "Closing a previously closed file stream", ErrNode);
+ DoubleCloseBugType, "Closing a previously closed file stream", ErrNode);
R->addRange(Call.getSourceRange());
R->markInteresting(FileDescSym);
C.emitReport(std::move(R));
@@ -220,7 +194,7 @@ void SimpleStreamChecker::reportLeaks(ArrayRef<SymbolRef> LeakedStreams,
// TODO: Identify the leaked file descriptor.
for (SymbolRef LeakedStream : LeakedStreams) {
auto R = std::make_unique<PathSensitiveBugReport>(
- *LeakBugType, "Opened file is never closed; potential resource leak",
+ LeakBugType, "Opened file is never closed; potential resource leak",
ErrNode);
R->markInteresting(LeakedStream);
C.emitReport(std::move(R));
@@ -254,11 +228,7 @@ SimpleStreamChecker::checkPointerEscape(ProgramStateRef State,
return State;
}
- for (InvalidatedSymbols::const_iterator I = Escaped.begin(),
- E = Escaped.end();
- I != E; ++I) {
- SymbolRef Sym = *I;
-
+ for (SymbolRef Sym : Escaped) {
// The symbol escaped. Optimistically, assume that the corresponding file
// handle will be closed somewhere else.
State = State->remove<StreamMap>(Sym);