Skip to content
This repository was archived by the owner on Oct 12, 2022. It is now read-only.

Commit 62da4de

Browse files
committed
fix issue 20155 - Allocating a struct with dtor on the GC heap can produce false pointers
clear padding area not completely zeroed for struct allocations with dtor
1 parent 396a0ec commit 62da4de

File tree

1 file changed

+40
-1
lines changed

1 file changed

+40
-1
lines changed

src/rt/lifetime.d

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1096,15 +1096,19 @@ extern (C) void* _d_newitemU(in TypeInfo _ti)
10961096
auto ti = unqualify(_ti);
10971097
auto flags = !(ti.flags & 1) ? BlkAttr.NO_SCAN : 0;
10981098
immutable tiSize = structTypeInfoSize(ti);
1099-
immutable size = ti.tsize + tiSize;
1099+
immutable itemSize = ti.tsize;
1100+
immutable size = itemSize + tiSize;
11001101
if (tiSize)
11011102
flags |= BlkAttr.STRUCTFINAL | BlkAttr.FINALIZE;
11021103

11031104
auto blkInf = GC.qalloc(size, flags, ti);
11041105
auto p = blkInf.base;
11051106

11061107
if (tiSize)
1108+
{
1109+
*cast(TypeInfo*)(p + itemSize) = null; // the GC might not have cleared this area
11071110
*cast(TypeInfo*)(p + blkInf.size - tiSize) = cast() ti;
1111+
}
11081112

11091113
return p;
11101114
}
@@ -2678,6 +2682,41 @@ deprecated unittest
26782682
}
26792683
}
26802684

2685+
// test struct dtor handling not causing false pointers
2686+
unittest
2687+
{
2688+
if (!callStructDtorsDuringGC)
2689+
return;
2690+
2691+
// for 64-bit, allocate a struct of size 40
2692+
static struct S
2693+
{
2694+
size_t[4] data;
2695+
S* ptr4;
2696+
}
2697+
auto p1 = new S;
2698+
auto p2 = new S;
2699+
p2.ptr4 = p1;
2700+
2701+
// a struct with a dtor with size 32, but the dtor will cause
2702+
// allocation to be larger by a pointer
2703+
static struct A
2704+
{
2705+
size_t[3] data;
2706+
S* ptr3;
2707+
2708+
~this() {}
2709+
}
2710+
2711+
GC.free(p2);
2712+
auto a = new A; // reuse same memory
2713+
if (cast(void*)a is cast(void*)p2) // reusage not guaranteed
2714+
{
2715+
auto ptr = cast(S**)(a + 1);
2716+
assert(*ptr != p1); // still same data as p2.ptr4?
2717+
}
2718+
}
2719+
26812720
// test class finalizers exception handling
26822721
unittest
26832722
{

0 commit comments

Comments
 (0)