CheckSizeofPointer.cpp revision 579ee4f9f5c7b8f939621c8008337a3c1c679957
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//==- CheckSizeofPointer.cpp - Check for sizeof on pointers ------*- C++ -*-==//
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//                     The LLVM Compiler Infrastructure
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This file is distributed under the University of Illinois Open Source
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// License. See LICENSE.TXT for details.
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//===----------------------------------------------------------------------===//
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//  This file defines a check for unintended use of sizeof() on pointer
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//  expressions.
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//===----------------------------------------------------------------------===//
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ClangSACheckers.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "clang/AST/StmtVisitor.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "clang/StaticAnalyzer/Core/Checker.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using namespace clang;
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using namespace ento;
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class WalkAST : public StmtVisitor<WalkAST> {
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BugReporter &BR;
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AnalysisDeclContext* AC;
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)public:
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WalkAST(BugReporter &br, AnalysisDeclContext* ac) : BR(br), AC(ac) {}
312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *E);
322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void VisitStmt(Stmt *S) { VisitChildren(S); }
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void VisitChildren(Stmt *S);
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void WalkAST::VisitChildren(Stmt *S) {
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (Stmt::child_iterator I = S->child_begin(), E = S->child_end(); I!=E; ++I)
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (Stmt *child = *I)
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      Visit(child);
412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// CWE-467: Use of sizeof() on a Pointer Type
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void WalkAST::VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *E) {
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (E->getKind() != UETT_SizeOf)
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If an explicit type is used in the code, usually the coder knows what he is
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // doing.
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (E->isArgumentType())
512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
52a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
53a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  QualType T = E->getTypeOfArgument();
54a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  if (T->isPointerType()) {
55a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
56a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    // Many false positives have the form 'sizeof *p'. This is reasonable
57a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    // because people know what they are doing when they intentionally
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // dereference the pointer.
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Expr *ArgEx = E->getArgumentExpr();
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!isa<DeclRefExpr>(ArgEx->IgnoreParens()))
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SourceRange R = ArgEx->getSourceRange();
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PathDiagnosticLocation ELoc =
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      PathDiagnosticLocation::createBegin(E, BR.getSourceManager(), AC);
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    BR.EmitBasicReport("Potential unintended use of sizeof() on pointer type",
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       "Logic",
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       "The code calls sizeof() on a pointer type. "
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       "This can produce an unexpected result.",
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       ELoc, &R, 1);
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//===----------------------------------------------------------------------===//
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// SizeofPointerChecker
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//===----------------------------------------------------------------------===//
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class SizeofPointerChecker : public Checker<check::ASTCodeBody> {
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)public:
812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void checkASTCodeBody(const Decl *D, AnalysisManager& mgr,
822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                        BugReporter &BR) const {
832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    WalkAST walker(BR, mgr.getAnalysisDeclContext(D));
842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    walker.Visit(D->getBody());
852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ento::registerSizeofPointerChecker(CheckerManager &mgr) {
902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  mgr.registerChecker<SizeofPointerChecker>();
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)