blob: 59ea9e0e84f58d06dc3721c4ae22a146cdaebfcd [file] [log] [blame]
Zhongxing Xuab280992010-05-25 04:59:19 +00001//=== CastSizeChecker.cpp ---------------------------------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// CastSizeChecker checks when casting a malloc'ed symbolic region to type T,
11// whether the size of the symbolic region is a multiple of the size of T.
12//
13//===----------------------------------------------------------------------===//
14#include "clang/AST/CharUnits.h"
15#include "clang/Checker/BugReporter/BugType.h"
16#include "clang/Checker/PathSensitive/CheckerVisitor.h"
17#include "GRExprEngineInternalChecks.h"
18
19using namespace clang;
20
21namespace {
22class CastSizeChecker : public CheckerVisitor<CastSizeChecker> {
23 BuiltinBug *BT;
24public:
25 CastSizeChecker() : BT(0) {}
26 static void *getTag();
27 void PreVisitCastExpr(CheckerContext &C, const CastExpr *B);
28};
29}
30
31void *CastSizeChecker::getTag() {
32 static int x;
33 return &x;
34}
35
36void CastSizeChecker::PreVisitCastExpr(CheckerContext &C, const CastExpr *CE) {
37 const Expr *E = CE->getSubExpr();
38 ASTContext &Ctx = C.getASTContext();
39 QualType ToTy = Ctx.getCanonicalType(CE->getType());
40 PointerType *ToPTy = dyn_cast<PointerType>(ToTy.getTypePtr());
41
42 if (!ToPTy)
43 return;
44
45 QualType ToPointeeTy = ToPTy->getPointeeType();
46
47 const MemRegion *R = C.getState()->getSVal(E).getAsRegion();
48 if (R == 0)
49 return;
50
51 const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(R);
52 if (SR == 0)
53 return;
54
55 llvm::Optional<SVal> V =
56 C.getEngine().getStoreManager().getExtent(C.getState(), SR);
57 if (!V)
58 return;
59
60 const nonloc::ConcreteInt *CI = dyn_cast<nonloc::ConcreteInt>(V);
61 if (!CI)
62 return;
63
64 CharUnits RegionSize = CharUnits::fromQuantity(CI->getValue().getSExtValue());
65 CharUnits TypeSize = C.getASTContext().getTypeSizeInChars(ToPointeeTy);
Jordy Rosec580f2e2010-06-20 04:30:57 +000066
67 // void, and a few other un-sizeable types
68 if (TypeSize.isZero())
69 return;
70
Zhongxing Xuab280992010-05-25 04:59:19 +000071 if (RegionSize % TypeSize != 0) {
72 if (ExplodedNode *N = C.GenerateSink()) {
73 if (!BT)
74 BT = new BuiltinBug("Cast region with wrong size.",
75 "Cast a region whose size is not a multiple of the"
76 " destination type size.");
77 RangedBugReport *R = new RangedBugReport(*BT, BT->getDescription(), N);
78 R->addRange(CE->getSourceRange());
79 C.EmitReport(R);
80 }
81 }
82}
83
84
85void clang::RegisterCastSizeChecker(GRExprEngine &Eng) {
86 Eng.registerCheck(new CastSizeChecker());
87}