summaryrefslogtreecommitdiffstats
path: root/clang/lib/StaticAnalyzer/Checkers/DanglingInternalBufferChecker.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/StaticAnalyzer/Checkers/DanglingInternalBufferChecker.cpp')
-rw-r--r--clang/lib/StaticAnalyzer/Checkers/DanglingInternalBufferChecker.cpp88
1 files changed, 88 insertions, 0 deletions
diff --git a/clang/lib/StaticAnalyzer/Checkers/DanglingInternalBufferChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/DanglingInternalBufferChecker.cpp
new file mode 100644
index 00000000000..e7884ee104a
--- /dev/null
+++ b/clang/lib/StaticAnalyzer/Checkers/DanglingInternalBufferChecker.cpp
@@ -0,0 +1,88 @@
+//=== DanglingInternalBufferChecker.cpp ---------------------------*- C++ -*--//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines a check that marks a raw pointer to a C++ standard library
+// container's inner buffer released when the object is destroyed. This
+// information can be used by MallocChecker to detect use-after-free problems.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/CommonBugCategories.h"
+#include "clang/StaticAnalyzer/Core/Checker.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
+#include "AllocationState.h"
+
+using namespace clang;
+using namespace ento;
+
+namespace {
+
+class DanglingInternalBufferChecker : public Checker<check::PostCall> {
+ CallDescription CStrFn;
+
+public:
+ DanglingInternalBufferChecker() : CStrFn("c_str") {}
+
+ /// Record the connection between the symbol returned by c_str() and the
+ /// corresponding string object region in the ProgramState. Mark the symbol
+ /// released if the string object is destroyed.
+ void checkPostCall(const CallEvent &Call, CheckerContext &C) const;
+};
+
+} // end anonymous namespace
+
+// FIXME: c_str() may be called on a string object many times, so it should
+// have a list of symbols associated with it.
+REGISTER_MAP_WITH_PROGRAMSTATE(RawPtrMap, const MemRegion *, SymbolRef)
+
+void DanglingInternalBufferChecker::checkPostCall(const CallEvent &Call,
+ CheckerContext &C) const {
+ const auto *ICall = dyn_cast<CXXInstanceCall>(&Call);
+ if (!ICall)
+ return;
+
+ SVal Obj = ICall->getCXXThisVal();
+ const auto *TypedR = dyn_cast_or_null<TypedValueRegion>(Obj.getAsRegion());
+ if (!TypedR)
+ return;
+
+ auto *TypeDecl = TypedR->getValueType()->getAsCXXRecordDecl();
+ if (TypeDecl->getName() != "basic_string")
+ return;
+
+ ProgramStateRef State = C.getState();
+
+ if (Call.isCalled(CStrFn)) {
+ SVal RawPtr = Call.getReturnValue();
+ if (!RawPtr.isUnknown()) {
+ State = State->set<RawPtrMap>(TypedR, RawPtr.getAsSymbol());
+ C.addTransition(State);
+ }
+ return;
+ }
+
+ if (isa<CXXDestructorCall>(ICall)) {
+ if (State->contains<RawPtrMap>(TypedR)) {
+ const SymbolRef *StrBufferPtr = State->get<RawPtrMap>(TypedR);
+ // FIXME: What if Origin is null?
+ const Expr *Origin = Call.getOriginExpr();
+ State = allocation_state::markReleased(State, *StrBufferPtr, Origin);
+ C.addTransition(State);
+ return;
+ }
+ }
+}
+
+void ento::registerDanglingInternalBufferChecker(CheckerManager &Mgr) {
+ registerNewDeleteChecker(Mgr);
+ Mgr.registerChecker<DanglingInternalBufferChecker>();
+}
OpenPOWER on IntegriCloud