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

Timm Baeder via cfe-commits cfe-commits at lists.llvm.org
Fri Sep 20 00:06:46 PDT 2024


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

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

>From 091ba215597e2fc41b3860182ae2136bcac7f5bf Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Timm=20B=C3=A4der?= <tbaeder at redhat.com>
Date: Fri, 20 Sep 2024 08:33:48 +0200
Subject: [PATCH] [clang][bytecode] Fix a problem with array size limits

Descriptor::MaxArrayElemBytes is an unsigned value, which might
overflow the SizeT we have in CheckArraySize.
---
 clang/lib/AST/ByteCode/Interp.h        |  7 +++++++
 clang/test/AST/ByteCode/new-delete.cpp | 15 +++++++++++++++
 2 files changed, 22 insertions(+)

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}}



More information about the cfe-commits mailing list