================
@@ -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