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