diff options
author | Artem Dergachev <artem.dergachev@gmail.com> | 2015-12-10 09:28:06 +0000 |
---|---|---|
committer | Artem Dergachev <artem.dergachev@gmail.com> | 2015-12-10 09:28:06 +0000 |
commit | 733e71b73b35eccd467c50baf12214d85941f0b0 (patch) | |
tree | d817b5cda01584f26d1cc933c984924fb7a551fe /clang/lib/StaticAnalyzer/Checkers/ExprInspectionChecker.cpp | |
parent | a5fbebc2065d12a403f82380cbe0c3a571cfccbe (diff) | |
download | bcm5719-llvm-733e71b73b35eccd467c50baf12214d85941f0b0.tar.gz bcm5719-llvm-733e71b73b35eccd467c50baf12214d85941f0b0.zip |
[analyzer] Fix symbolic element index lifetime.
SymbolReaper was destroying the symbol too early when it was referenced only
from an index SVal of a live ElementRegion.
In order to test certain aspects of this patch, extend the debug.ExprInspection
checker to allow testing SymbolReaper in a direct manner.
Differential Revision: http://reviews.llvm.org/D12726
llvm-svn: 255236
Diffstat (limited to 'clang/lib/StaticAnalyzer/Checkers/ExprInspectionChecker.cpp')
-rw-r--r-- | clang/lib/StaticAnalyzer/Checkers/ExprInspectionChecker.cpp | 46 |
1 files changed, 44 insertions, 2 deletions
diff --git a/clang/lib/StaticAnalyzer/Checkers/ExprInspectionChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/ExprInspectionChecker.cpp index 60c6aa534d1..8f6c20ab190 100644 --- a/clang/lib/StaticAnalyzer/Checkers/ExprInspectionChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/ExprInspectionChecker.cpp @@ -17,22 +17,26 @@ using namespace clang; using namespace ento; namespace { -class ExprInspectionChecker : public Checker< eval::Call > { +class ExprInspectionChecker : public Checker<eval::Call, check::DeadSymbols> { mutable std::unique_ptr<BugType> BT; void analyzerEval(const CallExpr *CE, CheckerContext &C) const; void analyzerCheckInlined(const CallExpr *CE, CheckerContext &C) const; void analyzerWarnIfReached(const CallExpr *CE, CheckerContext &C) const; void analyzerCrash(const CallExpr *CE, CheckerContext &C) const; + void analyzerWarnOnDeadSymbol(const CallExpr *CE, CheckerContext &C) const; typedef void (ExprInspectionChecker::*FnCheck)(const CallExpr *, CheckerContext &C) const; public: bool evalCall(const CallExpr *CE, CheckerContext &C) const; + void checkDeadSymbols(SymbolReaper &SymReaper, CheckerContext &C) const; }; } +REGISTER_SET_WITH_PROGRAMSTATE(MarkedSymbols, const void *) + bool ExprInspectionChecker::evalCall(const CallExpr *CE, CheckerContext &C) const { // These checks should have no effect on the surrounding environment @@ -42,7 +46,10 @@ bool ExprInspectionChecker::evalCall(const CallExpr *CE, .Case("clang_analyzer_checkInlined", &ExprInspectionChecker::analyzerCheckInlined) .Case("clang_analyzer_crash", &ExprInspectionChecker::analyzerCrash) - .Case("clang_analyzer_warnIfReached", &ExprInspectionChecker::analyzerWarnIfReached) + .Case("clang_analyzer_warnIfReached", + &ExprInspectionChecker::analyzerWarnIfReached) + .Case("clang_analyzer_warnOnDeadSymbol", + &ExprInspectionChecker::analyzerWarnOnDeadSymbol) .Default(nullptr); if (!Handler) @@ -137,6 +144,41 @@ void ExprInspectionChecker::analyzerCheckInlined(const CallExpr *CE, llvm::make_unique<BugReport>(*BT, getArgumentValueString(CE, C), N)); } +void ExprInspectionChecker::analyzerWarnOnDeadSymbol(const CallExpr *CE, + CheckerContext &C) const { + if (CE->getNumArgs() == 0) + return; + SVal Val = C.getSVal(CE->getArg(0)); + SymbolRef Sym = Val.getAsSymbol(); + if (!Sym) + return; + + ProgramStateRef State = C.getState(); + State = State->add<MarkedSymbols>(Sym); + C.addTransition(State); +} + +void ExprInspectionChecker::checkDeadSymbols(SymbolReaper &SymReaper, + CheckerContext &C) const { + ProgramStateRef State = C.getState(); + const MarkedSymbolsTy &Syms = State->get<MarkedSymbols>(); + for (auto I = Syms.begin(), E = Syms.end(); I != E; ++I) { + SymbolRef Sym = static_cast<SymbolRef>(*I); + if (!SymReaper.isDead(Sym)) + continue; + + if (!BT) + BT.reset(new BugType(this, "Checking analyzer assumptions", "debug")); + + ExplodedNode *N = C.generateNonFatalErrorNode(); + if (!N) + return; + + C.emitReport(llvm::make_unique<BugReport>(*BT, "SYMBOL DEAD", N)); + C.addTransition(State->remove<MarkedSymbols>(Sym), N); + } +} + void ExprInspectionChecker::analyzerCrash(const CallExpr *CE, CheckerContext &C) const { LLVM_BUILTIN_TRAP; |