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 675ffd83dbSDimitry 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 1525ffd83dbSDimitry 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 21106c3fb27SDimitry 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 23306c3fb27SDimitry 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 2640b57cec5SDimitry 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 3115ffd83dbSDimitry 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 3360b57cec5SDimitry Andric void ento::registerVLASizeChecker(CheckerManager &mgr) { 3370b57cec5SDimitry Andric mgr.registerChecker<VLASizeChecker>(); 3380b57cec5SDimitry Andric } 3390b57cec5SDimitry Andric 3405ffd83dbSDimitry Andric bool ento::shouldRegisterVLASizeChecker(const CheckerManager &mgr) { 3410b57cec5SDimitry Andric return true; 3420b57cec5SDimitry Andric } 343