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

Commit

Permalink
Fix issue 16470: Segfault with negative array length
Browse files Browse the repository at this point in the history
If the array length is too large, and the element
size small enough, the overflow might go undetected
in the check while multiplying array size and element
size, but it can later manifest when adding padding, etc.

https://issues.dlang.org/show_bug.cgi?id=16470
  • Loading branch information
Burgos committed Feb 12, 2017
1 parent 858d57e commit 2d38937
Showing 1 changed file with 26 additions and 4 deletions.
30 changes: 26 additions & 4 deletions src/rt/lifetime.d
Expand Up @@ -274,9 +274,17 @@ bool __setArrayAllocLength(ref BlkInfo info, size_t newlength, bool isshared, co

if(info.size <= 256)
{
if(newlength + SMALLPAD + typeInfoSize > info.size)
import core.checkedint;

bool overflow;
auto newlength_padded = addu(newlength,
addu(SMALLPAD, typeInfoSize, overflow),
overflow);

if(newlength_padded > info.size || overflow)
// new size does not fit inside block
return false;

auto length = cast(ubyte *)(info.base + info.size - typeInfoSize - SMALLPAD);
if(oldlength != ~0)
{
Expand Down Expand Up @@ -406,24 +414,38 @@ size_t __arrayPad(size_t size, const TypeInfo tinext) nothrow pure @trusted
*/
BlkInfo __arrayAlloc(size_t arrsize, const TypeInfo ti, const TypeInfo tinext) nothrow pure
{
import core.checkedint;

size_t typeInfoSize = structTypeInfoSize(tinext);
size_t padsize = arrsize > MAXMEDSIZE ? LARGEPAD : ((arrsize > MAXSMALLSIZE ? MEDPAD : SMALLPAD) + typeInfoSize);

if (arrsize + padsize < arrsize)
bool overflow;
auto padded_size = addu(arrsize, padsize, overflow);

if (overflow)
return BlkInfo();

uint attr = (!(tinext.flags & 1) ? BlkAttr.NO_SCAN : 0) | BlkAttr.APPENDABLE;
if (typeInfoSize)
attr |= BlkAttr.STRUCTFINAL | BlkAttr.FINALIZE;
return GC.qalloc(arrsize + padsize, attr, ti);
return GC.qalloc(padded_size, attr, ti);
}

BlkInfo __arrayAlloc(size_t arrsize, ref BlkInfo info, const TypeInfo ti, const TypeInfo tinext)
{
import core.checkedint;

if (!info.base)
return __arrayAlloc(arrsize, ti, tinext);

return GC.qalloc(arrsize + __arrayPad(arrsize, tinext), info.attr, ti);
bool overflow;
auto padded_size = addu(arrsize, __arrayPad(arrsize, tinext), overflow);
if (overflow)
{
return BlkInfo();
}

return GC.qalloc(padded_size, info.attr, ti);
}

/**
Expand Down

0 comments on commit 2d38937

Please sign in to comment.