1 //===--- UndefinedNewArraySizeChecker.cpp -----------------------*- C++ -*--==// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This defines UndefinedNewArraySizeChecker, a builtin check in ExprEngine 10 // that checks if the size of the array in a new[] expression is undefined. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h" 15 #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" 16 #include "clang/StaticAnalyzer/Core/Checker.h" 17 #include "clang/StaticAnalyzer/Core/CheckerManager.h" 18 #include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h" 19 #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" 20 21 using namespace clang; 22 using namespace ento; 23 24 namespace { 25 class UndefinedNewArraySizeChecker : public Checker<check::PreCall> { 26 27 private: 28 BugType BT{this, "Undefined array element count in new[]", 29 categories::LogicError}; 30 31 public: 32 void checkPreCall(const CallEvent &Call, CheckerContext &C) const; 33 void HandleUndefinedArrayElementCount(CheckerContext &C, SVal ArgVal, 34 const Expr *Init, 35 SourceRange Range) const; 36 }; 37 } // namespace 38 39 void UndefinedNewArraySizeChecker::checkPreCall(const CallEvent &Call, 40 CheckerContext &C) const { 41 if (const auto *AC = dyn_cast<CXXAllocatorCall>(&Call)) { 42 if (!AC->isArray()) 43 return; 44 45 auto *SizeEx = *AC->getArraySizeExpr(); 46 auto SizeVal = AC->getArraySizeVal(); 47 48 if (SizeVal.isUndef()) 49 HandleUndefinedArrayElementCount(C, SizeVal, SizeEx, 50 SizeEx->getSourceRange()); 51 } 52 } 53 54 void UndefinedNewArraySizeChecker::HandleUndefinedArrayElementCount( 55 CheckerContext &C, SVal ArgVal, const Expr *Init, SourceRange Range) const { 56 57 if (ExplodedNode *N = C.generateErrorNode()) { 58 59 SmallString<100> buf; 60 llvm::raw_svector_ostream os(buf); 61 62 os << "Element count in new[] is a garbage value"; 63 64 auto R = std::make_unique<PathSensitiveBugReport>(BT, os.str(), N); 65 R->markInteresting(ArgVal); 66 R->addRange(Range); 67 bugreporter::trackExpressionValue(N, Init, *R); 68 69 C.emitReport(std::move(R)); 70 } 71 } 72 73 void ento::registerUndefinedNewArraySizeChecker(CheckerManager &mgr) { 74 mgr.registerChecker<UndefinedNewArraySizeChecker>(); 75 } 76 77 bool ento::shouldRegisterUndefinedNewArraySizeChecker( 78 const CheckerManager &mgr) { 79 return mgr.getLangOpts().CPlusPlus; 80 } 81