diff options
author | George Karpenkov <ekarpenkov@apple.com> | 2018-10-03 22:31:09 +0000 |
---|---|---|
committer | George Karpenkov <ekarpenkov@apple.com> | 2018-10-03 22:31:09 +0000 |
commit | 4b86b52dd3d158145e338969e340d436f577cef1 (patch) | |
tree | b726023f6932b0e8db6c66a614b7857af3c75620 | |
parent | 520263a41117445fb491740168bbf4d5b4ab5546 (diff) |
[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
-rw-r--r-- | clang/lib/StaticAnalyzer/Checkers/TrustNonnullChecker.cpp | 22 | ||||
-rw-r--r-- | 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 eed1efd10e2..515c98cd116 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<NonNullImplicationMap>(Antecedent) - : State->get<NullImplicationMap>(Antecedent); + Negated ? InputState->get<NonNullImplicationMap>(Antecedent) + : InputState->get<NullImplicationMap>(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<DefinedSVal>(), Negated); + State = InputState->assume(ConsequentS.castAs<DefinedSVal>(), 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 e7ff5e1e223..4240502cbbd 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 |