UncountedCallArgsChecker.cpp 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. //=======- UncountedCallArgsChecker.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. #include "ASTUtils.h"
  9. #include "DiagOutputUtils.h"
  10. #include "PtrTypesSemantics.h"
  11. #include "clang/AST/CXXInheritance.h"
  12. #include "clang/AST/Decl.h"
  13. #include "clang/AST/DeclCXX.h"
  14. #include "clang/AST/RecursiveASTVisitor.h"
  15. #include "clang/Basic/SourceLocation.h"
  16. #include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
  17. #include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
  18. #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
  19. #include "clang/StaticAnalyzer/Core/Checker.h"
  20. #include "llvm/ADT/DenseSet.h"
  21. #include <optional>
  22. using namespace clang;
  23. using namespace ento;
  24. namespace {
  25. class UncountedCallArgsChecker
  26. : public Checker<check::ASTDecl<TranslationUnitDecl>> {
  27. BugType Bug{this,
  28. "Uncounted call argument for a raw pointer/reference parameter",
  29. "WebKit coding guidelines"};
  30. mutable BugReporter *BR;
  31. public:
  32. void checkASTDecl(const TranslationUnitDecl *TUD, AnalysisManager &MGR,
  33. BugReporter &BRArg) const {
  34. BR = &BRArg;
  35. // The calls to checkAST* from AnalysisConsumer don't
  36. // visit template instantiations or lambda classes. We
  37. // want to visit those, so we make our own RecursiveASTVisitor.
  38. struct LocalVisitor : public RecursiveASTVisitor<LocalVisitor> {
  39. const UncountedCallArgsChecker *Checker;
  40. explicit LocalVisitor(const UncountedCallArgsChecker *Checker)
  41. : Checker(Checker) {
  42. assert(Checker);
  43. }
  44. bool shouldVisitTemplateInstantiations() const { return true; }
  45. bool shouldVisitImplicitCode() const { return false; }
  46. bool VisitCallExpr(const CallExpr *CE) {
  47. Checker->visitCallExpr(CE);
  48. return true;
  49. }
  50. };
  51. LocalVisitor visitor(this);
  52. visitor.TraverseDecl(const_cast<TranslationUnitDecl *>(TUD));
  53. }
  54. void visitCallExpr(const CallExpr *CE) const {
  55. if (shouldSkipCall(CE))
  56. return;
  57. if (auto *F = CE->getDirectCallee()) {
  58. // Skip the first argument for overloaded member operators (e. g. lambda
  59. // or std::function call operator).
  60. unsigned ArgIdx = isa<CXXOperatorCallExpr>(CE) && isa_and_nonnull<CXXMethodDecl>(F);
  61. for (auto P = F->param_begin();
  62. // FIXME: Also check variadic function parameters.
  63. // FIXME: Also check default function arguments. Probably a different
  64. // checker. In case there are default arguments the call can have
  65. // fewer arguments than the callee has parameters.
  66. P < F->param_end() && ArgIdx < CE->getNumArgs(); ++P, ++ArgIdx) {
  67. // TODO: attributes.
  68. // if ((*P)->hasAttr<SafeRefCntblRawPtrAttr>())
  69. // continue;
  70. const auto *ArgType = (*P)->getType().getTypePtrOrNull();
  71. if (!ArgType)
  72. continue; // FIXME? Should we bail?
  73. // FIXME: more complex types (arrays, references to raw pointers, etc)
  74. std::optional<bool> IsUncounted = isUncountedPtr(ArgType);
  75. if (!IsUncounted || !(*IsUncounted))
  76. continue;
  77. const auto *Arg = CE->getArg(ArgIdx);
  78. std::pair<const clang::Expr *, bool> ArgOrigin =
  79. tryToFindPtrOrigin(Arg, true);
  80. // Temporary ref-counted object created as part of the call argument
  81. // would outlive the call.
  82. if (ArgOrigin.second)
  83. continue;
  84. if (isa<CXXNullPtrLiteralExpr>(ArgOrigin.first)) {
  85. // foo(nullptr)
  86. continue;
  87. }
  88. if (isa<IntegerLiteral>(ArgOrigin.first)) {
  89. // FIXME: Check the value.
  90. // foo(NULL)
  91. continue;
  92. }
  93. if (isASafeCallArg(ArgOrigin.first))
  94. continue;
  95. reportBug(Arg, *P);
  96. }
  97. }
  98. }
  99. bool shouldSkipCall(const CallExpr *CE) const {
  100. if (CE->getNumArgs() == 0)
  101. return false;
  102. // If an assignment is problematic we should warn about the sole existence
  103. // of object on LHS.
  104. if (auto *MemberOp = dyn_cast<CXXOperatorCallExpr>(CE)) {
  105. // Note: assignemnt to built-in type isn't derived from CallExpr.
  106. if (MemberOp->isAssignmentOp())
  107. return false;
  108. }
  109. const auto *Callee = CE->getDirectCallee();
  110. if (!Callee)
  111. return false;
  112. auto overloadedOperatorType = Callee->getOverloadedOperator();
  113. if (overloadedOperatorType == OO_EqualEqual ||
  114. overloadedOperatorType == OO_ExclaimEqual ||
  115. overloadedOperatorType == OO_LessEqual ||
  116. overloadedOperatorType == OO_GreaterEqual ||
  117. overloadedOperatorType == OO_Spaceship ||
  118. overloadedOperatorType == OO_AmpAmp ||
  119. overloadedOperatorType == OO_PipePipe)
  120. return true;
  121. if (isCtorOfRefCounted(Callee))
  122. return true;
  123. auto name = safeGetName(Callee);
  124. if (name == "adoptRef" || name == "getPtr" || name == "WeakPtr" ||
  125. name == "makeWeakPtr" || name == "downcast" || name == "bitwise_cast" ||
  126. name == "is" || name == "equal" || name == "hash" ||
  127. name == "isType"
  128. // FIXME: Most/all of these should be implemented via attributes.
  129. || name == "equalIgnoringASCIICase" ||
  130. name == "equalIgnoringASCIICaseCommon" ||
  131. name == "equalIgnoringNullity")
  132. return true;
  133. return false;
  134. }
  135. void reportBug(const Expr *CallArg, const ParmVarDecl *Param) const {
  136. assert(CallArg);
  137. SmallString<100> Buf;
  138. llvm::raw_svector_ostream Os(Buf);
  139. const std::string paramName = safeGetName(Param);
  140. Os << "Call argument";
  141. if (!paramName.empty()) {
  142. Os << " for parameter ";
  143. printQuotedQualifiedName(Os, Param);
  144. }
  145. Os << " is uncounted and unsafe.";
  146. const SourceLocation SrcLocToReport =
  147. isa<CXXDefaultArgExpr>(CallArg) ? Param->getDefaultArg()->getExprLoc()
  148. : CallArg->getSourceRange().getBegin();
  149. PathDiagnosticLocation BSLoc(SrcLocToReport, BR->getSourceManager());
  150. auto Report = std::make_unique<BasicBugReport>(Bug, Os.str(), BSLoc);
  151. Report->addRange(CallArg->getSourceRange());
  152. BR->emitReport(std::move(Report));
  153. }
  154. };
  155. } // namespace
  156. void ento::registerUncountedCallArgsChecker(CheckerManager &Mgr) {
  157. Mgr.registerChecker<UncountedCallArgsChecker>();
  158. }
  159. bool ento::shouldRegisterUncountedCallArgsChecker(const CheckerManager &) {
  160. return true;
  161. }