@@ -406,6 +406,22 @@ size_t __arrayPad(size_t size, const TypeInfo tinext) nothrow pure @trusted
406406 return size > MAXMEDSIZE ? LARGEPAD : ((size > MAXSMALLSIZE ? MEDPAD : SMALLPAD ) + structTypeInfoSize(tinext));
407407}
408408
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+
409425/**
410426 allocate an array memory block by applying the proper padding and
411427 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
426442 uint attr = (! (tinext.flags & 1 ) ? BlkAttr.NO_SCAN : 0 ) | BlkAttr.APPENDABLE ;
427443 if (typeInfoSize)
428444 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;
430449}
431450
432451BlkInfo __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
436455 if (! info.base)
437456 return __arrayAlloc (arrsize, ti, tinext);
438457
458+ immutable padsize = __arrayPad(arrsize, tinext);
439459 bool overflow;
440- auto padded_size = addu(arrsize, __arrayPad(arrsize, tinext) , overflow);
460+ auto padded_size = addu(arrsize, padsize , overflow);
441461 if (overflow)
442462 {
443463 return BlkInfo ();
444464 }
445465
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;
447469}
448470
449471/**
@@ -2715,6 +2737,45 @@ unittest
27152737 auto ptr = cast (S** )(a + 1 );
27162738 assert (* ptr != p1); // still same data as p2.ptr4?
27172739 }
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+ }
27182779}
27192780
27202781// test class finalizers exception handling
0 commit comments