1ab28099e3bd4859585ccb316f9f571c8c6b035fdZhongxing Xu//=== CastSizeChecker.cpp ---------------------------------------*- C++ -*-===// 2ab28099e3bd4859585ccb316f9f571c8c6b035fdZhongxing Xu// 3ab28099e3bd4859585ccb316f9f571c8c6b035fdZhongxing Xu// The LLVM Compiler Infrastructure 4ab28099e3bd4859585ccb316f9f571c8c6b035fdZhongxing Xu// 5ab28099e3bd4859585ccb316f9f571c8c6b035fdZhongxing Xu// This file is distributed under the University of Illinois Open Source 6ab28099e3bd4859585ccb316f9f571c8c6b035fdZhongxing Xu// License. See LICENSE.TXT for details. 7ab28099e3bd4859585ccb316f9f571c8c6b035fdZhongxing Xu// 8ab28099e3bd4859585ccb316f9f571c8c6b035fdZhongxing Xu//===----------------------------------------------------------------------===// 9ab28099e3bd4859585ccb316f9f571c8c6b035fdZhongxing Xu// 10ab28099e3bd4859585ccb316f9f571c8c6b035fdZhongxing Xu// CastSizeChecker checks when casting a malloc'ed symbolic region to type T, 11ab28099e3bd4859585ccb316f9f571c8c6b035fdZhongxing Xu// whether the size of the symbolic region is a multiple of the size of T. 12ab28099e3bd4859585ccb316f9f571c8c6b035fdZhongxing Xu// 13ab28099e3bd4859585ccb316f9f571c8c6b035fdZhongxing Xu//===----------------------------------------------------------------------===// 140d6b0c00823410c8d532fc15e40c9b62ae43a08bArgyrios Kyrtzidis#include "ClangSACheckers.h" 15ec8605f1d7ec846dbf51047bfd5c56d32d1ff91cArgyrios Kyrtzidis#include "clang/StaticAnalyzer/Core/Checker.h" 160d6b0c00823410c8d532fc15e40c9b62ae43a08bArgyrios Kyrtzidis#include "clang/StaticAnalyzer/Core/CheckerManager.h" 170d6b0c00823410c8d532fc15e40c9b62ae43a08bArgyrios Kyrtzidis#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" 189b663716449b618ba0390b1dbebc54fa8e971124Ted Kremenek#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" 190d6b0c00823410c8d532fc15e40c9b62ae43a08bArgyrios Kyrtzidis#include "clang/AST/CharUnits.h" 20ab28099e3bd4859585ccb316f9f571c8c6b035fdZhongxing Xu 21ab28099e3bd4859585ccb316f9f571c8c6b035fdZhongxing Xuusing namespace clang; 229ef6537a894c33003359b1f9b9676e9178e028b7Ted Kremenekusing namespace ento; 23ab28099e3bd4859585ccb316f9f571c8c6b035fdZhongxing Xu 24ab28099e3bd4859585ccb316f9f571c8c6b035fdZhongxing Xunamespace { 25ec8605f1d7ec846dbf51047bfd5c56d32d1ff91cArgyrios Kyrtzidisclass CastSizeChecker : public Checker< check::PreStmt<CastExpr> > { 260d6b0c00823410c8d532fc15e40c9b62ae43a08bArgyrios Kyrtzidis mutable llvm::OwningPtr<BuiltinBug> BT; 27ab28099e3bd4859585ccb316f9f571c8c6b035fdZhongxing Xupublic: 280d6b0c00823410c8d532fc15e40c9b62ae43a08bArgyrios Kyrtzidis void checkPreStmt(const CastExpr *CE, CheckerContext &C) const; 29ab28099e3bd4859585ccb316f9f571c8c6b035fdZhongxing Xu}; 30ab28099e3bd4859585ccb316f9f571c8c6b035fdZhongxing Xu} 31ab28099e3bd4859585ccb316f9f571c8c6b035fdZhongxing Xu 320d6b0c00823410c8d532fc15e40c9b62ae43a08bArgyrios Kyrtzidisvoid CastSizeChecker::checkPreStmt(const CastExpr *CE,CheckerContext &C) const { 33ab28099e3bd4859585ccb316f9f571c8c6b035fdZhongxing Xu const Expr *E = CE->getSubExpr(); 34ab28099e3bd4859585ccb316f9f571c8c6b035fdZhongxing Xu ASTContext &Ctx = C.getASTContext(); 35ab28099e3bd4859585ccb316f9f571c8c6b035fdZhongxing Xu QualType ToTy = Ctx.getCanonicalType(CE->getType()); 36f4c7371fb1d3cebcfb40abad4537bb82515704eaJohn McCall const PointerType *ToPTy = dyn_cast<PointerType>(ToTy.getTypePtr()); 37ab28099e3bd4859585ccb316f9f571c8c6b035fdZhongxing Xu 38ab28099e3bd4859585ccb316f9f571c8c6b035fdZhongxing Xu if (!ToPTy) 39ab28099e3bd4859585ccb316f9f571c8c6b035fdZhongxing Xu return; 40ab28099e3bd4859585ccb316f9f571c8c6b035fdZhongxing Xu 41ab28099e3bd4859585ccb316f9f571c8c6b035fdZhongxing Xu QualType ToPointeeTy = ToPTy->getPointeeType(); 42ab28099e3bd4859585ccb316f9f571c8c6b035fdZhongxing Xu 43f69cf18aa240b038dfd89f249e63f4cc6e1c5f65Ted Kremenek // Only perform the check if 'ToPointeeTy' is a complete type. 44f69cf18aa240b038dfd89f249e63f4cc6e1c5f65Ted Kremenek if (ToPointeeTy->isIncompleteType()) 45f69cf18aa240b038dfd89f249e63f4cc6e1c5f65Ted Kremenek return; 46f69cf18aa240b038dfd89f249e63f4cc6e1c5f65Ted Kremenek 4718c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek const ProgramState *state = C.getState(); 4832f2656b90900ac04c4b50e87c16749d0ceb9ef2Jordy Rose const MemRegion *R = state->getSVal(E).getAsRegion(); 49ab28099e3bd4859585ccb316f9f571c8c6b035fdZhongxing Xu if (R == 0) 50ab28099e3bd4859585ccb316f9f571c8c6b035fdZhongxing Xu return; 51ab28099e3bd4859585ccb316f9f571c8c6b035fdZhongxing Xu 52ab28099e3bd4859585ccb316f9f571c8c6b035fdZhongxing Xu const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(R); 53ab28099e3bd4859585ccb316f9f571c8c6b035fdZhongxing Xu if (SR == 0) 54ab28099e3bd4859585ccb316f9f571c8c6b035fdZhongxing Xu return; 55ab28099e3bd4859585ccb316f9f571c8c6b035fdZhongxing Xu 56c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek SValBuilder &svalBuilder = C.getSValBuilder(); 57c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek SVal extent = SR->getExtent(svalBuilder); 58c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek const llvm::APSInt *extentInt = svalBuilder.getKnownValue(state, extent); 59c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek if (!extentInt) 60ab28099e3bd4859585ccb316f9f571c8c6b035fdZhongxing Xu return; 61ab28099e3bd4859585ccb316f9f571c8c6b035fdZhongxing Xu 62c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek CharUnits regionSize = CharUnits::fromQuantity(extentInt->getSExtValue()); 63c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek CharUnits typeSize = C.getASTContext().getTypeSizeInChars(ToPointeeTy); 64c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek 6532f2656b90900ac04c4b50e87c16749d0ceb9ef2Jordy Rose // Ignore void, and a few other un-sizeable types. 66c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek if (typeSize.isZero()) 67c580f2e189810ae655c889536644470575bc551aJordy Rose return; 68c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek 69c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek if (regionSize % typeSize != 0) { 70d048c6ef5b6cfaa0cecb8cc1d4bdace32ed21d07Ted Kremenek if (ExplodedNode *errorNode = C.generateSink()) { 71ab28099e3bd4859585ccb316f9f571c8c6b035fdZhongxing Xu if (!BT) 720d6b0c00823410c8d532fc15e40c9b62ae43a08bArgyrios Kyrtzidis BT.reset(new BuiltinBug("Cast region with wrong size.", 73ab28099e3bd4859585ccb316f9f571c8c6b035fdZhongxing Xu "Cast a region whose size is not a multiple of the" 740d6b0c00823410c8d532fc15e40c9b62ae43a08bArgyrios Kyrtzidis " destination type size.")); 75e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks BugReport *R = new BugReport(*BT, BT->getDescription(), 76c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek errorNode); 77ab28099e3bd4859585ccb316f9f571c8c6b035fdZhongxing Xu R->addRange(CE->getSourceRange()); 78ab28099e3bd4859585ccb316f9f571c8c6b035fdZhongxing Xu C.EmitReport(R); 79ab28099e3bd4859585ccb316f9f571c8c6b035fdZhongxing Xu } 80ab28099e3bd4859585ccb316f9f571c8c6b035fdZhongxing Xu } 81ab28099e3bd4859585ccb316f9f571c8c6b035fdZhongxing Xu} 82ab28099e3bd4859585ccb316f9f571c8c6b035fdZhongxing Xu 83ab28099e3bd4859585ccb316f9f571c8c6b035fdZhongxing Xu 840d6b0c00823410c8d532fc15e40c9b62ae43a08bArgyrios Kyrtzidisvoid ento::registerCastSizeChecker(CheckerManager &mgr) { 850d6b0c00823410c8d532fc15e40c9b62ae43a08bArgyrios Kyrtzidis mgr.registerChecker<CastSizeChecker>(); 86ab28099e3bd4859585ccb316f9f571c8c6b035fdZhongxing Xu} 87