rnkovacs created this revision. rnkovacs added reviewers: NoQ, xazax.hun, george.karpenkov. Herald added subscribers: a.sidorin, dkrupp, szepet, baloghadamsoftware, whisperity, mgorny.
This check marks a raw pointer to a C++ string object's inner buffer "released" when the object itself is destroyed. This information can be used by MallocChecker to warn for use-after-free problems. Test cases using mocks are to be added. Until then, the following file is used for testing purposes: <<tests.cpp>>. Repository: rC Clang https://reviews.llvm.org/D47135 Files: include/clang/StaticAnalyzer/Checkers/Checkers.td lib/StaticAnalyzer/Checkers/CMakeLists.txt lib/StaticAnalyzer/Checkers/DanglingStringPointerChecker.cpp lib/StaticAnalyzer/Checkers/MallocChecker.cpp lib/StaticAnalyzer/Checkers/RegionState.h
Index: lib/StaticAnalyzer/Checkers/RegionState.h =================================================================== --- /dev/null +++ lib/StaticAnalyzer/Checkers/RegionState.h @@ -0,0 +1,28 @@ +//===--- RegionState.h ----------------------------------------- *- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_LIB_STATICANALYZER_CHECKERS_REGIONSTATE_H +#define LLVM_CLANG_LIB_STATICANALYZER_CHECKERS_REGIONSTATE_H + +#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h" + +namespace clang { +namespace ento { + +namespace region_state { + +ProgramStateRef markReleased(ProgramStateRef State, SymbolRef Sym, + const Expr *Origin); + +} // end namespace region_state + +} // end namespace ento +} // end namespace clang + +#endif Index: lib/StaticAnalyzer/Checkers/MallocChecker.cpp =================================================================== --- lib/StaticAnalyzer/Checkers/MallocChecker.cpp +++ lib/StaticAnalyzer/Checkers/MallocChecker.cpp @@ -30,6 +30,7 @@ #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringExtras.h" +#include "RegionState.h" #include <climits> #include <utility> @@ -2991,6 +2992,21 @@ } } +namespace clang { +namespace ento { +namespace region_state { + +ProgramStateRef +markReleased(ProgramStateRef State, SymbolRef Sym, const Expr *Origin) { + // FIXME: This might not be the best allocation family for this purpose. + AllocationFamily Family = AF_CXXNew; + return State->set<RegionState>(Sym, RefState::getReleased(Family, Origin)); +} + +} // end namespace region_state +} // end namespace ento +} // end namespace clang + void ento::registerNewDeleteLeaksChecker(CheckerManager &mgr) { registerCStringCheckerBasic(mgr); MallocChecker *checker = mgr.registerChecker<MallocChecker>(); Index: lib/StaticAnalyzer/Checkers/DanglingStringPointerChecker.cpp =================================================================== --- /dev/null +++ lib/StaticAnalyzer/Checkers/DanglingStringPointerChecker.cpp @@ -0,0 +1,85 @@ +//=== DanglingStringPointerChecker.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++ string object's +// inner buffer released when the object is destroyed. This information can +// then be used by MallocChecker to detect further 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 "RegionState.h" + +using namespace clang; +using namespace ento; + +namespace { + +class DanglingStringPointerChecker : public Checker<check::PostCall> { + CallDescription CStrFn; + +public: + DanglingStringPointerChecker() : 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 DanglingStringPointerChecker::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; + + QualType RegType = TypedR->getValueType(); + if (RegType.getAsString() != "std::string") + return; + + ProgramStateRef State = C.getState(); + + if (Call.isCalled(CStrFn)) { + SymbolRef RawPtr = Call.getReturnValue().getAsSymbol(); + State = State->set<RawPtrMap>(TypedR, RawPtr); + C.addTransition(State); + return; + } + + if (dyn_cast<CXXDestructorCall>(ICall)) { + if (State->contains<RawPtrMap>(TypedR)) { + const SymbolRef *StrBufferPtr = State->get<RawPtrMap>(TypedR); + const Expr *Origin = Call.getOriginExpr(); + State = region_state::markReleased(State, *StrBufferPtr, Origin); + C.addTransition(State); + return; + } + } +} + +// TODO: This check depends on MallocChecker. +void ento::registerDanglingStringPointerChecker(CheckerManager &Mgr) { + Mgr.registerChecker<DanglingStringPointerChecker>(); +} Index: lib/StaticAnalyzer/Checkers/CMakeLists.txt =================================================================== --- lib/StaticAnalyzer/Checkers/CMakeLists.txt +++ lib/StaticAnalyzer/Checkers/CMakeLists.txt @@ -27,6 +27,7 @@ CloneChecker.cpp ConversionChecker.cpp CXXSelfAssignmentChecker.cpp + DanglingStringPointerChecker.cpp DeadStoresChecker.cpp DebugCheckers.cpp DeleteWithNonVirtualDtorChecker.cpp Index: include/clang/StaticAnalyzer/Checkers/Checkers.td =================================================================== --- include/clang/StaticAnalyzer/Checkers/Checkers.td +++ include/clang/StaticAnalyzer/Checkers/Checkers.td @@ -300,6 +300,10 @@ let ParentPackage = CplusplusAlpha in { +def DanglingStringPointerChecker : Checker<"DanglingStringPointer">, + HelpText<"Checks for dangling inner raw pointers of C++ string objects">, + DescFile<"DanglingStringPointerChecker.cpp">; + def DeleteWithNonVirtualDtorChecker : Checker<"DeleteWithNonVirtualDtor">, HelpText<"Reports destructions of polymorphic objects with a non-virtual " "destructor in their base class">,
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits