[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