CheckSizeofPointer.cpp revision 579ee4f9f5c7b8f939621c8008337a3c1c679957
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//==- CheckSizeofPointer.cpp - Check for sizeof on pointers ------*- C++ -*-==// 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The LLVM Compiler Infrastructure 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This file is distributed under the University of Illinois Open Source 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// License. See LICENSE.TXT for details. 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//===----------------------------------------------------------------------===// 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This file defines a check for unintended use of sizeof() on pointer 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// expressions. 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//===----------------------------------------------------------------------===// 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ClangSACheckers.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "clang/AST/StmtVisitor.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "clang/StaticAnalyzer/Core/Checker.h" 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h" 192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h" 202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using namespace clang; 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using namespace ento; 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class WalkAST : public StmtVisitor<WalkAST> { 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BugReporter &BR; 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AnalysisDeclContext* AC; 282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)public: 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WalkAST(BugReporter &br, AnalysisDeclContext* ac) : BR(br), AC(ac) {} 312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) void VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *E); 322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) void VisitStmt(Stmt *S) { VisitChildren(S); } 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void VisitChildren(Stmt *S); 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void WalkAST::VisitChildren(Stmt *S) { 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (Stmt::child_iterator I = S->child_begin(), E = S->child_end(); I!=E; ++I) 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (Stmt *child = *I) 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Visit(child); 412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// CWE-467: Use of sizeof() on a Pointer Type 442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void WalkAST::VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *E) { 452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (E->getKind() != UETT_SizeOf) 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If an explicit type is used in the code, usually the coder knows what he is 492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // doing. 502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (E->isArgumentType()) 512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 52a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 53a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) QualType T = E->getTypeOfArgument(); 54a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) if (T->isPointerType()) { 55a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 56a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) // Many false positives have the form 'sizeof *p'. This is reasonable 57a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) // because people know what they are doing when they intentionally 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // dereference the pointer. 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Expr *ArgEx = E->getArgumentExpr(); 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!isa<DeclRefExpr>(ArgEx->IgnoreParens())) 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SourceRange R = ArgEx->getSourceRange(); 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PathDiagnosticLocation ELoc = 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PathDiagnosticLocation::createBegin(E, BR.getSourceManager(), AC); 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BR.EmitBasicReport("Potential unintended use of sizeof() on pointer type", 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Logic", 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "The code calls sizeof() on a pointer type. " 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "This can produce an unexpected result.", 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ELoc, &R, 1); 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//===----------------------------------------------------------------------===// 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// SizeofPointerChecker 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//===----------------------------------------------------------------------===// 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class SizeofPointerChecker : public Checker<check::ASTCodeBody> { 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)public: 812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) void checkASTCodeBody(const Decl *D, AnalysisManager& mgr, 822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) BugReporter &BR) const { 832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) WalkAST walker(BR, mgr.getAnalysisDeclContext(D)); 842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) walker.Visit(D->getBody()); 852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}; 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ento::registerSizeofPointerChecker(CheckerManager &mgr) { 902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) mgr.registerChecker<SizeofPointerChecker>(); 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)