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