[clang] [clang][bytecode] Fix a problem with array size limits (PR #109383)

via cfe-commits cfe-commits at lists.llvm.org
Fri Sep 20 00:07:21 PDT 2024


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clang

Author: Timm Baeder (tbaederr)

<details>
<summary>Changes</summary>

Descriptor::MaxArrayElemBytes is an unsigned value, which might overflow the SizeT we have in CheckArraySize.

---
Full diff: https://github.com/llvm/llvm-project/pull/109383.diff


2 Files Affected:

- (modified) clang/lib/AST/ByteCode/Interp.h (+7) 
- (modified) clang/test/AST/ByteCode/new-delete.cpp (+15) 


``````````diff
diff --git a/clang/lib/AST/ByteCode/Interp.h b/clang/lib/AST/ByteCode/Interp.h
index 52ccefee88642a..92bed32d56f4d5 100644
--- a/clang/lib/AST/ByteCode/Interp.h
+++ b/clang/lib/AST/ByteCode/Interp.h
@@ -241,11 +241,18 @@ bool CheckArraySize(InterpState &S, CodePtr OpPC, SizeT *NumElements,
   // FIXME: Both the SizeT::from() as well as the
   // NumElements.toAPSInt() in this function are rather expensive.
 
+  // Can't be too many elements if the bitwidth of NumElements is lower than
+  // that of Descriptor::MaxArrayElemBytes.
+  if ((NumElements->bitWidth() - NumElements->isSigned()) <
+      (sizeof(Descriptor::MaxArrayElemBytes) * 8))
+    return true;
+
   // FIXME: GH63562
   // APValue stores array extents as unsigned,
   // so anything that is greater that unsigned would overflow when
   // constructing the array, we catch this here.
   SizeT MaxElements = SizeT::from(Descriptor::MaxArrayElemBytes / ElemSize);
+  assert(MaxElements.isPositive());
   if (NumElements->toAPSInt().getActiveBits() >
           ConstantArrayType::getMaxSizeBits(S.getASTContext()) ||
       *NumElements > MaxElements) {
diff --git a/clang/test/AST/ByteCode/new-delete.cpp b/clang/test/AST/ByteCode/new-delete.cpp
index 76858aa94bb37d..2ba1286b250dc6 100644
--- a/clang/test/AST/ByteCode/new-delete.cpp
+++ b/clang/test/AST/ByteCode/new-delete.cpp
@@ -718,6 +718,21 @@ namespace OperatorNewDelete {
   static_assert((std::allocator<float>().deallocate(std::allocator<float>().allocate(10)), 1) == 1);
 }
 
+namespace Limits {
+  template<typename T>
+  constexpr T dynarray(int elems, int i) {
+    T *p;
+    if constexpr (sizeof(T) == 1)
+      p = new T[elems]{"fox"};
+    else
+      p = new T[elems]{1, 2, 3};
+    T n = p[i];
+    delete [] p;
+    return n;
+  }
+  static_assert(dynarray<char>(5, 0) == 'f');
+}
+
 #else
 /// Make sure we reject this prior to C++20
 constexpr int a() { // both-error {{never produces a constant expression}}

``````````

</details>


https://github.com/llvm/llvm-project/pull/109383


More information about the cfe-commits mailing list