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