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