UndefinedNewArraySizeChecker.cpp 2.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  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. #include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
  14. #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
  15. #include "clang/StaticAnalyzer/Core/Checker.h"
  16. #include "clang/StaticAnalyzer/Core/CheckerManager.h"
  17. #include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
  18. #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
  19. using namespace clang;
  20. using namespace ento;
  21. namespace {
  22. class UndefinedNewArraySizeChecker : public Checker<check::PreCall> {
  23. private:
  24. BugType BT{this, "Undefined array element count in new[]",
  25. categories::LogicError};
  26. public:
  27. void checkPreCall(const CallEvent &Call, CheckerContext &C) const;
  28. void HandleUndefinedArrayElementCount(CheckerContext &C, SVal ArgVal,
  29. const Expr *Init,
  30. SourceRange Range) const;
  31. };
  32. } // namespace
  33. void UndefinedNewArraySizeChecker::checkPreCall(const CallEvent &Call,
  34. CheckerContext &C) const {
  35. if (const auto *AC = dyn_cast<CXXAllocatorCall>(&Call)) {
  36. if (!AC->isArray())
  37. return;
  38. auto *SizeEx = *AC->getArraySizeExpr();
  39. auto SizeVal = AC->getArraySizeVal();
  40. if (SizeVal.isUndef())
  41. HandleUndefinedArrayElementCount(C, SizeVal, SizeEx,
  42. SizeEx->getSourceRange());
  43. }
  44. }
  45. void UndefinedNewArraySizeChecker::HandleUndefinedArrayElementCount(
  46. CheckerContext &C, SVal ArgVal, const Expr *Init, SourceRange Range) const {
  47. if (ExplodedNode *N = C.generateErrorNode()) {
  48. SmallString<100> buf;
  49. llvm::raw_svector_ostream os(buf);
  50. os << "Element count in new[] is a garbage value";
  51. auto R = std::make_unique<PathSensitiveBugReport>(BT, os.str(), N);
  52. R->markInteresting(ArgVal);
  53. R->addRange(Range);
  54. bugreporter::trackExpressionValue(N, Init, *R);
  55. C.emitReport(std::move(R));
  56. }
  57. }
  58. void ento::registerUndefinedNewArraySizeChecker(CheckerManager &mgr) {
  59. mgr.registerChecker<UndefinedNewArraySizeChecker>();
  60. }
  61. bool ento::shouldRegisterUndefinedNewArraySizeChecker(
  62. const CheckerManager &mgr) {
  63. return mgr.getLangOpts().CPlusPlus;
  64. }