diff options
author | Gabor Horvath <xazax@google.com> | 2019-12-06 17:11:37 -0800 |
---|---|---|
committer | Gabor Horvath <xazax@google.com> | 2019-12-10 08:51:33 -0800 |
commit | f3a28202ef58551db15818f8f51afd21e0f3e231 (patch) | |
tree | a1233f2ddbe0698f6513f47dc8803da57fc7a2fb /clang/lib/StaticAnalyzer/Core/ExprEngine.cpp | |
parent | a6e50e40e6ddaaefff944dc97379b51af7687cae (diff) | |
download | bcm5719-llvm-f3a28202ef58551db15818f8f51afd21e0f3e231.tar.gz bcm5719-llvm-f3a28202ef58551db15818f8f51afd21e0f3e231.zip |
[analyzer] Keep track of escaped locals
We want to escape all symbols that are stored into escaped regions.
The problem is, we did not know which local regions were escaped. Until now.
This should fix some false positives like the one in the tests.
Differential Revision: https://reviews.llvm.org/D71152
Diffstat (limited to 'clang/lib/StaticAnalyzer/Core/ExprEngine.cpp')
-rw-r--r-- | clang/lib/StaticAnalyzer/Core/ExprEngine.cpp | 18 |
1 files changed, 16 insertions, 2 deletions
diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp index efbc20f0925..b6f6481c369 100644 --- a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp +++ b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp @@ -193,6 +193,8 @@ typedef llvm::ImmutableMap<ConstructedObjectKey, SVal> REGISTER_TRAIT_WITH_PROGRAMSTATE(ObjectsUnderConstruction, ObjectsUnderConstructionMap) +REGISTER_SET_WITH_PROGRAMSTATE(EscapedLocals, const MemRegion *) + //===----------------------------------------------------------------------===// // Engine construction and deletion. //===----------------------------------------------------------------------===// @@ -723,6 +725,12 @@ void ExprEngine::removeDead(ExplodedNode *Pred, ExplodedNodeSet &Out, SymReaper.markLive(MR); } + EscapedLocalsTy EscapedRegions = CleanedState->get<EscapedLocals>(); + for (const MemRegion *MR : EscapedRegions) { + if (!SymReaper.isLiveRegion(MR)) + CleanedState = CleanedState->remove<EscapedLocals>(MR); + } + getCheckerManager().runCheckersForLiveSymbols(CleanedState, SymReaper); // Create a state in which dead bindings are removed from the environment @@ -1194,6 +1202,11 @@ ProgramStateRef ExprEngine::escapeValue(ProgramStateRef State, SVal V, State, Scanner.getSymbols(), /*CallEvent*/ nullptr, K, nullptr); } +ProgramStateRef ExprEngine::processLocalRegionEscape(ProgramStateRef State, + const MemRegion *R) const { + return State->add<EscapedLocals>(R); +} + void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred, ExplodedNodeSet &DstTop) { PrettyStackTraceLoc CrashInfo(getContext().getSourceManager(), @@ -2680,7 +2693,8 @@ void ExprEngine::VisitAtomicExpr(const AtomicExpr *AE, ExplodedNode *Pred, // A value escapes in four possible cases: // (1) We are binding to something that is not a memory region. -// (2) We are binding to a MemRegion that does not have stack storage. +// (2) We are binding to a MemRegion that does not have stack storage +// or the stack storage is escaped. // (3) We are binding to a top-level parameter region with a non-trivial // destructor. We won't see the destructor during analysis, but it's there. // (4) We are binding to a MemRegion with stack storage that the store @@ -2691,7 +2705,7 @@ ExprEngine::processPointerEscapedOnBind(ProgramStateRef State, SVal Loc, // Cases (1) and (2). const MemRegion *MR = Loc.getAsRegion(); - if (!MR || !MR->hasStackStorage()) + if (!MR || !MR->hasStackStorage() || State->contains<EscapedLocals>(MR)) return escapeValue(State, Val, PSK_EscapeOnBind); // Case (3). |