SignalHandlerCheck.cpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562
  1. //===--- SignalHandlerCheck.cpp - clang-tidy ------------------------------===//
  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. #include "SignalHandlerCheck.h"
  9. #include "clang/ASTMatchers/ASTMatchFinder.h"
  10. #include "llvm/ADT/DepthFirstIterator.h"
  11. #include "llvm/ADT/STLExtras.h"
  12. // This is the minimal set of safe functions.
  13. // https://wiki.sei.cmu.edu/confluence/display/c/SIG30-C.+Call+only+asynchronous-safe+functions+within+signal+handlers
  14. constexpr llvm::StringLiteral MinimalConformingFunctions[] = {
  15. "signal", "abort", "_Exit", "quick_exit"};
  16. // The POSIX-defined set of safe functions.
  17. // https://pubs.opengroup.org/onlinepubs/9699919799/functions/V2_chap02.html#tag_15_04_03
  18. // 'quick_exit' is added to the set additionally because it looks like the
  19. // mentioned POSIX specification was not updated after 'quick_exit' appeared
  20. // in the C11 standard.
  21. // Also, we want to keep the "minimal set" a subset of the "POSIX set".
  22. // The list is repeated in bugprone-signal-handler.rst and should be kept up to date.
  23. constexpr llvm::StringLiteral POSIXConformingFunctions[] = {
  24. "_Exit",
  25. "_exit",
  26. "abort",
  27. "accept",
  28. "access",
  29. "aio_error",
  30. "aio_return",
  31. "aio_suspend",
  32. "alarm",
  33. "bind",
  34. "cfgetispeed",
  35. "cfgetospeed",
  36. "cfsetispeed",
  37. "cfsetospeed",
  38. "chdir",
  39. "chmod",
  40. "chown",
  41. "clock_gettime",
  42. "close",
  43. "connect",
  44. "creat",
  45. "dup",
  46. "dup2",
  47. "execl",
  48. "execle",
  49. "execv",
  50. "execve",
  51. "faccessat",
  52. "fchdir",
  53. "fchmod",
  54. "fchmodat",
  55. "fchown",
  56. "fchownat",
  57. "fcntl",
  58. "fdatasync",
  59. "fexecve",
  60. "ffs",
  61. "fork",
  62. "fstat",
  63. "fstatat",
  64. "fsync",
  65. "ftruncate",
  66. "futimens",
  67. "getegid",
  68. "geteuid",
  69. "getgid",
  70. "getgroups",
  71. "getpeername",
  72. "getpgrp",
  73. "getpid",
  74. "getppid",
  75. "getsockname",
  76. "getsockopt",
  77. "getuid",
  78. "htonl",
  79. "htons",
  80. "kill",
  81. "link",
  82. "linkat",
  83. "listen",
  84. "longjmp",
  85. "lseek",
  86. "lstat",
  87. "memccpy",
  88. "memchr",
  89. "memcmp",
  90. "memcpy",
  91. "memmove",
  92. "memset",
  93. "mkdir",
  94. "mkdirat",
  95. "mkfifo",
  96. "mkfifoat",
  97. "mknod",
  98. "mknodat",
  99. "ntohl",
  100. "ntohs",
  101. "open",
  102. "openat",
  103. "pause",
  104. "pipe",
  105. "poll",
  106. "posix_trace_event",
  107. "pselect",
  108. "pthread_kill",
  109. "pthread_self",
  110. "pthread_sigmask",
  111. "quick_exit",
  112. "raise",
  113. "read",
  114. "readlink",
  115. "readlinkat",
  116. "recv",
  117. "recvfrom",
  118. "recvmsg",
  119. "rename",
  120. "renameat",
  121. "rmdir",
  122. "select",
  123. "sem_post",
  124. "send",
  125. "sendmsg",
  126. "sendto",
  127. "setgid",
  128. "setpgid",
  129. "setsid",
  130. "setsockopt",
  131. "setuid",
  132. "shutdown",
  133. "sigaction",
  134. "sigaddset",
  135. "sigdelset",
  136. "sigemptyset",
  137. "sigfillset",
  138. "sigismember",
  139. "siglongjmp",
  140. "signal",
  141. "sigpause",
  142. "sigpending",
  143. "sigprocmask",
  144. "sigqueue",
  145. "sigset",
  146. "sigsuspend",
  147. "sleep",
  148. "sockatmark",
  149. "socket",
  150. "socketpair",
  151. "stat",
  152. "stpcpy",
  153. "stpncpy",
  154. "strcat",
  155. "strchr",
  156. "strcmp",
  157. "strcpy",
  158. "strcspn",
  159. "strlen",
  160. "strncat",
  161. "strncmp",
  162. "strncpy",
  163. "strnlen",
  164. "strpbrk",
  165. "strrchr",
  166. "strspn",
  167. "strstr",
  168. "strtok_r",
  169. "symlink",
  170. "symlinkat",
  171. "tcdrain",
  172. "tcflow",
  173. "tcflush",
  174. "tcgetattr",
  175. "tcgetpgrp",
  176. "tcsendbreak",
  177. "tcsetattr",
  178. "tcsetpgrp",
  179. "time",
  180. "timer_getoverrun",
  181. "timer_gettime",
  182. "timer_settime",
  183. "times",
  184. "umask",
  185. "uname",
  186. "unlink",
  187. "unlinkat",
  188. "utime",
  189. "utimensat",
  190. "utimes",
  191. "wait",
  192. "waitpid",
  193. "wcpcpy",
  194. "wcpncpy",
  195. "wcscat",
  196. "wcschr",
  197. "wcscmp",
  198. "wcscpy",
  199. "wcscspn",
  200. "wcslen",
  201. "wcsncat",
  202. "wcsncmp",
  203. "wcsncpy",
  204. "wcsnlen",
  205. "wcspbrk",
  206. "wcsrchr",
  207. "wcsspn",
  208. "wcsstr",
  209. "wcstok",
  210. "wmemchr",
  211. "wmemcmp",
  212. "wmemcpy",
  213. "wmemmove",
  214. "wmemset",
  215. "write"};
  216. using namespace clang::ast_matchers;
  217. namespace clang::tidy {
  218. template <>
  219. struct OptionEnumMapping<
  220. bugprone::SignalHandlerCheck::AsyncSafeFunctionSetKind> {
  221. static llvm::ArrayRef<std::pair<
  222. bugprone::SignalHandlerCheck::AsyncSafeFunctionSetKind, StringRef>>
  223. getEnumMapping() {
  224. static constexpr std::pair<
  225. bugprone::SignalHandlerCheck::AsyncSafeFunctionSetKind, StringRef>
  226. Mapping[] = {
  227. {bugprone::SignalHandlerCheck::AsyncSafeFunctionSetKind::Minimal,
  228. "minimal"},
  229. {bugprone::SignalHandlerCheck::AsyncSafeFunctionSetKind::POSIX,
  230. "POSIX"},
  231. };
  232. return ArrayRef(Mapping);
  233. }
  234. };
  235. namespace bugprone {
  236. namespace {
  237. /// Returns if a function is declared inside a system header.
  238. /// These functions are considered to be "standard" (system-provided) library
  239. /// functions.
  240. bool isStandardFunction(const FunctionDecl *FD) {
  241. // Find a possible redeclaration in system header.
  242. // FIXME: Looking at the canonical declaration is not the most exact way
  243. // to do this.
  244. // Most common case will be inclusion directly from a header.
  245. // This works fine by using canonical declaration.
  246. // a.c
  247. // #include <sysheader.h>
  248. // Next most common case will be extern declaration.
  249. // Can't catch this with either approach.
  250. // b.c
  251. // extern void sysfunc(void);
  252. // Canonical declaration is the first found declaration, so this works.
  253. // c.c
  254. // #include <sysheader.h>
  255. // extern void sysfunc(void); // redecl won't matter
  256. // This does not work with canonical declaration.
  257. // Probably this is not a frequently used case but may happen (the first
  258. // declaration can be in a non-system header for example).
  259. // d.c
  260. // extern void sysfunc(void); // Canonical declaration, not in system header.
  261. // #include <sysheader.h>
  262. return FD->getASTContext().getSourceManager().isInSystemHeader(
  263. FD->getCanonicalDecl()->getLocation());
  264. }
  265. /// Check if a statement is "C++-only".
  266. /// This includes all statements that have a class name with "CXX" prefix
  267. /// and every other statement that is declared in file ExprCXX.h.
  268. bool isCXXOnlyStmt(const Stmt *S) {
  269. StringRef Name = S->getStmtClassName();
  270. if (Name.startswith("CXX"))
  271. return true;
  272. // Check for all other class names in ExprCXX.h that have no 'CXX' prefix.
  273. return isa<ArrayTypeTraitExpr, BuiltinBitCastExpr, CUDAKernelCallExpr,
  274. CoawaitExpr, CoreturnStmt, CoroutineBodyStmt, CoroutineSuspendExpr,
  275. CoyieldExpr, DependentCoawaitExpr, DependentScopeDeclRefExpr,
  276. ExprWithCleanups, ExpressionTraitExpr, FunctionParmPackExpr,
  277. LambdaExpr, MSDependentExistsStmt, MSPropertyRefExpr,
  278. MSPropertySubscriptExpr, MaterializeTemporaryExpr, OverloadExpr,
  279. PackExpansionExpr, SizeOfPackExpr, SubstNonTypeTemplateParmExpr,
  280. SubstNonTypeTemplateParmPackExpr, TypeTraitExpr,
  281. UserDefinedLiteral>(S);
  282. }
  283. /// Given a call graph node of a \p Caller function and a \p Callee that is
  284. /// called from \p Caller, get a \c CallExpr of the corresponding function call.
  285. /// It is unspecified which call is found if multiple calls exist, but the order
  286. /// should be deterministic (depend only on the AST).
  287. Expr *findCallExpr(const CallGraphNode *Caller, const CallGraphNode *Callee) {
  288. auto FoundCallee = llvm::find_if(
  289. Caller->callees(), [Callee](const CallGraphNode::CallRecord &Call) {
  290. return Call.Callee == Callee;
  291. });
  292. assert(FoundCallee != Caller->end() &&
  293. "Callee should be called from the caller function here.");
  294. return FoundCallee->CallExpr;
  295. }
  296. SourceRange getSourceRangeOfStmt(const Stmt *S, ASTContext &Ctx) {
  297. ParentMapContext &PM = Ctx.getParentMapContext();
  298. DynTypedNode P = DynTypedNode::create(*S);
  299. while (P.getSourceRange().isInvalid()) {
  300. DynTypedNodeList PL = PM.getParents(P);
  301. if (PL.size() != 1)
  302. return {};
  303. P = PL[0];
  304. }
  305. return P.getSourceRange();
  306. }
  307. } // namespace
  308. AST_MATCHER(FunctionDecl, isStandardFunction) {
  309. return isStandardFunction(&Node);
  310. }
  311. SignalHandlerCheck::SignalHandlerCheck(StringRef Name,
  312. ClangTidyContext *Context)
  313. : ClangTidyCheck(Name, Context),
  314. AsyncSafeFunctionSet(Options.get("AsyncSafeFunctionSet",
  315. AsyncSafeFunctionSetKind::POSIX)) {
  316. if (AsyncSafeFunctionSet == AsyncSafeFunctionSetKind::Minimal) {
  317. for (StringRef v : MinimalConformingFunctions)
  318. ConformingFunctions.insert(v);
  319. } else {
  320. for (StringRef v : POSIXConformingFunctions)
  321. ConformingFunctions.insert(v);
  322. }
  323. }
  324. void SignalHandlerCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
  325. Options.store(Opts, "AsyncSafeFunctionSet", AsyncSafeFunctionSet);
  326. }
  327. bool SignalHandlerCheck::isLanguageVersionSupported(
  328. const LangOptions &LangOpts) const {
  329. return !LangOpts.CPlusPlus17;
  330. }
  331. void SignalHandlerCheck::registerMatchers(MatchFinder *Finder) {
  332. auto SignalFunction = functionDecl(hasAnyName("::signal", "::std::signal"),
  333. parameterCountIs(2), isStandardFunction());
  334. auto HandlerExpr =
  335. declRefExpr(hasDeclaration(functionDecl().bind("handler_decl")),
  336. unless(isExpandedFromMacro("SIG_IGN")),
  337. unless(isExpandedFromMacro("SIG_DFL")))
  338. .bind("handler_expr");
  339. auto HandlerLambda = cxxMemberCallExpr(
  340. on(expr(ignoringParenImpCasts(lambdaExpr().bind("handler_lambda")))));
  341. Finder->addMatcher(callExpr(callee(SignalFunction),
  342. hasArgument(1, anyOf(HandlerExpr, HandlerLambda)))
  343. .bind("register_call"),
  344. this);
  345. }
  346. void SignalHandlerCheck::check(const MatchFinder::MatchResult &Result) {
  347. if (const auto *HandlerLambda =
  348. Result.Nodes.getNodeAs<LambdaExpr>("handler_lambda")) {
  349. diag(HandlerLambda->getBeginLoc(),
  350. "lambda function is not allowed as signal handler (until C++17)")
  351. << HandlerLambda->getSourceRange();
  352. return;
  353. }
  354. const auto *HandlerDecl =
  355. Result.Nodes.getNodeAs<FunctionDecl>("handler_decl");
  356. const auto *HandlerExpr = Result.Nodes.getNodeAs<DeclRefExpr>("handler_expr");
  357. assert(Result.Nodes.getNodeAs<CallExpr>("register_call") && HandlerDecl &&
  358. HandlerExpr && "All of these should exist in a match here.");
  359. if (CG.size() <= 1) {
  360. // Call graph must be populated with the entire TU at the beginning.
  361. // (It is possible to add a single function but the functions called from it
  362. // are not analysed in this case.)
  363. CG.addToCallGraph(const_cast<TranslationUnitDecl *>(
  364. HandlerDecl->getTranslationUnitDecl()));
  365. assert(CG.size() > 1 &&
  366. "There should be at least one function added to call graph.");
  367. }
  368. if (!HandlerDecl->hasBody()) {
  369. // Check the handler function.
  370. // The warning is placed to the signal handler registration.
  371. // No need to display a call chain and no need for more checks.
  372. (void)checkFunction(HandlerDecl, HandlerExpr, {});
  373. return;
  374. }
  375. // FIXME: Update CallGraph::getNode to use canonical decl?
  376. CallGraphNode *HandlerNode = CG.getNode(HandlerDecl->getCanonicalDecl());
  377. assert(HandlerNode &&
  378. "Handler with body should be present in the call graph.");
  379. // Start from signal handler and visit every function call.
  380. auto Itr = llvm::df_begin(HandlerNode), ItrE = llvm::df_end(HandlerNode);
  381. while (Itr != ItrE) {
  382. const auto *CallF = dyn_cast<FunctionDecl>((*Itr)->getDecl());
  383. unsigned int PathL = Itr.getPathLength();
  384. if (CallF) {
  385. // A signal handler or a function transitively reachable from the signal
  386. // handler was found to be unsafe.
  387. // Generate notes for the whole call chain (including the signal handler
  388. // registration).
  389. const Expr *CallOrRef = (PathL > 1)
  390. ? findCallExpr(Itr.getPath(PathL - 2), *Itr)
  391. : HandlerExpr;
  392. auto ChainReporter = [this, &Itr, HandlerExpr](bool SkipPathEnd) {
  393. reportHandlerChain(Itr, HandlerExpr, SkipPathEnd);
  394. };
  395. // If problems were found in a function (`CallF`), skip the analysis of
  396. // functions that are called from it.
  397. if (checkFunction(CallF, CallOrRef, ChainReporter))
  398. Itr.skipChildren();
  399. else
  400. ++Itr;
  401. } else {
  402. ++Itr;
  403. }
  404. }
  405. }
  406. bool SignalHandlerCheck::checkFunction(
  407. const FunctionDecl *FD, const Expr *CallOrRef,
  408. std::function<void(bool)> ChainReporter) {
  409. bool FunctionIsCalled = isa<CallExpr>(CallOrRef);
  410. if (isStandardFunction(FD)) {
  411. if (!isStandardFunctionAsyncSafe(FD)) {
  412. diag(CallOrRef->getBeginLoc(), "standard function %0 may not be "
  413. "asynchronous-safe; "
  414. "%select{using it as|calling it from}1 "
  415. "a signal handler may be dangerous")
  416. << FD << FunctionIsCalled << CallOrRef->getSourceRange();
  417. if (ChainReporter)
  418. ChainReporter(/*SkipPathEnd=*/true);
  419. return true;
  420. }
  421. return false;
  422. }
  423. if (!FD->hasBody()) {
  424. diag(CallOrRef->getBeginLoc(), "cannot verify that external function %0 is "
  425. "asynchronous-safe; "
  426. "%select{using it as|calling it from}1 "
  427. "a signal handler may be dangerous")
  428. << FD << FunctionIsCalled << CallOrRef->getSourceRange();
  429. if (ChainReporter)
  430. ChainReporter(/*SkipPathEnd=*/true);
  431. return true;
  432. }
  433. if (getLangOpts().CPlusPlus)
  434. return checkFunctionCPP14(FD, CallOrRef, ChainReporter);
  435. return false;
  436. }
  437. bool SignalHandlerCheck::checkFunctionCPP14(
  438. const FunctionDecl *FD, const Expr *CallOrRef,
  439. std::function<void(bool)> ChainReporter) {
  440. if (!FD->isExternC()) {
  441. diag(CallOrRef->getBeginLoc(),
  442. "functions without C linkage are not allowed as signal "
  443. "handler (until C++17)");
  444. if (ChainReporter)
  445. ChainReporter(/*SkipPathEnd=*/true);
  446. return true;
  447. }
  448. const FunctionDecl *FBody;
  449. const Stmt *BodyS = FD->getBody(FBody);
  450. if (!BodyS)
  451. return false;
  452. bool StmtProblemsFound = false;
  453. ASTContext &Ctx = FBody->getASTContext();
  454. auto Matches =
  455. match(decl(forEachDescendant(stmt().bind("stmt"))), *FBody, Ctx);
  456. for (const auto &Match : Matches) {
  457. const auto *FoundS = Match.getNodeAs<Stmt>("stmt");
  458. if (isCXXOnlyStmt(FoundS)) {
  459. SourceRange R = getSourceRangeOfStmt(FoundS, Ctx);
  460. if (R.isInvalid())
  461. continue;
  462. diag(R.getBegin(),
  463. "C++-only construct is not allowed in signal handler (until C++17)")
  464. << R;
  465. diag(R.getBegin(), "internally, the statement is parsed as a '%0'",
  466. DiagnosticIDs::Remark)
  467. << FoundS->getStmtClassName();
  468. if (ChainReporter)
  469. ChainReporter(/*SkipPathEnd=*/false);
  470. StmtProblemsFound = true;
  471. }
  472. }
  473. return StmtProblemsFound;
  474. }
  475. bool SignalHandlerCheck::isStandardFunctionAsyncSafe(
  476. const FunctionDecl *FD) const {
  477. assert(isStandardFunction(FD));
  478. const IdentifierInfo *II = FD->getIdentifier();
  479. // Unnamed functions are not explicitly allowed.
  480. // C++ std operators may be unsafe and not within the
  481. // "common subset of C and C++".
  482. if (!II)
  483. return false;
  484. if (!FD->isInStdNamespace() && !FD->isGlobal())
  485. return false;
  486. if (ConformingFunctions.count(II->getName()))
  487. return true;
  488. return false;
  489. }
  490. void SignalHandlerCheck::reportHandlerChain(
  491. const llvm::df_iterator<clang::CallGraphNode *> &Itr,
  492. const DeclRefExpr *HandlerRef, bool SkipPathEnd) {
  493. int CallLevel = Itr.getPathLength() - 2;
  494. assert(CallLevel >= -1 && "Empty iterator?");
  495. const CallGraphNode *Caller = Itr.getPath(CallLevel + 1), *Callee = nullptr;
  496. while (CallLevel >= 0) {
  497. Callee = Caller;
  498. Caller = Itr.getPath(CallLevel);
  499. const Expr *CE = findCallExpr(Caller, Callee);
  500. if (SkipPathEnd)
  501. SkipPathEnd = false;
  502. else
  503. diag(CE->getBeginLoc(), "function %0 called here from %1",
  504. DiagnosticIDs::Note)
  505. << cast<FunctionDecl>(Callee->getDecl())
  506. << cast<FunctionDecl>(Caller->getDecl());
  507. --CallLevel;
  508. }
  509. if (!SkipPathEnd)
  510. diag(HandlerRef->getBeginLoc(),
  511. "function %0 registered here as signal handler", DiagnosticIDs::Note)
  512. << cast<FunctionDecl>(Caller->getDecl())
  513. << HandlerRef->getSourceRange();
  514. }
  515. } // namespace bugprone
  516. } // namespace clang::tidy