clang API Documentation
00001 //==- CheckSizeofPointer.cpp - Check for sizeof on pointers ------*- C++ -*-==// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 // 00010 // This file defines a check for unintended use of sizeof() on pointer 00011 // expressions. 00012 // 00013 //===----------------------------------------------------------------------===// 00014 00015 #include "ClangSACheckers.h" 00016 #include "clang/AST/StmtVisitor.h" 00017 #include "clang/StaticAnalyzer/Core/Checker.h" 00018 #include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h" 00019 #include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h" 00020 00021 using namespace clang; 00022 using namespace ento; 00023 00024 namespace { 00025 class WalkAST : public StmtVisitor<WalkAST> { 00026 BugReporter &BR; 00027 AnalysisDeclContext* AC; 00028 00029 public: 00030 WalkAST(BugReporter &br, AnalysisDeclContext* ac) : BR(br), AC(ac) {} 00031 void VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *E); 00032 void VisitStmt(Stmt *S) { VisitChildren(S); } 00033 void VisitChildren(Stmt *S); 00034 }; 00035 } 00036 00037 void WalkAST::VisitChildren(Stmt *S) { 00038 for (Stmt::child_iterator I = S->child_begin(), E = S->child_end(); I!=E; ++I) 00039 if (Stmt *child = *I) 00040 Visit(child); 00041 } 00042 00043 // CWE-467: Use of sizeof() on a Pointer Type 00044 void WalkAST::VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *E) { 00045 if (E->getKind() != UETT_SizeOf) 00046 return; 00047 00048 // If an explicit type is used in the code, usually the coder knows what he is 00049 // doing. 00050 if (E->isArgumentType()) 00051 return; 00052 00053 QualType T = E->getTypeOfArgument(); 00054 if (T->isPointerType()) { 00055 00056 // Many false positives have the form 'sizeof *p'. This is reasonable 00057 // because people know what they are doing when they intentionally 00058 // dereference the pointer. 00059 Expr *ArgEx = E->getArgumentExpr(); 00060 if (!isa<DeclRefExpr>(ArgEx->IgnoreParens())) 00061 return; 00062 00063 SourceRange R = ArgEx->getSourceRange(); 00064 PathDiagnosticLocation ELoc = 00065 PathDiagnosticLocation::createBegin(E, BR.getSourceManager(), AC); 00066 BR.EmitBasicReport(AC->getDecl(), 00067 "Potential unintended use of sizeof() on pointer type", 00068 "Logic", 00069 "The code calls sizeof() on a pointer type. " 00070 "This can produce an unexpected result.", 00071 ELoc, &R, 1); 00072 } 00073 } 00074 00075 //===----------------------------------------------------------------------===// 00076 // SizeofPointerChecker 00077 //===----------------------------------------------------------------------===// 00078 00079 namespace { 00080 class SizeofPointerChecker : public Checker<check::ASTCodeBody> { 00081 public: 00082 void checkASTCodeBody(const Decl *D, AnalysisManager& mgr, 00083 BugReporter &BR) const { 00084 WalkAST walker(BR, mgr.getAnalysisDeclContext(D)); 00085 walker.Visit(D->getBody()); 00086 } 00087 }; 00088 } 00089 00090 void ento::registerSizeofPointerChecker(CheckerManager &mgr) { 00091 mgr.registerChecker<SizeofPointerChecker>(); 00092 }