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