1 //== TrustNonnullChecker.cpp - Checker for trusting annotations -*- C++ -*--==// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // This checker adds an assumption that methods annotated with _Nonnull 11 // which come from system headers actually return a non-null pointer. 12 // 13 //===----------------------------------------------------------------------===// 14 15 #include "ClangSACheckers.h" 16 #include "clang/StaticAnalyzer/Core/Checker.h" 17 #include "clang/StaticAnalyzer/Core/CheckerManager.h" 18 #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" 19 #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerHelpers.h" 20 #include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h" 21 22 using namespace clang; 23 using namespace ento; 24 25 namespace { 26 27 class TrustNonnullChecker : public Checker<check::PostCall> { 28 private: 29 /// \returns Whether we trust the result of the method call to be 30 /// a non-null pointer. 31 bool isNonNullPtr(const CallEvent &Call, CheckerContext &C) const { 32 QualType ExprRetType = Call.getResultType(); 33 if (!ExprRetType->isAnyPointerType()) 34 return false; 35 36 if (getNullabilityAnnotation(ExprRetType) == Nullability::Nonnull) 37 return true; 38 39 // The logic for ObjC instance method calls is more complicated, 40 // as the return value is nil when the receiver is nil. 41 if (!isa<ObjCMethodCall>(&Call)) 42 return false; 43 44 const auto *MCall = cast<ObjCMethodCall>(&Call); 45 const ObjCMethodDecl *MD = MCall->getDecl(); 46 47 // Distrust protocols. 48 if (isa<ObjCProtocolDecl>(MD->getDeclContext())) 49 return false; 50 51 QualType DeclRetType = MD->getReturnType(); 52 if (getNullabilityAnnotation(DeclRetType) != Nullability::Nonnull) 53 return false; 54 55 // For class messages it is sufficient for the declaration to be 56 // annotated _Nonnull. 57 if (!MCall->isInstanceMessage()) 58 return true; 59 60 // Alternatively, the analyzer could know that the receiver is not null. 61 SVal Receiver = MCall->getReceiverSVal(); 62 ConditionTruthVal TV = C.getState()->isNonNull(Receiver); 63 if (TV.isConstrainedTrue()) 64 return true; 65 66 return false; 67 } 68 69 public: 70 void checkPostCall(const CallEvent &Call, CheckerContext &C) const { 71 // Only trust annotations for system headers for non-protocols. 72 if (!Call.isInSystemHeader()) 73 return; 74 75 ProgramStateRef State = C.getState(); 76 77 if (isNonNullPtr(Call, C)) 78 if (auto L = Call.getReturnValue().getAs<Loc>()) 79 State = State->assume(*L, /*Assumption=*/true); 80 81 C.addTransition(State); 82 } 83 }; 84 85 } // end empty namespace 86 87 88 void ento::registerTrustNonnullChecker(CheckerManager &Mgr) { 89 Mgr.registerChecker<TrustNonnullChecker>(); 90 } 91