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