1 //=== CastSizeChecker.cpp ---------------------------------------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
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.
13 //===----------------------------------------------------------------------===//
14 #include "clang/AST/CharUnits.h"
15 #include "clang/GR/BugReporter/BugType.h"
16 #include "clang/GR/PathSensitive/CheckerVisitor.h"
17 #include "GRExprEngineInternalChecks.h"
19 using namespace clang
;
23 class CastSizeChecker
: public CheckerVisitor
<CastSizeChecker
> {
26 CastSizeChecker() : BT(0) {}
27 static void *getTag();
28 void PreVisitCastExpr(CheckerContext
&C
, const CastExpr
*B
);
32 void *CastSizeChecker::getTag() {
37 void CastSizeChecker::PreVisitCastExpr(CheckerContext
&C
, const CastExpr
*CE
) {
38 const Expr
*E
= CE
->getSubExpr();
39 ASTContext
&Ctx
= C
.getASTContext();
40 QualType ToTy
= Ctx
.getCanonicalType(CE
->getType());
41 PointerType
*ToPTy
= dyn_cast
<PointerType
>(ToTy
.getTypePtr());
46 QualType ToPointeeTy
= ToPTy
->getPointeeType();
48 // Only perform the check if 'ToPointeeTy' is a complete type.
49 if (ToPointeeTy
->isIncompleteType())
52 const GRState
*state
= C
.getState();
53 const MemRegion
*R
= state
->getSVal(E
).getAsRegion();
57 const SymbolicRegion
*SR
= dyn_cast
<SymbolicRegion
>(R
);
61 SValBuilder
&svalBuilder
= C
.getSValBuilder();
62 SVal extent
= SR
->getExtent(svalBuilder
);
63 const llvm::APSInt
*extentInt
= svalBuilder
.getKnownValue(state
, extent
);
67 CharUnits regionSize
= CharUnits::fromQuantity(extentInt
->getSExtValue());
68 CharUnits typeSize
= C
.getASTContext().getTypeSizeInChars(ToPointeeTy
);
70 // Ignore void, and a few other un-sizeable types.
71 if (typeSize
.isZero())
74 if (regionSize
% typeSize
!= 0) {
75 if (ExplodedNode
*errorNode
= C
.generateSink()) {
77 BT
= new BuiltinBug("Cast region with wrong size.",
78 "Cast a region whose size is not a multiple of the"
79 " destination type size.");
80 RangedBugReport
*R
= new RangedBugReport(*BT
, BT
->getDescription(),
82 R
->addRange(CE
->getSourceRange());
89 void GR::RegisterCastSizeChecker(GRExprEngine
&Eng
) {
90 Eng
.registerCheck(new CastSizeChecker());