blob: d4e9d3533983fe1566335c0c448d0d3066711732 [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"
Argyrios Kyrtzidis8d602a82010-12-22 18:51:49 +000019#include "clang/GR/BugReporter/BugType.h"
20#include "clang/GR/PathSensitive/CheckerVisitor.h"
21#include "clang/GR/PathSensitive/GRExprEngine.h"
Zhongxing Xu259d4642009-11-04 01:43:07 +000022
23using namespace clang;
Argyrios Kyrtzidisca08fba2010-12-22 18:53:20 +000024using namespace GR;
Zhongxing Xu259d4642009-11-04 01:43:07 +000025
Ted Kremenek795c6112009-11-06 21:51:50 +000026namespace {
Kovarththanan Rajaratnam65c65662009-11-28 06:07:30 +000027class VLASizeChecker : public CheckerVisitor<VLASizeChecker> {
Ted Kremenekae3361d2009-11-07 03:56:57 +000028 BugType *BT_zero;
29 BugType *BT_undef;
Ted Kremenek795c6112009-11-06 21:51:50 +000030
31public:
Ted Kremenekae3361d2009-11-07 03:56:57 +000032 VLASizeChecker() : BT_zero(0), BT_undef(0) {}
33 static void *getTag() { static int tag = 0; return &tag; }
34 void PreVisitDeclStmt(CheckerContext &C, const DeclStmt *DS);
Ted Kremenek795c6112009-11-06 21:51:50 +000035};
36} // end anonymous namespace
37
Argyrios Kyrtzidisca08fba2010-12-22 18:53:20 +000038void GR::RegisterVLASizeChecker(GRExprEngine &Eng) {
Ted Kremenekae3361d2009-11-07 03:56:57 +000039 Eng.registerCheck(new VLASizeChecker());
Ted Kremenek795c6112009-11-06 21:51:50 +000040}
41
Ted Kremenekae3361d2009-11-07 03:56:57 +000042void VLASizeChecker::PreVisitDeclStmt(CheckerContext &C, const DeclStmt *DS) {
43 if (!DS->isSingleDecl())
44 return;
45
46 const VarDecl *VD = dyn_cast<VarDecl>(DS->getSingleDecl());
47 if (!VD)
48 return;
Jordy Rosee6b999b2010-07-05 00:50:15 +000049
50 ASTContext &Ctx = C.getASTContext();
51 const VariableArrayType *VLA = Ctx.getAsVariableArrayType(VD->getType());
Ted Kremenekae3361d2009-11-07 03:56:57 +000052 if (!VLA)
53 return;
Zhongxing Xu259d4642009-11-04 01:43:07 +000054
Ted Kremenekae3361d2009-11-07 03:56:57 +000055 // FIXME: Handle multi-dimensional VLAs.
56 const Expr* SE = VLA->getSizeExpr();
57 const GRState *state = C.getState();
Ted Kremenek57f09892010-02-08 16:18:51 +000058 SVal sizeV = state->getSVal(SE);
Zhongxing Xu259d4642009-11-04 01:43:07 +000059
Ted Kremenekae3361d2009-11-07 03:56:57 +000060 if (sizeV.isUndef()) {
61 // Generate an error node.
Ted Kremenek750b7ac2010-12-20 21:19:09 +000062 ExplodedNode *N = C.generateSink();
Ted Kremenekae3361d2009-11-07 03:56:57 +000063 if (!N)
64 return;
65
66 if (!BT_undef)
67 BT_undef = new BuiltinBug("Declared variable-length array (VLA) uses a "
68 "garbage value as its size");
Zhongxing Xu259d4642009-11-04 01:43:07 +000069
Ted Kremenekae3361d2009-11-07 03:56:57 +000070 EnhancedBugReport *report =
Benjamin Kramerf4c511b2009-11-14 12:08:24 +000071 new EnhancedBugReport(*BT_undef, BT_undef->getName(), N);
Ted Kremenekae3361d2009-11-07 03:56:57 +000072 report->addRange(SE->getSourceRange());
73 report->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, SE);
74 C.EmitReport(report);
75 return;
Zhongxing Xu259d4642009-11-04 01:43:07 +000076 }
Jordy Rosee6b999b2010-07-05 00:50:15 +000077
78 // See if the size value is known. It can't be undefined because we would have
79 // warned about that already.
80 if (sizeV.isUnknown())
81 return;
Ted Kremenekae3361d2009-11-07 03:56:57 +000082
83 // Check if the size is zero.
Jordy Rosee6b999b2010-07-05 00:50:15 +000084 DefinedSVal sizeD = cast<DefinedSVal>(sizeV);
Zhongxing Xu259d4642009-11-04 01:43:07 +000085
Ted Kremenekae3361d2009-11-07 03:56:57 +000086 const GRState *stateNotZero, *stateZero;
Ted Kremenekc5bea1e2010-12-01 22:16:56 +000087 llvm::tie(stateNotZero, stateZero) = state->assume(sizeD);
Zhongxing Xu259d4642009-11-04 01:43:07 +000088
Ted Kremenekae3361d2009-11-07 03:56:57 +000089 if (stateZero && !stateNotZero) {
Ted Kremenek750b7ac2010-12-20 21:19:09 +000090 ExplodedNode* N = C.generateSink(stateZero);
Ted Kremenekae3361d2009-11-07 03:56:57 +000091 if (!BT_zero)
92 BT_zero = new BuiltinBug("Declared variable-length array (VLA) has zero "
93 "size");
Zhongxing Xu259d4642009-11-04 01:43:07 +000094
Ted Kremenekae3361d2009-11-07 03:56:57 +000095 EnhancedBugReport *report =
Benjamin Kramerf4c511b2009-11-14 12:08:24 +000096 new EnhancedBugReport(*BT_zero, BT_zero->getName(), N);
Ted Kremenekae3361d2009-11-07 03:56:57 +000097 report->addRange(SE->getSourceRange());
98 report->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, SE);
99 C.EmitReport(report);
100 return;
Zhongxing Xu259d4642009-11-04 01:43:07 +0000101 }
Ted Kremenekae3361d2009-11-07 03:56:57 +0000102
103 // From this point on, assume that the size is not zero.
Jordy Rosee6b999b2010-07-05 00:50:15 +0000104 state = stateNotZero;
105
Jordy Rosecf781e52010-07-06 23:33:54 +0000106 // VLASizeChecker is responsible for defining the extent of the array being
107 // declared. We do this by multiplying the array length by the element size,
108 // then matching that with the array region's extent symbol.
109
Jordy Rosee6b999b2010-07-05 00:50:15 +0000110 // Convert the array length to size_t.
Ted Kremenek90af9092010-12-02 07:49:45 +0000111 SValBuilder &svalBuilder = C.getSValBuilder();
Jordy Rosee6b999b2010-07-05 00:50:15 +0000112 QualType SizeTy = Ctx.getSizeType();
Ted Kremenek90af9092010-12-02 07:49:45 +0000113 NonLoc ArrayLength = cast<NonLoc>(svalBuilder.evalCast(sizeD, SizeTy,
114 SE->getType()));
Jordy Rosee6b999b2010-07-05 00:50:15 +0000115
116 // Get the element size.
117 CharUnits EleSize = Ctx.getTypeSizeInChars(VLA->getElementType());
Ted Kremenek90af9092010-12-02 07:49:45 +0000118 SVal EleSizeVal = svalBuilder.makeIntVal(EleSize.getQuantity(), SizeTy);
Jordy Rosee6b999b2010-07-05 00:50:15 +0000119
120 // Multiply the array length by the element size.
Ted Kremenek90af9092010-12-02 07:49:45 +0000121 SVal ArraySizeVal = svalBuilder.evalBinOpNN(state, BO_Mul, ArrayLength,
122 cast<NonLoc>(EleSizeVal), SizeTy);
Jordy Rosee6b999b2010-07-05 00:50:15 +0000123
Ted Kremenekc5bea1e2010-12-01 22:16:56 +0000124 // Finally, assume that the array's extent matches the given size.
Jordy Rosee6b999b2010-07-05 00:50:15 +0000125 const LocationContext *LC = C.getPredecessor()->getLocationContext();
Ted Kremenek90af9092010-12-02 07:49:45 +0000126 DefinedOrUnknownSVal Extent =
127 state->getRegion(VD, LC)->getExtent(svalBuilder);
Jordy Rosee6b999b2010-07-05 00:50:15 +0000128 DefinedOrUnknownSVal ArraySize = cast<DefinedOrUnknownSVal>(ArraySizeVal);
Ted Kremenek90af9092010-12-02 07:49:45 +0000129 DefinedOrUnknownSVal sizeIsKnown =
130 svalBuilder.evalEQ(state, Extent, ArraySize);
131 state = state->assume(sizeIsKnown, true);
Jordy Rosee6b999b2010-07-05 00:50:15 +0000132
Zhongxing Xu5b488b12010-07-06 07:08:47 +0000133 // Assume should not fail at this point.
134 assert(state);
135
Jordy Rosee6b999b2010-07-05 00:50:15 +0000136 // Remember our assumptions!
137 C.addTransition(state);
Zhongxing Xu259d4642009-11-04 01:43:07 +0000138}