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 
checkPreCall(const CallEvent & Call,CheckerContext & C) const39 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 
HandleUndefinedArrayElementCount(CheckerContext & C,SVal ArgVal,const Expr * Init,SourceRange Range) const54 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 
registerUndefinedNewArraySizeChecker(CheckerManager & mgr)73 void ento::registerUndefinedNewArraySizeChecker(CheckerManager &mgr) {
74   mgr.registerChecker<UndefinedNewArraySizeChecker>();
75 }
76 
shouldRegisterUndefinedNewArraySizeChecker(const CheckerManager & mgr)77 bool ento::shouldRegisterUndefinedNewArraySizeChecker(
78     const CheckerManager &mgr) {
79   return mgr.getLangOpts().CPlusPlus;
80 }
81