ErrnoModeling.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346
  1. //=== ErrnoModeling.cpp -----------------------------------------*- C++ -*-===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. //
  9. // This defines a checker `ErrnoModeling`, which is used to make the system
  10. // value 'errno' available to other checkers.
  11. // The 'errno' value is stored at a special memory region that is accessible
  12. // through the `errno_modeling` namespace. The memory region is either the
  13. // region of `errno` itself if it is a variable, otherwise an artifically
  14. // created region (in the system memory space). If `errno` is defined by using
  15. // a function which returns the address of it (this is always the case if it is
  16. // not a variable) this function is recognized and evaluated. In this way
  17. // `errno` becomes visible to the analysis and checkers can change its value.
  18. //
  19. //===----------------------------------------------------------------------===//
  20. #include "ErrnoModeling.h"
  21. #include "clang/AST/ParentMapContext.h"
  22. #include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
  23. #include "clang/StaticAnalyzer/Core/Checker.h"
  24. #include "clang/StaticAnalyzer/Core/CheckerManager.h"
  25. #include "clang/StaticAnalyzer/Core/PathSensitive/CallDescription.h"
  26. #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
  27. #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
  28. #include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
  29. #include "llvm/ADT/STLExtras.h"
  30. #include <optional>
  31. using namespace clang;
  32. using namespace ento;
  33. namespace {
  34. // Name of the "errno" variable.
  35. // FIXME: Is there a system where it is not called "errno" but is a variable?
  36. const char *ErrnoVarName = "errno";
  37. // Names of functions that return a location of the "errno" value.
  38. // FIXME: Are there other similar function names?
  39. const char *ErrnoLocationFuncNames[] = {"__errno_location", "___errno",
  40. "__errno", "_errno", "__error"};
  41. class ErrnoModeling
  42. : public Checker<check::ASTDecl<TranslationUnitDecl>, check::BeginFunction,
  43. check::LiveSymbols, eval::Call> {
  44. public:
  45. void checkASTDecl(const TranslationUnitDecl *D, AnalysisManager &Mgr,
  46. BugReporter &BR) const;
  47. void checkBeginFunction(CheckerContext &C) const;
  48. void checkLiveSymbols(ProgramStateRef State, SymbolReaper &SR) const;
  49. bool evalCall(const CallEvent &Call, CheckerContext &C) const;
  50. // The declaration of an "errno" variable or "errno location" function.
  51. mutable const Decl *ErrnoDecl = nullptr;
  52. private:
  53. // FIXME: Names from `ErrnoLocationFuncNames` are used to build this set.
  54. CallDescriptionSet ErrnoLocationCalls{{{"__errno_location"}, 0, 0},
  55. {{"___errno"}, 0, 0},
  56. {{"__errno"}, 0, 0},
  57. {{"_errno"}, 0, 0},
  58. {{"__error"}, 0, 0}};
  59. };
  60. } // namespace
  61. /// Store a MemRegion that contains the 'errno' integer value.
  62. /// The value is null if the 'errno' value was not recognized in the AST.
  63. REGISTER_TRAIT_WITH_PROGRAMSTATE(ErrnoRegion, const MemRegion *)
  64. REGISTER_TRAIT_WITH_PROGRAMSTATE(ErrnoState, errno_modeling::ErrnoCheckState)
  65. /// Search for a variable called "errno" in the AST.
  66. /// Return nullptr if not found.
  67. static const VarDecl *getErrnoVar(ASTContext &ACtx) {
  68. IdentifierInfo &II = ACtx.Idents.get(ErrnoVarName);
  69. auto LookupRes = ACtx.getTranslationUnitDecl()->lookup(&II);
  70. auto Found = llvm::find_if(LookupRes, [&ACtx](const Decl *D) {
  71. if (auto *VD = dyn_cast<VarDecl>(D))
  72. return ACtx.getSourceManager().isInSystemHeader(VD->getLocation()) &&
  73. VD->hasExternalStorage() &&
  74. VD->getType().getCanonicalType() == ACtx.IntTy;
  75. return false;
  76. });
  77. if (Found == LookupRes.end())
  78. return nullptr;
  79. return cast<VarDecl>(*Found);
  80. }
  81. /// Search for a function with a specific name that is used to return a pointer
  82. /// to "errno".
  83. /// Return nullptr if no such function was found.
  84. static const FunctionDecl *getErrnoFunc(ASTContext &ACtx) {
  85. SmallVector<const Decl *> LookupRes;
  86. for (StringRef ErrnoName : ErrnoLocationFuncNames) {
  87. IdentifierInfo &II = ACtx.Idents.get(ErrnoName);
  88. llvm::append_range(LookupRes, ACtx.getTranslationUnitDecl()->lookup(&II));
  89. }
  90. auto Found = llvm::find_if(LookupRes, [&ACtx](const Decl *D) {
  91. if (auto *FD = dyn_cast<FunctionDecl>(D))
  92. return ACtx.getSourceManager().isInSystemHeader(FD->getLocation()) &&
  93. FD->isExternC() && FD->getNumParams() == 0 &&
  94. FD->getReturnType().getCanonicalType() ==
  95. ACtx.getPointerType(ACtx.IntTy);
  96. return false;
  97. });
  98. if (Found == LookupRes.end())
  99. return nullptr;
  100. return cast<FunctionDecl>(*Found);
  101. }
  102. void ErrnoModeling::checkASTDecl(const TranslationUnitDecl *D,
  103. AnalysisManager &Mgr, BugReporter &BR) const {
  104. // Try to find an usable `errno` value.
  105. // It can be an external variable called "errno" or a function that returns a
  106. // pointer to the "errno" value. This function can have different names.
  107. // The actual case is dependent on the C library implementation, we
  108. // can only search for a match in one of these variations.
  109. // We assume that exactly one of these cases might be true.
  110. ErrnoDecl = getErrnoVar(Mgr.getASTContext());
  111. if (!ErrnoDecl)
  112. ErrnoDecl = getErrnoFunc(Mgr.getASTContext());
  113. }
  114. void ErrnoModeling::checkBeginFunction(CheckerContext &C) const {
  115. if (!C.inTopFrame())
  116. return;
  117. ASTContext &ACtx = C.getASTContext();
  118. ProgramStateRef State = C.getState();
  119. if (const auto *ErrnoVar = dyn_cast_or_null<VarDecl>(ErrnoDecl)) {
  120. // There is an external 'errno' variable.
  121. // Use its memory region.
  122. // The memory region for an 'errno'-like variable is allocated in system
  123. // space by MemRegionManager.
  124. const MemRegion *ErrnoR =
  125. State->getRegion(ErrnoVar, C.getLocationContext());
  126. assert(ErrnoR && "Memory region should exist for the 'errno' variable.");
  127. State = State->set<ErrnoRegion>(ErrnoR);
  128. State =
  129. errno_modeling::setErrnoValue(State, C, 0, errno_modeling::Irrelevant);
  130. C.addTransition(State);
  131. } else if (ErrnoDecl) {
  132. assert(isa<FunctionDecl>(ErrnoDecl) && "Invalid errno location function.");
  133. // There is a function that returns the location of 'errno'.
  134. // We must create a memory region for it in system space.
  135. // Currently a symbolic region is used with an artifical symbol.
  136. // FIXME: It is better to have a custom (new) kind of MemRegion for such
  137. // cases.
  138. SValBuilder &SVB = C.getSValBuilder();
  139. MemRegionManager &RMgr = C.getStateManager().getRegionManager();
  140. const MemSpaceRegion *GlobalSystemSpace =
  141. RMgr.getGlobalsRegion(MemRegion::GlobalSystemSpaceRegionKind);
  142. // Create an artifical symbol for the region.
  143. // It is not possible to associate a statement or expression in this case.
  144. const SymbolConjured *Sym = SVB.conjureSymbol(
  145. nullptr, C.getLocationContext(),
  146. ACtx.getLValueReferenceType(ACtx.IntTy), C.blockCount(), &ErrnoDecl);
  147. // The symbolic region is untyped, create a typed sub-region in it.
  148. // The ElementRegion is used to make the errno region a typed region.
  149. const MemRegion *ErrnoR = RMgr.getElementRegion(
  150. ACtx.IntTy, SVB.makeZeroArrayIndex(),
  151. RMgr.getSymbolicRegion(Sym, GlobalSystemSpace), C.getASTContext());
  152. State = State->set<ErrnoRegion>(ErrnoR);
  153. State =
  154. errno_modeling::setErrnoValue(State, C, 0, errno_modeling::Irrelevant);
  155. C.addTransition(State);
  156. }
  157. }
  158. bool ErrnoModeling::evalCall(const CallEvent &Call, CheckerContext &C) const {
  159. // Return location of "errno" at a call to an "errno address returning"
  160. // function.
  161. if (ErrnoLocationCalls.contains(Call)) {
  162. ProgramStateRef State = C.getState();
  163. const MemRegion *ErrnoR = State->get<ErrnoRegion>();
  164. if (!ErrnoR)
  165. return false;
  166. State = State->BindExpr(Call.getOriginExpr(), C.getLocationContext(),
  167. loc::MemRegionVal{ErrnoR});
  168. C.addTransition(State);
  169. return true;
  170. }
  171. return false;
  172. }
  173. void ErrnoModeling::checkLiveSymbols(ProgramStateRef State,
  174. SymbolReaper &SR) const {
  175. // The special errno region should never garbage collected.
  176. if (const auto *ErrnoR = State->get<ErrnoRegion>())
  177. SR.markLive(ErrnoR);
  178. }
  179. namespace clang {
  180. namespace ento {
  181. namespace errno_modeling {
  182. std::optional<SVal> getErrnoValue(ProgramStateRef State) {
  183. const MemRegion *ErrnoR = State->get<ErrnoRegion>();
  184. if (!ErrnoR)
  185. return {};
  186. QualType IntTy = State->getAnalysisManager().getASTContext().IntTy;
  187. return State->getSVal(ErrnoR, IntTy);
  188. }
  189. ProgramStateRef setErrnoValue(ProgramStateRef State,
  190. const LocationContext *LCtx, SVal Value,
  191. ErrnoCheckState EState) {
  192. const MemRegion *ErrnoR = State->get<ErrnoRegion>();
  193. if (!ErrnoR)
  194. return State;
  195. // First set the errno value, the old state is still available at 'checkBind'
  196. // or 'checkLocation' for errno value.
  197. State = State->bindLoc(loc::MemRegionVal{ErrnoR}, Value, LCtx);
  198. return State->set<ErrnoState>(EState);
  199. }
  200. ProgramStateRef setErrnoValue(ProgramStateRef State, CheckerContext &C,
  201. uint64_t Value, ErrnoCheckState EState) {
  202. const MemRegion *ErrnoR = State->get<ErrnoRegion>();
  203. if (!ErrnoR)
  204. return State;
  205. State = State->bindLoc(
  206. loc::MemRegionVal{ErrnoR},
  207. C.getSValBuilder().makeIntVal(Value, C.getASTContext().IntTy),
  208. C.getLocationContext());
  209. return State->set<ErrnoState>(EState);
  210. }
  211. std::optional<Loc> getErrnoLoc(ProgramStateRef State) {
  212. const MemRegion *ErrnoR = State->get<ErrnoRegion>();
  213. if (!ErrnoR)
  214. return {};
  215. return loc::MemRegionVal{ErrnoR};
  216. }
  217. ErrnoCheckState getErrnoState(ProgramStateRef State) {
  218. return State->get<ErrnoState>();
  219. }
  220. ProgramStateRef setErrnoState(ProgramStateRef State, ErrnoCheckState EState) {
  221. return State->set<ErrnoState>(EState);
  222. }
  223. ProgramStateRef clearErrnoState(ProgramStateRef State) {
  224. return setErrnoState(State, Irrelevant);
  225. }
  226. bool isErrno(const Decl *D) {
  227. if (const auto *VD = dyn_cast_or_null<VarDecl>(D))
  228. if (const IdentifierInfo *II = VD->getIdentifier())
  229. return II->getName() == ErrnoVarName;
  230. if (const auto *FD = dyn_cast_or_null<FunctionDecl>(D))
  231. if (const IdentifierInfo *II = FD->getIdentifier())
  232. return llvm::is_contained(ErrnoLocationFuncNames, II->getName());
  233. return false;
  234. }
  235. const char *describeErrnoCheckState(ErrnoCheckState CS) {
  236. assert(CS == errno_modeling::MustNotBeChecked &&
  237. "Errno description not applicable.");
  238. return "may be undefined after the call and should not be used";
  239. }
  240. const NoteTag *getErrnoNoteTag(CheckerContext &C, const std::string &Message) {
  241. return C.getNoteTag([Message](PathSensitiveBugReport &BR) -> std::string {
  242. const MemRegion *ErrnoR = BR.getErrorNode()->getState()->get<ErrnoRegion>();
  243. if (ErrnoR && BR.isInteresting(ErrnoR)) {
  244. BR.markNotInteresting(ErrnoR);
  245. return Message;
  246. }
  247. return "";
  248. });
  249. }
  250. ProgramStateRef setErrnoForStdSuccess(ProgramStateRef State,
  251. CheckerContext &C) {
  252. return setErrnoState(State, MustNotBeChecked);
  253. }
  254. ProgramStateRef setErrnoForStdFailure(ProgramStateRef State, CheckerContext &C,
  255. NonLoc ErrnoSym) {
  256. SValBuilder &SVB = C.getSValBuilder();
  257. NonLoc ZeroVal = SVB.makeZeroVal(C.getASTContext().IntTy).castAs<NonLoc>();
  258. DefinedOrUnknownSVal Cond =
  259. SVB.evalBinOp(State, BO_NE, ErrnoSym, ZeroVal, SVB.getConditionType())
  260. .castAs<DefinedOrUnknownSVal>();
  261. State = State->assume(Cond, true);
  262. if (!State)
  263. return nullptr;
  264. return setErrnoValue(State, C.getLocationContext(), ErrnoSym, Irrelevant);
  265. }
  266. ProgramStateRef setErrnoStdMustBeChecked(ProgramStateRef State,
  267. CheckerContext &C,
  268. const Expr *InvalE) {
  269. const MemRegion *ErrnoR = State->get<ErrnoRegion>();
  270. if (!ErrnoR)
  271. return State;
  272. State = State->invalidateRegions(ErrnoR, InvalE, C.blockCount(),
  273. C.getLocationContext(), false);
  274. if (!State)
  275. return nullptr;
  276. return setErrnoState(State, MustBeChecked);
  277. }
  278. const NoteTag *getNoteTagForStdSuccess(CheckerContext &C, llvm::StringRef Fn) {
  279. return getErrnoNoteTag(
  280. C, (Twine("Assuming that function '") + Twine(Fn) +
  281. Twine("' is successful, in this case the value 'errno' ") +
  282. Twine(describeErrnoCheckState(MustNotBeChecked)))
  283. .str());
  284. }
  285. const NoteTag *getNoteTagForStdMustBeChecked(CheckerContext &C,
  286. llvm::StringRef Fn) {
  287. return getErrnoNoteTag(
  288. C, (Twine("Function '") + Twine(Fn) +
  289. Twine("' indicates failure only by setting of 'errno'"))
  290. .str());
  291. }
  292. } // namespace errno_modeling
  293. } // namespace ento
  294. } // namespace clang
  295. void ento::registerErrnoModeling(CheckerManager &mgr) {
  296. mgr.registerChecker<ErrnoModeling>();
  297. }
  298. bool ento::shouldRegisterErrnoModeling(const CheckerManager &mgr) {
  299. return true;
  300. }