================
@@ -0,0 +1,163 @@
+//===- ContainerOfModeling.h ------------------------------------*- 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
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/StaticAnalyzer/Checkers/ContainerOfModeling.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/DynamicExtent.h"
+
+namespace clang::ento {
+
+static QualType getRegionObjectType(const MemRegion *Region) {
+  if (const auto *TVR = dyn_cast<TypedValueRegion>(Region))
+    return TVR->getValueType();
+  if (const auto *SR = dyn_cast<SymbolicRegion>(Region))
+    return SR->getPointeeStaticType();
+  return {};
+}
+
+/// Return true when the region containing \p ContainerRegion has type
+/// \p ContainerType. ElementRegion represents both array elements and casts,
+/// so the type of ContainerRegion itself is not sufficient evidence.
+static bool hasContainerTypeProvenance(const SubRegion *ContainerRegion,
+                                       QualType ContainerType,
+                                       ASTContext &Ctx) {
+  const MemRegion *StorageRegion = ContainerRegion;
+  if (const auto *ER = dyn_cast<ElementRegion>(ContainerRegion)) {
+    if (!ASTContext::hasSameUnqualifiedType(ER->getElementType(),
+                                            ContainerType))
+      return false;
+    StorageRegion = ER->getSuperRegion();
+  }
+
+  QualType StorageType = getRegionObjectType(StorageRegion);
+  if (StorageType.isNull())
+    return false;
+
+  if (const ArrayType *AT = Ctx.getAsArrayType(StorageType))
+    StorageType = AT->getElementType();
+
+  return ASTContext::hasSameUnqualifiedType(StorageType, ContainerType);
+}
+
+/// Return whether the concrete storage containing \p ContainerRegion is large
+/// enough to contain an object of \p ContainerType at that region's offset.
+/// Return std::nullopt when either the offset or the extent is symbolic.
+static std::optional<bool>
+hasSufficientContainerExtent(ProgramStateRef State,
+                             const SubRegion *ContainerRegion,
+                             QualType ContainerType, SValBuilder &SVB) {
+  ASTContext &Ctx = SVB.getContext();
+  RegionOffset Offset = ContainerRegion->getAsOffset();
+  if (!Offset.isValid() || Offset.hasSymbolicOffset())
+    return std::nullopt;
+
+  const int64_t OffsetBits = Offset.getOffset();
+  const uint64_t CharWidth = Ctx.getCharWidth();
+  if (OffsetBits < 0 || static_cast<uint64_t>(OffsetBits) % CharWidth != 0)
+    return false;
+
+  const MemRegion *BaseRegion = Offset.getRegion();
+  const auto BaseExtent =
+      getDynamicExtent(State, BaseRegion, SVB).getAs<nonloc::ConcreteInt>();
+  if (!BaseExtent)
+    return std::nullopt;
+
+  const int64_t ContainerSize =
+      Ctx.getTypeSizeInChars(ContainerType).getQuantity();
+  if (ContainerSize < 0)
+    return false;
+
+  const uint64_t OffsetChars = static_cast<uint64_t>(OffsetBits) / CharWidth;
+  const uint64_t ContainerSizeChars = static_cast<uint64_t>(ContainerSize);
+  if (OffsetChars > std::numeric_limits<uint64_t>::max() - ContainerSizeChars)
+    return false;
+
+  const uint64_t RequiredExtent = OffsetChars + ContainerSizeChars;
+  const llvm::APSInt RequiredExtentValue =
+      llvm::APSInt::getUnsigned(RequiredExtent);
+  return llvm::APSInt::compareValues(*BaseExtent->getValue(),
+                                     RequiredExtentValue) >= 0;
+}
+
+const SubRegion *getContainerOfParentRegion(const ElementRegion *ContainerER,
+                                            ProgramStateRef State,
+                                            SValBuilder &SVB) {
+  ASTContext &Ctx = SVB.getContext();
+  const MemRegion *SuperRegion = ContainerER->getSuperRegion();
+  const FieldRegion *FieldR = nullptr;
+  int64_t CharacterIndex = 0;
+
+  if (const auto *CharacterER = dyn_cast<ElementRegion>(SuperRegion)) {
+    QualType CharacterType = CharacterER->getElementType();
+    if (!CharacterType->isCharType() ||
+        Ctx.getTypeSizeInChars(CharacterType).getQuantity() != 1)
----------------
NagyDonat wrote:

```suggestion
    if (!CharacterType->isCharType())
```
`isCharType()` is only true for `char`, `signed char` and `unsigned char` and 
I'm pretty sure that the standard guarantees that these always have size 1 (in 
char units).

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

Reply via email to