1935ef90f4b065c7c865ee5b2a99c5f9b1a115d72Zhongxing Xu//=== NoReturnFunctionChecker.cpp -------------------------------*- C++ -*-===// 2935ef90f4b065c7c865ee5b2a99c5f9b1a115d72Zhongxing Xu// 3935ef90f4b065c7c865ee5b2a99c5f9b1a115d72Zhongxing Xu// The LLVM Compiler Infrastructure 4935ef90f4b065c7c865ee5b2a99c5f9b1a115d72Zhongxing Xu// 5935ef90f4b065c7c865ee5b2a99c5f9b1a115d72Zhongxing Xu// This file is distributed under the University of Illinois Open Source 6935ef90f4b065c7c865ee5b2a99c5f9b1a115d72Zhongxing Xu// License. See LICENSE.TXT for details. 7935ef90f4b065c7c865ee5b2a99c5f9b1a115d72Zhongxing Xu// 8935ef90f4b065c7c865ee5b2a99c5f9b1a115d72Zhongxing Xu//===----------------------------------------------------------------------===// 9935ef90f4b065c7c865ee5b2a99c5f9b1a115d72Zhongxing Xu// 10935ef90f4b065c7c865ee5b2a99c5f9b1a115d72Zhongxing Xu// This defines NoReturnFunctionChecker, which evaluates functions that do not 11935ef90f4b065c7c865ee5b2a99c5f9b1a115d72Zhongxing Xu// return to the caller. 12935ef90f4b065c7c865ee5b2a99c5f9b1a115d72Zhongxing Xu// 13935ef90f4b065c7c865ee5b2a99c5f9b1a115d72Zhongxing Xu//===----------------------------------------------------------------------===// 14935ef90f4b065c7c865ee5b2a99c5f9b1a115d72Zhongxing Xu 153267d9563f8265bfce967b3801273a7c53b91346Argyrios Kyrtzidis#include "ClangSACheckers.h" 16ec8605f1d7ec846dbf51047bfd5c56d32d1ff91cArgyrios Kyrtzidis#include "clang/StaticAnalyzer/Core/Checker.h" 173267d9563f8265bfce967b3801273a7c53b91346Argyrios Kyrtzidis#include "clang/StaticAnalyzer/Core/CheckerManager.h" 18f540c54701e3eeb34cb619a3a4eb18f1ac70ef2dJordan Rose#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h" 193267d9563f8265bfce967b3801273a7c53b91346Argyrios Kyrtzidis#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" 20935ef90f4b065c7c865ee5b2a99c5f9b1a115d72Zhongxing Xu#include "llvm/ADT/StringSwitch.h" 21d9f5a709ddbffe35dcc419c9c3fa6a852e833f7aBenjamin Kramer#include <cstdarg> 22935ef90f4b065c7c865ee5b2a99c5f9b1a115d72Zhongxing Xu 23935ef90f4b065c7c865ee5b2a99c5f9b1a115d72Zhongxing Xuusing namespace clang; 249ef6537a894c33003359b1f9b9676e9178e028b7Ted Kremenekusing namespace ento; 25935ef90f4b065c7c865ee5b2a99c5f9b1a115d72Zhongxing Xu 26935ef90f4b065c7c865ee5b2a99c5f9b1a115d72Zhongxing Xunamespace { 27935ef90f4b065c7c865ee5b2a99c5f9b1a115d72Zhongxing Xu 28e62e87bdb14ec0237819a3b66f6a30105a8f5a0cJordy Roseclass NoReturnFunctionChecker : public Checker< check::PostStmt<CallExpr>, 29e62e87bdb14ec0237819a3b66f6a30105a8f5a0cJordy Rose check::PostObjCMessage > { 30935ef90f4b065c7c865ee5b2a99c5f9b1a115d72Zhongxing Xupublic: 313267d9563f8265bfce967b3801273a7c53b91346Argyrios Kyrtzidis void checkPostStmt(const CallExpr *CE, CheckerContext &C) const; 32de507eaf3cb54d3cb234dc14499c10ab3373d15fJordan Rose void checkPostObjCMessage(const ObjCMethodCall &msg, CheckerContext &C) const; 33935ef90f4b065c7c865ee5b2a99c5f9b1a115d72Zhongxing Xu}; 34935ef90f4b065c7c865ee5b2a99c5f9b1a115d72Zhongxing Xu 35935ef90f4b065c7c865ee5b2a99c5f9b1a115d72Zhongxing Xu} 36935ef90f4b065c7c865ee5b2a99c5f9b1a115d72Zhongxing Xu 373267d9563f8265bfce967b3801273a7c53b91346Argyrios Kyrtzidisvoid NoReturnFunctionChecker::checkPostStmt(const CallExpr *CE, 383267d9563f8265bfce967b3801273a7c53b91346Argyrios Kyrtzidis CheckerContext &C) const { 398bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek ProgramStateRef state = C.getState(); 40935ef90f4b065c7c865ee5b2a99c5f9b1a115d72Zhongxing Xu const Expr *Callee = CE->getCallee(); 41935ef90f4b065c7c865ee5b2a99c5f9b1a115d72Zhongxing Xu 42264ba48dc98f3f843935a485d5b086f7e0fdc4f1Rafael Espindola bool BuildSinks = getFunctionExtInfo(Callee->getType()).getNoReturn(); 43935ef90f4b065c7c865ee5b2a99c5f9b1a115d72Zhongxing Xu 44cfd8ea930a119dc8a1e9a343d2a5cfe142b3d964Ted Kremenek if (!BuildSinks) { 455eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek SVal L = state->getSVal(Callee, C.getLocationContext()); 46cfd8ea930a119dc8a1e9a343d2a5cfe142b3d964Ted Kremenek const FunctionDecl *FD = L.getAsFunctionDecl(); 47cfd8ea930a119dc8a1e9a343d2a5cfe142b3d964Ted Kremenek if (!FD) 48cfd8ea930a119dc8a1e9a343d2a5cfe142b3d964Ted Kremenek return; 49cfd8ea930a119dc8a1e9a343d2a5cfe142b3d964Ted Kremenek 50cfd8ea930a119dc8a1e9a343d2a5cfe142b3d964Ted Kremenek if (FD->getAttr<AnalyzerNoReturnAttr>()) 51cfd8ea930a119dc8a1e9a343d2a5cfe142b3d964Ted Kremenek BuildSinks = true; 52cfd8ea930a119dc8a1e9a343d2a5cfe142b3d964Ted Kremenek else if (const IdentifierInfo *II = FD->getIdentifier()) { 53cfd8ea930a119dc8a1e9a343d2a5cfe142b3d964Ted Kremenek // HACK: Some functions are not marked noreturn, and don't return. 54cfd8ea930a119dc8a1e9a343d2a5cfe142b3d964Ted Kremenek // Here are a few hardwired ones. If this takes too long, we can 55cfd8ea930a119dc8a1e9a343d2a5cfe142b3d964Ted Kremenek // potentially cache these results. 56cfd8ea930a119dc8a1e9a343d2a5cfe142b3d964Ted Kremenek BuildSinks 575f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner = llvm::StringSwitch<bool>(StringRef(II->getName())) 58cfd8ea930a119dc8a1e9a343d2a5cfe142b3d964Ted Kremenek .Case("exit", true) 59cfd8ea930a119dc8a1e9a343d2a5cfe142b3d964Ted Kremenek .Case("panic", true) 60cfd8ea930a119dc8a1e9a343d2a5cfe142b3d964Ted Kremenek .Case("error", true) 61cfd8ea930a119dc8a1e9a343d2a5cfe142b3d964Ted Kremenek .Case("Assert", true) 62cfd8ea930a119dc8a1e9a343d2a5cfe142b3d964Ted Kremenek // FIXME: This is just a wrapper around throwing an exception. 63cfd8ea930a119dc8a1e9a343d2a5cfe142b3d964Ted Kremenek // Eventually inter-procedural analysis should handle this easily. 64cfd8ea930a119dc8a1e9a343d2a5cfe142b3d964Ted Kremenek .Case("ziperr", true) 65cfd8ea930a119dc8a1e9a343d2a5cfe142b3d964Ted Kremenek .Case("assfail", true) 66cfd8ea930a119dc8a1e9a343d2a5cfe142b3d964Ted Kremenek .Case("db_error", true) 67cfd8ea930a119dc8a1e9a343d2a5cfe142b3d964Ted Kremenek .Case("__assert", true) 68cfd8ea930a119dc8a1e9a343d2a5cfe142b3d964Ted Kremenek .Case("__assert_rtn", true) 69cfd8ea930a119dc8a1e9a343d2a5cfe142b3d964Ted Kremenek .Case("__assert_fail", true) 70cfd8ea930a119dc8a1e9a343d2a5cfe142b3d964Ted Kremenek .Case("dtrace_assfail", true) 71cfd8ea930a119dc8a1e9a343d2a5cfe142b3d964Ted Kremenek .Case("yy_fatal_error", true) 72cfd8ea930a119dc8a1e9a343d2a5cfe142b3d964Ted Kremenek .Case("_XCAssertionFailureHandler", true) 73cfd8ea930a119dc8a1e9a343d2a5cfe142b3d964Ted Kremenek .Case("_DTAssertionFailureHandler", true) 74cfd8ea930a119dc8a1e9a343d2a5cfe142b3d964Ted Kremenek .Case("_TSAssertionFailureHandler", true) 75cfd8ea930a119dc8a1e9a343d2a5cfe142b3d964Ted Kremenek .Default(false); 76cfd8ea930a119dc8a1e9a343d2a5cfe142b3d964Ted Kremenek } 77935ef90f4b065c7c865ee5b2a99c5f9b1a115d72Zhongxing Xu } 78935ef90f4b065c7c865ee5b2a99c5f9b1a115d72Zhongxing Xu 79cfd8ea930a119dc8a1e9a343d2a5cfe142b3d964Ted Kremenek if (BuildSinks) 808ba721428af297e540fb40b176eeeea0ee010c1fAnna Zaks C.generateSink(); 81935ef90f4b065c7c865ee5b2a99c5f9b1a115d72Zhongxing Xu} 823267d9563f8265bfce967b3801273a7c53b91346Argyrios Kyrtzidis 831af9d9e5f6d0f07917c01b1017620104dbbc0e7fJordy Rosestatic bool END_WITH_NULL isMultiArgSelector(const Selector *Sel, ...) { 84e62e87bdb14ec0237819a3b66f6a30105a8f5a0cJordy Rose va_list argp; 85e62e87bdb14ec0237819a3b66f6a30105a8f5a0cJordy Rose va_start(argp, Sel); 86e62e87bdb14ec0237819a3b66f6a30105a8f5a0cJordy Rose 87e62e87bdb14ec0237819a3b66f6a30105a8f5a0cJordy Rose unsigned Slot = 0; 88e62e87bdb14ec0237819a3b66f6a30105a8f5a0cJordy Rose const char *Arg; 89e62e87bdb14ec0237819a3b66f6a30105a8f5a0cJordy Rose while ((Arg = va_arg(argp, const char *))) { 901af9d9e5f6d0f07917c01b1017620104dbbc0e7fJordy Rose if (!Sel->getNameForSlot(Slot).equals(Arg)) 91e62e87bdb14ec0237819a3b66f6a30105a8f5a0cJordy Rose break; // still need to va_end! 92e62e87bdb14ec0237819a3b66f6a30105a8f5a0cJordy Rose ++Slot; 93e62e87bdb14ec0237819a3b66f6a30105a8f5a0cJordy Rose } 94e62e87bdb14ec0237819a3b66f6a30105a8f5a0cJordy Rose 95e62e87bdb14ec0237819a3b66f6a30105a8f5a0cJordy Rose va_end(argp); 96e62e87bdb14ec0237819a3b66f6a30105a8f5a0cJordy Rose 97e62e87bdb14ec0237819a3b66f6a30105a8f5a0cJordy Rose // We only succeeded if we made it to the end of the argument list. 98e62e87bdb14ec0237819a3b66f6a30105a8f5a0cJordy Rose return (Arg == NULL); 99e62e87bdb14ec0237819a3b66f6a30105a8f5a0cJordy Rose} 100e62e87bdb14ec0237819a3b66f6a30105a8f5a0cJordy Rose 101de507eaf3cb54d3cb234dc14499c10ab3373d15fJordan Rosevoid NoReturnFunctionChecker::checkPostObjCMessage(const ObjCMethodCall &Msg, 102e62e87bdb14ec0237819a3b66f6a30105a8f5a0cJordy Rose CheckerContext &C) const { 103e62e87bdb14ec0237819a3b66f6a30105a8f5a0cJordy Rose // HACK: This entire check is to handle two messages in the Cocoa frameworks: 104e62e87bdb14ec0237819a3b66f6a30105a8f5a0cJordy Rose // -[NSAssertionHandler 105e62e87bdb14ec0237819a3b66f6a30105a8f5a0cJordy Rose // handleFailureInMethod:object:file:lineNumber:description:] 106e62e87bdb14ec0237819a3b66f6a30105a8f5a0cJordy Rose // -[NSAssertionHandler 107e62e87bdb14ec0237819a3b66f6a30105a8f5a0cJordy Rose // handleFailureInFunction:file:lineNumber:description:] 108e62e87bdb14ec0237819a3b66f6a30105a8f5a0cJordy Rose // Eventually these should be annotated with __attribute__((noreturn)). 109e62e87bdb14ec0237819a3b66f6a30105a8f5a0cJordy Rose // Because ObjC messages use dynamic dispatch, it is not generally safe to 110e62e87bdb14ec0237819a3b66f6a30105a8f5a0cJordy Rose // assume certain methods can't return. In cases where it is definitely valid, 111e62e87bdb14ec0237819a3b66f6a30105a8f5a0cJordy Rose // see if you can mark the methods noreturn or analyzer_noreturn instead of 112e62e87bdb14ec0237819a3b66f6a30105a8f5a0cJordy Rose // adding more explicit checks to this method. 113e62e87bdb14ec0237819a3b66f6a30105a8f5a0cJordy Rose 114e62e87bdb14ec0237819a3b66f6a30105a8f5a0cJordy Rose if (!Msg.isInstanceMessage()) 115e62e87bdb14ec0237819a3b66f6a30105a8f5a0cJordy Rose return; 116e62e87bdb14ec0237819a3b66f6a30105a8f5a0cJordy Rose 117e62e87bdb14ec0237819a3b66f6a30105a8f5a0cJordy Rose const ObjCInterfaceDecl *Receiver = Msg.getReceiverInterface(); 118e62e87bdb14ec0237819a3b66f6a30105a8f5a0cJordy Rose if (!Receiver) 119e62e87bdb14ec0237819a3b66f6a30105a8f5a0cJordy Rose return; 120e62e87bdb14ec0237819a3b66f6a30105a8f5a0cJordy Rose if (!Receiver->getIdentifier()->isStr("NSAssertionHandler")) 121e62e87bdb14ec0237819a3b66f6a30105a8f5a0cJordy Rose return; 122e62e87bdb14ec0237819a3b66f6a30105a8f5a0cJordy Rose 123e62e87bdb14ec0237819a3b66f6a30105a8f5a0cJordy Rose Selector Sel = Msg.getSelector(); 124e62e87bdb14ec0237819a3b66f6a30105a8f5a0cJordy Rose switch (Sel.getNumArgs()) { 125e62e87bdb14ec0237819a3b66f6a30105a8f5a0cJordy Rose default: 126e62e87bdb14ec0237819a3b66f6a30105a8f5a0cJordy Rose return; 127e62e87bdb14ec0237819a3b66f6a30105a8f5a0cJordy Rose case 4: 1281af9d9e5f6d0f07917c01b1017620104dbbc0e7fJordy Rose if (!isMultiArgSelector(&Sel, "handleFailureInFunction", "file", 129e62e87bdb14ec0237819a3b66f6a30105a8f5a0cJordy Rose "lineNumber", "description", NULL)) 130e62e87bdb14ec0237819a3b66f6a30105a8f5a0cJordy Rose return; 131e62e87bdb14ec0237819a3b66f6a30105a8f5a0cJordy Rose break; 132e62e87bdb14ec0237819a3b66f6a30105a8f5a0cJordy Rose case 5: 1331af9d9e5f6d0f07917c01b1017620104dbbc0e7fJordy Rose if (!isMultiArgSelector(&Sel, "handleFailureInMethod", "object", "file", 134e62e87bdb14ec0237819a3b66f6a30105a8f5a0cJordy Rose "lineNumber", "description", NULL)) 135e62e87bdb14ec0237819a3b66f6a30105a8f5a0cJordy Rose return; 136e62e87bdb14ec0237819a3b66f6a30105a8f5a0cJordy Rose break; 137e62e87bdb14ec0237819a3b66f6a30105a8f5a0cJordy Rose } 138e62e87bdb14ec0237819a3b66f6a30105a8f5a0cJordy Rose 139e62e87bdb14ec0237819a3b66f6a30105a8f5a0cJordy Rose // If we got here, it's one of the messages we care about. 140e62e87bdb14ec0237819a3b66f6a30105a8f5a0cJordy Rose C.generateSink(); 141e62e87bdb14ec0237819a3b66f6a30105a8f5a0cJordy Rose} 142e62e87bdb14ec0237819a3b66f6a30105a8f5a0cJordy Rose 143e62e87bdb14ec0237819a3b66f6a30105a8f5a0cJordy Rose 1443267d9563f8265bfce967b3801273a7c53b91346Argyrios Kyrtzidisvoid ento::registerNoReturnFunctionChecker(CheckerManager &mgr) { 1453267d9563f8265bfce967b3801273a7c53b91346Argyrios Kyrtzidis mgr.registerChecker<NoReturnFunctionChecker>(); 1463267d9563f8265bfce967b3801273a7c53b91346Argyrios Kyrtzidis} 147