@@ -406,6 +406,22 @@ size_t __arrayPad(size_t size, const TypeInfo tinext) nothrow pure @trusted
406
406
return size > MAXMEDSIZE ? LARGEPAD : ((size > MAXSMALLSIZE ? MEDPAD : SMALLPAD ) + structTypeInfoSize(tinext));
407
407
}
408
408
409
+ /**
410
+ clear padding that might not be zeroed by the GC (it assumes it is within the
411
+ requested size from the start, but it is actually at the end of the allocated block)
412
+ */
413
+ private void __arrayClearPad (ref BlkInfo info, size_t arrsize, size_t padsize) nothrow pure
414
+ {
415
+ import core.stdc.string ;
416
+ if (padsize > MEDPAD && ! (info.attr & BlkAttr.NO_SCAN ) && info.base)
417
+ {
418
+ if (info.size < PAGESIZE )
419
+ memset(info.base + arrsize, 0 , padsize);
420
+ else
421
+ memset(info.base, 0 , LARGEPREFIX );
422
+ }
423
+ }
424
+
409
425
/**
410
426
allocate an array memory block by applying the proper padding and
411
427
assigning block attributes if not inherited from the existing block
@@ -426,7 +442,10 @@ BlkInfo __arrayAlloc(size_t arrsize, const TypeInfo ti, const TypeInfo tinext) n
426
442
uint attr = (! (tinext.flags & 1 ) ? BlkAttr.NO_SCAN : 0 ) | BlkAttr.APPENDABLE ;
427
443
if (typeInfoSize)
428
444
attr |= BlkAttr.STRUCTFINAL | BlkAttr.FINALIZE ;
429
- return GC .qalloc(padded_size, attr, tinext);
445
+
446
+ auto bi = GC .qalloc(padded_size, attr, tinext);
447
+ __arrayClearPad(bi, arrsize, padsize);
448
+ return bi;
430
449
}
431
450
432
451
BlkInfo __arrayAlloc (size_t arrsize, ref BlkInfo info, const TypeInfo ti, const TypeInfo tinext)
@@ -436,14 +455,17 @@ BlkInfo __arrayAlloc(size_t arrsize, ref BlkInfo info, const TypeInfo ti, const
436
455
if (! info.base)
437
456
return __arrayAlloc (arrsize, ti, tinext);
438
457
458
+ immutable padsize = __arrayPad(arrsize, tinext);
439
459
bool overflow;
440
- auto padded_size = addu(arrsize, __arrayPad(arrsize, tinext) , overflow);
460
+ auto padded_size = addu(arrsize, padsize , overflow);
441
461
if (overflow)
442
462
{
443
463
return BlkInfo ();
444
464
}
445
465
446
- return GC .qalloc(padded_size, info.attr, tinext);
466
+ auto bi = GC .qalloc(padded_size, info.attr, tinext);
467
+ __arrayClearPad(bi, arrsize, padsize);
468
+ return bi;
447
469
}
448
470
449
471
/**
@@ -2715,6 +2737,45 @@ unittest
2715
2737
auto ptr = cast (S** )(a + 1 );
2716
2738
assert (* ptr != p1); // still same data as p2.ptr4?
2717
2739
}
2740
+
2741
+ // small array
2742
+ static struct SArr
2743
+ {
2744
+ void * [10 ] data;
2745
+ }
2746
+ auto arr1 = new SArr;
2747
+ arr1.data[] = p1;
2748
+ GC .free(arr1);
2749
+
2750
+ // allocates 2*A.sizeof + (void*).sizeof (TypeInfo) + 1 (array length)
2751
+ auto arr2 = new A[2 ];
2752
+ if (cast (void * )arr1 is cast (void * )arr2.ptr) // reusage not guaranteed
2753
+ {
2754
+ auto ptr = cast (S** )(arr2.ptr + 2 );
2755
+ assert (* ptr != p1); // still same data as p2.ptr4?
2756
+ }
2757
+
2758
+ // large array
2759
+ static struct LArr
2760
+ {
2761
+ void * [1023 ] data;
2762
+ }
2763
+ auto larr1 = new LArr;
2764
+ larr1.data[] = p1;
2765
+ GC .free(larr1);
2766
+
2767
+ auto larr2 = new S[255 ];
2768
+ if (cast (void * )larr1 is cast (void * )larr2.ptr - LARGEPREFIX ) // reusage not guaranteed
2769
+ {
2770
+ auto ptr = cast (S** )larr1;
2771
+ assert (ptr[0 ] != p1); // 16 bytes array header
2772
+ assert (ptr[1 ] != p1);
2773
+ version (D_LP64 ) {} else
2774
+ {
2775
+ assert (ptr[2 ] != p1);
2776
+ assert (ptr[3 ] != p1);
2777
+ }
2778
+ }
2718
2779
}
2719
2780
2720
2781
// test class finalizers exception handling
0 commit comments