blob: 2b79797f7e1f4109069470c4779711a92a7711a1 [file] [log] [blame]
Zhongxing Xu259d4642009-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 Kremenekae3361d2009-11-07 03:56:57 +000010// This defines VLASizeChecker, a builtin check in GRExprEngine that
Zhongxing Xu259d4642009-11-04 01:43:07 +000011// performs checks for declaration of VLA of undefined or zero size.
Jordy Rosecf781e52010-07-06 23:33:54 +000012// In addition, VLASizeChecker is responsible for defining the extent
13// of the MemRegion that represents a VLA.
Zhongxing Xu259d4642009-11-04 01:43:07 +000014//
15//===----------------------------------------------------------------------===//
16
Ted Kremenek795c6112009-11-06 21:51:50 +000017#include "GRExprEngineInternalChecks.h"
Jordy Rosee6b999b2010-07-05 00:50:15 +000018#include "clang/AST/CharUnits.h"
Benjamin Kramerc0483222010-03-27 21:19:47 +000019#include "clang/Checker/BugReporter/BugType.h"
Ted Kremenekd6b87082010-01-25 04:41:41 +000020#include "clang/Checker/PathSensitive/CheckerVisitor.h"
21#include "clang/Checker/PathSensitive/GRExprEngine.h"
Zhongxing Xu259d4642009-11-04 01:43:07 +000022
23using namespace clang;
24
Ted Kremenek795c6112009-11-06 21:51:50 +000025namespace {
Kovarththanan Rajaratnam65c65662009-11-28 06:07:30 +000026class VLASizeChecker : public CheckerVisitor<VLASizeChecker> {
Ted Kremenekae3361d2009-11-07 03:56:57 +000027 BugType *BT_zero;
28 BugType *BT_undef;
Ted Kremenek795c6112009-11-06 21:51:50 +000029
30public:
Ted Kremenekae3361d2009-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 Kremenek795c6112009-11-06 21:51:50 +000034};
35} // end anonymous namespace
36
37void clang::RegisterVLASizeChecker(GRExprEngine &Eng) {
Ted Kremenekae3361d2009-11-07 03:56:57 +000038 Eng.registerCheck(new VLASizeChecker());
Ted Kremenek795c6112009-11-06 21:51:50 +000039}
40
Ted Kremenekae3361d2009-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 Rosee6b999b2010-07-05 00:50:15 +000048
49 ASTContext &Ctx = C.getASTContext();
50 const VariableArrayType *VLA = Ctx.getAsVariableArrayType(VD->getType());
Ted Kremenekae3361d2009-11-07 03:56:57 +000051 if (!VLA)
52 return;
Zhongxing Xu259d4642009-11-04 01:43:07 +000053
Ted Kremenekae3361d2009-11-07 03:56:57 +000054 // FIXME: Handle multi-dimensional VLAs.
55 const Expr* SE = VLA->getSizeExpr();
56 const GRState *state = C.getState();
Ted Kremenek57f09892010-02-08 16:18:51 +000057 SVal sizeV = state->getSVal(SE);
Zhongxing Xu259d4642009-11-04 01:43:07 +000058
Ted Kremenekae3361d2009-11-07 03:56:57 +000059 if (sizeV.isUndef()) {
60 // Generate an error node.
Ted Kremenekf5735152009-11-23 22:22:01 +000061 ExplodedNode *N = C.GenerateSink();
Ted Kremenekae3361d2009-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 Xu259d4642009-11-04 01:43:07 +000068
Ted Kremenekae3361d2009-11-07 03:56:57 +000069 EnhancedBugReport *report =
Benjamin Kramerf4c511b2009-11-14 12:08:24 +000070 new EnhancedBugReport(*BT_undef, BT_undef->getName(), N);
Ted Kremenekae3361d2009-11-07 03:56:57 +000071 report->addRange(SE->getSourceRange());
72 report->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, SE);
73 C.EmitReport(report);
74 return;
Zhongxing Xu259d4642009-11-04 01:43:07 +000075 }
Jordy Rosee6b999b2010-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 Kremenekae3361d2009-11-07 03:56:57 +000081
82 // Check if the size is zero.
Jordy Rosee6b999b2010-07-05 00:50:15 +000083 DefinedSVal sizeD = cast<DefinedSVal>(sizeV);
Zhongxing Xu259d4642009-11-04 01:43:07 +000084
Ted Kremenekae3361d2009-11-07 03:56:57 +000085 const GRState *stateNotZero, *stateZero;
Ted Kremenekc5bea1e2010-12-01 22:16:56 +000086 llvm::tie(stateNotZero, stateZero) = state->assume(sizeD);
Zhongxing Xu259d4642009-11-04 01:43:07 +000087
Ted Kremenekae3361d2009-11-07 03:56:57 +000088 if (stateZero && !stateNotZero) {
Ted Kremenekf5735152009-11-23 22:22:01 +000089 ExplodedNode* N = C.GenerateSink(stateZero);
Ted Kremenekae3361d2009-11-07 03:56:57 +000090 if (!BT_zero)
91 BT_zero = new BuiltinBug("Declared variable-length array (VLA) has zero "
92 "size");
Zhongxing Xu259d4642009-11-04 01:43:07 +000093
Ted Kremenekae3361d2009-11-07 03:56:57 +000094 EnhancedBugReport *report =
Benjamin Kramerf4c511b2009-11-14 12:08:24 +000095 new EnhancedBugReport(*BT_zero, BT_zero->getName(), N);
Ted Kremenekae3361d2009-11-07 03:56:57 +000096 report->addRange(SE->getSourceRange());
97 report->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, SE);
98 C.EmitReport(report);
99 return;
Zhongxing Xu259d4642009-11-04 01:43:07 +0000100 }
Ted Kremenekae3361d2009-11-07 03:56:57 +0000101
102 // From this point on, assume that the size is not zero.
Jordy Rosee6b999b2010-07-05 00:50:15 +0000103 state = stateNotZero;
104
Jordy Rosecf781e52010-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 Rosee6b999b2010-07-05 00:50:15 +0000109 // Convert the array length to size_t.
110 ValueManager &ValMgr = C.getValueManager();
Ted Kremenek9d0bb1e2010-12-01 21:28:31 +0000111 SValBuilder &SV = ValMgr.getSValBuilder();
Jordy Rosee6b999b2010-07-05 00:50:15 +0000112 QualType SizeTy = Ctx.getSizeType();
Ted Kremenekdc891422010-12-01 21:57:22 +0000113 NonLoc ArrayLength = cast<NonLoc>(SV.evalCast(sizeD, SizeTy, SE->getType()));
Jordy Rosee6b999b2010-07-05 00:50:15 +0000114
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.
Ted Kremenekdc891422010-12-01 21:57:22 +0000120 SVal ArraySizeVal = SV.evalBinOpNN(state, BO_Mul, ArrayLength,
Jordy Rosee6b999b2010-07-05 00:50:15 +0000121 cast<NonLoc>(EleSizeVal), SizeTy);
122
Ted Kremenekc5bea1e2010-12-01 22:16:56 +0000123 // Finally, assume that the array's extent matches the given size.
Jordy Rosee6b999b2010-07-05 00:50:15 +0000124 const LocationContext *LC = C.getPredecessor()->getLocationContext();
125 DefinedOrUnknownSVal Extent = state->getRegion(VD, LC)->getExtent(ValMgr);
126 DefinedOrUnknownSVal ArraySize = cast<DefinedOrUnknownSVal>(ArraySizeVal);
Ted Kremenekdc891422010-12-01 21:57:22 +0000127 DefinedOrUnknownSVal SizeIsKnown = SV.evalEQ(state, Extent, ArraySize);
Ted Kremenekc5bea1e2010-12-01 22:16:56 +0000128 state = state->assume(SizeIsKnown, true);
Jordy Rosee6b999b2010-07-05 00:50:15 +0000129
Zhongxing Xu5b488b12010-07-06 07:08:47 +0000130 // Assume should not fail at this point.
131 assert(state);
132
Jordy Rosee6b999b2010-07-05 00:50:15 +0000133 // Remember our assumptions!
134 C.addTransition(state);
Zhongxing Xu259d4642009-11-04 01:43:07 +0000135}