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