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?= <tbae...@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}} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits