UnixAPIChecker.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382
  1. //= UnixAPIChecker.h - Checks preconditions for various Unix APIs --*- 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 UnixAPIChecker, which is an assortment of checks on calls
  11. // to various, widely used UNIX/Posix functions.
  12. //
  13. //===----------------------------------------------------------------------===//
  14. #include "ClangSACheckers.h"
  15. #include "clang/Basic/TargetInfo.h"
  16. #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
  17. #include "clang/StaticAnalyzer/Core/Checker.h"
  18. #include "clang/StaticAnalyzer/Core/CheckerManager.h"
  19. #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
  20. #include "llvm/ADT/Optional.h"
  21. #include "llvm/ADT/STLExtras.h"
  22. #include "llvm/ADT/SmallString.h"
  23. #include "llvm/ADT/StringSwitch.h"
  24. #include "llvm/Support/raw_ostream.h"
  25. #include <fcntl.h>
  26. using namespace clang;
  27. using namespace ento;
  28. namespace {
  29. class UnixAPIChecker : public Checker< check::PreStmt<CallExpr> > {
  30. mutable std::unique_ptr<BugType> BT_open, BT_pthreadOnce, BT_mallocZero;
  31. mutable Optional<uint64_t> Val_O_CREAT;
  32. public:
  33. void checkPreStmt(const CallExpr *CE, CheckerContext &C) const;
  34. void CheckOpen(CheckerContext &C, const CallExpr *CE) const;
  35. void CheckPthreadOnce(CheckerContext &C, const CallExpr *CE) const;
  36. void CheckCallocZero(CheckerContext &C, const CallExpr *CE) const;
  37. void CheckMallocZero(CheckerContext &C, const CallExpr *CE) const;
  38. void CheckReallocZero(CheckerContext &C, const CallExpr *CE) const;
  39. void CheckReallocfZero(CheckerContext &C, const CallExpr *CE) const;
  40. void CheckAllocaZero(CheckerContext &C, const CallExpr *CE) const;
  41. void CheckVallocZero(CheckerContext &C, const CallExpr *CE) const;
  42. typedef void (UnixAPIChecker::*SubChecker)(CheckerContext &,
  43. const CallExpr *) const;
  44. private:
  45. bool ReportZeroByteAllocation(CheckerContext &C,
  46. ProgramStateRef falseState,
  47. const Expr *arg,
  48. const char *fn_name) const;
  49. void BasicAllocationCheck(CheckerContext &C,
  50. const CallExpr *CE,
  51. const unsigned numArgs,
  52. const unsigned sizeArg,
  53. const char *fn) const;
  54. void LazyInitialize(std::unique_ptr<BugType> &BT, const char *name) const {
  55. if (BT)
  56. return;
  57. BT.reset(new BugType(this, name, categories::UnixAPI));
  58. }
  59. void ReportOpenBug(CheckerContext &C,
  60. ProgramStateRef State,
  61. const char *Msg,
  62. SourceRange SR) const;
  63. };
  64. } //end anonymous namespace
  65. //===----------------------------------------------------------------------===//
  66. // "open" (man 2 open)
  67. //===----------------------------------------------------------------------===//
  68. void UnixAPIChecker::ReportOpenBug(CheckerContext &C,
  69. ProgramStateRef State,
  70. const char *Msg,
  71. SourceRange SR) const {
  72. ExplodedNode *N = C.generateSink(State);
  73. if (!N)
  74. return;
  75. LazyInitialize(BT_open, "Improper use of 'open'");
  76. auto Report = llvm::make_unique<BugReport>(*BT_open, Msg, N);
  77. Report->addRange(SR);
  78. C.emitReport(std::move(Report));
  79. }
  80. void UnixAPIChecker::CheckOpen(CheckerContext &C, const CallExpr *CE) const {
  81. ProgramStateRef state = C.getState();
  82. if (CE->getNumArgs() < 2) {
  83. // The frontend should issue a warning for this case, so this is a sanity
  84. // check.
  85. return;
  86. } else if (CE->getNumArgs() == 3) {
  87. const Expr *Arg = CE->getArg(2);
  88. QualType QT = Arg->getType();
  89. if (!QT->isIntegerType()) {
  90. ReportOpenBug(C, state,
  91. "Third argument to 'open' is not an integer",
  92. Arg->getSourceRange());
  93. return;
  94. }
  95. } else if (CE->getNumArgs() > 3) {
  96. ReportOpenBug(C, state,
  97. "Call to 'open' with more than three arguments",
  98. CE->getArg(3)->getSourceRange());
  99. return;
  100. }
  101. // The definition of O_CREAT is platform specific. We need a better way
  102. // of querying this information from the checking environment.
  103. if (!Val_O_CREAT.hasValue()) {
  104. if (C.getASTContext().getTargetInfo().getTriple().getVendor()
  105. == llvm::Triple::Apple)
  106. Val_O_CREAT = 0x0200;
  107. else {
  108. // FIXME: We need a more general way of getting the O_CREAT value.
  109. // We could possibly grovel through the preprocessor state, but
  110. // that would require passing the Preprocessor object to the ExprEngine.
  111. // See also: MallocChecker.cpp / M_ZERO.
  112. return;
  113. }
  114. }
  115. // Now check if oflags has O_CREAT set.
  116. const Expr *oflagsEx = CE->getArg(1);
  117. const SVal V = state->getSVal(oflagsEx, C.getLocationContext());
  118. if (!V.getAs<NonLoc>()) {
  119. // The case where 'V' can be a location can only be due to a bad header,
  120. // so in this case bail out.
  121. return;
  122. }
  123. NonLoc oflags = V.castAs<NonLoc>();
  124. NonLoc ocreateFlag = C.getSValBuilder()
  125. .makeIntVal(Val_O_CREAT.getValue(), oflagsEx->getType()).castAs<NonLoc>();
  126. SVal maskedFlagsUC = C.getSValBuilder().evalBinOpNN(state, BO_And,
  127. oflags, ocreateFlag,
  128. oflagsEx->getType());
  129. if (maskedFlagsUC.isUnknownOrUndef())
  130. return;
  131. DefinedSVal maskedFlags = maskedFlagsUC.castAs<DefinedSVal>();
  132. // Check if maskedFlags is non-zero.
  133. ProgramStateRef trueState, falseState;
  134. std::tie(trueState, falseState) = state->assume(maskedFlags);
  135. // Only emit an error if the value of 'maskedFlags' is properly
  136. // constrained;
  137. if (!(trueState && !falseState))
  138. return;
  139. if (CE->getNumArgs() < 3) {
  140. ReportOpenBug(C, trueState,
  141. "Call to 'open' requires a third argument when "
  142. "the 'O_CREAT' flag is set",
  143. oflagsEx->getSourceRange());
  144. }
  145. }
  146. //===----------------------------------------------------------------------===//
  147. // pthread_once
  148. //===----------------------------------------------------------------------===//
  149. void UnixAPIChecker::CheckPthreadOnce(CheckerContext &C,
  150. const CallExpr *CE) const {
  151. // This is similar to 'CheckDispatchOnce' in the MacOSXAPIChecker.
  152. // They can possibly be refactored.
  153. if (CE->getNumArgs() < 1)
  154. return;
  155. // Check if the first argument is stack allocated. If so, issue a warning
  156. // because that's likely to be bad news.
  157. ProgramStateRef state = C.getState();
  158. const MemRegion *R =
  159. state->getSVal(CE->getArg(0), C.getLocationContext()).getAsRegion();
  160. if (!R || !isa<StackSpaceRegion>(R->getMemorySpace()))
  161. return;
  162. ExplodedNode *N = C.generateSink(state);
  163. if (!N)
  164. return;
  165. SmallString<256> S;
  166. llvm::raw_svector_ostream os(S);
  167. os << "Call to 'pthread_once' uses";
  168. if (const VarRegion *VR = dyn_cast<VarRegion>(R))
  169. os << " the local variable '" << VR->getDecl()->getName() << '\'';
  170. else
  171. os << " stack allocated memory";
  172. os << " for the \"control\" value. Using such transient memory for "
  173. "the control value is potentially dangerous.";
  174. if (isa<VarRegion>(R) && isa<StackLocalsSpaceRegion>(R->getMemorySpace()))
  175. os << " Perhaps you intended to declare the variable as 'static'?";
  176. LazyInitialize(BT_pthreadOnce, "Improper use of 'pthread_once'");
  177. auto report = llvm::make_unique<BugReport>(*BT_pthreadOnce, os.str(), N);
  178. report->addRange(CE->getArg(0)->getSourceRange());
  179. C.emitReport(std::move(report));
  180. }
  181. //===----------------------------------------------------------------------===//
  182. // "calloc", "malloc", "realloc", "reallocf", "alloca" and "valloc"
  183. // with allocation size 0
  184. //===----------------------------------------------------------------------===//
  185. // FIXME: Eventually these should be rolled into the MallocChecker, but right now
  186. // they're more basic and valuable for widespread use.
  187. // Returns true if we try to do a zero byte allocation, false otherwise.
  188. // Fills in trueState and falseState.
  189. static bool IsZeroByteAllocation(ProgramStateRef state,
  190. const SVal argVal,
  191. ProgramStateRef *trueState,
  192. ProgramStateRef *falseState) {
  193. std::tie(*trueState, *falseState) =
  194. state->assume(argVal.castAs<DefinedSVal>());
  195. return (*falseState && !*trueState);
  196. }
  197. // Generates an error report, indicating that the function whose name is given
  198. // will perform a zero byte allocation.
  199. // Returns false if an error occurred, true otherwise.
  200. bool UnixAPIChecker::ReportZeroByteAllocation(CheckerContext &C,
  201. ProgramStateRef falseState,
  202. const Expr *arg,
  203. const char *fn_name) const {
  204. ExplodedNode *N = C.generateSink(falseState);
  205. if (!N)
  206. return false;
  207. LazyInitialize(BT_mallocZero,
  208. "Undefined allocation of 0 bytes (CERT MEM04-C; CWE-131)");
  209. SmallString<256> S;
  210. llvm::raw_svector_ostream os(S);
  211. os << "Call to '" << fn_name << "' has an allocation size of 0 bytes";
  212. auto report = llvm::make_unique<BugReport>(*BT_mallocZero, os.str(), N);
  213. report->addRange(arg->getSourceRange());
  214. bugreporter::trackNullOrUndefValue(N, arg, *report);
  215. C.emitReport(std::move(report));
  216. return true;
  217. }
  218. // Does a basic check for 0-sized allocations suitable for most of the below
  219. // functions (modulo "calloc")
  220. void UnixAPIChecker::BasicAllocationCheck(CheckerContext &C,
  221. const CallExpr *CE,
  222. const unsigned numArgs,
  223. const unsigned sizeArg,
  224. const char *fn) const {
  225. // Sanity check for the correct number of arguments
  226. if (CE->getNumArgs() != numArgs)
  227. return;
  228. // Check if the allocation size is 0.
  229. ProgramStateRef state = C.getState();
  230. ProgramStateRef trueState = nullptr, falseState = nullptr;
  231. const Expr *arg = CE->getArg(sizeArg);
  232. SVal argVal = state->getSVal(arg, C.getLocationContext());
  233. if (argVal.isUnknownOrUndef())
  234. return;
  235. // Is the value perfectly constrained to zero?
  236. if (IsZeroByteAllocation(state, argVal, &trueState, &falseState)) {
  237. (void) ReportZeroByteAllocation(C, falseState, arg, fn);
  238. return;
  239. }
  240. // Assume the value is non-zero going forward.
  241. assert(trueState);
  242. if (trueState != state)
  243. C.addTransition(trueState);
  244. }
  245. void UnixAPIChecker::CheckCallocZero(CheckerContext &C,
  246. const CallExpr *CE) const {
  247. unsigned int nArgs = CE->getNumArgs();
  248. if (nArgs != 2)
  249. return;
  250. ProgramStateRef state = C.getState();
  251. ProgramStateRef trueState = nullptr, falseState = nullptr;
  252. unsigned int i;
  253. for (i = 0; i < nArgs; i++) {
  254. const Expr *arg = CE->getArg(i);
  255. SVal argVal = state->getSVal(arg, C.getLocationContext());
  256. if (argVal.isUnknownOrUndef()) {
  257. if (i == 0)
  258. continue;
  259. else
  260. return;
  261. }
  262. if (IsZeroByteAllocation(state, argVal, &trueState, &falseState)) {
  263. if (ReportZeroByteAllocation(C, falseState, arg, "calloc"))
  264. return;
  265. else if (i == 0)
  266. continue;
  267. else
  268. return;
  269. }
  270. }
  271. // Assume the value is non-zero going forward.
  272. assert(trueState);
  273. if (trueState != state)
  274. C.addTransition(trueState);
  275. }
  276. void UnixAPIChecker::CheckMallocZero(CheckerContext &C,
  277. const CallExpr *CE) const {
  278. BasicAllocationCheck(C, CE, 1, 0, "malloc");
  279. }
  280. void UnixAPIChecker::CheckReallocZero(CheckerContext &C,
  281. const CallExpr *CE) const {
  282. BasicAllocationCheck(C, CE, 2, 1, "realloc");
  283. }
  284. void UnixAPIChecker::CheckReallocfZero(CheckerContext &C,
  285. const CallExpr *CE) const {
  286. BasicAllocationCheck(C, CE, 2, 1, "reallocf");
  287. }
  288. void UnixAPIChecker::CheckAllocaZero(CheckerContext &C,
  289. const CallExpr *CE) const {
  290. BasicAllocationCheck(C, CE, 1, 0, "alloca");
  291. }
  292. void UnixAPIChecker::CheckVallocZero(CheckerContext &C,
  293. const CallExpr *CE) const {
  294. BasicAllocationCheck(C, CE, 1, 0, "valloc");
  295. }
  296. //===----------------------------------------------------------------------===//
  297. // Central dispatch function.
  298. //===----------------------------------------------------------------------===//
  299. void UnixAPIChecker::checkPreStmt(const CallExpr *CE,
  300. CheckerContext &C) const {
  301. const FunctionDecl *FD = C.getCalleeDecl(CE);
  302. if (!FD || FD->getKind() != Decl::Function)
  303. return;
  304. StringRef FName = C.getCalleeName(FD);
  305. if (FName.empty())
  306. return;
  307. SubChecker SC =
  308. llvm::StringSwitch<SubChecker>(FName)
  309. .Case("open", &UnixAPIChecker::CheckOpen)
  310. .Case("pthread_once", &UnixAPIChecker::CheckPthreadOnce)
  311. .Case("calloc", &UnixAPIChecker::CheckCallocZero)
  312. .Case("malloc", &UnixAPIChecker::CheckMallocZero)
  313. .Case("realloc", &UnixAPIChecker::CheckReallocZero)
  314. .Case("reallocf", &UnixAPIChecker::CheckReallocfZero)
  315. .Cases("alloca", "__builtin_alloca", &UnixAPIChecker::CheckAllocaZero)
  316. .Case("valloc", &UnixAPIChecker::CheckVallocZero)
  317. .Default(nullptr);
  318. if (SC)
  319. (this->*SC)(C, CE);
  320. }
  321. //===----------------------------------------------------------------------===//
  322. // Registration.
  323. //===----------------------------------------------------------------------===//
  324. void ento::registerUnixAPIChecker(CheckerManager &mgr) {
  325. mgr.registerChecker<UnixAPIChecker>();
  326. }