r339067 - [analyzer] InnerPointerChecker: fix displayed checker name.
Author: rkovacs Date: Mon Aug 6 15:03:42 2018 New Revision: 339067 URL: http://llvm.org/viewvc/llvm-project?rev=339067&view=rev Log: [analyzer] InnerPointerChecker: fix displayed checker name. For InnerPointerChecker to function properly, both the checker itself and parts of MallocChecker that handle relevant use-after-free problems need to be turned on. So far, the latter part has been developed within MallocChecker's NewDelete sub-checker, often causing warnings to appear under that name. This patch defines a new CheckKind within MallocChecker for the inner pointer checking functionality, so that the correct name is displayed in warnings and in the ExplodedGraph. Tested on clang-tidy. Differential Review: https://reviews.llvm.org/D50211 Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/InnerPointerChecker.cpp cfe/trunk/lib/StaticAnalyzer/Checkers/InterCheckerAPI.h cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/InnerPointerChecker.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/InnerPointerChecker.cpp?rev=339067&r1=339066&r2=339067&view=diff == --- cfe/trunk/lib/StaticAnalyzer/Checkers/InnerPointerChecker.cpp (original) +++ cfe/trunk/lib/StaticAnalyzer/Checkers/InnerPointerChecker.cpp Mon Aug 6 15:03:42 2018 @@ -15,6 +15,7 @@ #include "AllocationState.h" #include "ClangSACheckers.h" +#include "InterCheckerAPI.h" #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" #include "clang/StaticAnalyzer/Core/BugReporter/CommonBugCategories.h" #include "clang/StaticAnalyzer/Core/Checker.h" @@ -313,6 +314,6 @@ std::unique_ptr getI } // end namespace clang void ento::registerInnerPointerChecker(CheckerManager &Mgr) { - registerNewDeleteChecker(Mgr); + registerInnerPointerCheckerAux(Mgr); Mgr.registerChecker(); } Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/InterCheckerAPI.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/InterCheckerAPI.h?rev=339067&r1=339066&r2=339067&view=diff == --- cfe/trunk/lib/StaticAnalyzer/Checkers/InterCheckerAPI.h (original) +++ cfe/trunk/lib/StaticAnalyzer/Checkers/InterCheckerAPI.h Mon Aug 6 15:03:42 2018 @@ -20,5 +20,8 @@ namespace ento { /// Register the checker which evaluates CString API calls. void registerCStringCheckerBasic(CheckerManager &Mgr); +/// Register the part of MallocChecker connected to InnerPointerChecker. +void registerInnerPointerCheckerAux(CheckerManager &Mgr); + }} #endif /* INTERCHECKERAPI_H_ */ Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp?rev=339067&r1=339066&r2=339067&view=diff == --- cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp (original) +++ cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp Mon Aug 6 15:03:42 2018 @@ -194,6 +194,7 @@ public: CK_NewDeleteChecker, CK_NewDeleteLeaksChecker, CK_MismatchedDeallocatorChecker, +CK_InnerPointerChecker, CK_NumCheckKinds }; @@ -1662,13 +1663,10 @@ MallocChecker::getCheckIfTracked(Allocat case AF_IfNameIndex: { if (ChecksEnabled[CK_MallocChecker]) return CK_MallocChecker; - -return Optional(); +return None; } case AF_CXXNew: - case AF_CXXNewArray: - // FIXME: Add new CheckKind for AF_InnerBuffer. - case AF_InnerBuffer: { + case AF_CXXNewArray: { if (IsALeakCheck) { if (ChecksEnabled[CK_NewDeleteLeaksChecker]) return CK_NewDeleteLeaksChecker; @@ -1677,7 +1675,12 @@ MallocChecker::getCheckIfTracked(Allocat if (ChecksEnabled[CK_NewDeleteChecker]) return CK_NewDeleteChecker; } -return Optional(); +return None; + } + case AF_InnerBuffer: { +if (ChecksEnabled[CK_InnerPointerChecker]) + return CK_InnerPointerChecker; +return None; } case AF_None: { llvm_unreachable("no family"); @@ -1980,7 +1983,8 @@ void MallocChecker::ReportUseAfterFree(C SymbolRef Sym) const { if (!ChecksEnabled[CK_MallocChecker] && - !ChecksEnabled[CK_NewDeleteChecker]) + !ChecksEnabled[CK_NewDeleteChecker] && + !ChecksEnabled[CK_InnerPointerChecker]) return; Optional CheckKind = getCheckIfTracked(C, Sym); @@ -3109,6 +3113,18 @@ void ento::registerNewDeleteLeaksChecker } } +// Intended to be used in InnerPointerChecker to register the part of +// MallocChecker connected to it. +void ento::registerInnerPointerCheckerAux(CheckerManager &mgr) { +registerCStringCheckerBasic(mgr); +MallocChecker *checker = mgr.registerChecker(); +checker->IsOptimistic = mgr.getAnalyzerOptions().getBooleanOption( +"
r339489 - [analyzer] InnerPointerChecker: improve warning messages and notes.
Author: rkovacs Date: Fri Aug 10 16:56:57 2018 New Revision: 339489 URL: http://llvm.org/viewvc/llvm-project?rev=339489&view=rev Log: [analyzer] InnerPointerChecker: improve warning messages and notes. Differential Revision: https://reviews.llvm.org/D49570 Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/AllocationState.h cfe/trunk/lib/StaticAnalyzer/Checkers/InnerPointerChecker.cpp cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp cfe/trunk/test/Analysis/inner-pointer.cpp Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/AllocationState.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/AllocationState.h?rev=339489&r1=339488&r2=339489&view=diff == --- cfe/trunk/lib/StaticAnalyzer/Checkers/AllocationState.h (original) +++ cfe/trunk/lib/StaticAnalyzer/Checkers/AllocationState.h Fri Aug 10 16:56:57 2018 @@ -26,6 +26,11 @@ ProgramStateRef markReleased(ProgramStat /// AF_InnerBuffer symbols. std::unique_ptr getInnerPointerBRVisitor(SymbolRef Sym); +/// 'Sym' represents a pointer to the inner buffer of a container object. +/// This function looks up the memory region of that object in +/// DanglingInternalBufferChecker's program state map. +const MemRegion *getContainerObjRegion(ProgramStateRef State, SymbolRef Sym); + } // end namespace allocation_state } // end namespace ento Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/InnerPointerChecker.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/InnerPointerChecker.cpp?rev=339489&r1=339488&r2=339489&view=diff == --- cfe/trunk/lib/StaticAnalyzer/Checkers/InnerPointerChecker.cpp (original) +++ cfe/trunk/lib/StaticAnalyzer/Checkers/InnerPointerChecker.cpp Fri Aug 10 16:56:57 2018 @@ -279,6 +279,28 @@ void InnerPointerChecker::checkDeadSymbo C.addTransition(State); } +namespace clang { +namespace ento { +namespace allocation_state { + +std::unique_ptr getInnerPointerBRVisitor(SymbolRef Sym) { + return llvm::make_unique(Sym); +} + +const MemRegion *getContainerObjRegion(ProgramStateRef State, SymbolRef Sym) { + RawPtrMapTy Map = State->get(); + for (const auto Entry : Map) { +if (Entry.second.contains(Sym)) { + return Entry.first; +} + } + return nullptr; +} + +} // end namespace allocation_state +} // end namespace ento +} // end namespace clang + std::shared_ptr InnerPointerChecker::InnerPointerBRVisitor::VisitNode(const ExplodedNode *N, const ExplodedNode *PrevN, @@ -292,27 +314,21 @@ InnerPointerChecker::InnerPointerBRVisit if (!S) return nullptr; + const MemRegion *ObjRegion = + allocation_state::getContainerObjRegion(N->getState(), PtrToBuf); + const auto *TypedRegion = cast(ObjRegion); + QualType ObjTy = TypedRegion->getValueType(); + SmallString<256> Buf; llvm::raw_svector_ostream OS(Buf); - OS << "Dangling inner pointer obtained here"; + OS << "Pointer to inner buffer of '" << ObjTy.getAsString() + << "' obtained here"; PathDiagnosticLocation Pos(S, BRC.getSourceManager(), N->getLocationContext()); return std::make_shared(Pos, OS.str(), true, nullptr); } -namespace clang { -namespace ento { -namespace allocation_state { - -std::unique_ptr getInnerPointerBRVisitor(SymbolRef Sym) { - return llvm::make_unique(Sym); -} - -} // end namespace allocation_state -} // end namespace ento -} // end namespace clang - void ento::registerInnerPointerChecker(CheckerManager &Mgr) { registerInnerPointerCheckerAux(Mgr); Mgr.registerChecker(); Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp?rev=339489&r1=339488&r2=339489&view=diff == --- cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp (original) +++ cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp Fri Aug 10 16:56:57 2018 @@ -1996,15 +1996,20 @@ void MallocChecker::ReportUseAfterFree(C BT_UseFree[*CheckKind].reset(new BugType( CheckNames[*CheckKind], "Use-after-free", categories::MemoryError)); +AllocationFamily AF = +C.getState()->get(Sym)->getAllocationFamily(); + auto R = llvm::make_unique(*BT_UseFree[*CheckKind], - "Use of memory after it is freed", N); +AF == AF_InnerBuffer + ? "Inner pointer of container used after re/deallocation" + : "Use of memory after it is freed", +N); R->markInteresting(Sym); R->addRange(Range); R->addVisitor(llvm::make_unique(Sym)); -const RefState *RS = C.getState()->get(Sym); -if (RS->getAlloc
r337463 - [analyzer] Add support for more basic_string API in
Author: rkovacs Date: Thu Jul 19 08:10:06 2018 New Revision: 337463 URL: http://llvm.org/viewvc/llvm-project?rev=337463&view=rev Log: [analyzer] Add support for more basic_string API in DanglingInternalBufferChecker. A pointer referring to the elements of a basic_string may be invalidated by calling a non-const member function, except operator[], at, front, back, begin, rbegin, end, and rend. The checker now warns if the pointer is used after such operations. Differential Revision: https://reviews.llvm.org/D49360 Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/DanglingInternalBufferChecker.cpp cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp cfe/trunk/test/Analysis/dangling-internal-buffer.cpp Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/DanglingInternalBufferChecker.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/DanglingInternalBufferChecker.cpp?rev=337463&r1=337462&r2=337463&view=diff == --- cfe/trunk/lib/StaticAnalyzer/Checkers/DanglingInternalBufferChecker.cpp (original) +++ cfe/trunk/lib/StaticAnalyzer/Checkers/DanglingInternalBufferChecker.cpp Thu Jul 19 08:10:06 2018 @@ -32,8 +32,8 @@ REGISTER_MAP_WITH_PROGRAMSTATE(RawPtrMap // This is a trick to gain access to PtrSet's Factory. namespace clang { namespace ento { -template<> struct ProgramStateTrait - : public ProgramStatePartialTrait { +template <> +struct ProgramStateTrait : public ProgramStatePartialTrait { static void *GDMIndex() { static int Index = 0; return &Index; @@ -46,7 +46,10 @@ namespace { class DanglingInternalBufferChecker : public Checker { - CallDescription CStrFn, DataFn; + + CallDescription AppendFn, AssignFn, ClearFn, CStrFn, DataFn, EraseFn, + InsertFn, PopBackFn, PushBackFn, ReplaceFn, ReserveFn, ResizeFn, + ShrinkToFitFn, SwapFn; public: class DanglingBufferBRVisitor : public BugReporterVisitor { @@ -81,7 +84,17 @@ public: } }; - DanglingInternalBufferChecker() : CStrFn("c_str"), DataFn("data") {} + DanglingInternalBufferChecker() + : AppendFn("append"), AssignFn("assign"), ClearFn("clear"), +CStrFn("c_str"), DataFn("data"), EraseFn("erase"), InsertFn("insert"), +PopBackFn("pop_back"), PushBackFn("push_back"), ReplaceFn("replace"), +ReserveFn("reserve"), ResizeFn("resize"), +ShrinkToFitFn("shrink_to_fit"), SwapFn("swap") {} + + /// Check whether the function called on the container object is a + /// member function that potentially invalidates pointers referring + /// to the objects's internal buffer. + bool mayInvalidateBuffer(const CallEvent &Call) const; /// Record the connection between the symbol returned by c_str() and the /// corresponding string object region in the ProgramState. Mark the symbol @@ -94,6 +107,37 @@ public: } // end anonymous namespace +// [string.require] +// +// "References, pointers, and iterators referring to the elements of a +// basic_string sequence may be invalidated by the following uses of that +// basic_string object: +// +// -- TODO: As an argument to any standard library function taking a reference +// to non-const basic_string as an argument. For example, as an argument to +// non-member functions swap(), operator>>(), and getline(), or as an argument +// to basic_string::swap(). +// +// -- Calling non-const member functions, except operator[], at, front, back, +// begin, rbegin, end, and rend." +// +bool DanglingInternalBufferChecker::mayInvalidateBuffer( +const CallEvent &Call) const { + if (const auto *MemOpCall = dyn_cast(&Call)) { +OverloadedOperatorKind Opc = MemOpCall->getOriginExpr()->getOperator(); +if (Opc == OO_Equal || Opc == OO_PlusEqual) + return true; +return false; + } + return (isa(Call) || Call.isCalled(AppendFn) || + Call.isCalled(AssignFn) || Call.isCalled(ClearFn) || + Call.isCalled(EraseFn) || Call.isCalled(InsertFn) || + Call.isCalled(PopBackFn) || Call.isCalled(PushBackFn) || + Call.isCalled(ReplaceFn) || Call.isCalled(ReserveFn) || + Call.isCalled(ResizeFn) || Call.isCalled(ShrinkToFitFn) || + Call.isCalled(SwapFn)); +} + void DanglingInternalBufferChecker::checkPostCall(const CallEvent &Call, CheckerContext &C) const { const auto *ICall = dyn_cast(&Call); @@ -127,7 +171,7 @@ void DanglingInternalBufferChecker::chec return; } - if (isa(ICall)) { + if (mayInvalidateBuffer(Call)) { if (const PtrSet *PS = State->get(ObjRegion)) { // Mark all pointer symbols associated with the deleted object released. const Expr *Origin = Call.getOriginExpr(); @@ -161,8 +205,8 @@ void DanglingInternalBufferChecker::chec CleanedUpSet = F.remove(CleanedUpSet, Symbol); } State = CleanedUpSet.isEmpty() - ? State->remove(Entry.first) -
r337466 - [analyzer] Fix disappearing notes in DanglingInternalBufferChecker tests
Author: rkovacs Date: Thu Jul 19 08:44:46 2018 New Revision: 337466 URL: http://llvm.org/viewvc/llvm-project?rev=337466&view=rev Log: [analyzer] Fix disappearing notes in DanglingInternalBufferChecker tests Correct a mistake of the exact same kind I am writing this checker for. Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp?rev=337466&r1=337465&r2=337466&view=diff == --- cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp (original) +++ cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp Thu Jul 19 08:44:46 2018 @@ -2901,6 +2901,9 @@ std::shared_ptr Mal // Find out if this is an interesting point and what is the kind. const char *Msg = nullptr; StackHintGeneratorForSymbol *StackHint = nullptr; + SmallString<256> Buf; + llvm::raw_svector_ostream OS(Buf); + if (Mode == Normal) { if (isAllocated(RS, RSPrev, S)) { Msg = "Memory is allocated"; @@ -2917,8 +2920,6 @@ std::shared_ptr Mal Msg = "Memory is released"; break; case AF_InternalBuffer: { - SmallString<256> Buf; - llvm::raw_svector_ostream OS(Buf); OS << "Inner pointer invalidated by call to "; if (N->getLocation().getKind() == ProgramPoint::PostImplicitCallKind) { OS << "destructor"; ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
r337474 - [analyzer] Fix memory sanitizer error in MallocChecker.
Author: rkovacs Date: Thu Jul 19 10:43:09 2018 New Revision: 337474 URL: http://llvm.org/viewvc/llvm-project?rev=337474&view=rev Log: [analyzer] Fix memory sanitizer error in MallocChecker. StringRef's data() returns a string that may be non-null-terminated. Switch to using StringRefs from const char pointers in visitor notes to avoid problems. Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp?rev=337474&r1=337473&r2=337474&view=diff == --- cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp (original) +++ cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp Thu Jul 19 10:43:09 2018 @@ -2899,7 +2899,7 @@ std::shared_ptr Mal // (__attribute__((cleanup))). // Find out if this is an interesting point and what is the kind. - const char *Msg = nullptr; + StringRef Msg; StackHintGeneratorForSymbol *StackHint = nullptr; SmallString<256> Buf; llvm::raw_svector_ostream OS(Buf); @@ -2933,7 +2933,7 @@ std::shared_ptr Mal } OS << "'"; } - Msg = OS.str().data(); + Msg = OS.str(); break; } case AF_None: @@ -3004,7 +3004,7 @@ std::shared_ptr Mal } } - if (!Msg) + if (Msg.empty()) return nullptr; assert(StackHint); ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
r337559 - [analyzer] Rename DanglingInternalBufferChecker to InnerPointerChecker.
Author: rkovacs Date: Fri Jul 20 08:14:49 2018 New Revision: 337559 URL: http://llvm.org/viewvc/llvm-project?rev=337559&view=rev Log: [analyzer] Rename DanglingInternalBufferChecker to InnerPointerChecker. Differential Revision: https://reviews.llvm.org/D49553 Added: cfe/trunk/lib/StaticAnalyzer/Checkers/InnerPointerChecker.cpp - copied, changed from r337555, cfe/trunk/lib/StaticAnalyzer/Checkers/DanglingInternalBufferChecker.cpp cfe/trunk/test/Analysis/inner-pointer.cpp - copied, changed from r337555, cfe/trunk/test/Analysis/dangling-internal-buffer.cpp Removed: cfe/trunk/lib/StaticAnalyzer/Checkers/DanglingInternalBufferChecker.cpp cfe/trunk/test/Analysis/dangling-internal-buffer.cpp Modified: cfe/trunk/include/clang/StaticAnalyzer/Checkers/Checkers.td cfe/trunk/lib/StaticAnalyzer/Checkers/AllocationState.h cfe/trunk/lib/StaticAnalyzer/Checkers/CMakeLists.txt cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp Modified: cfe/trunk/include/clang/StaticAnalyzer/Checkers/Checkers.td URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Checkers/Checkers.td?rev=337559&r1=337558&r2=337559&view=diff == --- cfe/trunk/include/clang/StaticAnalyzer/Checkers/Checkers.td (original) +++ cfe/trunk/include/clang/StaticAnalyzer/Checkers/Checkers.td Fri Jul 20 08:14:49 2018 @@ -300,16 +300,15 @@ def VirtualCallChecker : Checker<"Virtua let ParentPackage = CplusplusAlpha in { -def DanglingInternalBufferChecker : Checker<"DanglingInternalBuffer">, - HelpText<"Check for internal raw pointers of C++ standard library containers " - "used after deallocation">, - DescFile<"DanglingInternalBufferChecker.cpp">; - def DeleteWithNonVirtualDtorChecker : Checker<"DeleteWithNonVirtualDtor">, HelpText<"Reports destructions of polymorphic objects with a non-virtual " "destructor in their base class">, DescFile<"DeleteWithNonVirtualDtorChecker.cpp">; +def InnerPointerChecker : Checker<"InnerPointer">, + HelpText<"Check for inner pointers of C++ containers used after re/deallocation">, + DescFile<"InnerPointerChecker.cpp">; + def IteratorRangeChecker : Checker<"IteratorRange">, HelpText<"Check for iterators used outside their valid ranges">, DescFile<"IteratorChecker.cpp">; Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/AllocationState.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/AllocationState.h?rev=337559&r1=337558&r2=337559&view=diff == --- cfe/trunk/lib/StaticAnalyzer/Checkers/AllocationState.h (original) +++ cfe/trunk/lib/StaticAnalyzer/Checkers/AllocationState.h Fri Jul 20 08:14:49 2018 @@ -23,8 +23,8 @@ ProgramStateRef markReleased(ProgramStat /// This function provides an additional visitor that augments the bug report /// with information relevant to memory errors caused by the misuse of -/// AF_InternalBuffer symbols. -std::unique_ptr getDanglingBufferBRVisitor(SymbolRef Sym); +/// AF_InnerBuffer symbols. +std::unique_ptr getInnerPointerBRVisitor(SymbolRef Sym); } // end namespace allocation_state Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/CMakeLists.txt URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/CMakeLists.txt?rev=337559&r1=337558&r2=337559&view=diff == --- cfe/trunk/lib/StaticAnalyzer/Checkers/CMakeLists.txt (original) +++ cfe/trunk/lib/StaticAnalyzer/Checkers/CMakeLists.txt Fri Jul 20 08:14:49 2018 @@ -27,7 +27,6 @@ add_clang_library(clangStaticAnalyzerChe CloneChecker.cpp ConversionChecker.cpp CXXSelfAssignmentChecker.cpp - DanglingInternalBufferChecker.cpp DeadStoresChecker.cpp DebugCheckers.cpp DeleteWithNonVirtualDtorChecker.cpp @@ -42,6 +41,7 @@ add_clang_library(clangStaticAnalyzerChe GenericTaintChecker.cpp GTestChecker.cpp IdenticalExprChecker.cpp + InnerPointerChecker.cpp IteratorChecker.cpp IvarInvalidationChecker.cpp LLVMConventionsChecker.cpp Removed: cfe/trunk/lib/StaticAnalyzer/Checkers/DanglingInternalBufferChecker.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/DanglingInternalBufferChecker.cpp?rev=337558&view=auto == --- cfe/trunk/lib/StaticAnalyzer/Checkers/DanglingInternalBufferChecker.cpp (original) +++ cfe/trunk/lib/StaticAnalyzer/Checkers/DanglingInternalBufferChecker.cpp (removed) @@ -1,253 +0,0 @@ -//=== DanglingInternalBufferChecker.cpp ---*- C++ -*--// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===---
r338259 - [analyzer] Add support for more invalidating functions in InnerPointerChecker.
Author: rkovacs Date: Mon Jul 30 08:43:45 2018 New Revision: 338259 URL: http://llvm.org/viewvc/llvm-project?rev=338259&view=rev Log: [analyzer] Add support for more invalidating functions in InnerPointerChecker. According to the standard, pointers referring to the elements of a `basic_string` may be invalidated if they are used as an argument to any standard library function taking a reference to non-const `basic_string` as an argument. This patch makes InnerPointerChecker warn for these cases. Differential Revision: https://reviews.llvm.org/D49656 Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/InnerPointerChecker.cpp cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp cfe/trunk/test/Analysis/inner-pointer.cpp Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/InnerPointerChecker.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/InnerPointerChecker.cpp?rev=338259&r1=338258&r2=338259&view=diff == --- cfe/trunk/lib/StaticAnalyzer/Checkers/InnerPointerChecker.cpp (original) +++ cfe/trunk/lib/StaticAnalyzer/Checkers/InnerPointerChecker.cpp Mon Jul 30 08:43:45 2018 @@ -91,37 +91,53 @@ public: ReserveFn("reserve"), ResizeFn("resize"), ShrinkToFitFn("shrink_to_fit"), SwapFn("swap") {} - /// Check whether the function called on the container object is a - /// member function that potentially invalidates pointers referring - /// to the objects's internal buffer. - bool mayInvalidateBuffer(const CallEvent &Call) const; - - /// 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. + /// Check if the object of this member function call is a `basic_string`. + bool isCalledOnStringObject(const CXXInstanceCall *ICall) const; + + /// Check whether the called member function potentially invalidates + /// pointers referring to the container object's inner buffer. + bool isInvalidatingMemberFunction(const CallEvent &Call) const; + + /// Mark pointer symbols associated with the given memory region released + /// in the program state. + void markPtrSymbolsReleased(const CallEvent &Call, ProgramStateRef State, + const MemRegion *ObjRegion, + CheckerContext &C) const; + + /// Standard library functions that take a non-const `basic_string` argument by + /// reference may invalidate its inner pointers. Check for these cases and + /// mark the pointers released. + void checkFunctionArguments(const CallEvent &Call, ProgramStateRef State, + CheckerContext &C) const; + + /// Record the connection between raw pointers referring to a container + /// object's inner buffer and the object's memory region in the program state. + /// Mark potentially invalidated pointers released. void checkPostCall(const CallEvent &Call, CheckerContext &C) const; - /// Clean up the ProgramState map. + /// Clean up the program state map. void checkDeadSymbols(SymbolReaper &SymReaper, CheckerContext &C) const; }; } // end anonymous namespace -// [string.require] -// -// "References, pointers, and iterators referring to the elements of a -// basic_string sequence may be invalidated by the following uses of that -// basic_string object: -// -// -- TODO: As an argument to any standard library function taking a reference -// to non-const basic_string as an argument. For example, as an argument to -// non-member functions swap(), operator>>(), and getline(), or as an argument -// to basic_string::swap(). -// -// -- Calling non-const member functions, except operator[], at, front, back, -// begin, rbegin, end, and rend." -// -bool InnerPointerChecker::mayInvalidateBuffer(const CallEvent &Call) const { +bool InnerPointerChecker::isCalledOnStringObject( +const CXXInstanceCall *ICall) const { + const auto *ObjRegion = +dyn_cast_or_null(ICall->getCXXThisVal().getAsRegion()); + if (!ObjRegion) +return false; + + QualType ObjTy = ObjRegion->getValueType(); + if (ObjTy.isNull() || + ObjTy->getAsCXXRecordDecl()->getName() != "basic_string") +return false; + + return true; +} + +bool InnerPointerChecker::isInvalidatingMemberFunction( +const CallEvent &Call) const { if (const auto *MemOpCall = dyn_cast(&Call)) { OverloadedOperatorKind Opc = MemOpCall->getOriginExpr()->getOperator(); if (Opc == OO_Equal || Opc == OO_PlusEqual) @@ -137,53 +153,104 @@ bool InnerPointerChecker::mayInvalidateB Call.isCalled(SwapFn)); } -void InnerPointerChecker::checkPostCall(const CallEvent &Call, -CheckerContext &C) const { - const auto *ICall = dyn_cast(&Call); - if (!ICall) -return; - - SVal Obj = ICall->getCXXThisVal(); - const auto *ObjRegion = dyn_cast_or_null(Obj.
r338263 - [analyzer] Add missing state transition in IteratorChecker.
Author: rkovacs Date: Mon Jul 30 09:14:59 2018 New Revision: 338263 URL: http://llvm.org/viewvc/llvm-project?rev=338263&view=rev Log: [analyzer] Add missing state transition in IteratorChecker. After cleaning up program state maps in `checkDeadSymbols()`, a transition should be added to generate the new state. Differential Revision: https://reviews.llvm.org/D47417 Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp?rev=338263&r1=338262&r2=338263&view=diff == --- cfe/trunk/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp (original) +++ cfe/trunk/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp Mon Jul 30 09:14:59 2018 @@ -551,6 +551,8 @@ void IteratorChecker::checkDeadSymbols(S State = State->remove(Comp.first); } } + + C.addTransition(State); } ProgramStateRef IteratorChecker::evalAssume(ProgramStateRef State, SVal Cond, ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
r338433 - [analyzer] Move InnerPointerChecker out of alpha.
Author: rkovacs Date: Tue Jul 31 13:27:11 2018 New Revision: 338433 URL: http://llvm.org/viewvc/llvm-project?rev=338433&view=rev Log: [analyzer] Move InnerPointerChecker out of alpha. Differential Revision: https://reviews.llvm.org/D49058 Modified: cfe/trunk/include/clang/StaticAnalyzer/Checkers/Checkers.td cfe/trunk/test/Analysis/inner-pointer.cpp Modified: cfe/trunk/include/clang/StaticAnalyzer/Checkers/Checkers.td URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Checkers/Checkers.td?rev=338433&r1=338432&r2=338433&view=diff == --- cfe/trunk/include/clang/StaticAnalyzer/Checkers/Checkers.td (original) +++ cfe/trunk/include/clang/StaticAnalyzer/Checkers/Checkers.td Tue Jul 31 13:27:11 2018 @@ -276,6 +276,10 @@ def ReturnUndefChecker : Checker<"UndefR let ParentPackage = Cplusplus in { +def InnerPointerChecker : Checker<"InnerPointer">, + HelpText<"Check for inner pointers of C++ containers used after re/deallocation">, + DescFile<"InnerPointerChecker.cpp">; + def NewDeleteChecker : Checker<"NewDelete">, HelpText<"Check for double-free and use-after-free problems. Traces memory managed by new/delete.">, DescFile<"MallocChecker.cpp">; @@ -305,10 +309,6 @@ def DeleteWithNonVirtualDtorChecker : Ch "destructor in their base class">, DescFile<"DeleteWithNonVirtualDtorChecker.cpp">; -def InnerPointerChecker : Checker<"InnerPointer">, - HelpText<"Check for inner pointers of C++ containers used after re/deallocation">, - DescFile<"InnerPointerChecker.cpp">; - def IteratorRangeChecker : Checker<"IteratorRange">, HelpText<"Check for iterators used outside their valid ranges">, DescFile<"IteratorChecker.cpp">; Modified: cfe/trunk/test/Analysis/inner-pointer.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/inner-pointer.cpp?rev=338433&r1=338432&r2=338433&view=diff == --- cfe/trunk/test/Analysis/inner-pointer.cpp (original) +++ cfe/trunk/test/Analysis/inner-pointer.cpp Tue Jul 31 13:27:11 2018 @@ -1,4 +1,4 @@ -//RUN: %clang_analyze_cc1 -analyzer-checker=alpha.cplusplus.InnerPointer %s -analyzer-output=text -verify +//RUN: %clang_analyze_cc1 -analyzer-checker=cplusplus.InnerPointer %s -analyzer-output=text -verify namespace std { ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
r338775 - [analyzer] Add a safety check to InnerPointerChecker.
Author: rkovacs Date: Thu Aug 2 15:19:57 2018 New Revision: 338775 URL: http://llvm.org/viewvc/llvm-project?rev=338775&view=rev Log: [analyzer] Add a safety check to InnerPointerChecker. Do not crash if the CXXRecordDecl of an object is not available. Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/InnerPointerChecker.cpp Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/InnerPointerChecker.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/InnerPointerChecker.cpp?rev=338775&r1=338774&r2=338775&view=diff == --- cfe/trunk/lib/StaticAnalyzer/Checkers/InnerPointerChecker.cpp (original) +++ cfe/trunk/lib/StaticAnalyzer/Checkers/InnerPointerChecker.cpp Thu Aug 2 15:19:57 2018 @@ -129,8 +129,11 @@ bool InnerPointerChecker::isCalledOnStri return false; QualType ObjTy = ObjRegion->getValueType(); - if (ObjTy.isNull() || - ObjTy->getAsCXXRecordDecl()->getName() != "basic_string") + if (ObjTy.isNull()) +return false; + + CXXRecordDecl *Decl = ObjTy->getAsCXXRecordDecl(); + if (!Decl || Decl->getName() != "basic_string") return false; return true; ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
r338777 - [analyzer] Obtain a ReturnStmt from a CFGAutomaticObjDtor.
Author: rkovacs Date: Thu Aug 2 15:31:03 2018 New Revision: 338777 URL: http://llvm.org/viewvc/llvm-project?rev=338777&view=rev Log: [analyzer] Obtain a ReturnStmt from a CFGAutomaticObjDtor. The CoreEngine only gives us a ReturnStmt if the last element in the CFGBlock is a CFGStmt, otherwise the ReturnStmt is nullptr. This patch adds support for the case when the last element is a CFGAutomaticObjDtor, by returning its TriggerStmt as a ReturnStmt. Differential Revision: https://reviews.llvm.org/D49811 Added: cfe/trunk/test/Analysis/end-function-return-stmt.cpp Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/AnalysisOrderChecker.cpp cfe/trunk/lib/StaticAnalyzer/Core/CoreEngine.cpp Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/AnalysisOrderChecker.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/AnalysisOrderChecker.cpp?rev=338777&r1=338776&r2=338777&view=diff == --- cfe/trunk/lib/StaticAnalyzer/Checkers/AnalysisOrderChecker.cpp (original) +++ cfe/trunk/lib/StaticAnalyzer/Checkers/AnalysisOrderChecker.cpp Thu Aug 2 15:31:03 2018 @@ -16,6 +16,7 @@ #include "ClangSACheckers.h" #include "clang/AST/ExprCXX.h" +#include "clang/Analysis/CFGStmtMap.h" #include "clang/StaticAnalyzer/Core/Checker.h" #include "clang/StaticAnalyzer/Core/CheckerManager.h" #include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h" @@ -37,6 +38,7 @@ class AnalysisOrderChecker check::PostStmt, check::PreCall, check::PostCall, + check::EndFunction, check::NewAllocator, check::Bind, check::RegionChanges, @@ -121,6 +123,23 @@ public: } } + void checkEndFunction(const ReturnStmt *S, CheckerContext &C) const { +if (isCallbackEnabled(C, "EndFunction")) { + llvm::errs() << "EndFunction\nReturnStmt: " << (S ? "yes" : "no") << "\n"; + if (!S) +return; + + llvm::errs() << "CFGElement: "; + CFGStmtMap *Map = C.getCurrentAnalysisDeclContext()->getCFGStmtMap(); + CFGElement LastElement = Map->getBlock(S)->back(); + + if (LastElement.getAs()) +llvm::errs() << "CFGStmt\n"; + else if (LastElement.getAs()) +llvm::errs() << "CFGAutomaticObjDtor\n"; +} + } + void checkNewAllocator(const CXXNewExpr *CNE, SVal Target, CheckerContext &C) const { if (isCallbackEnabled(C, "NewAllocator")) Modified: cfe/trunk/lib/StaticAnalyzer/Core/CoreEngine.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/CoreEngine.cpp?rev=338777&r1=338776&r2=338777&view=diff == --- cfe/trunk/lib/StaticAnalyzer/Core/CoreEngine.cpp (original) +++ cfe/trunk/lib/StaticAnalyzer/Core/CoreEngine.cpp Thu Aug 2 15:31:03 2018 @@ -223,8 +223,12 @@ void CoreEngine::HandleBlockEdge(const B // Get return statement.. const ReturnStmt *RS = nullptr; if (!L.getSrc()->empty()) { - if (Optional LastStmt = L.getSrc()->back().getAs()) { + CFGElement LastElement = L.getSrc()->back(); + if (Optional LastStmt = LastElement.getAs()) { RS = dyn_cast(LastStmt->getStmt()); + } else if (Optional AutoDtor = + LastElement.getAs()) { +RS = dyn_cast(AutoDtor->getTriggerStmt()); } } Added: cfe/trunk/test/Analysis/end-function-return-stmt.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/end-function-return-stmt.cpp?rev=338777&view=auto == --- cfe/trunk/test/Analysis/end-function-return-stmt.cpp (added) +++ cfe/trunk/test/Analysis/end-function-return-stmt.cpp Thu Aug 2 15:31:03 2018 @@ -0,0 +1,34 @@ +//RUN: %clang_analyze_cc1 -analyzer-checker=debug.AnalysisOrder -analyzer-config debug.AnalysisOrder:EndFunction=true %s 2>&1 | FileCheck %s + +// At the end of a function, we can only obtain a ReturnStmt if the last +// CFGElement in the CFGBlock is either a CFGStmt or a CFGAutomaticObjDtor. + +void noReturnStmt() {} + +struct S { + S(); + ~S(); +}; + +int dtorAfterReturnStmt() { + S s; + return 0; +} + +S endsWithReturnStmt() { + return S(); +} + +// endsWithReturnStmt() +// CHECK: EndFunction +// CHECK-NEXT: ReturnStmt: yes +// CHECK-NEXT: CFGElement: CFGStmt + +// dtorAfterReturnStmt() +// CHECK: EndFunction +// CHECK-NEXT: ReturnStmt: yes +// CHECK-NEXT: CFGElement: CFGAutomaticObjDtor + +// noReturnStmt() +// CHECK: EndFunction +// CHECK-NEXT: ReturnStmt: no ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
r338780 - [analyzer] Detect pointers escaped after ReturnStmt execution in MallocChecker.
Author: rkovacs Date: Thu Aug 2 16:02:08 2018 New Revision: 338780 URL: http://llvm.org/viewvc/llvm-project?rev=338780&view=rev Log: [analyzer] Detect pointers escaped after ReturnStmt execution in MallocChecker. Objects local to a function are destroyed right after the statement returning (part of) them is executed in the analyzer. This patch enables MallocChecker to warn in these cases. Differential Revision: https://reviews.llvm.org/D49361 Added: cfe/trunk/test/Analysis/malloc-free-after-return.cpp Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp cfe/trunk/test/Analysis/inner-pointer.cpp Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp?rev=338780&r1=338779&r2=338780&view=diff == --- cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp (original) +++ cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp Thu Aug 2 16:02:08 2018 @@ -161,6 +161,7 @@ class MallocChecker : public Checker, + check::EndFunction, check::PreCall, check::PostStmt, check::PostStmt, @@ -217,6 +218,7 @@ public: void checkPostStmt(const BlockExpr *BE, CheckerContext &C) const; void checkDeadSymbols(SymbolReaper &SymReaper, CheckerContext &C) const; void checkPreStmt(const ReturnStmt *S, CheckerContext &C) const; + void checkEndFunction(const ReturnStmt *S, CheckerContext &C) const; ProgramStateRef evalAssume(ProgramStateRef state, SVal Cond, bool Assumption) const; void checkLocation(SVal l, bool isLoad, const Stmt *S, @@ -353,7 +355,7 @@ private: static ProgramStateRef CallocMem(CheckerContext &C, const CallExpr *CE, ProgramStateRef State); - ///Check if the memory associated with this symbol was released. + /// Check if the memory associated with this symbol was released. bool isReleased(SymbolRef Sym, CheckerContext &C) const; bool checkUseAfterFree(SymbolRef Sym, CheckerContext &C, const Stmt *S) const; @@ -377,13 +379,16 @@ private: ProgramStateRef State, SymbolRef &EscapingSymbol) const; - // Implementation of the checkPointerEscape callabcks. + // Implementation of the checkPointerEscape callbacks. ProgramStateRef checkPointerEscapeAux(ProgramStateRef State, const InvalidatedSymbols &Escaped, const CallEvent *Call, PointerEscapeKind Kind, bool(*CheckRefState)(const RefState*)) const; + // Implementation of the checkPreStmt and checkEndFunction callbacks. + void checkEscapeOnReturn(const ReturnStmt *S, CheckerContext &C) const; + ///@{ /// Tells if a given family/call/symbol is tracked by the current checker. /// Sets CheckKind to the kind of the checker responsible for this @@ -2451,7 +2456,24 @@ void MallocChecker::checkPreCall(const C } } -void MallocChecker::checkPreStmt(const ReturnStmt *S, CheckerContext &C) const { +void MallocChecker::checkPreStmt(const ReturnStmt *S, + CheckerContext &C) const { + checkEscapeOnReturn(S, C); +} + +// In the CFG, automatic destructors come after the return statement. +// This callback checks for returning memory that is freed by automatic +// destructors, as those cannot be reached in checkPreStmt(). +void MallocChecker::checkEndFunction(const ReturnStmt *S, + CheckerContext &C) const { + checkEscapeOnReturn(S, C); +} + +void MallocChecker::checkEscapeOnReturn(const ReturnStmt *S, +CheckerContext &C) const { + if (!S) +return; + const Expr *E = S->getRetValue(); if (!E) return; Modified: cfe/trunk/test/Analysis/inner-pointer.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/inner-pointer.cpp?rev=338780&r1=338779&r2=338780&view=diff == --- cfe/trunk/test/Analysis/inner-pointer.cpp (original) +++ cfe/trunk/test/Analysis/inner-pointer.cpp Thu Aug 2 16:02:08 2018 @@ -361,3 +361,24 @@ void func_default_arg() { consume(c);// expected-warning {{Use of memory after it is freed}} // expected-note@-1 {{Use of memory after it is freed}} } + +struct S { + std::string to_string() { return s; } +private: + std::string s; +}; + +const char *escape_via_return_temp() { + S x; + return x.to_string().c_str(); // expected-note {{Dangling inner pointer obtained here}} + // expected-note@-1 {{Inner pointer invalidated by call to destructor}} + // expected-warning@
r338918 - [analyzer] Add test for a crash fixed in r338775.
Author: rkovacs Date: Fri Aug 3 13:42:02 2018 New Revision: 338918 URL: http://llvm.org/viewvc/llvm-project?rev=338918&view=rev Log: [analyzer] Add test for a crash fixed in r338775. Do not crash if a CXXRecordDecl cannot be obtained for an object. Special thanks for the reproduction to Alexander Kornienko. Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/InnerPointerChecker.cpp cfe/trunk/test/Analysis/inner-pointer.cpp Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/InnerPointerChecker.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/InnerPointerChecker.cpp?rev=338918&r1=338917&r2=338918&view=diff == --- cfe/trunk/lib/StaticAnalyzer/Checkers/InnerPointerChecker.cpp (original) +++ cfe/trunk/lib/StaticAnalyzer/Checkers/InnerPointerChecker.cpp Fri Aug 3 13:42:02 2018 @@ -133,10 +133,7 @@ bool InnerPointerChecker::isCalledOnStri return false; CXXRecordDecl *Decl = ObjTy->getAsCXXRecordDecl(); - if (!Decl || Decl->getName() != "basic_string") -return false; - - return true; + return Decl && Decl->getName() == "basic_string"; } bool InnerPointerChecker::isInvalidatingMemberFunction( Modified: cfe/trunk/test/Analysis/inner-pointer.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/inner-pointer.cpp?rev=338918&r1=338917&r2=338918&view=diff == --- cfe/trunk/test/Analysis/inner-pointer.cpp (original) +++ cfe/trunk/test/Analysis/inner-pointer.cpp Fri Aug 3 13:42:02 2018 @@ -382,3 +382,13 @@ const char *escape_via_return_local() { // expected-note@-1 {{Inner pointer invalidated by call to destructor}} } // expected-warning {{Use of memory after it is freed}} // expected-note@-1 {{Use of memory after it is freed}} + + +char *c(); +class A {}; + +void no_CXXRecordDecl() { + A a, *b; + *(void **)&b = c() + 1; + *b = a; // no-crash +} ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
r334348 - [analyzer] Add dangling internal buffer check.
Author: rkovacs Date: Sat Jun 9 06:03:49 2018 New Revision: 334348 URL: http://llvm.org/viewvc/llvm-project?rev=334348&view=rev Log: [analyzer] Add dangling internal buffer check. This check will mark raw pointers to C++ standard library container internal buffers 'released' when the objects themselves are destroyed. Such information can be used by MallocChecker to warn about use-after-free problems. In this first version, 'std::basic_string's are supported. Differential Revision: https://reviews.llvm.org/D47135 Added: cfe/trunk/lib/StaticAnalyzer/Checkers/AllocationState.h cfe/trunk/lib/StaticAnalyzer/Checkers/DanglingInternalBufferChecker.cpp cfe/trunk/test/Analysis/dangling-internal-buffer.cpp Modified: cfe/trunk/include/clang/StaticAnalyzer/Checkers/Checkers.td cfe/trunk/lib/StaticAnalyzer/Checkers/CMakeLists.txt cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp Modified: cfe/trunk/include/clang/StaticAnalyzer/Checkers/Checkers.td URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Checkers/Checkers.td?rev=334348&r1=334347&r2=334348&view=diff == --- cfe/trunk/include/clang/StaticAnalyzer/Checkers/Checkers.td (original) +++ cfe/trunk/include/clang/StaticAnalyzer/Checkers/Checkers.td Sat Jun 9 06:03:49 2018 @@ -300,6 +300,11 @@ def VirtualCallChecker : Checker<"Virtua let ParentPackage = CplusplusAlpha in { +def DanglingInternalBufferChecker : Checker<"DanglingInternalBuffer">, + HelpText<"Check for internal raw pointers of C++ standard library containers " + "used after deallocation">, + DescFile<"DanglingInternalBufferChecker.cpp">; + def DeleteWithNonVirtualDtorChecker : Checker<"DeleteWithNonVirtualDtor">, HelpText<"Reports destructions of polymorphic objects with a non-virtual " "destructor in their base class">, Added: cfe/trunk/lib/StaticAnalyzer/Checkers/AllocationState.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/AllocationState.h?rev=334348&view=auto == --- cfe/trunk/lib/StaticAnalyzer/Checkers/AllocationState.h (added) +++ cfe/trunk/lib/StaticAnalyzer/Checkers/AllocationState.h Sat Jun 9 06:03:49 2018 @@ -0,0 +1,28 @@ +//===--- AllocationState.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_ALLOCATIONSTATE_H +#define LLVM_CLANG_LIB_STATICANALYZER_CHECKERS_ALLOCATIONSTATE_H + +#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h" + +namespace clang { +namespace ento { + +namespace allocation_state { + +ProgramStateRef markReleased(ProgramStateRef State, SymbolRef Sym, + const Expr *Origin); + +} // end namespace allocation_state + +} // end namespace ento +} // end namespace clang + +#endif Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/CMakeLists.txt URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/CMakeLists.txt?rev=334348&r1=334347&r2=334348&view=diff == --- cfe/trunk/lib/StaticAnalyzer/Checkers/CMakeLists.txt (original) +++ cfe/trunk/lib/StaticAnalyzer/Checkers/CMakeLists.txt Sat Jun 9 06:03:49 2018 @@ -27,6 +27,7 @@ add_clang_library(clangStaticAnalyzerChe CloneChecker.cpp ConversionChecker.cpp CXXSelfAssignmentChecker.cpp + DanglingInternalBufferChecker.cpp DeadStoresChecker.cpp DebugCheckers.cpp DeleteWithNonVirtualDtorChecker.cpp Added: cfe/trunk/lib/StaticAnalyzer/Checkers/DanglingInternalBufferChecker.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/DanglingInternalBufferChecker.cpp?rev=334348&view=auto == --- cfe/trunk/lib/StaticAnalyzer/Checkers/DanglingInternalBufferChecker.cpp (added) +++ cfe/trunk/lib/StaticAnalyzer/Checkers/DanglingInternalBufferChecker.cpp Sat Jun 9 06:03:49 2018 @@ -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. +// +//===---
r334352 - [analyzer] Clean up the program state map of DanglingInternalBufferChecker.
Author: rkovacs Date: Sat Jun 9 14:08:27 2018 New Revision: 334352 URL: http://llvm.org/viewvc/llvm-project?rev=334352&view=rev Log: [analyzer] Clean up the program state map of DanglingInternalBufferChecker. Symbols are cleaned up from the program state map when they go out of scope. Memory regions are cleaned up when the corresponding object is destroyed, and additionally in 'checkDeadSymbols' in case destructor modeling was incomplete. Differential Revision: https://reviews.llvm.org/D47416 Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/DanglingInternalBufferChecker.cpp Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/DanglingInternalBufferChecker.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/DanglingInternalBufferChecker.cpp?rev=334352&r1=334351&r2=334352&view=diff == --- cfe/trunk/lib/StaticAnalyzer/Checkers/DanglingInternalBufferChecker.cpp (original) +++ cfe/trunk/lib/StaticAnalyzer/Checkers/DanglingInternalBufferChecker.cpp Sat Jun 9 14:08:27 2018 @@ -26,7 +26,8 @@ using namespace ento; namespace { -class DanglingInternalBufferChecker : public Checker { +class DanglingInternalBufferChecker : public Checker { CallDescription CStrFn; public: @@ -36,6 +37,9 @@ public: /// 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; + + /// Clean up the ProgramState map. + void checkDeadSymbols(SymbolReaper &SymReaper, CheckerContext &C) const; }; } // end anonymous namespace @@ -76,12 +80,29 @@ void DanglingInternalBufferChecker::chec // FIXME: What if Origin is null? const Expr *Origin = Call.getOriginExpr(); State = allocation_state::markReleased(State, *StrBufferPtr, Origin); + State = State->remove(TypedR); C.addTransition(State); return; } } } +void DanglingInternalBufferChecker::checkDeadSymbols(SymbolReaper &SymReaper, + CheckerContext &C) const { + ProgramStateRef State = C.getState(); + RawPtrMapTy RPM = State->get(); + for (const auto Entry : RPM) { +if (!SymReaper.isLive(Entry.second)) + State = State->remove(Entry.first); +if (!SymReaper.isLiveRegion(Entry.first)) { + // Due to incomplete destructor support, some dead regions might still + // remain in the program state map. Clean them up. + State = State->remove(Entry.first); +} + } + C.addTransition(State); +} + void ento::registerDanglingInternalBufferChecker(CheckerManager &Mgr) { registerNewDeleteChecker(Mgr); Mgr.registerChecker(); ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
r314061 - [docs] Fix typos in Clang's User's Manual.
Author: rkovacs Date: Sat Sep 23 05:13:32 2017 New Revision: 314061 URL: http://llvm.org/viewvc/llvm-project?rev=314061&view=rev Log: [docs] Fix typos in Clang's User's Manual. Modified: cfe/trunk/docs/UsersManual.rst Modified: cfe/trunk/docs/UsersManual.rst URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/docs/UsersManual.rst?rev=314061&r1=314060&r2=314061&view=diff == --- cfe/trunk/docs/UsersManual.rst (original) +++ cfe/trunk/docs/UsersManual.rst Sat Sep 23 05:13:32 2017 @@ -107,7 +107,7 @@ Options to Control Error and Warning Mes .. option:: -Wno-error=foo - Turn warning "foo" into an warning even if :option:`-Werror` is specified. + Turn warning "foo" into a warning even if :option:`-Werror` is specified. .. option:: -Wfoo @@ -677,7 +677,7 @@ Current limitations Other Options - -Clang options that that don't fit neatly into other categories. +Clang options that don't fit neatly into other categories. .. option:: -MV ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
r336493 - [analyzer] Fix -Wcovered-switch-default warning in MallocChecker.
Author: rkovacs Date: Sat Jul 7 11:37:37 2018 New Revision: 336493 URL: http://llvm.org/viewvc/llvm-project?rev=336493&view=rev Log: [analyzer] Fix -Wcovered-switch-default warning in MallocChecker. Remove unnecessary default case that caused buildbot failures. Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp?rev=336493&r1=336492&r2=336493&view=diff == --- cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp (original) +++ cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp Sat Jul 7 11:37:37 2018 @@ -2915,7 +2915,6 @@ std::shared_ptr Mal Msg = "Internal buffer is released because the object was destroyed"; break; case AF_None: -default: llvm_unreachable("Unhandled allocation family!"); } StackHint = new StackHintGeneratorForSymbol(Sym, ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
r336489 - [analyzer] Highlight container object destruction in MallocChecker.
Author: rkovacs Date: Sat Jul 7 10:22:45 2018 New Revision: 336489 URL: http://llvm.org/viewvc/llvm-project?rev=336489&view=rev Log: [analyzer] Highlight container object destruction in MallocChecker. Extend MallocBugVisitor to place a note at the point where objects with AF_InternalBuffer allocation family are destroyed. Differential Revision: https://reviews.llvm.org/D48521 Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp cfe/trunk/test/Analysis/dangling-internal-buffer.cpp Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp?rev=336489&r1=336488&r2=336489&view=diff == --- cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp (original) +++ cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp Sat Jul 7 10:22:45 2018 @@ -480,8 +480,13 @@ private: inline bool isReleased(const RefState *S, const RefState *SPrev, const Stmt *Stmt) { // Did not track -> released. Other state (allocated) -> released. - return (Stmt && (isa(Stmt) || isa(Stmt)) && - (S && S->isReleased()) && (!SPrev || !SPrev->isReleased())); + // The statement associated with the release might be missing. + bool IsReleased = (S && S->isReleased()) && +(!SPrev || !SPrev->isReleased()); + assert(!IsReleased || + (Stmt && (isa(Stmt) || isa(Stmt))) || + (!Stmt && S->getAllocationFamily() == AF_InternalBuffer)); + return IsReleased; } inline bool isRelinquished(const RefState *S, const RefState *SPrev, @@ -2850,8 +2855,17 @@ static bool isReferenceCountingPointerDe std::shared_ptr MallocChecker::MallocBugVisitor::VisitNode( const ExplodedNode *N, const ExplodedNode *PrevN, BugReporterContext &BRC, BugReport &BR) { + + ProgramStateRef state = N->getState(); + ProgramStateRef statePrev = PrevN->getState(); + + const RefState *RS = state->get(Sym); + const RefState *RSPrev = statePrev->get(Sym); + const Stmt *S = PathDiagnosticLocation::getStmt(N); - if (!S) + // When dealing with containers, we sometimes want to give a note + // even if the statement is missing. + if (!S && (!RS || RS->getAllocationFamily() != AF_InternalBuffer)) return nullptr; const LocationContext *CurrentLC = N->getLocationContext(); @@ -2876,14 +2890,6 @@ std::shared_ptr Mal } } - ProgramStateRef state = N->getState(); - ProgramStateRef statePrev = PrevN->getState(); - - const RefState *RS = state->get(Sym); - const RefState *RSPrev = statePrev->get(Sym); - if (!RS) -return nullptr; - // FIXME: We will eventually need to handle non-statement-based events // (__attribute__((cleanup))). @@ -2896,7 +2902,22 @@ std::shared_ptr Mal StackHint = new StackHintGeneratorForSymbol(Sym, "Returned allocated memory"); } else if (isReleased(RS, RSPrev, S)) { - Msg = "Memory is released"; + const auto Family = RS->getAllocationFamily(); + switch(Family) { +case AF_Alloca: +case AF_Malloc: +case AF_CXXNew: +case AF_CXXNewArray: +case AF_IfNameIndex: + Msg = "Memory is released"; + break; +case AF_InternalBuffer: + Msg = "Internal buffer is released because the object was destroyed"; + break; +case AF_None: +default: + llvm_unreachable("Unhandled allocation family!"); + } StackHint = new StackHintGeneratorForSymbol(Sym, "Returning; memory was released"); @@ -2967,8 +2988,19 @@ std::shared_ptr Mal assert(StackHint); // Generate the extra diagnostic. - PathDiagnosticLocation Pos(S, BRC.getSourceManager(), - N->getLocationContext()); + PathDiagnosticLocation Pos; + if (!S) { +assert(RS->getAllocationFamily() == AF_InternalBuffer); +auto PostImplCall = N->getLocation().getAs(); +if (!PostImplCall) + return nullptr; +Pos = PathDiagnosticLocation(PostImplCall->getLocation(), + BRC.getSourceManager()); + } else { +Pos = PathDiagnosticLocation(S, BRC.getSourceManager(), + N->getLocationContext()); + } + return std::make_shared(Pos, Msg, true, StackHint); } Modified: cfe/trunk/test/Analysis/dangling-internal-buffer.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/dangling-internal-buffer.cpp?rev=336489&r1=336488&r2=336489&view=diff == --- cfe/trunk/test/Analysis/dangling-internal-buffer.cpp (original) +++ cfe/trunk/test/Analysis/dangling-internal-buffer.cpp Sat Jul 7 10:22:45 2018 @@ -26,7 +26,7 @@ void deref_after_sc
r336497 - [analyzer] Add support for data() in DanglingInternalBufferChecker.
Author: rkovacs Date: Sat Jul 7 13:29:24 2018 New Revision: 336497 URL: http://llvm.org/viewvc/llvm-project?rev=336497&view=rev Log: [analyzer] Add support for data() in DanglingInternalBufferChecker. DanglingInternalBufferChecker now tracks use-after-free problems related to the incorrect usage of std::basic_string::data(). Differential Revision: https://reviews.llvm.org/D48532 Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/DanglingInternalBufferChecker.cpp cfe/trunk/test/Analysis/dangling-internal-buffer.cpp Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/DanglingInternalBufferChecker.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/DanglingInternalBufferChecker.cpp?rev=336497&r1=336496&r2=336497&view=diff == --- cfe/trunk/lib/StaticAnalyzer/Checkers/DanglingInternalBufferChecker.cpp (original) +++ cfe/trunk/lib/StaticAnalyzer/Checkers/DanglingInternalBufferChecker.cpp Sat Jul 7 13:29:24 2018 @@ -24,15 +24,16 @@ using namespace clang; using namespace ento; -// FIXME: c_str() may be called on a string object many times, so it should -// have a list of symbols associated with it. +// FIXME: member functions that return a pointer to the container's internal +// buffer may be called on the object many times, so the object's memory +// region should have a list of pointer symbols associated with it. REGISTER_MAP_WITH_PROGRAMSTATE(RawPtrMap, const MemRegion *, SymbolRef) namespace { class DanglingInternalBufferChecker : public Checker { - CallDescription CStrFn; + CallDescription CStrFn, DataFn; public: class DanglingBufferBRVisitor : public BugReporterVisitor { @@ -67,7 +68,7 @@ public: } }; - DanglingInternalBufferChecker() : CStrFn("c_str") {} + DanglingInternalBufferChecker() : CStrFn("c_str"), DataFn("data") {} /// Record the connection between the symbol returned by c_str() and the /// corresponding string object region in the ProgramState. Mark the symbol @@ -97,7 +98,7 @@ void DanglingInternalBufferChecker::chec ProgramStateRef State = C.getState(); - if (Call.isCalled(CStrFn)) { + if (Call.isCalled(CStrFn) || Call.isCalled(DataFn)) { SVal RawPtr = Call.getReturnValue(); if (!RawPtr.isUnknown()) { State = State->set(TypedR, RawPtr.getAsSymbol()); Modified: cfe/trunk/test/Analysis/dangling-internal-buffer.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/dangling-internal-buffer.cpp?rev=336497&r1=336496&r2=336497&view=diff == --- cfe/trunk/test/Analysis/dangling-internal-buffer.cpp (original) +++ cfe/trunk/test/Analysis/dangling-internal-buffer.cpp Sat Jul 7 13:29:24 2018 @@ -7,6 +7,8 @@ class basic_string { public: ~basic_string(); const CharT *c_str() const; + const CharT *data() const; + CharT *data(); }; typedef basic_string string; @@ -21,59 +23,92 @@ void consume(const wchar_t *) {} void consume(const char16_t *) {} void consume(const char32_t *) {} -void deref_after_scope_char() { +void deref_after_scope_char_cstr() { const char *c; { std::string s; c = s.c_str(); // expected-note {{Pointer to dangling buffer was obtained here}} } // expected-note {{Internal buffer is released because the object was destroyed}} + std::string s; + const char *c2 = s.c_str(); consume(c); // expected-warning {{Use of memory after it is freed}} // expected-note@-1 {{Use of memory after it is freed}} } -void deref_after_scope_char2() { +void deref_after_scope_char_data() { const char *c; { std::string s; -c = s.c_str(); // expected-note {{Pointer to dangling buffer was obtained here}} +c = s.data(); // expected-note {{Pointer to dangling buffer was obtained here}} } // expected-note {{Internal buffer is released because the object was destroyed}} std::string s; - const char *c2 = s.c_str(); + const char *c2 = s.data(); + consume(c); // expected-warning {{Use of memory after it is freed}} + // expected-note@-1 {{Use of memory after it is freed}} +} + +void deref_after_scope_char_data_non_const() { + char *c; + { +std::string s; +c = s.data(); // expected-note {{Pointer to dangling buffer was obtained here}} + } // expected-note {{Internal buffer is released because the object was destroyed}} + std::string s; + char *c2 = s.data(); consume(c); // expected-warning {{Use of memory after it is freed}} // expected-note@-1 {{Use of memory after it is freed}} } -void deref_after_scope_wchar_t() { + +void deref_after_scope_wchar_t_cstr() { const wchar_t *w; { std::wstring ws; w = ws.c_str(); // expected-note {{Pointer to dangling buffer was obtained here}} } // expected-note {{Internal buffer is released because the object was destroyed}} + std::wstring ws; + const wchar_t *w2 = ws.c_str(); + consume(w); //
r336495 - [analyzer] Highlight c_str() call in DanglingInternalBufferChecker.
Author: rkovacs Date: Sat Jul 7 12:27:18 2018 New Revision: 336495 URL: http://llvm.org/viewvc/llvm-project?rev=336495&view=rev Log: [analyzer] Highlight c_str() call in DanglingInternalBufferChecker. Add a bug visitor to DanglingInternalBufferChecker that places a note at the point where the dangling pointer was obtained. The visitor is handed over to MallocChecker and attached to the report there. Differential Revision: https://reviews.llvm.org/D48522 Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/AllocationState.h cfe/trunk/lib/StaticAnalyzer/Checkers/DanglingInternalBufferChecker.cpp cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp cfe/trunk/test/Analysis/dangling-internal-buffer.cpp Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/AllocationState.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/AllocationState.h?rev=336495&r1=336494&r2=336495&view=diff == --- cfe/trunk/lib/StaticAnalyzer/Checkers/AllocationState.h (original) +++ cfe/trunk/lib/StaticAnalyzer/Checkers/AllocationState.h Sat Jul 7 12:27:18 2018 @@ -10,6 +10,7 @@ #ifndef LLVM_CLANG_LIB_STATICANALYZER_CHECKERS_ALLOCATIONSTATE_H #define LLVM_CLANG_LIB_STATICANALYZER_CHECKERS_ALLOCATIONSTATE_H +#include "clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitors.h" #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h" namespace clang { @@ -20,6 +21,11 @@ namespace allocation_state { ProgramStateRef markReleased(ProgramStateRef State, SymbolRef Sym, const Expr *Origin); +/// This function provides an additional visitor that augments the bug report +/// with information relevant to memory errors caused by the misuse of +/// AF_InternalBuffer symbols. +std::unique_ptr getDanglingBufferBRVisitor(SymbolRef Sym); + } // end namespace allocation_state } // end namespace ento Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/DanglingInternalBufferChecker.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/DanglingInternalBufferChecker.cpp?rev=336495&r1=336494&r2=336495&view=diff == --- cfe/trunk/lib/StaticAnalyzer/Checkers/DanglingInternalBufferChecker.cpp (original) +++ cfe/trunk/lib/StaticAnalyzer/Checkers/DanglingInternalBufferChecker.cpp Sat Jul 7 12:27:18 2018 @@ -7,30 +7,66 @@ // //===--===// // -// 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. +// This file defines a check that marks a raw pointer to a C++ container's +// inner buffer released when the object is destroyed. This information can +// be used by MallocChecker to detect use-after-free problems. // //===--===// +#include "AllocationState.h" #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; +// 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) + namespace { -class DanglingInternalBufferChecker : public Checker { +class DanglingInternalBufferChecker +: public Checker { CallDescription CStrFn; public: + class DanglingBufferBRVisitor : public BugReporterVisitor { +SymbolRef PtrToBuf; + + public: +DanglingBufferBRVisitor(SymbolRef Sym) : PtrToBuf(Sym) {} + +static void *getTag() { + static int Tag = 0; + return &Tag; +} + +void Profile(llvm::FoldingSetNodeID &ID) const override { + ID.AddPointer(getTag()); +} + +std::shared_ptr VisitNode(const ExplodedNode *N, + const ExplodedNode *PrevN, + BugReporterContext &BRC, + BugReport &BR) override; + +// FIXME: Scan the map once in the visitor's constructor and do a direct +// lookup by region. +bool isSymbolTracked(ProgramStateRef State, SymbolRef Sym) { + RawPtrMapTy Map = State->get(); + for (const auto Entry : Map) { +if (Entry.second == Sym) + return true; + } + return false; +} + }; + DanglingInternalBufferChecker() : CStrFn("c_str") {} /// Re
r336835 - [analyzer] Track multiple raw pointer symbols in DanglingInternalBufferChecker.
Author: rkovacs Date: Wed Jul 11 12:08:02 2018 New Revision: 336835 URL: http://llvm.org/viewvc/llvm-project?rev=336835&view=rev Log: [analyzer] Track multiple raw pointer symbols in DanglingInternalBufferChecker. Previously, the checker only tracked one raw pointer symbol for each container object. But member functions returning a pointer to the object's inner buffer may be called on the object several times. These pointer symbols are now collected in a set inside the program state map and thus all of them is checked for use-after-free problems. Differential Revision: https://reviews.llvm.org/D49057 Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/DanglingInternalBufferChecker.cpp cfe/trunk/test/Analysis/dangling-internal-buffer.cpp Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/DanglingInternalBufferChecker.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/DanglingInternalBufferChecker.cpp?rev=336835&r1=336834&r2=336835&view=diff == --- cfe/trunk/lib/StaticAnalyzer/Checkers/DanglingInternalBufferChecker.cpp (original) +++ cfe/trunk/lib/StaticAnalyzer/Checkers/DanglingInternalBufferChecker.cpp Wed Jul 11 12:08:02 2018 @@ -24,10 +24,23 @@ using namespace clang; using namespace ento; -// FIXME: member functions that return a pointer to the container's internal -// buffer may be called on the object many times, so the object's memory -// region should have a list of pointer symbols associated with it. -REGISTER_MAP_WITH_PROGRAMSTATE(RawPtrMap, const MemRegion *, SymbolRef) +using PtrSet = llvm::ImmutableSet; + +// Associate container objects with a set of raw pointer symbols. +REGISTER_MAP_WITH_PROGRAMSTATE(RawPtrMap, const MemRegion *, PtrSet) + +// This is a trick to gain access to PtrSet's Factory. +namespace clang { +namespace ento { +template<> struct ProgramStateTrait + : public ProgramStatePartialTrait { + static void *GDMIndex() { +static int Index = 0; +return &Index; + } +}; +} // end namespace ento +} // end namespace clang namespace { @@ -61,7 +74,7 @@ public: bool isSymbolTracked(ProgramStateRef State, SymbolRef Sym) { RawPtrMapTy Map = State->get(); for (const auto Entry : Map) { -if (Entry.second == Sym) +if (Entry.second.contains(Sym)) return true; } return false; @@ -88,11 +101,11 @@ void DanglingInternalBufferChecker::chec return; SVal Obj = ICall->getCXXThisVal(); - const auto *TypedR = dyn_cast_or_null(Obj.getAsRegion()); - if (!TypedR) + const auto *ObjRegion = dyn_cast_or_null(Obj.getAsRegion()); + if (!ObjRegion) return; - auto *TypeDecl = TypedR->getValueType()->getAsCXXRecordDecl(); + auto *TypeDecl = ObjRegion->getValueType()->getAsCXXRecordDecl(); if (TypeDecl->getName() != "basic_string") return; @@ -100,20 +113,30 @@ void DanglingInternalBufferChecker::chec if (Call.isCalled(CStrFn) || Call.isCalled(DataFn)) { SVal RawPtr = Call.getReturnValue(); -if (!RawPtr.isUnknown()) { - State = State->set(TypedR, RawPtr.getAsSymbol()); +if (SymbolRef Sym = RawPtr.getAsSymbol(/*IncludeBaseRegions=*/true)) { + // Start tracking this raw pointer by adding it to the set of symbols + // associated with this container object in the program state map. + PtrSet::Factory &F = State->getStateManager().get_context(); + const PtrSet *SetPtr = State->get(ObjRegion); + PtrSet Set = SetPtr ? *SetPtr : F.getEmptySet(); + assert(C.wasInlined || !Set.contains(Sym)); + Set = F.add(Set, Sym); + State = State->set(ObjRegion, Set); C.addTransition(State); } return; } if (isa(ICall)) { -if (State->contains(TypedR)) { - const SymbolRef *StrBufferPtr = State->get(TypedR); - // FIXME: What if Origin is null? +if (const PtrSet *PS = State->get(ObjRegion)) { + // Mark all pointer symbols associated with the deleted object released. const Expr *Origin = Call.getOriginExpr(); - State = allocation_state::markReleased(State, *StrBufferPtr, Origin); - State = State->remove(TypedR); + for (const auto Symbol : *PS) { +// NOTE: `Origin` may be null, and will be stored so in the symbol's +// `RefState` in MallocChecker's `RegionState` program state map. +State = allocation_state::markReleased(State, Symbol, Origin); + } + State = State->remove(ObjRegion); C.addTransition(State); return; } @@ -123,15 +146,24 @@ void DanglingInternalBufferChecker::chec void DanglingInternalBufferChecker::checkDeadSymbols(SymbolReaper &SymReaper, CheckerContext &C) const { ProgramStateRef State = C.getState(); + PtrSet::Factory &F = State->getStateManager().get_context(); RawPtrMapTy RPM = State->get(); for (const auto Entry : RPM) { -if (!SymReaper.isLive(Entr
r337215 - [analyzer] Make checkEndFunction() give access to the return statement.
Author: rkovacs Date: Mon Jul 16 13:47:45 2018 New Revision: 337215 URL: http://llvm.org/viewvc/llvm-project?rev=337215&view=rev Log: [analyzer] Make checkEndFunction() give access to the return statement. Differential Revision: https://reviews.llvm.org/D49387 Modified: cfe/trunk/include/clang/StaticAnalyzer/Core/Checker.h cfe/trunk/include/clang/StaticAnalyzer/Core/CheckerManager.h cfe/trunk/lib/StaticAnalyzer/Checkers/CheckObjCDealloc.cpp cfe/trunk/lib/StaticAnalyzer/Checkers/CheckerDocumentation.cpp cfe/trunk/lib/StaticAnalyzer/Checkers/MisusedMovedObjectChecker.cpp cfe/trunk/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp cfe/trunk/lib/StaticAnalyzer/Checkers/StackAddrEscapeChecker.cpp cfe/trunk/lib/StaticAnalyzer/Checkers/TestAfterDivZeroChecker.cpp cfe/trunk/lib/StaticAnalyzer/Checkers/TraversalChecker.cpp cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObjectChecker.cpp cfe/trunk/lib/StaticAnalyzer/Checkers/VirtualCallChecker.cpp cfe/trunk/lib/StaticAnalyzer/Core/CheckerManager.cpp cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp Modified: cfe/trunk/include/clang/StaticAnalyzer/Core/Checker.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Core/Checker.h?rev=337215&r1=337214&r2=337215&view=diff == --- cfe/trunk/include/clang/StaticAnalyzer/Core/Checker.h (original) +++ cfe/trunk/include/clang/StaticAnalyzer/Core/Checker.h Mon Jul 16 13:47:45 2018 @@ -254,9 +254,9 @@ public: class EndFunction { template - static void _checkEndFunction(void *checker, + static void _checkEndFunction(void *checker, const ReturnStmt *RS, CheckerContext &C) { -((const CHECKER *)checker)->checkEndFunction(C); +((const CHECKER *)checker)->checkEndFunction(RS, C); } public: Modified: cfe/trunk/include/clang/StaticAnalyzer/Core/CheckerManager.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Core/CheckerManager.h?rev=337215&r1=337214&r2=337215&view=diff == --- cfe/trunk/include/clang/StaticAnalyzer/Core/CheckerManager.h (original) +++ cfe/trunk/include/clang/StaticAnalyzer/Core/CheckerManager.h Mon Jul 16 13:47:45 2018 @@ -296,7 +296,8 @@ public: void runCheckersForEndFunction(NodeBuilderContext &BC, ExplodedNodeSet &Dst, ExplodedNode *Pred, - ExprEngine &Eng); + ExprEngine &Eng, + const ReturnStmt *RS); /// Run checkers for branch condition. void runCheckersForBranchCondition(const Stmt *condition, @@ -438,7 +439,8 @@ public: using CheckBeginFunctionFunc = CheckerFn; - using CheckEndFunctionFunc = CheckerFn; + using CheckEndFunctionFunc = + CheckerFn; using CheckBranchConditionFunc = CheckerFn; @@ -496,7 +498,7 @@ public: void _registerForEndAnalysis(CheckEndAnalysisFunc checkfn); - void _registerForBeginFunction(CheckEndFunctionFunc checkfn); + void _registerForBeginFunction(CheckBeginFunctionFunc checkfn); void _registerForEndFunction(CheckEndFunctionFunc checkfn); void _registerForBranchCondition(CheckBranchConditionFunc checkfn); Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/CheckObjCDealloc.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/CheckObjCDealloc.cpp?rev=337215&r1=337214&r2=337215&view=diff == --- cfe/trunk/lib/StaticAnalyzer/Checkers/CheckObjCDealloc.cpp (original) +++ cfe/trunk/lib/StaticAnalyzer/Checkers/CheckObjCDealloc.cpp Mon Jul 16 13:47:45 2018 @@ -126,7 +126,7 @@ public: const CallEvent *Call, PointerEscapeKind Kind) const; void checkPreStmt(const ReturnStmt *RS, CheckerContext &C) const; - void checkEndFunction(CheckerContext &Ctx) const; + void checkEndFunction(const ReturnStmt *RS, CheckerContext &Ctx) const; private: void diagnoseMissingReleases(CheckerContext &C) const; @@ -398,7 +398,7 @@ void ObjCDeallocChecker::checkPostObjCMe /// Check for missing releases even when -dealloc does not call /// '[super dealloc]'. void ObjCDeallocChecker::checkEndFunction( -CheckerContext &C) const { +const ReturnStmt *RS, CheckerContext &C) const { diagnoseMissingReleases(C); } Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/CheckerDocumentation.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/CheckerDocumentation.cpp?rev=337215&r1=337214&r2=337215&view=diff == --- cfe/trunk/lib/StaticAnalyzer/Checkers/CheckerDocumentation.cpp (original) +