CallAndMessageChecker.cpp 13 KB

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