blob: 518cf963bef4b127ff562c5a4b16ca365e7f7dec [file] [log] [blame]
Zhongxing Xu658dd8b2010-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"
Ted Kremenekf8cbac42011-02-10 01:03:03 +000015#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
16#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.h"
Argyrios Kyrtzidisf99d5952011-02-08 22:30:02 +000017#include "InternalChecks.h"
Zhongxing Xu658dd8b2010-05-25 04:59:19 +000018
19using namespace clang;
Ted Kremenek98857c92010-12-23 07:20:52 +000020using namespace ento;
Zhongxing Xu658dd8b2010-05-25 04:59:19 +000021
22namespace {
23class CastSizeChecker : public CheckerVisitor<CastSizeChecker> {
24 BuiltinBug *BT;
25public:
26 CastSizeChecker() : BT(0) {}
27 static void *getTag();
28 void PreVisitCastExpr(CheckerContext &C, const CastExpr *B);
29};
30}
31
32void *CastSizeChecker::getTag() {
33 static int x;
34 return &x;
35}
36
37void 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());
John McCall424cec92011-01-19 06:33:43 +000041 const PointerType *ToPTy = dyn_cast<PointerType>(ToTy.getTypePtr());
Zhongxing Xu658dd8b2010-05-25 04:59:19 +000042
43 if (!ToPTy)
44 return;
45
46 QualType ToPointeeTy = ToPTy->getPointeeType();
47
Ted Kremenek026cb582010-09-01 20:35:38 +000048 // Only perform the check if 'ToPointeeTy' is a complete type.
49 if (ToPointeeTy->isIncompleteType())
50 return;
51
Jordy Rose674bd552010-07-04 00:00:41 +000052 const GRState *state = C.getState();
53 const MemRegion *R = state->getSVal(E).getAsRegion();
Zhongxing Xu658dd8b2010-05-25 04:59:19 +000054 if (R == 0)
55 return;
56
57 const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(R);
58 if (SR == 0)
59 return;
60
Ted Kremenek90af9092010-12-02 07:49:45 +000061 SValBuilder &svalBuilder = C.getSValBuilder();
62 SVal extent = SR->getExtent(svalBuilder);
63 const llvm::APSInt *extentInt = svalBuilder.getKnownValue(state, extent);
64 if (!extentInt)
Zhongxing Xu658dd8b2010-05-25 04:59:19 +000065 return;
66
Ted Kremenek90af9092010-12-02 07:49:45 +000067 CharUnits regionSize = CharUnits::fromQuantity(extentInt->getSExtValue());
68 CharUnits typeSize = C.getASTContext().getTypeSizeInChars(ToPointeeTy);
69
Jordy Rose674bd552010-07-04 00:00:41 +000070 // Ignore void, and a few other un-sizeable types.
Ted Kremenek90af9092010-12-02 07:49:45 +000071 if (typeSize.isZero())
Jordy Rose2dd9b022010-06-20 04:30:57 +000072 return;
Ted Kremenek90af9092010-12-02 07:49:45 +000073
74 if (regionSize % typeSize != 0) {
Ted Kremenek750b7ac2010-12-20 21:19:09 +000075 if (ExplodedNode *errorNode = C.generateSink()) {
Zhongxing Xu658dd8b2010-05-25 04:59:19 +000076 if (!BT)
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.");
Ted Kremenek90af9092010-12-02 07:49:45 +000080 RangedBugReport *R = new RangedBugReport(*BT, BT->getDescription(),
81 errorNode);
Zhongxing Xu658dd8b2010-05-25 04:59:19 +000082 R->addRange(CE->getSourceRange());
83 C.EmitReport(R);
84 }
85 }
86}
87
88
Ted Kremenek98857c92010-12-23 07:20:52 +000089void ento::RegisterCastSizeChecker(ExprEngine &Eng) {
Zhongxing Xu658dd8b2010-05-25 04:59:19 +000090 Eng.registerCheck(new CastSizeChecker());
91}