blob: 1248d12c911a449dba7a73c3447f188c011e7c56 [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"
Argyrios Kyrtzidis98cabba2010-12-22 18:51:49 +000015#include "clang/GR/BugReporter/BugType.h"
16#include "clang/GR/PathSensitive/CheckerVisitor.h"
Zhongxing Xuab280992010-05-25 04:59:19 +000017#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
Ted Kremenekf69cf182010-09-01 20:35:38 +000047 // Only perform the check if 'ToPointeeTy' is a complete type.
48 if (ToPointeeTy->isIncompleteType())
49 return;
50
Jordy Rose32f26562010-07-04 00:00:41 +000051 const GRState *state = C.getState();
52 const MemRegion *R = state->getSVal(E).getAsRegion();
Zhongxing Xuab280992010-05-25 04:59:19 +000053 if (R == 0)
54 return;
55
56 const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(R);
57 if (SR == 0)
58 return;
59
Ted Kremenekc8413fd2010-12-02 07:49:45 +000060 SValBuilder &svalBuilder = C.getSValBuilder();
61 SVal extent = SR->getExtent(svalBuilder);
62 const llvm::APSInt *extentInt = svalBuilder.getKnownValue(state, extent);
63 if (!extentInt)
Zhongxing Xuab280992010-05-25 04:59:19 +000064 return;
65
Ted Kremenekc8413fd2010-12-02 07:49:45 +000066 CharUnits regionSize = CharUnits::fromQuantity(extentInt->getSExtValue());
67 CharUnits typeSize = C.getASTContext().getTypeSizeInChars(ToPointeeTy);
68
Jordy Rose32f26562010-07-04 00:00:41 +000069 // Ignore void, and a few other un-sizeable types.
Ted Kremenekc8413fd2010-12-02 07:49:45 +000070 if (typeSize.isZero())
Jordy Rosec580f2e2010-06-20 04:30:57 +000071 return;
Ted Kremenekc8413fd2010-12-02 07:49:45 +000072
73 if (regionSize % typeSize != 0) {
Ted Kremenekd048c6e2010-12-20 21:19:09 +000074 if (ExplodedNode *errorNode = C.generateSink()) {
Zhongxing Xuab280992010-05-25 04:59:19 +000075 if (!BT)
76 BT = new BuiltinBug("Cast region with wrong size.",
77 "Cast a region whose size is not a multiple of the"
78 " destination type size.");
Ted Kremenekc8413fd2010-12-02 07:49:45 +000079 RangedBugReport *R = new RangedBugReport(*BT, BT->getDescription(),
80 errorNode);
Zhongxing Xuab280992010-05-25 04:59:19 +000081 R->addRange(CE->getSourceRange());
82 C.EmitReport(R);
83 }
84 }
85}
86
87
88void clang::RegisterCastSizeChecker(GRExprEngine &Eng) {
89 Eng.registerCheck(new CastSizeChecker());
90}