CheckSizeofPointer.cpp 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. //==- CheckSizeofPointer.cpp - Check for sizeof on pointers ------*- 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 file defines a check for unintended use of sizeof() on pointer
  11. // expressions.
  12. //
  13. //===----------------------------------------------------------------------===//
  14. #include "ClangSACheckers.h"
  15. #include "clang/AST/StmtVisitor.h"
  16. #include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
  17. #include "clang/StaticAnalyzer/Core/Checker.h"
  18. #include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
  19. using namespace clang;
  20. using namespace ento;
  21. namespace {
  22. class WalkAST : public StmtVisitor<WalkAST> {
  23. BugReporter &BR;
  24. const CheckerBase *Checker;
  25. AnalysisDeclContext* AC;
  26. public:
  27. WalkAST(BugReporter &br, const CheckerBase *checker, AnalysisDeclContext *ac)
  28. : BR(br), Checker(checker), AC(ac) {}
  29. void VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *E);
  30. void VisitStmt(Stmt *S) { VisitChildren(S); }
  31. void VisitChildren(Stmt *S);
  32. };
  33. }
  34. void WalkAST::VisitChildren(Stmt *S) {
  35. for (Stmt *Child : S->children())
  36. if (Child)
  37. Visit(Child);
  38. }
  39. // CWE-467: Use of sizeof() on a Pointer Type
  40. void WalkAST::VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *E) {
  41. if (E->getKind() != UETT_SizeOf)
  42. return;
  43. // If an explicit type is used in the code, usually the coder knows what they are
  44. // doing.
  45. if (E->isArgumentType())
  46. return;
  47. QualType T = E->getTypeOfArgument();
  48. if (T->isPointerType()) {
  49. // Many false positives have the form 'sizeof *p'. This is reasonable
  50. // because people know what they are doing when they intentionally
  51. // dereference the pointer.
  52. Expr *ArgEx = E->getArgumentExpr();
  53. if (!isa<DeclRefExpr>(ArgEx->IgnoreParens()))
  54. return;
  55. PathDiagnosticLocation ELoc =
  56. PathDiagnosticLocation::createBegin(E, BR.getSourceManager(), AC);
  57. BR.EmitBasicReport(AC->getDecl(), Checker,
  58. "Potential unintended use of sizeof() on pointer type",
  59. categories::LogicError,
  60. "The code calls sizeof() on a pointer type. "
  61. "This can produce an unexpected result.",
  62. ELoc, ArgEx->getSourceRange());
  63. }
  64. }
  65. //===----------------------------------------------------------------------===//
  66. // SizeofPointerChecker
  67. //===----------------------------------------------------------------------===//
  68. namespace {
  69. class SizeofPointerChecker : public Checker<check::ASTCodeBody> {
  70. public:
  71. void checkASTCodeBody(const Decl *D, AnalysisManager& mgr,
  72. BugReporter &BR) const {
  73. WalkAST walker(BR, this, mgr.getAnalysisDeclContext(D));
  74. walker.Visit(D->getBody());
  75. }
  76. };
  77. }
  78. void ento::registerSizeofPointerChecker(CheckerManager &mgr) {
  79. mgr.registerChecker<SizeofPointerChecker>();
  80. }