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/BugReporter/BugReporter.h" 00018 #include "clang/StaticAnalyzer/Core/Checker.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 const CheckerBase *Checker; 00028 AnalysisDeclContext* AC; 00029 00030 public: 00031 WalkAST(BugReporter &br, const CheckerBase *checker, AnalysisDeclContext *ac) 00032 : BR(br), Checker(checker), AC(ac) {} 00033 void VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *E); 00034 void VisitStmt(Stmt *S) { VisitChildren(S); } 00035 void VisitChildren(Stmt *S); 00036 }; 00037 } 00038 00039 void WalkAST::VisitChildren(Stmt *S) { 00040 for (Stmt::child_iterator I = S->child_begin(), E = S->child_end(); I!=E; ++I) 00041 if (Stmt *child = *I) 00042 Visit(child); 00043 } 00044 00045 // CWE-467: Use of sizeof() on a Pointer Type 00046 void WalkAST::VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *E) { 00047 if (E->getKind() != UETT_SizeOf) 00048 return; 00049 00050 // If an explicit type is used in the code, usually the coder knows what they are 00051 // doing. 00052 if (E->isArgumentType()) 00053 return; 00054 00055 QualType T = E->getTypeOfArgument(); 00056 if (T->isPointerType()) { 00057 00058 // Many false positives have the form 'sizeof *p'. This is reasonable 00059 // because people know what they are doing when they intentionally 00060 // dereference the pointer. 00061 Expr *ArgEx = E->getArgumentExpr(); 00062 if (!isa<DeclRefExpr>(ArgEx->IgnoreParens())) 00063 return; 00064 00065 PathDiagnosticLocation ELoc = 00066 PathDiagnosticLocation::createBegin(E, BR.getSourceManager(), AC); 00067 BR.EmitBasicReport(AC->getDecl(), Checker, 00068 "Potential unintended use of sizeof() on pointer type", 00069 categories::LogicError, 00070 "The code calls sizeof() on a pointer type. " 00071 "This can produce an unexpected result.", 00072 ELoc, ArgEx->getSourceRange()); 00073 } 00074 } 00075 00076 //===----------------------------------------------------------------------===// 00077 // SizeofPointerChecker 00078 //===----------------------------------------------------------------------===// 00079 00080 namespace { 00081 class SizeofPointerChecker : public Checker<check::ASTCodeBody> { 00082 public: 00083 void checkASTCodeBody(const Decl *D, AnalysisManager& mgr, 00084 BugReporter &BR) const { 00085 WalkAST walker(BR, this, mgr.getAnalysisDeclContext(D)); 00086 walker.Visit(D->getBody()); 00087 } 00088 }; 00089 } 00090 00091 void ento::registerSizeofPointerChecker(CheckerManager &mgr) { 00092 mgr.registerChecker<SizeofPointerChecker>(); 00093 }