VLASizeChecker.cpp revision 0bd6b110e908892d4b5c8671a9f435a1d72ad16a
105a2338f7ba1c8a0136e120502f80a38cf0e9fd3Zhongxing Xu//=== VLASizeChecker.cpp - Undefined dereference checker --------*- C++ -*-===//
205a2338f7ba1c8a0136e120502f80a38cf0e9fd3Zhongxing Xu//
305a2338f7ba1c8a0136e120502f80a38cf0e9fd3Zhongxing Xu//                     The LLVM Compiler Infrastructure
405a2338f7ba1c8a0136e120502f80a38cf0e9fd3Zhongxing Xu//
505a2338f7ba1c8a0136e120502f80a38cf0e9fd3Zhongxing Xu// This file is distributed under the University of Illinois Open Source
605a2338f7ba1c8a0136e120502f80a38cf0e9fd3Zhongxing Xu// License. See LICENSE.TXT for details.
705a2338f7ba1c8a0136e120502f80a38cf0e9fd3Zhongxing Xu//
805a2338f7ba1c8a0136e120502f80a38cf0e9fd3Zhongxing Xu//===----------------------------------------------------------------------===//
905a2338f7ba1c8a0136e120502f80a38cf0e9fd3Zhongxing Xu//
10d2592a34a059e7cbb2b11dc53649ac4912422909Argyrios Kyrtzidis// This defines VLASizeChecker, a builtin check in ExprEngine that
1105a2338f7ba1c8a0136e120502f80a38cf0e9fd3Zhongxing Xu// performs checks for declaration of VLA of undefined or zero size.
12b2242d1b6fe4ae073361e6d8f3db751c95159ca5Jordy Rose// In addition, VLASizeChecker is responsible for defining the extent
13b2242d1b6fe4ae073361e6d8f3db751c95159ca5Jordy Rose// of the MemRegion that represents a VLA.
1405a2338f7ba1c8a0136e120502f80a38cf0e9fd3Zhongxing Xu//
1505a2338f7ba1c8a0136e120502f80a38cf0e9fd3Zhongxing Xu//===----------------------------------------------------------------------===//
1605a2338f7ba1c8a0136e120502f80a38cf0e9fd3Zhongxing Xu
173ce2b48461115af047ee1e957e1892af255bf120Argyrios Kyrtzidis#include "ClangSACheckers.h"
18ec8605f1d7ec846dbf51047bfd5c56d32d1ff91cArgyrios Kyrtzidis#include "clang/StaticAnalyzer/Core/Checker.h"
193ce2b48461115af047ee1e957e1892af255bf120Argyrios Kyrtzidis#include "clang/StaticAnalyzer/Core/CheckerManager.h"
203ce2b48461115af047ee1e957e1892af255bf120Argyrios Kyrtzidis#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
219b663716449b618ba0390b1dbebc54fa8e971124Ted Kremenek#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
223ce2b48461115af047ee1e957e1892af255bf120Argyrios Kyrtzidis#include "clang/AST/CharUnits.h"
2305a2338f7ba1c8a0136e120502f80a38cf0e9fd3Zhongxing Xu
2405a2338f7ba1c8a0136e120502f80a38cf0e9fd3Zhongxing Xuusing namespace clang;
259ef6537a894c33003359b1f9b9676e9178e028b7Ted Kremenekusing namespace ento;
2605a2338f7ba1c8a0136e120502f80a38cf0e9fd3Zhongxing Xu
2784b3595729d249d89b8b67a547e0992797e19793Ted Kremeneknamespace {
28ec8605f1d7ec846dbf51047bfd5c56d32d1ff91cArgyrios Kyrtzidisclass VLASizeChecker : public Checker< check::PreStmt<DeclStmt> > {
293ce2b48461115af047ee1e957e1892af255bf120Argyrios Kyrtzidis  mutable llvm::OwningPtr<BugType> BT_zero;
303ce2b48461115af047ee1e957e1892af255bf120Argyrios Kyrtzidis  mutable llvm::OwningPtr<BugType> BT_undef;
3184b3595729d249d89b8b67a547e0992797e19793Ted Kremenek
3284b3595729d249d89b8b67a547e0992797e19793Ted Kremenekpublic:
333ce2b48461115af047ee1e957e1892af255bf120Argyrios Kyrtzidis  void checkPreStmt(const DeclStmt *DS, CheckerContext &C) const;
3484b3595729d249d89b8b67a547e0992797e19793Ted Kremenek};
3584b3595729d249d89b8b67a547e0992797e19793Ted Kremenek} // end anonymous namespace
3684b3595729d249d89b8b67a547e0992797e19793Ted Kremenek
373ce2b48461115af047ee1e957e1892af255bf120Argyrios Kyrtzidisvoid VLASizeChecker::checkPreStmt(const DeclStmt *DS, CheckerContext &C) const {
38ae1623345aed43dcd2e069970a00618378a37b34Ted Kremenek  if (!DS->isSingleDecl())
39ae1623345aed43dcd2e069970a00618378a37b34Ted Kremenek    return;
40ae1623345aed43dcd2e069970a00618378a37b34Ted Kremenek
41ae1623345aed43dcd2e069970a00618378a37b34Ted Kremenek  const VarDecl *VD = dyn_cast<VarDecl>(DS->getSingleDecl());
42ae1623345aed43dcd2e069970a00618378a37b34Ted Kremenek  if (!VD)
43ae1623345aed43dcd2e069970a00618378a37b34Ted Kremenek    return;
4452e04c537633377fb14cfa4fa3c95e3e510fc942Jordy Rose
4552e04c537633377fb14cfa4fa3c95e3e510fc942Jordy Rose  ASTContext &Ctx = C.getASTContext();
4652e04c537633377fb14cfa4fa3c95e3e510fc942Jordy Rose  const VariableArrayType *VLA = Ctx.getAsVariableArrayType(VD->getType());
47ae1623345aed43dcd2e069970a00618378a37b34Ted Kremenek  if (!VLA)
48ae1623345aed43dcd2e069970a00618378a37b34Ted Kremenek    return;
49ae1623345aed43dcd2e069970a00618378a37b34Ted Kremenek
50ae1623345aed43dcd2e069970a00618378a37b34Ted Kremenek  // FIXME: Handle multi-dimensional VLAs.
519c378f705405d37f49795d5e915989de774fe11fTed Kremenek  const Expr *SE = VLA->getSizeExpr();
5218c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek  const ProgramState *state = C.getState();
531397663af9dbcc24dbf0e11de43931b3dc08fdbbTed Kremenek  SVal sizeV = state->getSVal(SE);
54ae1623345aed43dcd2e069970a00618378a37b34Ted Kremenek
55ae1623345aed43dcd2e069970a00618378a37b34Ted Kremenek  if (sizeV.isUndef()) {
56ae1623345aed43dcd2e069970a00618378a37b34Ted Kremenek    // Generate an error node.
57d048c6ef5b6cfaa0cecb8cc1d4bdace32ed21d07Ted Kremenek    ExplodedNode *N = C.generateSink();
58ae1623345aed43dcd2e069970a00618378a37b34Ted Kremenek    if (!N)
59ae1623345aed43dcd2e069970a00618378a37b34Ted Kremenek      return;
60ae1623345aed43dcd2e069970a00618378a37b34Ted Kremenek
61ae1623345aed43dcd2e069970a00618378a37b34Ted Kremenek    if (!BT_undef)
623ce2b48461115af047ee1e957e1892af255bf120Argyrios Kyrtzidis      BT_undef.reset(new BuiltinBug("Declared variable-length array (VLA) "
633ce2b48461115af047ee1e957e1892af255bf120Argyrios Kyrtzidis                                    "uses a garbage value as its size"));
64ae1623345aed43dcd2e069970a00618378a37b34Ted Kremenek
65e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks    BugReport *report =
66e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks      new BugReport(*BT_undef, BT_undef->getName(), N);
67ae1623345aed43dcd2e069970a00618378a37b34Ted Kremenek    report->addRange(SE->getSourceRange());
6850bbc165b063155cc23c360deb7b865502e068e2Anna Zaks    report->addVisitor(bugreporter::getTrackNullOrUndefValueVisitor(N, SE));
69ae1623345aed43dcd2e069970a00618378a37b34Ted Kremenek    C.EmitReport(report);
70ae1623345aed43dcd2e069970a00618378a37b34Ted Kremenek    return;
7105a2338f7ba1c8a0136e120502f80a38cf0e9fd3Zhongxing Xu  }
7252e04c537633377fb14cfa4fa3c95e3e510fc942Jordy Rose
7352e04c537633377fb14cfa4fa3c95e3e510fc942Jordy Rose  // See if the size value is known. It can't be undefined because we would have
7452e04c537633377fb14cfa4fa3c95e3e510fc942Jordy Rose  // warned about that already.
7552e04c537633377fb14cfa4fa3c95e3e510fc942Jordy Rose  if (sizeV.isUnknown())
7652e04c537633377fb14cfa4fa3c95e3e510fc942Jordy Rose    return;
77ae1623345aed43dcd2e069970a00618378a37b34Ted Kremenek
78ae1623345aed43dcd2e069970a00618378a37b34Ted Kremenek  // Check if the size is zero.
7952e04c537633377fb14cfa4fa3c95e3e510fc942Jordy Rose  DefinedSVal sizeD = cast<DefinedSVal>(sizeV);
80ae1623345aed43dcd2e069970a00618378a37b34Ted Kremenek
8118c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek  const ProgramState *stateNotZero, *stateZero;
8228f47b92e760ccf641ac91cb0fe1c12d9ca89795Ted Kremenek  llvm::tie(stateNotZero, stateZero) = state->assume(sizeD);
83ae1623345aed43dcd2e069970a00618378a37b34Ted Kremenek
84ae1623345aed43dcd2e069970a00618378a37b34Ted Kremenek  if (stateZero && !stateNotZero) {
859c378f705405d37f49795d5e915989de774fe11fTed Kremenek    ExplodedNode *N = C.generateSink(stateZero);
86ae1623345aed43dcd2e069970a00618378a37b34Ted Kremenek    if (!BT_zero)
873ce2b48461115af047ee1e957e1892af255bf120Argyrios Kyrtzidis      BT_zero.reset(new BuiltinBug("Declared variable-length array (VLA) has "
883ce2b48461115af047ee1e957e1892af255bf120Argyrios Kyrtzidis                                   "zero size"));
89ae1623345aed43dcd2e069970a00618378a37b34Ted Kremenek
90e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks    BugReport *report =
91e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks      new BugReport(*BT_zero, BT_zero->getName(), N);
92ae1623345aed43dcd2e069970a00618378a37b34Ted Kremenek    report->addRange(SE->getSourceRange());
9350bbc165b063155cc23c360deb7b865502e068e2Anna Zaks    report->addVisitor(bugreporter::getTrackNullOrUndefValueVisitor(N, SE));
94ae1623345aed43dcd2e069970a00618378a37b34Ted Kremenek    C.EmitReport(report);
95ae1623345aed43dcd2e069970a00618378a37b34Ted Kremenek    return;
9605a2338f7ba1c8a0136e120502f80a38cf0e9fd3Zhongxing Xu  }
97ae1623345aed43dcd2e069970a00618378a37b34Ted Kremenek
98ae1623345aed43dcd2e069970a00618378a37b34Ted Kremenek  // From this point on, assume that the size is not zero.
9952e04c537633377fb14cfa4fa3c95e3e510fc942Jordy Rose  state = stateNotZero;
10052e04c537633377fb14cfa4fa3c95e3e510fc942Jordy Rose
101b2242d1b6fe4ae073361e6d8f3db751c95159ca5Jordy Rose  // VLASizeChecker is responsible for defining the extent of the array being
102b2242d1b6fe4ae073361e6d8f3db751c95159ca5Jordy Rose  // declared. We do this by multiplying the array length by the element size,
103b2242d1b6fe4ae073361e6d8f3db751c95159ca5Jordy Rose  // then matching that with the array region's extent symbol.
104b2242d1b6fe4ae073361e6d8f3db751c95159ca5Jordy Rose
10552e04c537633377fb14cfa4fa3c95e3e510fc942Jordy Rose  // Convert the array length to size_t.
106c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek  SValBuilder &svalBuilder = C.getSValBuilder();
10752e04c537633377fb14cfa4fa3c95e3e510fc942Jordy Rose  QualType SizeTy = Ctx.getSizeType();
108c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek  NonLoc ArrayLength = cast<NonLoc>(svalBuilder.evalCast(sizeD, SizeTy,
109c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek                                                         SE->getType()));
11052e04c537633377fb14cfa4fa3c95e3e510fc942Jordy Rose
11152e04c537633377fb14cfa4fa3c95e3e510fc942Jordy Rose  // Get the element size.
11252e04c537633377fb14cfa4fa3c95e3e510fc942Jordy Rose  CharUnits EleSize = Ctx.getTypeSizeInChars(VLA->getElementType());
113c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek  SVal EleSizeVal = svalBuilder.makeIntVal(EleSize.getQuantity(), SizeTy);
11452e04c537633377fb14cfa4fa3c95e3e510fc942Jordy Rose
11552e04c537633377fb14cfa4fa3c95e3e510fc942Jordy Rose  // Multiply the array length by the element size.
116c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek  SVal ArraySizeVal = svalBuilder.evalBinOpNN(state, BO_Mul, ArrayLength,
117c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek                                              cast<NonLoc>(EleSizeVal), SizeTy);
11852e04c537633377fb14cfa4fa3c95e3e510fc942Jordy Rose
11928f47b92e760ccf641ac91cb0fe1c12d9ca89795Ted Kremenek  // Finally, assume that the array's extent matches the given size.
12052e04c537633377fb14cfa4fa3c95e3e510fc942Jordy Rose  const LocationContext *LC = C.getPredecessor()->getLocationContext();
121c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek  DefinedOrUnknownSVal Extent =
122c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek    state->getRegion(VD, LC)->getExtent(svalBuilder);
12352e04c537633377fb14cfa4fa3c95e3e510fc942Jordy Rose  DefinedOrUnknownSVal ArraySize = cast<DefinedOrUnknownSVal>(ArraySizeVal);
124c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek  DefinedOrUnknownSVal sizeIsKnown =
125c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek    svalBuilder.evalEQ(state, Extent, ArraySize);
126c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek  state = state->assume(sizeIsKnown, true);
12752e04c537633377fb14cfa4fa3c95e3e510fc942Jordy Rose
128e4f5d72a504be32483aebdeb48fd2effce6756f2Zhongxing Xu  // Assume should not fail at this point.
129e4f5d72a504be32483aebdeb48fd2effce6756f2Zhongxing Xu  assert(state);
130e4f5d72a504be32483aebdeb48fd2effce6756f2Zhongxing Xu
13152e04c537633377fb14cfa4fa3c95e3e510fc942Jordy Rose  // Remember our assumptions!
1320bd6b110e908892d4b5c8671a9f435a1d72ad16aAnna Zaks  C.addTransition(state);
13305a2338f7ba1c8a0136e120502f80a38cf0e9fd3Zhongxing Xu}
1343ce2b48461115af047ee1e957e1892af255bf120Argyrios Kyrtzidis
1353ce2b48461115af047ee1e957e1892af255bf120Argyrios Kyrtzidisvoid ento::registerVLASizeChecker(CheckerManager &mgr) {
1363ce2b48461115af047ee1e957e1892af255bf120Argyrios Kyrtzidis  mgr.registerChecker<VLASizeChecker>();
1373ce2b48461115af047ee1e957e1892af255bf120Argyrios Kyrtzidis}
138