Skip to content

Commit 9a32f28

Browse files
authored
[clang][bytecode] Fix a problem with array size limits (#109383)
Descriptor::MaxArrayElemBytes is an unsigned value, which might overflow the SizeT we have in CheckArraySize.
1 parent 0f23557 commit 9a32f28

File tree

2 files changed

+22
-0
lines changed

2 files changed

+22
-0
lines changed

clang/lib/AST/ByteCode/Interp.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -241,11 +241,18 @@ bool CheckArraySize(InterpState &S, CodePtr OpPC, SizeT *NumElements,
241241
// FIXME: Both the SizeT::from() as well as the
242242
// NumElements.toAPSInt() in this function are rather expensive.
243243

244+
// Can't be too many elements if the bitwidth of NumElements is lower than
245+
// that of Descriptor::MaxArrayElemBytes.
246+
if ((NumElements->bitWidth() - NumElements->isSigned()) <
247+
(sizeof(Descriptor::MaxArrayElemBytes) * 8))
248+
return true;
249+
244250
// FIXME: GH63562
245251
// APValue stores array extents as unsigned,
246252
// so anything that is greater that unsigned would overflow when
247253
// constructing the array, we catch this here.
248254
SizeT MaxElements = SizeT::from(Descriptor::MaxArrayElemBytes / ElemSize);
255+
assert(MaxElements.isPositive());
249256
if (NumElements->toAPSInt().getActiveBits() >
250257
ConstantArrayType::getMaxSizeBits(S.getASTContext()) ||
251258
*NumElements > MaxElements) {

clang/test/AST/ByteCode/new-delete.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -718,6 +718,21 @@ namespace OperatorNewDelete {
718718
static_assert((std::allocator<float>().deallocate(std::allocator<float>().allocate(10)), 1) == 1);
719719
}
720720

721+
namespace Limits {
722+
template<typename T>
723+
constexpr T dynarray(int elems, int i) {
724+
T *p;
725+
if constexpr (sizeof(T) == 1)
726+
p = new T[elems]{"fox"};
727+
else
728+
p = new T[elems]{1, 2, 3};
729+
T n = p[i];
730+
delete [] p;
731+
return n;
732+
}
733+
static_assert(dynarray<char>(5, 0) == 'f');
734+
}
735+
721736
#else
722737
/// Make sure we reject this prior to C++20
723738
constexpr int a() { // both-error {{never produces a constant expression}}

0 commit comments

Comments
 (0)