|  | //==- CheckSizeofPointer.cpp - Check for sizeof on pointers ------*- C++ -*-==// | 
|  | // | 
|  | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | 
|  | // See https://llvm.org/LICENSE.txt for license information. | 
|  | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | 
|  | // | 
|  | //===----------------------------------------------------------------------===// | 
|  | // | 
|  | //  This file defines a check for unintended use of sizeof() on pointer | 
|  | //  expressions. | 
|  | // | 
|  | //===----------------------------------------------------------------------===// | 
|  |  | 
|  | #include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h" | 
|  | #include "clang/AST/StmtVisitor.h" | 
|  | #include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h" | 
|  | #include "clang/StaticAnalyzer/Core/Checker.h" | 
|  | #include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h" | 
|  |  | 
|  | using namespace clang; | 
|  | using namespace ento; | 
|  |  | 
|  | namespace { | 
|  | class WalkAST : public StmtVisitor<WalkAST> { | 
|  | BugReporter &BR; | 
|  | const CheckerBase *Checker; | 
|  | AnalysisDeclContext* AC; | 
|  |  | 
|  | public: | 
|  | WalkAST(BugReporter &br, const CheckerBase *checker, AnalysisDeclContext *ac) | 
|  | : BR(br), Checker(checker), AC(ac) {} | 
|  | void VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *E); | 
|  | void VisitStmt(Stmt *S) { VisitChildren(S); } | 
|  | void VisitChildren(Stmt *S); | 
|  | }; | 
|  | } | 
|  |  | 
|  | void WalkAST::VisitChildren(Stmt *S) { | 
|  | for (Stmt *Child : S->children()) | 
|  | if (Child) | 
|  | Visit(Child); | 
|  | } | 
|  |  | 
|  | // CWE-467: Use of sizeof() on a Pointer Type | 
|  | void WalkAST::VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *E) { | 
|  | if (E->getKind() != UETT_SizeOf) | 
|  | return; | 
|  |  | 
|  | // If an explicit type is used in the code, usually the coder knows what they are | 
|  | // doing. | 
|  | if (E->isArgumentType()) | 
|  | return; | 
|  |  | 
|  | QualType T = E->getTypeOfArgument(); | 
|  | if (T->isPointerType()) { | 
|  |  | 
|  | // Many false positives have the form 'sizeof *p'. This is reasonable | 
|  | // because people know what they are doing when they intentionally | 
|  | // dereference the pointer. | 
|  | Expr *ArgEx = E->getArgumentExpr(); | 
|  | if (!isa<DeclRefExpr>(ArgEx->IgnoreParens())) | 
|  | return; | 
|  |  | 
|  | PathDiagnosticLocation ELoc = | 
|  | PathDiagnosticLocation::createBegin(E, BR.getSourceManager(), AC); | 
|  | BR.EmitBasicReport(AC->getDecl(), Checker, | 
|  | "Potential unintended use of sizeof() on pointer type", | 
|  | categories::LogicError, | 
|  | "The code calls sizeof() on a pointer type. " | 
|  | "This can produce an unexpected result.", | 
|  | ELoc, ArgEx->getSourceRange()); | 
|  | } | 
|  | } | 
|  |  | 
|  | //===----------------------------------------------------------------------===// | 
|  | // SizeofPointerChecker | 
|  | //===----------------------------------------------------------------------===// | 
|  |  | 
|  | namespace { | 
|  | class SizeofPointerChecker : public Checker<check::ASTCodeBody> { | 
|  | public: | 
|  | void checkASTCodeBody(const Decl *D, AnalysisManager& mgr, | 
|  | BugReporter &BR) const { | 
|  | WalkAST walker(BR, this, mgr.getAnalysisDeclContext(D)); | 
|  | walker.Visit(D->getBody()); | 
|  | } | 
|  | }; | 
|  | } | 
|  |  | 
|  | void ento::registerSizeofPointerChecker(CheckerManager &mgr) { | 
|  | mgr.registerChecker<SizeofPointerChecker>(); | 
|  | } | 
|  |  | 
|  | bool ento::shouldRegisterSizeofPointerChecker(const LangOptions &LO) { | 
|  | return true; | 
|  | } |