1 //==- CheckSizeofPointer.cpp - Check for sizeof on pointers ------*- C++ -*-==// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This file defines a check for unintended use of sizeof() on pointer 10 // expressions. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h" 15 #include "clang/AST/StmtVisitor.h" 16 #include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h" 17 #include "clang/StaticAnalyzer/Core/Checker.h" 18 #include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h" 19 20 using namespace clang; 21 using namespace ento; 22 23 namespace { 24 class WalkAST : public StmtVisitor<WalkAST> { 25 BugReporter &BR; 26 const CheckerBase *Checker; 27 AnalysisDeclContext* AC; 28 29 public: 30 WalkAST(BugReporter &br, const CheckerBase *checker, AnalysisDeclContext *ac) 31 : BR(br), Checker(checker), AC(ac) {} 32 void VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *E); 33 void VisitStmt(Stmt *S) { VisitChildren(S); } 34 void VisitChildren(Stmt *S); 35 }; 36 } 37 38 void WalkAST::VisitChildren(Stmt *S) { 39 for (Stmt *Child : S->children()) 40 if (Child) 41 Visit(Child); 42 } 43 44 // CWE-467: Use of sizeof() on a Pointer Type 45 void WalkAST::VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *E) { 46 if (E->getKind() != UETT_SizeOf) 47 return; 48 49 // If an explicit type is used in the code, usually the coder knows what they are 50 // doing. 51 if (E->isArgumentType()) 52 return; 53 54 QualType T = E->getTypeOfArgument(); 55 if (T->isPointerType()) { 56 57 // Many false positives have the form 'sizeof *p'. This is reasonable 58 // because people know what they are doing when they intentionally 59 // dereference the pointer. 60 Expr *ArgEx = E->getArgumentExpr(); 61 if (!isa<DeclRefExpr>(ArgEx->IgnoreParens())) 62 return; 63 64 PathDiagnosticLocation ELoc = 65 PathDiagnosticLocation::createBegin(E, BR.getSourceManager(), AC); 66 BR.EmitBasicReport(AC->getDecl(), Checker, 67 "Potential unintended use of sizeof() on pointer type", 68 categories::LogicError, 69 "The code calls sizeof() on a pointer type. " 70 "This can produce an unexpected result.", 71 ELoc, ArgEx->getSourceRange()); 72 } 73 } 74 75 //===----------------------------------------------------------------------===// 76 // SizeofPointerChecker 77 //===----------------------------------------------------------------------===// 78 79 namespace { 80 class SizeofPointerChecker : public Checker<check::ASTCodeBody> { 81 public: 82 void checkASTCodeBody(const Decl *D, AnalysisManager& mgr, 83 BugReporter &BR) const { 84 WalkAST walker(BR, this, mgr.getAnalysisDeclContext(D)); 85 walker.Visit(D->getBody()); 86 } 87 }; 88 } 89 90 void ento::registerSizeofPointerChecker(CheckerManager &mgr) { 91 mgr.registerChecker<SizeofPointerChecker>(); 92 } 93 94 bool ento::shouldRegisterSizeofPointerChecker(const LangOptions &LO) { 95 return true; 96 } 97