summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGeorge Karpenkov <ekarpenkov@apple.com>2018-10-03 22:31:09 +0000
committerGeorge Karpenkov <ekarpenkov@apple.com>2018-10-03 22:31:09 +0000
commit4b86b52dd3d158145e338969e340d436f577cef1 (patch)
treeb726023f6932b0e8db6c66a614b7857af3c75620
parent520263a41117445fb491740168bbf4d5b4ab5546 (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.cpp22
-rw-r--r--clang/test/Analysis/trustnonnullchecker_test.m22
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