fix bugzilla 21995 Struct with size uint.max or greater causes ICE

This commit is contained in:
Walter Bright 2024-09-26 07:23:36 -07:00 committed by The Dlang Bot
parent ef02f08456
commit c2fb0d4273
4 changed files with 23 additions and 21 deletions

View file

@ -793,6 +793,7 @@ public uint alignmember(structalign_t alignment, uint memalignsize, uint offset)
/****************************************
* Place a field (mem) into an aggregate (agg), which can be a struct, union or class
* Params:
* loc = source location for error messages
* nextoffset = location just past the end of the previous field in the aggregate.
* Updated to be just past the end of this field to be placed, i.e. the future nextoffset
* memsize = size of field
@ -805,8 +806,8 @@ public uint alignmember(structalign_t alignment, uint memalignsize, uint offset)
* aligned offset to place field at
*
*/
public uint placeField(ref uint nextoffset, uint memsize, uint memalignsize,
structalign_t alignment, ref uint aggsize, ref uint aggalignsize, bool isunion) @safe pure nothrow
public uint placeField(Loc loc, ref uint nextoffset, uint memsize, uint memalignsize,
structalign_t alignment, ref uint aggsize, ref uint aggalignsize, bool isunion) @trusted nothrow
{
static if (0)
{
@ -829,7 +830,12 @@ public uint placeField(ref uint nextoffset, uint memsize, uint memalignsize,
bool overflow;
const sz = addu(memsize, actualAlignment, overflow);
addu(ofs, sz, overflow);
if (overflow) assert(0);
if (overflow)
{
error(loc, "max object size %u exceeded from adding field size %u + alignment adjustment %u + field offset %u when placing field in aggregate",
uint.max, memsize, actualAlignment, ofs);
return 0;
}
// Skip no-op for noreturn without custom aligment
if (memalignsize != 0 || !alignment.isDefault())

View file

@ -7126,7 +7126,7 @@ private extern(C++) class SetFieldOffsetVisitor : Visitor
assert(sz != SIZE_INVALID && sz < uint.max);
uint memsize = cast(uint)sz; // size of member
uint memalignsize = target.fieldalign(t); // size of member for alignment purposes
vd.offset = placeField(
vd.offset = placeField(vd.loc,
fieldState.offset,
memsize, memalignsize, vd.alignment,
ad.structsize, ad.alignsize,
@ -7193,7 +7193,7 @@ private extern(C++) class SetFieldOffsetVisitor : Visitor
alignsize = memsize; // not memalignsize
uint dummy;
bfd.offset = placeField(
bfd.offset = placeField(bfd.loc,
fieldState.offset,
memsize, alignsize, bfd.alignment,
ad.structsize,
@ -7395,7 +7395,7 @@ private extern(C++) class SetFieldOffsetVisitor : Visitor
/* Given the anon 'member's size and alignment,
* go ahead and place it.
*/
anond.anonoffset = placeField(
anond.anonoffset = placeField(anond.loc,
fieldState.offset,
anond.anonstructsize, anond.anonalignsize, alignment,
ad.structsize, ad.alignsize,

View file

@ -1,15 +0,0 @@
/*
TEST_OUTPUT:
---
fail_compilation/failCopyCtor.d(10): Error: `struct A` may not define both a rvalue constructor and a copy constructor
fail_compilation/failCopyCtor.d(12): rvalue constructor defined here
fail_compilation/failCopyCtor.d(13): copy constructor defined here
---
*/
struct A
{
this(immutable A a) {}
this(ref shared A a) immutable {}
this(ref A a) {}
}

View file

@ -0,0 +1,11 @@
/* TEST_OUTPUT:
---
fail_compilation/test21995.d(10): Error: max object size 4294967295 exceeded from adding field size 3 + alignment adjustment 1 + field offset 4294967292 when placing field in aggregate
---
*/
struct S
{
ubyte[0x7ffffffe] a;
ubyte[0x7ffffffe] b;
ubyte[3] c;
}