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

Commit 441376b

Browse files
committed
clear "shadow" padding area of array, too.
1 parent 62da4de commit 441376b

File tree

1 file changed

+64
-3
lines changed

1 file changed

+64
-3
lines changed

src/rt/lifetime.d

Lines changed: 64 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -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

432451
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
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

Comments
 (0)