@@ -1096,15 +1096,19 @@ extern (C) void* _d_newitemU(in TypeInfo _ti)
1096
1096
auto ti = unqualify(_ti);
1097
1097
auto flags = ! (ti.flags & 1 ) ? BlkAttr.NO_SCAN : 0 ;
1098
1098
immutable tiSize = structTypeInfoSize(ti);
1099
- immutable size = ti.tsize + tiSize;
1099
+ immutable itemSize = ti.tsize;
1100
+ immutable size = itemSize + tiSize;
1100
1101
if (tiSize)
1101
1102
flags |= BlkAttr.STRUCTFINAL | BlkAttr.FINALIZE ;
1102
1103
1103
1104
auto blkInf = GC .qalloc(size, flags, ti);
1104
1105
auto p = blkInf.base;
1105
1106
1106
1107
if (tiSize)
1108
+ {
1109
+ * cast (TypeInfo * )(p + itemSize) = null ; // the GC might not have cleared this area
1107
1110
* cast (TypeInfo * )(p + blkInf.size - tiSize) = cast () ti;
1111
+ }
1108
1112
1109
1113
return p;
1110
1114
}
@@ -2678,6 +2682,41 @@ deprecated unittest
2678
2682
}
2679
2683
}
2680
2684
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
+
2681
2720
// test class finalizers exception handling
2682
2721
unittest
2683
2722
{
0 commit comments