xref: /freebsd/contrib/llvm-project/clang/lib/StaticAnalyzer/Checkers/VLASizeChecker.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
10b57cec5SDimitry Andric //=== VLASizeChecker.cpp - Undefined dereference checker --------*- C++ -*-===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This defines VLASizeChecker, a builtin check in ExprEngine that
100b57cec5SDimitry Andric // performs checks for declaration of VLA of undefined or zero size.
110b57cec5SDimitry Andric // In addition, VLASizeChecker is responsible for defining the extent
120b57cec5SDimitry Andric // of the MemRegion that represents a VLA.
130b57cec5SDimitry Andric //
140b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
150b57cec5SDimitry Andric 
160b57cec5SDimitry Andric #include "clang/AST/CharUnits.h"
175ffd83dbSDimitry Andric #include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
1881ad6265SDimitry Andric #include "clang/StaticAnalyzer/Checkers/Taint.h"
190b57cec5SDimitry Andric #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
200b57cec5SDimitry Andric #include "clang/StaticAnalyzer/Core/Checker.h"
210b57cec5SDimitry Andric #include "clang/StaticAnalyzer/Core/CheckerManager.h"
220b57cec5SDimitry Andric #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
23fe6060f1SDimitry Andric #include "clang/StaticAnalyzer/Core/PathSensitive/DynamicExtent.h"
240b57cec5SDimitry Andric #include "llvm/ADT/STLExtras.h"
250b57cec5SDimitry Andric #include "llvm/ADT/SmallString.h"
260b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
27bdd1243dSDimitry Andric #include <optional>
280b57cec5SDimitry Andric 
290b57cec5SDimitry Andric using namespace clang;
300b57cec5SDimitry Andric using namespace ento;
310b57cec5SDimitry Andric using namespace taint;
320b57cec5SDimitry Andric 
330b57cec5SDimitry Andric namespace {
345ffd83dbSDimitry Andric class VLASizeChecker
355ffd83dbSDimitry Andric     : public Checker<check::PreStmt<DeclStmt>,
365ffd83dbSDimitry Andric                      check::PreStmt<UnaryExprOrTypeTraitExpr>> {
37647cbc5dSDimitry Andric   const BugType BT{this, "Dangerous variable-length array (VLA) declaration"};
38647cbc5dSDimitry Andric   const BugType TaintBT{this,
39647cbc5dSDimitry Andric                         "Dangerous variable-length array (VLA) declaration",
40647cbc5dSDimitry Andric                         categories::TaintedData};
4106c3fb27SDimitry Andric   enum VLASize_Kind { VLA_Garbage, VLA_Zero, VLA_Negative, VLA_Overflow };
425ffd83dbSDimitry Andric 
435ffd83dbSDimitry Andric   /// Check a VLA for validity.
445ffd83dbSDimitry Andric   /// Every dimension of the array and the total size is checked for validity.
455ffd83dbSDimitry Andric   /// Returns null or a new state where the size is validated.
465ffd83dbSDimitry Andric   /// 'ArraySize' will contain SVal that refers to the total size (in char)
475ffd83dbSDimitry Andric   /// of the array.
485ffd83dbSDimitry Andric   ProgramStateRef checkVLA(CheckerContext &C, ProgramStateRef State,
495ffd83dbSDimitry Andric                            const VariableArrayType *VLA, SVal &ArraySize) const;
505ffd83dbSDimitry Andric   /// Check a single VLA index size expression for validity.
515ffd83dbSDimitry Andric   ProgramStateRef checkVLAIndexSize(CheckerContext &C, ProgramStateRef State,
525ffd83dbSDimitry Andric                                     const Expr *SizeE) const;
530b57cec5SDimitry Andric 
540b57cec5SDimitry Andric   void reportBug(VLASize_Kind Kind, const Expr *SizeE, ProgramStateRef State,
5506c3fb27SDimitry Andric                  CheckerContext &C) const;
5606c3fb27SDimitry Andric 
5706c3fb27SDimitry Andric   void reportTaintBug(const Expr *SizeE, ProgramStateRef State,
5806c3fb27SDimitry Andric                       CheckerContext &C, SVal TaintedSVal) const;
590b57cec5SDimitry Andric 
600b57cec5SDimitry Andric public:
610b57cec5SDimitry Andric   void checkPreStmt(const DeclStmt *DS, CheckerContext &C) const;
625ffd83dbSDimitry Andric   void checkPreStmt(const UnaryExprOrTypeTraitExpr *UETTE,
635ffd83dbSDimitry Andric                     CheckerContext &C) const;
640b57cec5SDimitry Andric };
650b57cec5SDimitry Andric } // end anonymous namespace
660b57cec5SDimitry Andric 
checkVLA(CheckerContext & C,ProgramStateRef State,const VariableArrayType * VLA,SVal & ArraySize) const675ffd83dbSDimitry Andric ProgramStateRef VLASizeChecker::checkVLA(CheckerContext &C,
685ffd83dbSDimitry Andric                                          ProgramStateRef State,
695ffd83dbSDimitry Andric                                          const VariableArrayType *VLA,
705ffd83dbSDimitry Andric                                          SVal &ArraySize) const {
715ffd83dbSDimitry Andric   assert(VLA && "Function should be called with non-null VLA argument.");
725ffd83dbSDimitry Andric 
735ffd83dbSDimitry Andric   const VariableArrayType *VLALast = nullptr;
745ffd83dbSDimitry Andric   llvm::SmallVector<const Expr *, 2> VLASizes;
755ffd83dbSDimitry Andric 
765ffd83dbSDimitry Andric   // Walk over the VLAs for every dimension until a non-VLA is found.
775ffd83dbSDimitry Andric   // There is a VariableArrayType for every dimension (fixed or variable) until
785ffd83dbSDimitry Andric   // the most inner array that is variably modified.
795ffd83dbSDimitry Andric   // Dimension sizes are collected into 'VLASizes'. 'VLALast' is set to the
805ffd83dbSDimitry Andric   // innermost VLA that was encountered.
815ffd83dbSDimitry Andric   // In "int vla[x][2][y][3]" this will be the array for index "y" (with type
825ffd83dbSDimitry Andric   // int[3]). 'VLASizes' contains 'x', '2', and 'y'.
835ffd83dbSDimitry Andric   while (VLA) {
845ffd83dbSDimitry Andric     const Expr *SizeE = VLA->getSizeExpr();
855ffd83dbSDimitry Andric     State = checkVLAIndexSize(C, State, SizeE);
865ffd83dbSDimitry Andric     if (!State)
875ffd83dbSDimitry Andric       return nullptr;
885ffd83dbSDimitry Andric     VLASizes.push_back(SizeE);
895ffd83dbSDimitry Andric     VLALast = VLA;
905ffd83dbSDimitry Andric     VLA = C.getASTContext().getAsVariableArrayType(VLA->getElementType());
915ffd83dbSDimitry Andric   };
925ffd83dbSDimitry Andric   assert(VLALast &&
935ffd83dbSDimitry Andric          "Array should have at least one variably-modified dimension.");
945ffd83dbSDimitry Andric 
955ffd83dbSDimitry Andric   ASTContext &Ctx = C.getASTContext();
965ffd83dbSDimitry Andric   SValBuilder &SVB = C.getSValBuilder();
975ffd83dbSDimitry Andric   CanQualType SizeTy = Ctx.getSizeType();
985ffd83dbSDimitry Andric   uint64_t SizeMax =
995ffd83dbSDimitry Andric       SVB.getBasicValueFactory().getMaxValue(SizeTy).getZExtValue();
1005ffd83dbSDimitry Andric 
1015ffd83dbSDimitry Andric   // Get the element size.
1025ffd83dbSDimitry Andric   CharUnits EleSize = Ctx.getTypeSizeInChars(VLALast->getElementType());
1035ffd83dbSDimitry Andric   NonLoc ArrSize =
1045ffd83dbSDimitry Andric       SVB.makeIntVal(EleSize.getQuantity(), SizeTy).castAs<NonLoc>();
1055ffd83dbSDimitry Andric 
1065ffd83dbSDimitry Andric   // Try to calculate the known real size of the array in KnownSize.
1075ffd83dbSDimitry Andric   uint64_t KnownSize = 0;
1085ffd83dbSDimitry Andric   if (const llvm::APSInt *KV = SVB.getKnownValue(State, ArrSize))
1095ffd83dbSDimitry Andric     KnownSize = KV->getZExtValue();
1105ffd83dbSDimitry Andric 
1115ffd83dbSDimitry Andric   for (const Expr *SizeE : VLASizes) {
1125ffd83dbSDimitry Andric     auto SizeD = C.getSVal(SizeE).castAs<DefinedSVal>();
1135ffd83dbSDimitry Andric     // Convert the array length to size_t.
1145ffd83dbSDimitry Andric     NonLoc IndexLength =
1155ffd83dbSDimitry Andric         SVB.evalCast(SizeD, SizeTy, SizeE->getType()).castAs<NonLoc>();
1165ffd83dbSDimitry Andric     // Multiply the array length by the element size.
1175ffd83dbSDimitry Andric     SVal Mul = SVB.evalBinOpNN(State, BO_Mul, ArrSize, IndexLength, SizeTy);
1185ffd83dbSDimitry Andric     if (auto MulNonLoc = Mul.getAs<NonLoc>())
1195ffd83dbSDimitry Andric       ArrSize = *MulNonLoc;
1205ffd83dbSDimitry Andric     else
1215ffd83dbSDimitry Andric       // Extent could not be determined.
1225ffd83dbSDimitry Andric       return State;
1235ffd83dbSDimitry Andric 
1245ffd83dbSDimitry Andric     if (const llvm::APSInt *IndexLVal = SVB.getKnownValue(State, IndexLength)) {
1255ffd83dbSDimitry Andric       // Check if the array size will overflow.
1265ffd83dbSDimitry Andric       // Size overflow check does not work with symbolic expressions because a
1275ffd83dbSDimitry Andric       // overflow situation can not be detected easily.
1285ffd83dbSDimitry Andric       uint64_t IndexL = IndexLVal->getZExtValue();
1295ffd83dbSDimitry Andric       // FIXME: See https://reviews.llvm.org/D80903 for discussion of
1305ffd83dbSDimitry Andric       // some difference in assume and getKnownValue that leads to
1315ffd83dbSDimitry Andric       // unexpected behavior. Just bail on IndexL == 0 at this point.
1325ffd83dbSDimitry Andric       if (IndexL == 0)
1335ffd83dbSDimitry Andric         return nullptr;
1345ffd83dbSDimitry Andric 
1355ffd83dbSDimitry Andric       if (KnownSize <= SizeMax / IndexL) {
1365ffd83dbSDimitry Andric         KnownSize *= IndexL;
1375ffd83dbSDimitry Andric       } else {
1385ffd83dbSDimitry Andric         // Array size does not fit into size_t.
1395ffd83dbSDimitry Andric         reportBug(VLA_Overflow, SizeE, State, C);
1405ffd83dbSDimitry Andric         return nullptr;
1415ffd83dbSDimitry Andric       }
1425ffd83dbSDimitry Andric     } else {
1435ffd83dbSDimitry Andric       KnownSize = 0;
1445ffd83dbSDimitry Andric     }
1455ffd83dbSDimitry Andric   }
1465ffd83dbSDimitry Andric 
1475ffd83dbSDimitry Andric   ArraySize = ArrSize;
1485ffd83dbSDimitry Andric 
1495ffd83dbSDimitry Andric   return State;
1505ffd83dbSDimitry Andric }
1515ffd83dbSDimitry Andric 
checkVLAIndexSize(CheckerContext & C,ProgramStateRef State,const Expr * SizeE) const1525ffd83dbSDimitry Andric ProgramStateRef VLASizeChecker::checkVLAIndexSize(CheckerContext &C,
1535ffd83dbSDimitry Andric                                                   ProgramStateRef State,
1545ffd83dbSDimitry Andric                                                   const Expr *SizeE) const {
1555ffd83dbSDimitry Andric   SVal SizeV = C.getSVal(SizeE);
1565ffd83dbSDimitry Andric 
1575ffd83dbSDimitry Andric   if (SizeV.isUndef()) {
1585ffd83dbSDimitry Andric     reportBug(VLA_Garbage, SizeE, State, C);
1595ffd83dbSDimitry Andric     return nullptr;
1605ffd83dbSDimitry Andric   }
1615ffd83dbSDimitry Andric 
1625ffd83dbSDimitry Andric   // See if the size value is known. It can't be undefined because we would have
1635ffd83dbSDimitry Andric   // warned about that already.
1645ffd83dbSDimitry Andric   if (SizeV.isUnknown())
1655ffd83dbSDimitry Andric     return nullptr;
1665ffd83dbSDimitry Andric 
1675ffd83dbSDimitry Andric   // Check if the size is zero.
1685ffd83dbSDimitry Andric   DefinedSVal SizeD = SizeV.castAs<DefinedSVal>();
1695ffd83dbSDimitry Andric 
1705ffd83dbSDimitry Andric   ProgramStateRef StateNotZero, StateZero;
1715ffd83dbSDimitry Andric   std::tie(StateNotZero, StateZero) = State->assume(SizeD);
1725ffd83dbSDimitry Andric 
1735ffd83dbSDimitry Andric   if (StateZero && !StateNotZero) {
1745ffd83dbSDimitry Andric     reportBug(VLA_Zero, SizeE, StateZero, C);
1755ffd83dbSDimitry Andric     return nullptr;
1765ffd83dbSDimitry Andric   }
1775ffd83dbSDimitry Andric 
1785ffd83dbSDimitry Andric   // From this point on, assume that the size is not zero.
1795ffd83dbSDimitry Andric   State = StateNotZero;
1805ffd83dbSDimitry Andric 
1815ffd83dbSDimitry Andric   // Check if the size is negative.
1825ffd83dbSDimitry Andric   SValBuilder &SVB = C.getSValBuilder();
1835ffd83dbSDimitry Andric 
1845ffd83dbSDimitry Andric   QualType SizeTy = SizeE->getType();
1855ffd83dbSDimitry Andric   DefinedOrUnknownSVal Zero = SVB.makeZeroVal(SizeTy);
1865ffd83dbSDimitry Andric 
1875f757f3fSDimitry Andric   SVal LessThanZeroVal =
1885f757f3fSDimitry Andric       SVB.evalBinOp(State, BO_LT, SizeD, Zero, SVB.getConditionType());
189*0fca6ea1SDimitry Andric   ProgramStateRef StatePos, StateNeg;
190bdd1243dSDimitry Andric   if (std::optional<DefinedSVal> LessThanZeroDVal =
1915ffd83dbSDimitry Andric           LessThanZeroVal.getAs<DefinedSVal>()) {
1925ffd83dbSDimitry Andric     ConstraintManager &CM = C.getConstraintManager();
1935ffd83dbSDimitry Andric 
1945ffd83dbSDimitry Andric     std::tie(StateNeg, StatePos) = CM.assumeDual(State, *LessThanZeroDVal);
1955ffd83dbSDimitry Andric     if (StateNeg && !StatePos) {
1965ffd83dbSDimitry Andric       reportBug(VLA_Negative, SizeE, State, C);
1975ffd83dbSDimitry Andric       return nullptr;
1985ffd83dbSDimitry Andric     }
1995ffd83dbSDimitry Andric     State = StatePos;
2005ffd83dbSDimitry Andric   }
2015ffd83dbSDimitry Andric 
202*0fca6ea1SDimitry Andric   // Check if the size is tainted.
203*0fca6ea1SDimitry Andric   if ((StateNeg || StateZero) && isTainted(State, SizeV)) {
204*0fca6ea1SDimitry Andric     reportTaintBug(SizeE, State, C, SizeV);
205*0fca6ea1SDimitry Andric     return nullptr;
206*0fca6ea1SDimitry Andric   }
207*0fca6ea1SDimitry Andric 
2085ffd83dbSDimitry Andric   return State;
2095ffd83dbSDimitry Andric }
2105ffd83dbSDimitry Andric 
reportTaintBug(const Expr * SizeE,ProgramStateRef State,CheckerContext & C,SVal TaintedSVal) const21106c3fb27SDimitry Andric void VLASizeChecker::reportTaintBug(const Expr *SizeE, ProgramStateRef State,
21206c3fb27SDimitry Andric                                     CheckerContext &C, SVal TaintedSVal) const {
21306c3fb27SDimitry Andric   // Generate an error node.
21406c3fb27SDimitry Andric   ExplodedNode *N = C.generateErrorNode(State);
21506c3fb27SDimitry Andric   if (!N)
21606c3fb27SDimitry Andric     return;
21706c3fb27SDimitry Andric 
21806c3fb27SDimitry Andric   SmallString<256> buf;
21906c3fb27SDimitry Andric   llvm::raw_svector_ostream os(buf);
22006c3fb27SDimitry Andric   os << "Declared variable-length array (VLA) ";
221*0fca6ea1SDimitry Andric   os << "has tainted (attacker controlled) size that can be 0 or negative";
22206c3fb27SDimitry Andric 
223647cbc5dSDimitry Andric   auto report = std::make_unique<PathSensitiveBugReport>(TaintBT, os.str(), N);
22406c3fb27SDimitry Andric   report->addRange(SizeE->getSourceRange());
22506c3fb27SDimitry Andric   bugreporter::trackExpressionValue(N, SizeE, *report);
22606c3fb27SDimitry Andric   // The vla size may be a complex expression where multiple memory locations
22706c3fb27SDimitry Andric   // are tainted.
22806c3fb27SDimitry Andric   for (auto Sym : getTaintedSymbols(State, TaintedSVal))
22906c3fb27SDimitry Andric     report->markInteresting(Sym);
23006c3fb27SDimitry Andric   C.emitReport(std::move(report));
23106c3fb27SDimitry Andric }
23206c3fb27SDimitry Andric 
reportBug(VLASize_Kind Kind,const Expr * SizeE,ProgramStateRef State,CheckerContext & C) const23306c3fb27SDimitry Andric void VLASizeChecker::reportBug(VLASize_Kind Kind, const Expr *SizeE,
23406c3fb27SDimitry Andric                                ProgramStateRef State, CheckerContext &C) const {
2350b57cec5SDimitry Andric   // Generate an error node.
2360b57cec5SDimitry Andric   ExplodedNode *N = C.generateErrorNode(State);
2370b57cec5SDimitry Andric   if (!N)
2380b57cec5SDimitry Andric     return;
2390b57cec5SDimitry Andric 
2400b57cec5SDimitry Andric   SmallString<256> buf;
2410b57cec5SDimitry Andric   llvm::raw_svector_ostream os(buf);
2420b57cec5SDimitry Andric   os << "Declared variable-length array (VLA) ";
2430b57cec5SDimitry Andric   switch (Kind) {
2440b57cec5SDimitry Andric   case VLA_Garbage:
2450b57cec5SDimitry Andric     os << "uses a garbage value as its size";
2460b57cec5SDimitry Andric     break;
2470b57cec5SDimitry Andric   case VLA_Zero:
2480b57cec5SDimitry Andric     os << "has zero size";
2490b57cec5SDimitry Andric     break;
2500b57cec5SDimitry Andric   case VLA_Negative:
2510b57cec5SDimitry Andric     os << "has negative size";
2520b57cec5SDimitry Andric     break;
2535ffd83dbSDimitry Andric   case VLA_Overflow:
2545ffd83dbSDimitry Andric     os << "has too large size";
2555ffd83dbSDimitry Andric     break;
2560b57cec5SDimitry Andric   }
2570b57cec5SDimitry Andric 
258647cbc5dSDimitry Andric   auto report = std::make_unique<PathSensitiveBugReport>(BT, os.str(), N);
2590b57cec5SDimitry Andric   report->addRange(SizeE->getSourceRange());
2600b57cec5SDimitry Andric   bugreporter::trackExpressionValue(N, SizeE, *report);
2610b57cec5SDimitry Andric   C.emitReport(std::move(report));
2620b57cec5SDimitry Andric }
2630b57cec5SDimitry Andric 
checkPreStmt(const DeclStmt * DS,CheckerContext & C) const2640b57cec5SDimitry Andric void VLASizeChecker::checkPreStmt(const DeclStmt *DS, CheckerContext &C) const {
2650b57cec5SDimitry Andric   if (!DS->isSingleDecl())
2660b57cec5SDimitry Andric     return;
2670b57cec5SDimitry Andric 
2685ffd83dbSDimitry Andric   ASTContext &Ctx = C.getASTContext();
2695ffd83dbSDimitry Andric   SValBuilder &SVB = C.getSValBuilder();
2705ffd83dbSDimitry Andric   ProgramStateRef State = C.getState();
2715ffd83dbSDimitry Andric   QualType TypeToCheck;
2725ffd83dbSDimitry Andric 
2730b57cec5SDimitry Andric   const VarDecl *VD = dyn_cast<VarDecl>(DS->getSingleDecl());
2745ffd83dbSDimitry Andric 
2755ffd83dbSDimitry Andric   if (VD)
2765ffd83dbSDimitry Andric     TypeToCheck = VD->getType().getCanonicalType();
2775ffd83dbSDimitry Andric   else if (const auto *TND = dyn_cast<TypedefNameDecl>(DS->getSingleDecl()))
2785ffd83dbSDimitry Andric     TypeToCheck = TND->getUnderlyingType().getCanonicalType();
2795ffd83dbSDimitry Andric   else
2800b57cec5SDimitry Andric     return;
2810b57cec5SDimitry Andric 
2825ffd83dbSDimitry Andric   const VariableArrayType *VLA = Ctx.getAsVariableArrayType(TypeToCheck);
2830b57cec5SDimitry Andric   if (!VLA)
2840b57cec5SDimitry Andric     return;
2850b57cec5SDimitry Andric 
2865ffd83dbSDimitry Andric   // Check the VLA sizes for validity.
2870b57cec5SDimitry Andric 
2885ffd83dbSDimitry Andric   SVal ArraySize;
2895ffd83dbSDimitry Andric 
2905ffd83dbSDimitry Andric   State = checkVLA(C, State, VLA, ArraySize);
2915ffd83dbSDimitry Andric   if (!State)
2925ffd83dbSDimitry Andric     return;
2935ffd83dbSDimitry Andric 
29481ad6265SDimitry Andric   if (!isa<NonLoc>(ArraySize)) {
2955ffd83dbSDimitry Andric     // Array size could not be determined but state may contain new assumptions.
2965ffd83dbSDimitry Andric     C.addTransition(State);
2970b57cec5SDimitry Andric     return;
2980b57cec5SDimitry Andric   }
2990b57cec5SDimitry Andric 
300fe6060f1SDimitry Andric   // VLASizeChecker is responsible for defining the extent of the array.
3015ffd83dbSDimitry Andric   if (VD) {
302fe6060f1SDimitry Andric     State =
303fe6060f1SDimitry Andric         setDynamicExtent(State, State->getRegion(VD, C.getLocationContext()),
30481ad6265SDimitry Andric                          ArraySize.castAs<NonLoc>(), SVB);
3055ffd83dbSDimitry Andric   }
3060b57cec5SDimitry Andric 
3070b57cec5SDimitry Andric   // Remember our assumptions!
3085ffd83dbSDimitry Andric   C.addTransition(State);
3095ffd83dbSDimitry Andric }
3105ffd83dbSDimitry Andric 
checkPreStmt(const UnaryExprOrTypeTraitExpr * UETTE,CheckerContext & C) const3115ffd83dbSDimitry Andric void VLASizeChecker::checkPreStmt(const UnaryExprOrTypeTraitExpr *UETTE,
3125ffd83dbSDimitry Andric                                   CheckerContext &C) const {
3135ffd83dbSDimitry Andric   // Want to check for sizeof.
3145ffd83dbSDimitry Andric   if (UETTE->getKind() != UETT_SizeOf)
3155ffd83dbSDimitry Andric     return;
3165ffd83dbSDimitry Andric 
3175ffd83dbSDimitry Andric   // Ensure a type argument.
3185ffd83dbSDimitry Andric   if (!UETTE->isArgumentType())
3195ffd83dbSDimitry Andric     return;
3205ffd83dbSDimitry Andric 
3215ffd83dbSDimitry Andric   const VariableArrayType *VLA = C.getASTContext().getAsVariableArrayType(
3225ffd83dbSDimitry Andric       UETTE->getTypeOfArgument().getCanonicalType());
3235ffd83dbSDimitry Andric   // Ensure that the type is a VLA.
3245ffd83dbSDimitry Andric   if (!VLA)
3255ffd83dbSDimitry Andric     return;
3265ffd83dbSDimitry Andric 
3275ffd83dbSDimitry Andric   ProgramStateRef State = C.getState();
3285ffd83dbSDimitry Andric   SVal ArraySize;
3295ffd83dbSDimitry Andric   State = checkVLA(C, State, VLA, ArraySize);
3305ffd83dbSDimitry Andric   if (!State)
3315ffd83dbSDimitry Andric     return;
3325ffd83dbSDimitry Andric 
3335ffd83dbSDimitry Andric   C.addTransition(State);
3340b57cec5SDimitry Andric }
3350b57cec5SDimitry Andric 
registerVLASizeChecker(CheckerManager & mgr)3360b57cec5SDimitry Andric void ento::registerVLASizeChecker(CheckerManager &mgr) {
3370b57cec5SDimitry Andric   mgr.registerChecker<VLASizeChecker>();
3380b57cec5SDimitry Andric }
3390b57cec5SDimitry Andric 
shouldRegisterVLASizeChecker(const CheckerManager & mgr)3405ffd83dbSDimitry Andric bool ento::shouldRegisterVLASizeChecker(const CheckerManager &mgr) {
3410b57cec5SDimitry Andric   return true;
3420b57cec5SDimitry Andric }
343