summaryrefslogtreecommitdiffstats
path: root/clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp
diff options
context:
space:
mode:
authorBalázs Kéri <1.int32@gmail.com>2019-12-04 17:15:03 +0100
committerBalázs Kéri <1.int32@gmail.com>2019-12-05 11:08:44 +0100
commit7eafde981c699efa87c96d4b7714cbfe98c3d1c6 (patch)
tree68d136901d969809b3e793b348f0f8833540eb06 /clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp
parent4d6c4cb4269e8e8e04854fca812c2dda13f83f9d (diff)
downloadbcm5719-llvm-7eafde981c699efa87c96d4b7714cbfe98c3d1c6.tar.gz
bcm5719-llvm-7eafde981c699efa87c96d4b7714cbfe98c3d1c6.zip
[Checkers] Added support for freopen to StreamChecker.
Summary: Extend StreamChecker with a new evaluation function for API call 'freopen'. Reviewers: NoQ, baloghadamsoftware, Szelethus, martong Reviewed By: baloghadamsoftware, martong Subscribers: martong, rnkovacs, dkrupp, Szelethus, gamesh411, cfe-commits Tags: #clang Differential Revision: https://reviews.llvm.org/D69948
Diffstat (limited to 'clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp')
-rw-r--r--clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp45
1 files changed, 45 insertions, 0 deletions
diff --git a/clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp
index 7a0dda56328..47099f2afb6 100644
--- a/clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp
@@ -64,6 +64,7 @@ private:
CallDescriptionMap<FnCheck> Callbacks = {
{{"fopen"}, &StreamChecker::evalFopen},
+ {{"freopen", 3}, &StreamChecker::evalFreopen},
{{"tmpfile"}, &StreamChecker::evalFopen},
{{"fclose", 1}, &StreamChecker::evalFclose},
{{"fread", 4},
@@ -90,6 +91,7 @@ private:
};
void evalFopen(const CallEvent &Call, CheckerContext &C) const;
+ void evalFreopen(const CallEvent &Call, CheckerContext &C) const;
void evalFclose(const CallEvent &Call, CheckerContext &C) const;
void evalFseek(const CallEvent &Call, CheckerContext &C) const;
@@ -160,6 +162,49 @@ void StreamChecker::evalFopen(const CallEvent &Call, CheckerContext &C) const {
C.addTransition(stateNull);
}
+void StreamChecker::evalFreopen(const CallEvent &Call,
+ CheckerContext &C) const {
+ ProgramStateRef State = C.getState();
+
+ auto *CE = dyn_cast_or_null<CallExpr>(Call.getOriginExpr());
+ if (!CE)
+ return;
+
+ Optional<DefinedSVal> StreamVal = Call.getArgSVal(2).getAs<DefinedSVal>();
+ if (!StreamVal)
+ return;
+ // Do not allow NULL as passed stream pointer.
+ // This is not specified in the man page but may crash on some system.
+ checkNullStream(*StreamVal, C, State);
+ // Check if error was generated.
+ if (C.isDifferent())
+ return;
+
+ SymbolRef StreamSym = StreamVal->getAsSymbol();
+ // Do not care about special values for stream ("(FILE *)0x12345"?).
+ if (!StreamSym)
+ return;
+
+ // Generate state for non-failed case.
+ // Return value is the passed stream pointer.
+ // According to the documentations, the stream is closed first
+ // but any close error is ignored. The state changes to (or remains) opened.
+ ProgramStateRef StateRetNotNull =
+ State->BindExpr(CE, C.getLocationContext(), *StreamVal);
+ // Generate state for NULL return value.
+ // Stream switches to OpenFailed state.
+ ProgramStateRef StateRetNull = State->BindExpr(CE, C.getLocationContext(),
+ C.getSValBuilder().makeNull());
+
+ StateRetNotNull =
+ StateRetNotNull->set<StreamMap>(StreamSym, StreamState::getOpened());
+ StateRetNull =
+ StateRetNull->set<StreamMap>(StreamSym, StreamState::getOpenFailed());
+
+ C.addTransition(StateRetNotNull);
+ C.addTransition(StateRetNull);
+}
+
void StreamChecker::evalFclose(const CallEvent &Call, CheckerContext &C) const {
ProgramStateRef State = C.getState();
if (checkDoubleClose(Call, C, State))
OpenPOWER on IntegriCloud