From 0550dac3ed5fb7babd96ef037b11e3ebd69b4943 Mon Sep 17 00:00:00 2001 From: George Karpenkov Date: Wed, 3 Oct 2018 22:31:09 +0000 Subject: [PATCH] [analyzer] Do not crash if the assumption added in TrustNonNullChecker is enough to make the state unfeasible rdar://43541814 Differential Revision: https://reviews.llvm.org/D52848 llvm-svn: 343735 --- .../Checkers/TrustNonnullChecker.cpp | 22 ++++++++++++++-------- clang/test/Analysis/trustnonnullchecker_test.m | 22 ++++++++++++++++++++++ 2 files changed, 36 insertions(+), 8 deletions(-) diff --git a/clang/lib/StaticAnalyzer/Checkers/TrustNonnullChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/TrustNonnullChecker.cpp index eed1efd..515c98c 100644 --- a/clang/lib/StaticAnalyzer/Checkers/TrustNonnullChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/TrustNonnullChecker.cpp @@ -212,20 +212,26 @@ private: /// the negation of \p Antecedent. /// Checks NonNullImplicationMap and assumes \p Antecedent otherwise. ProgramStateRef addImplication(SymbolRef Antecedent, - ProgramStateRef State, + ProgramStateRef InputState, bool Negated) const { - SValBuilder &SVB = State->getStateManager().getSValBuilder(); + if (!InputState) + return nullptr; + SValBuilder &SVB = InputState->getStateManager().getSValBuilder(); const SymbolRef *Consequent = - Negated ? State->get(Antecedent) - : State->get(Antecedent); + Negated ? InputState->get(Antecedent) + : InputState->get(Antecedent); if (!Consequent) - return State; + return InputState; SVal AntecedentV = SVB.makeSymbolVal(Antecedent); - if ((Negated && State->isNonNull(AntecedentV).isConstrainedTrue()) - || (!Negated && State->isNull(AntecedentV).isConstrainedTrue())) { + ProgramStateRef State = InputState; + + if ((Negated && InputState->isNonNull(AntecedentV).isConstrainedTrue()) + || (!Negated && InputState->isNull(AntecedentV).isConstrainedTrue())) { SVal ConsequentS = SVB.makeSymbolVal(*Consequent); - State = State->assume(ConsequentS.castAs(), Negated); + State = InputState->assume(ConsequentS.castAs(), Negated); + if (!State) + return nullptr; // Drop implications from the map. if (Negated) { diff --git a/clang/test/Analysis/trustnonnullchecker_test.m b/clang/test/Analysis/trustnonnullchecker_test.m index e7ff5e1..4240502 100644 --- a/clang/test/Analysis/trustnonnullchecker_test.m +++ b/clang/test/Analysis/trustnonnullchecker_test.m @@ -170,3 +170,25 @@ NSString *_Nonnull checkAssumeOnMutableDictionaryOtherMethod(NSMutableDictionary if (k) {} return k; // no-warning } + +// Check that we don't crash when the added assumption is enough +// to make the state unfeasible. +@class DummyClass; +@interface DictionarySubclass : NSDictionary { + DummyClass *g; + DictionarySubclass *d; +} +@end +@implementation DictionarySubclass +- (id) objectForKey:(id)e { + if (e) {} + return d; +} +- (void) coder { + for (id e in g) { + id f = [self objectForKey:e]; + if (f) + (void)e; + } +} +@end -- 2.7.4