1218887Sdim//=== CastSizeChecker.cpp ---------------------------------------*- C++ -*-===// 2218887Sdim// 3218887Sdim// The LLVM Compiler Infrastructure 4218887Sdim// 5218887Sdim// This file is distributed under the University of Illinois Open Source 6218887Sdim// License. See LICENSE.TXT for details. 7218887Sdim// 8218887Sdim//===----------------------------------------------------------------------===// 9218887Sdim// 10218887Sdim// CastSizeChecker checks when casting a malloc'ed symbolic region to type T, 11218887Sdim// whether the size of the symbolic region is a multiple of the size of T. 12218887Sdim// 13218887Sdim//===----------------------------------------------------------------------===// 14219077Sdim#include "ClangSACheckers.h" 15249423Sdim#include "clang/AST/CharUnits.h" 16249423Sdim#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" 17221345Sdim#include "clang/StaticAnalyzer/Core/Checker.h" 18219077Sdim#include "clang/StaticAnalyzer/Core/CheckerManager.h" 19219077Sdim#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" 20218887Sdim 21218887Sdimusing namespace clang; 22218887Sdimusing namespace ento; 23218887Sdim 24218887Sdimnamespace { 25221345Sdimclass CastSizeChecker : public Checker< check::PreStmt<CastExpr> > { 26234353Sdim mutable OwningPtr<BuiltinBug> BT; 27218887Sdimpublic: 28219077Sdim void checkPreStmt(const CastExpr *CE, CheckerContext &C) const; 29218887Sdim}; 30218887Sdim} 31218887Sdim 32219077Sdimvoid CastSizeChecker::checkPreStmt(const CastExpr *CE,CheckerContext &C) const { 33218887Sdim const Expr *E = CE->getSubExpr(); 34218887Sdim ASTContext &Ctx = C.getASTContext(); 35218887Sdim QualType ToTy = Ctx.getCanonicalType(CE->getType()); 36218887Sdim const PointerType *ToPTy = dyn_cast<PointerType>(ToTy.getTypePtr()); 37218887Sdim 38218887Sdim if (!ToPTy) 39218887Sdim return; 40218887Sdim 41218887Sdim QualType ToPointeeTy = ToPTy->getPointeeType(); 42218887Sdim 43218887Sdim // Only perform the check if 'ToPointeeTy' is a complete type. 44218887Sdim if (ToPointeeTy->isIncompleteType()) 45218887Sdim return; 46218887Sdim 47234353Sdim ProgramStateRef state = C.getState(); 48234353Sdim const MemRegion *R = state->getSVal(E, C.getLocationContext()).getAsRegion(); 49218887Sdim if (R == 0) 50218887Sdim return; 51218887Sdim 52218887Sdim const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(R); 53218887Sdim if (SR == 0) 54218887Sdim return; 55218887Sdim 56218887Sdim SValBuilder &svalBuilder = C.getSValBuilder(); 57218887Sdim SVal extent = SR->getExtent(svalBuilder); 58218887Sdim const llvm::APSInt *extentInt = svalBuilder.getKnownValue(state, extent); 59218887Sdim if (!extentInt) 60218887Sdim return; 61218887Sdim 62218887Sdim CharUnits regionSize = CharUnits::fromQuantity(extentInt->getSExtValue()); 63218887Sdim CharUnits typeSize = C.getASTContext().getTypeSizeInChars(ToPointeeTy); 64218887Sdim 65218887Sdim // Ignore void, and a few other un-sizeable types. 66218887Sdim if (typeSize.isZero()) 67218887Sdim return; 68218887Sdim 69218887Sdim if (regionSize % typeSize != 0) { 70218887Sdim if (ExplodedNode *errorNode = C.generateSink()) { 71218887Sdim if (!BT) 72219077Sdim BT.reset(new BuiltinBug("Cast region with wrong size.", 73218887Sdim "Cast a region whose size is not a multiple of the" 74219077Sdim " destination type size.")); 75226633Sdim BugReport *R = new BugReport(*BT, BT->getDescription(), 76218887Sdim errorNode); 77218887Sdim R->addRange(CE->getSourceRange()); 78243830Sdim C.emitReport(R); 79218887Sdim } 80218887Sdim } 81218887Sdim} 82218887Sdim 83218887Sdim 84219077Sdimvoid ento::registerCastSizeChecker(CheckerManager &mgr) { 85219077Sdim mgr.registerChecker<CastSizeChecker>(); 86218887Sdim} 87