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