CallAndMessageChecker.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360
  1. //===--- CallAndMessageChecker.cpp ------------------------------*- 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 defines CallAndMessageChecker, a builtin checker that checks for various
  11. // errors of call and objc message expressions.
  12. //
  13. //===----------------------------------------------------------------------===//
  14. #include "ClangSACheckers.h"
  15. #include "clang/StaticAnalyzer/Core/Checker.h"
  16. #include "clang/StaticAnalyzer/Core/CheckerManager.h"
  17. #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
  18. #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
  19. #include "clang/AST/ParentMap.h"
  20. #include "clang/Basic/TargetInfo.h"
  21. using namespace clang;
  22. using namespace ento;
  23. namespace {
  24. class CallAndMessageChecker
  25. : public Checker< check::PreStmt<CallExpr>, check::PreObjCMessage > {
  26. mutable llvm::OwningPtr<BugType> BT_call_null;
  27. mutable llvm::OwningPtr<BugType> BT_call_undef;
  28. mutable llvm::OwningPtr<BugType> BT_call_arg;
  29. mutable llvm::OwningPtr<BugType> BT_msg_undef;
  30. mutable llvm::OwningPtr<BugType> BT_msg_arg;
  31. mutable llvm::OwningPtr<BugType> BT_msg_ret;
  32. public:
  33. void checkPreStmt(const CallExpr *CE, CheckerContext &C) const;
  34. void checkPreObjCMessage(ObjCMessage msg, CheckerContext &C) const;
  35. private:
  36. static void PreVisitProcessArgs(CheckerContext &C,CallOrObjCMessage callOrMsg,
  37. const char *BT_desc, llvm::OwningPtr<BugType> &BT);
  38. static bool PreVisitProcessArg(CheckerContext &C, SVal V,SourceRange argRange,
  39. const Expr *argEx, const char *BT_desc, llvm::OwningPtr<BugType> &BT);
  40. static void EmitBadCall(BugType *BT, CheckerContext &C, const CallExpr *CE);
  41. void emitNilReceiverBug(CheckerContext &C, const ObjCMessage &msg,
  42. ExplodedNode *N) const;
  43. void HandleNilReceiver(CheckerContext &C,
  44. const ProgramState *state,
  45. ObjCMessage msg) const;
  46. static void LazyInit_BT(const char *desc, llvm::OwningPtr<BugType> &BT) {
  47. if (!BT)
  48. BT.reset(new BuiltinBug(desc));
  49. }
  50. };
  51. } // end anonymous namespace
  52. void CallAndMessageChecker::EmitBadCall(BugType *BT, CheckerContext &C,
  53. const CallExpr *CE) {
  54. ExplodedNode *N = C.generateSink();
  55. if (!N)
  56. return;
  57. BugReport *R = new BugReport(*BT, BT->getName(), N);
  58. R->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue,
  59. bugreporter::GetCalleeExpr(N));
  60. C.EmitReport(R);
  61. }
  62. void CallAndMessageChecker::PreVisitProcessArgs(CheckerContext &C,
  63. CallOrObjCMessage callOrMsg,
  64. const char *BT_desc,
  65. llvm::OwningPtr<BugType> &BT) {
  66. for (unsigned i = 0, e = callOrMsg.getNumArgs(); i != e; ++i)
  67. if (PreVisitProcessArg(C, callOrMsg.getArgSVal(i),
  68. callOrMsg.getArgSourceRange(i), callOrMsg.getArg(i),
  69. BT_desc, BT))
  70. return;
  71. }
  72. bool CallAndMessageChecker::PreVisitProcessArg(CheckerContext &C,
  73. SVal V, SourceRange argRange,
  74. const Expr *argEx,
  75. const char *BT_desc,
  76. llvm::OwningPtr<BugType> &BT) {
  77. if (V.isUndef()) {
  78. if (ExplodedNode *N = C.generateSink()) {
  79. LazyInit_BT(BT_desc, BT);
  80. // Generate a report for this bug.
  81. BugReport *R = new BugReport(*BT, BT->getName(), N);
  82. R->addRange(argRange);
  83. if (argEx)
  84. R->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, argEx);
  85. C.EmitReport(R);
  86. }
  87. return true;
  88. }
  89. if (const nonloc::LazyCompoundVal *LV =
  90. dyn_cast<nonloc::LazyCompoundVal>(&V)) {
  91. class FindUninitializedField {
  92. public:
  93. SmallVector<const FieldDecl *, 10> FieldChain;
  94. private:
  95. ASTContext &C;
  96. StoreManager &StoreMgr;
  97. MemRegionManager &MrMgr;
  98. Store store;
  99. public:
  100. FindUninitializedField(ASTContext &c, StoreManager &storeMgr,
  101. MemRegionManager &mrMgr, Store s)
  102. : C(c), StoreMgr(storeMgr), MrMgr(mrMgr), store(s) {}
  103. bool Find(const TypedValueRegion *R) {
  104. QualType T = R->getValueType();
  105. if (const RecordType *RT = T->getAsStructureType()) {
  106. const RecordDecl *RD = RT->getDecl()->getDefinition();
  107. assert(RD && "Referred record has no definition");
  108. for (RecordDecl::field_iterator I =
  109. RD->field_begin(), E = RD->field_end(); I!=E; ++I) {
  110. const FieldRegion *FR = MrMgr.getFieldRegion(*I, R);
  111. FieldChain.push_back(*I);
  112. T = (*I)->getType();
  113. if (T->getAsStructureType()) {
  114. if (Find(FR))
  115. return true;
  116. }
  117. else {
  118. const SVal &V = StoreMgr.Retrieve(store, loc::MemRegionVal(FR));
  119. if (V.isUndef())
  120. return true;
  121. }
  122. FieldChain.pop_back();
  123. }
  124. }
  125. return false;
  126. }
  127. };
  128. const LazyCompoundValData *D = LV->getCVData();
  129. FindUninitializedField F(C.getASTContext(),
  130. C.getState()->getStateManager().getStoreManager(),
  131. C.getSValBuilder().getRegionManager(),
  132. D->getStore());
  133. if (F.Find(D->getRegion())) {
  134. if (ExplodedNode *N = C.generateSink()) {
  135. LazyInit_BT(BT_desc, BT);
  136. llvm::SmallString<512> Str;
  137. llvm::raw_svector_ostream os(Str);
  138. os << "Passed-by-value struct argument contains uninitialized data";
  139. if (F.FieldChain.size() == 1)
  140. os << " (e.g., field: '" << F.FieldChain[0] << "')";
  141. else {
  142. os << " (e.g., via the field chain: '";
  143. bool first = true;
  144. for (SmallVectorImpl<const FieldDecl *>::iterator
  145. DI = F.FieldChain.begin(), DE = F.FieldChain.end(); DI!=DE;++DI){
  146. if (first)
  147. first = false;
  148. else
  149. os << '.';
  150. os << *DI;
  151. }
  152. os << "')";
  153. }
  154. // Generate a report for this bug.
  155. BugReport *R = new BugReport(*BT, os.str(), N);
  156. R->addRange(argRange);
  157. // FIXME: enhance track back for uninitialized value for arbitrary
  158. // memregions
  159. C.EmitReport(R);
  160. }
  161. return true;
  162. }
  163. }
  164. return false;
  165. }
  166. void CallAndMessageChecker::checkPreStmt(const CallExpr *CE,
  167. CheckerContext &C) const{
  168. const Expr *Callee = CE->getCallee()->IgnoreParens();
  169. SVal L = C.getState()->getSVal(Callee);
  170. if (L.isUndef()) {
  171. if (!BT_call_undef)
  172. BT_call_undef.reset(new BuiltinBug("Called function pointer is an "
  173. "uninitalized pointer value"));
  174. EmitBadCall(BT_call_undef.get(), C, CE);
  175. return;
  176. }
  177. if (isa<loc::ConcreteInt>(L)) {
  178. if (!BT_call_null)
  179. BT_call_null.reset(
  180. new BuiltinBug("Called function pointer is null (null dereference)"));
  181. EmitBadCall(BT_call_null.get(), C, CE);
  182. }
  183. PreVisitProcessArgs(C, CallOrObjCMessage(CE, C.getState()),
  184. "Function call argument is an uninitialized value",
  185. BT_call_arg);
  186. }
  187. void CallAndMessageChecker::checkPreObjCMessage(ObjCMessage msg,
  188. CheckerContext &C) const {
  189. const ProgramState *state = C.getState();
  190. // FIXME: Handle 'super'?
  191. if (const Expr *receiver = msg.getInstanceReceiver()) {
  192. SVal recVal = state->getSVal(receiver);
  193. if (recVal.isUndef()) {
  194. if (ExplodedNode *N = C.generateSink()) {
  195. if (!BT_msg_undef)
  196. BT_msg_undef.reset(new BuiltinBug("Receiver in message expression is "
  197. "an uninitialized value"));
  198. BugReport *R =
  199. new BugReport(*BT_msg_undef, BT_msg_undef->getName(), N);
  200. R->addRange(receiver->getSourceRange());
  201. R->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue,
  202. receiver);
  203. C.EmitReport(R);
  204. }
  205. return;
  206. } else {
  207. // Bifurcate the state into nil and non-nil ones.
  208. DefinedOrUnknownSVal receiverVal = cast<DefinedOrUnknownSVal>(recVal);
  209. const ProgramState *notNilState, *nilState;
  210. llvm::tie(notNilState, nilState) = state->assume(receiverVal);
  211. // Handle receiver must be nil.
  212. if (nilState && !notNilState) {
  213. HandleNilReceiver(C, state, msg);
  214. return;
  215. }
  216. }
  217. }
  218. const char *bugDesc = msg.isPropertySetter() ?
  219. "Argument for property setter is an uninitialized value"
  220. : "Argument in message expression is an uninitialized value";
  221. // Check for any arguments that are uninitialized/undefined.
  222. PreVisitProcessArgs(C, CallOrObjCMessage(msg, state), bugDesc, BT_msg_arg);
  223. }
  224. void CallAndMessageChecker::emitNilReceiverBug(CheckerContext &C,
  225. const ObjCMessage &msg,
  226. ExplodedNode *N) const {
  227. if (!BT_msg_ret)
  228. BT_msg_ret.reset(
  229. new BuiltinBug("Receiver in message expression is "
  230. "'nil' and returns a garbage value"));
  231. llvm::SmallString<200> buf;
  232. llvm::raw_svector_ostream os(buf);
  233. os << "The receiver of message '" << msg.getSelector().getAsString()
  234. << "' is nil and returns a value of type '"
  235. << msg.getType(C.getASTContext()).getAsString() << "' that will be garbage";
  236. BugReport *report = new BugReport(*BT_msg_ret, os.str(), N);
  237. if (const Expr *receiver = msg.getInstanceReceiver()) {
  238. report->addRange(receiver->getSourceRange());
  239. report->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue,
  240. receiver);
  241. }
  242. C.EmitReport(report);
  243. }
  244. static bool supportsNilWithFloatRet(const llvm::Triple &triple) {
  245. return triple.getVendor() == llvm::Triple::Apple &&
  246. (!triple.isMacOSXVersionLT(10,5) ||
  247. triple.getArch() == llvm::Triple::arm ||
  248. triple.getArch() == llvm::Triple::thumb);
  249. }
  250. void CallAndMessageChecker::HandleNilReceiver(CheckerContext &C,
  251. const ProgramState *state,
  252. ObjCMessage msg) const {
  253. ASTContext &Ctx = C.getASTContext();
  254. // Check the return type of the message expression. A message to nil will
  255. // return different values depending on the return type and the architecture.
  256. QualType RetTy = msg.getType(Ctx);
  257. CanQualType CanRetTy = Ctx.getCanonicalType(RetTy);
  258. if (CanRetTy->isStructureOrClassType()) {
  259. // FIXME: At some point we shouldn't rely on isConsumedExpr(), but instead
  260. // have the "use of undefined value" be smarter about where the
  261. // undefined value came from.
  262. if (C.getPredecessor()->getParentMap().isConsumedExpr(msg.getOriginExpr())){
  263. if (ExplodedNode *N = C.generateSink(state))
  264. emitNilReceiverBug(C, msg, N);
  265. return;
  266. }
  267. // The result is not consumed by a surrounding expression. Just propagate
  268. // the current state.
  269. C.addTransition(state);
  270. return;
  271. }
  272. // Other cases: check if the return type is smaller than void*.
  273. if (CanRetTy != Ctx.VoidTy &&
  274. C.getPredecessor()->getParentMap().isConsumedExpr(msg.getOriginExpr())) {
  275. // Compute: sizeof(void *) and sizeof(return type)
  276. const uint64_t voidPtrSize = Ctx.getTypeSize(Ctx.VoidPtrTy);
  277. const uint64_t returnTypeSize = Ctx.getTypeSize(CanRetTy);
  278. if (voidPtrSize < returnTypeSize &&
  279. !(supportsNilWithFloatRet(Ctx.Target.getTriple()) &&
  280. (Ctx.FloatTy == CanRetTy ||
  281. Ctx.DoubleTy == CanRetTy ||
  282. Ctx.LongDoubleTy == CanRetTy ||
  283. Ctx.LongLongTy == CanRetTy ||
  284. Ctx.UnsignedLongLongTy == CanRetTy))) {
  285. if (ExplodedNode *N = C.generateSink(state))
  286. emitNilReceiverBug(C, msg, N);
  287. return;
  288. }
  289. // Handle the safe cases where the return value is 0 if the
  290. // receiver is nil.
  291. //
  292. // FIXME: For now take the conservative approach that we only
  293. // return null values if we *know* that the receiver is nil.
  294. // This is because we can have surprises like:
  295. //
  296. // ... = [[NSScreens screens] objectAtIndex:0];
  297. //
  298. // What can happen is that [... screens] could return nil, but
  299. // it most likely isn't nil. We should assume the semantics
  300. // of this case unless we have *a lot* more knowledge.
  301. //
  302. SVal V = C.getSValBuilder().makeZeroVal(msg.getType(Ctx));
  303. C.generateNode(state->BindExpr(msg.getOriginExpr(), V));
  304. return;
  305. }
  306. C.addTransition(state);
  307. }
  308. void ento::registerCallAndMessageChecker(CheckerManager &mgr) {
  309. mgr.registerChecker<CallAndMessageChecker>();
  310. }