blob: 936991d6133c051380a686b1246913734c5109e9 [file] [log] [blame]
Zhongxing Xu05a23382009-11-04 01:43:07 +00001//=== VLASizeChecker.cpp - Undefined dereference checker --------*- 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//
Ted Kremenekae162332009-11-07 03:56:57 +000010// This defines VLASizeChecker, a builtin check in GRExprEngine that
Zhongxing Xu05a23382009-11-04 01:43:07 +000011// performs checks for declaration of VLA of undefined or zero size.
Jordy Roseb2242d12010-07-06 23:33:54 +000012// In addition, VLASizeChecker is responsible for defining the extent
13// of the MemRegion that represents a VLA.
Zhongxing Xu05a23382009-11-04 01:43:07 +000014//
15//===----------------------------------------------------------------------===//
16
Ted Kremenek84b35952009-11-06 21:51:50 +000017#include "GRExprEngineInternalChecks.h"
Jordy Rose52e04c52010-07-05 00:50:15 +000018#include "clang/AST/CharUnits.h"
Benjamin Kramer5e2d2c22010-03-27 21:19:47 +000019#include "clang/Checker/BugReporter/BugType.h"
Ted Kremenek1309f9a2010-01-25 04:41:41 +000020#include "clang/Checker/PathSensitive/CheckerVisitor.h"
21#include "clang/Checker/PathSensitive/GRExprEngine.h"
Zhongxing Xu05a23382009-11-04 01:43:07 +000022
23using namespace clang;
24
Ted Kremenek84b35952009-11-06 21:51:50 +000025namespace {
Kovarththanan Rajaratnamba5fb5a2009-11-28 06:07:30 +000026class VLASizeChecker : public CheckerVisitor<VLASizeChecker> {
Ted Kremenekae162332009-11-07 03:56:57 +000027 BugType *BT_zero;
28 BugType *BT_undef;
Ted Kremenek84b35952009-11-06 21:51:50 +000029
30public:
Ted Kremenekae162332009-11-07 03:56:57 +000031 VLASizeChecker() : BT_zero(0), BT_undef(0) {}
32 static void *getTag() { static int tag = 0; return &tag; }
33 void PreVisitDeclStmt(CheckerContext &C, const DeclStmt *DS);
Ted Kremenek84b35952009-11-06 21:51:50 +000034};
35} // end anonymous namespace
36
37void clang::RegisterVLASizeChecker(GRExprEngine &Eng) {
Ted Kremenekae162332009-11-07 03:56:57 +000038 Eng.registerCheck(new VLASizeChecker());
Ted Kremenek84b35952009-11-06 21:51:50 +000039}
40
Ted Kremenekae162332009-11-07 03:56:57 +000041void VLASizeChecker::PreVisitDeclStmt(CheckerContext &C, const DeclStmt *DS) {
42 if (!DS->isSingleDecl())
43 return;
44
45 const VarDecl *VD = dyn_cast<VarDecl>(DS->getSingleDecl());
46 if (!VD)
47 return;
Jordy Rose52e04c52010-07-05 00:50:15 +000048
49 ASTContext &Ctx = C.getASTContext();
50 const VariableArrayType *VLA = Ctx.getAsVariableArrayType(VD->getType());
Ted Kremenekae162332009-11-07 03:56:57 +000051 if (!VLA)
52 return;
Zhongxing Xu05a23382009-11-04 01:43:07 +000053
Ted Kremenekae162332009-11-07 03:56:57 +000054 // FIXME: Handle multi-dimensional VLAs.
55 const Expr* SE = VLA->getSizeExpr();
56 const GRState *state = C.getState();
Ted Kremenek13976632010-02-08 16:18:51 +000057 SVal sizeV = state->getSVal(SE);
Zhongxing Xu05a23382009-11-04 01:43:07 +000058
Ted Kremenekae162332009-11-07 03:56:57 +000059 if (sizeV.isUndef()) {
60 // Generate an error node.
Ted Kremenek19d67b52009-11-23 22:22:01 +000061 ExplodedNode *N = C.GenerateSink();
Ted Kremenekae162332009-11-07 03:56:57 +000062 if (!N)
63 return;
64
65 if (!BT_undef)
66 BT_undef = new BuiltinBug("Declared variable-length array (VLA) uses a "
67 "garbage value as its size");
Zhongxing Xu05a23382009-11-04 01:43:07 +000068
Ted Kremenekae162332009-11-07 03:56:57 +000069 EnhancedBugReport *report =
Benjamin Kramerd02e2322009-11-14 12:08:24 +000070 new EnhancedBugReport(*BT_undef, BT_undef->getName(), N);
Ted Kremenekae162332009-11-07 03:56:57 +000071 report->addRange(SE->getSourceRange());
72 report->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, SE);
73 C.EmitReport(report);
74 return;
Zhongxing Xu05a23382009-11-04 01:43:07 +000075 }
Jordy Rose52e04c52010-07-05 00:50:15 +000076
77 // See if the size value is known. It can't be undefined because we would have
78 // warned about that already.
79 if (sizeV.isUnknown())
80 return;
Ted Kremenekae162332009-11-07 03:56:57 +000081
82 // Check if the size is zero.
Jordy Rose52e04c52010-07-05 00:50:15 +000083 DefinedSVal sizeD = cast<DefinedSVal>(sizeV);
Zhongxing Xu05a23382009-11-04 01:43:07 +000084
Ted Kremenekae162332009-11-07 03:56:57 +000085 const GRState *stateNotZero, *stateZero;
86 llvm::tie(stateNotZero, stateZero) = state->Assume(sizeD);
Zhongxing Xu05a23382009-11-04 01:43:07 +000087
Ted Kremenekae162332009-11-07 03:56:57 +000088 if (stateZero && !stateNotZero) {
Ted Kremenek19d67b52009-11-23 22:22:01 +000089 ExplodedNode* N = C.GenerateSink(stateZero);
Ted Kremenekae162332009-11-07 03:56:57 +000090 if (!BT_zero)
91 BT_zero = new BuiltinBug("Declared variable-length array (VLA) has zero "
92 "size");
Zhongxing Xu05a23382009-11-04 01:43:07 +000093
Ted Kremenekae162332009-11-07 03:56:57 +000094 EnhancedBugReport *report =
Benjamin Kramerd02e2322009-11-14 12:08:24 +000095 new EnhancedBugReport(*BT_zero, BT_zero->getName(), N);
Ted Kremenekae162332009-11-07 03:56:57 +000096 report->addRange(SE->getSourceRange());
97 report->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, SE);
98 C.EmitReport(report);
99 return;
Zhongxing Xu05a23382009-11-04 01:43:07 +0000100 }
Ted Kremenekae162332009-11-07 03:56:57 +0000101
102 // From this point on, assume that the size is not zero.
Jordy Rose52e04c52010-07-05 00:50:15 +0000103 state = stateNotZero;
104
Jordy Roseb2242d12010-07-06 23:33:54 +0000105 // VLASizeChecker is responsible for defining the extent of the array being
106 // declared. We do this by multiplying the array length by the element size,
107 // then matching that with the array region's extent symbol.
108
Jordy Rose52e04c52010-07-05 00:50:15 +0000109 // Convert the array length to size_t.
110 ValueManager &ValMgr = C.getValueManager();
111 SValuator &SV = ValMgr.getSValuator();
112 QualType SizeTy = Ctx.getSizeType();
113 NonLoc ArrayLength = cast<NonLoc>(SV.EvalCast(sizeD, SizeTy, SE->getType()));
114
115 // Get the element size.
116 CharUnits EleSize = Ctx.getTypeSizeInChars(VLA->getElementType());
117 SVal EleSizeVal = ValMgr.makeIntVal(EleSize.getQuantity(), SizeTy);
118
119 // Multiply the array length by the element size.
120 SVal ArraySizeVal = SV.EvalBinOpNN(state, BinaryOperator::Mul, ArrayLength,
121 cast<NonLoc>(EleSizeVal), SizeTy);
122
123 // Finally, Assume that the array's extent matches the given size.
124 const LocationContext *LC = C.getPredecessor()->getLocationContext();
125 DefinedOrUnknownSVal Extent = state->getRegion(VD, LC)->getExtent(ValMgr);
126 DefinedOrUnknownSVal ArraySize = cast<DefinedOrUnknownSVal>(ArraySizeVal);
127 DefinedOrUnknownSVal SizeIsKnown = SV.EvalEQ(state, Extent, ArraySize);
128 state = state->Assume(SizeIsKnown, true);
129
Zhongxing Xue4f5d722010-07-06 07:08:47 +0000130 // Assume should not fail at this point.
131 assert(state);
132
Jordy Rose52e04c52010-07-05 00:50:15 +0000133 // Remember our assumptions!
134 C.addTransition(state);
Zhongxing Xu05a23382009-11-04 01:43:07 +0000135}