================
@@ -0,0 +1,339 @@
+//===- DestroyedAsWrongTypeChecker.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
+//
+//===----------------------------------------------------------------------===//
+//
+// Defines a checker that finds storage reused by placement new for an object
+// of a different type and then destroyed or deleted as the original type
+// (C++ [basic.life]p11, [expr.delete]p3).
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/AST/ExprCXX.h"
+#include "clang/Analysis/CFG.h"
+#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"
+#include <optional>
+
+using namespace clang;
+using namespace ento;
+
+namespace {
+struct WrongDestruction {
+  QualType Placed;
+  const CXXRecordDecl *DtorClass;
+  const CXXDeleteExpr *Delete;
+
+  bool operator==(const WrongDestruction &X) const {
+    return Placed == X.Placed && DtorClass == X.DtorClass && Delete == 
X.Delete;
+  }
+  void Profile(llvm::FoldingSetNodeID &ID) const {
+    ID.Add(Placed);
+    ID.AddPointer(DtorClass);
+    ID.AddPointer(Delete);
+  }
+};
+} // namespace
+
+REGISTER_MAP_WITH_PROGRAMSTATE(PlacedObjectTypes, const MemRegion *, QualType)
+REGISTER_SET_WITH_PROGRAMSTATE(NewAllocatedObjects, const MemRegion *)
+REGISTER_MAP_WITH_PROGRAMSTATE(PendingDestructions, const MemRegion *,
+                               WrongDestruction)
+
+namespace {
+class DestroyedAsWrongTypeChecker
+    : public Checker<check::PostStmt<CXXNewExpr>, check::PreCall,
+                     check::PostCall, check::DeadSymbols> {
+  const BugType BT{this, "Object destroyed as a type it no longer has",
+                   categories::MemoryError};
+
+  void reportBug(const MemRegion *R, const WrongDestruction &W,
+                 CheckerContext &C) const;
+  void reportOrDefer(const MemRegion *R, const WrongDestruction &W,
+                     CheckerContext &C) const;
+
+public:
+  void checkPostStmt(const CXXNewExpr *NE, CheckerContext &C) const;
+  void checkPreCall(const CallEvent &Call, CheckerContext &C) const;
+  void checkPostCall(const CallEvent &Call, CheckerContext &C) const;
+  void checkDeadSymbols(SymbolReaper &SR, CheckerContext &C) const;
+};
+} // namespace
+
+// An array is keyed by its first element, the object its destructor gets.
+static const MemRegion *getStorageRegion(SVal V, CheckerContext &C) {
+  const MemRegion *R = V.getAsRegion();
+  if (!R)
+    return nullptr;
+  R = R->StripCasts();
+  ASTContext &Ctx = C.getASTContext();
+  while (const auto *TR = dyn_cast<TypedValueRegion>(R)) {
+    const ArrayType *AT = Ctx.getAsArrayType(TR->getValueType());
+    if (!AT)
+      break;
+    R = C.getStoreManager().getRegionManager().getElementRegion(
+        AT->getElementType(), C.getSValBuilder().makeZeroArrayIndex(), TR, 
Ctx);
----------------
NagyDonat wrote:

```suggestion
    R = C.getStoreManager().GetElementZeroRegion(TR, AT->getElementType());
```
It turns out that `StoreManager` provides a shortcut for this đŸ˜…. (I 
thought/hoped that perhaps it would have a method `getElementRegion` as a 
trivial wrapper around `RegionManager::getElementRegion`, but I found this 
instead.)

_The analyzer has too many random manager/factory/etc. singletons and scattered 
helper methods; it is difficult to notice that we have a specific tool for 
something._

https://github.com/llvm/llvm-project/pull/237801
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to