blob: cea9d191aa77c41465414d0769b3adad225a6aa0 [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.
12//
13//===----------------------------------------------------------------------===//
14
Ted Kremenek84b35952009-11-06 21:51:50 +000015#include "GRExprEngineInternalChecks.h"
Benjamin Kramer5e2d2c22010-03-27 21:19:47 +000016#include "clang/Checker/BugReporter/BugType.h"
Ted Kremenek1309f9a2010-01-25 04:41:41 +000017#include "clang/Checker/PathSensitive/CheckerVisitor.h"
18#include "clang/Checker/PathSensitive/GRExprEngine.h"
Zhongxing Xu05a23382009-11-04 01:43:07 +000019
20using namespace clang;
21
Ted Kremenek84b35952009-11-06 21:51:50 +000022namespace {
Kovarththanan Rajaratnamba5fb5a2009-11-28 06:07:30 +000023class VLASizeChecker : public CheckerVisitor<VLASizeChecker> {
Ted Kremenekae162332009-11-07 03:56:57 +000024 BugType *BT_zero;
25 BugType *BT_undef;
Ted Kremenek84b35952009-11-06 21:51:50 +000026
27public:
Ted Kremenekae162332009-11-07 03:56:57 +000028 VLASizeChecker() : BT_zero(0), BT_undef(0) {}
29 static void *getTag() { static int tag = 0; return &tag; }
30 void PreVisitDeclStmt(CheckerContext &C, const DeclStmt *DS);
Ted Kremenek84b35952009-11-06 21:51:50 +000031};
32} // end anonymous namespace
33
34void clang::RegisterVLASizeChecker(GRExprEngine &Eng) {
Ted Kremenekae162332009-11-07 03:56:57 +000035 Eng.registerCheck(new VLASizeChecker());
Ted Kremenek84b35952009-11-06 21:51:50 +000036}
37
Ted Kremenekae162332009-11-07 03:56:57 +000038void VLASizeChecker::PreVisitDeclStmt(CheckerContext &C, const DeclStmt *DS) {
39 if (!DS->isSingleDecl())
40 return;
41
42 const VarDecl *VD = dyn_cast<VarDecl>(DS->getSingleDecl());
43 if (!VD)
44 return;
45
Douglas Gregor89c49f02009-11-09 22:08:55 +000046 const VariableArrayType *VLA
47 = C.getASTContext().getAsVariableArrayType(VD->getType());
Ted Kremenekae162332009-11-07 03:56:57 +000048 if (!VLA)
49 return;
Zhongxing Xu05a23382009-11-04 01:43:07 +000050
Ted Kremenekae162332009-11-07 03:56:57 +000051 // FIXME: Handle multi-dimensional VLAs.
52 const Expr* SE = VLA->getSizeExpr();
53 const GRState *state = C.getState();
Ted Kremenek13976632010-02-08 16:18:51 +000054 SVal sizeV = state->getSVal(SE);
Zhongxing Xu05a23382009-11-04 01:43:07 +000055
Ted Kremenekae162332009-11-07 03:56:57 +000056 if (sizeV.isUndef()) {
57 // Generate an error node.
Ted Kremenek19d67b52009-11-23 22:22:01 +000058 ExplodedNode *N = C.GenerateSink();
Ted Kremenekae162332009-11-07 03:56:57 +000059 if (!N)
60 return;
61
62 if (!BT_undef)
63 BT_undef = new BuiltinBug("Declared variable-length array (VLA) uses a "
64 "garbage value as its size");
Zhongxing Xu05a23382009-11-04 01:43:07 +000065
Ted Kremenekae162332009-11-07 03:56:57 +000066 EnhancedBugReport *report =
Benjamin Kramerd02e2322009-11-14 12:08:24 +000067 new EnhancedBugReport(*BT_undef, BT_undef->getName(), N);
Ted Kremenekae162332009-11-07 03:56:57 +000068 report->addRange(SE->getSourceRange());
69 report->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, SE);
70 C.EmitReport(report);
71 return;
Zhongxing Xu05a23382009-11-04 01:43:07 +000072 }
Ted Kremenekae162332009-11-07 03:56:57 +000073
74 // Check if the size is zero.
75 DefinedOrUnknownSVal sizeD = cast<DefinedOrUnknownSVal>(sizeV);
Zhongxing Xu05a23382009-11-04 01:43:07 +000076
Ted Kremenekae162332009-11-07 03:56:57 +000077 const GRState *stateNotZero, *stateZero;
78 llvm::tie(stateNotZero, stateZero) = state->Assume(sizeD);
Zhongxing Xu05a23382009-11-04 01:43:07 +000079
Ted Kremenekae162332009-11-07 03:56:57 +000080 if (stateZero && !stateNotZero) {
Ted Kremenek19d67b52009-11-23 22:22:01 +000081 ExplodedNode* N = C.GenerateSink(stateZero);
Ted Kremenekae162332009-11-07 03:56:57 +000082 if (!BT_zero)
83 BT_zero = new BuiltinBug("Declared variable-length array (VLA) has zero "
84 "size");
Zhongxing Xu05a23382009-11-04 01:43:07 +000085
Ted Kremenekae162332009-11-07 03:56:57 +000086 EnhancedBugReport *report =
Benjamin Kramerd02e2322009-11-14 12:08:24 +000087 new EnhancedBugReport(*BT_zero, BT_zero->getName(), N);
Ted Kremenekae162332009-11-07 03:56:57 +000088 report->addRange(SE->getSourceRange());
89 report->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, SE);
90 C.EmitReport(report);
91 return;
Zhongxing Xu05a23382009-11-04 01:43:07 +000092 }
Ted Kremenekae162332009-11-07 03:56:57 +000093
94 // From this point on, assume that the size is not zero.
Ted Kremenek19d67b52009-11-23 22:22:01 +000095 C.addTransition(stateNotZero);
Zhongxing Xu05a23382009-11-04 01:43:07 +000096}