mirror of
https://github.com/corda/corda.git
synced 2025-01-19 11:16:54 +00:00
fix thread heap overflow corner case in allocate3
The previous code relied on the invalid assumption that the thread-local heaps for all threads would have been cleared immediately following a garbage collection. However, the last thing the garbage collection function does is run finalizers which may allocate new objects. This can lead allocate3 to call allocateSmall with a size which is too large to accomodate, overflowing the heap. The solution is to iterate until there really is enough room for the original allocation request.
This commit is contained in:
parent
3e4336eba4
commit
47ab980550
@ -2061,42 +2061,47 @@ allocate3(Thread* t, Allocator* allocator, Machine::AllocationType type,
|
||||
}
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
case Machine::MovableAllocation:
|
||||
if (t->heapIndex + ceiling(sizeInBytes, BytesPerWord)
|
||||
> ThreadHeapSizeInWords)
|
||||
{
|
||||
t->heap = 0;
|
||||
if (t->m->heapPoolIndex < ThreadHeapPoolSize) {
|
||||
t->heap = static_cast<uintptr_t*>
|
||||
(t->m->heap->tryAllocate(ThreadHeapSizeInBytes));
|
||||
do {
|
||||
switch (type) {
|
||||
case Machine::MovableAllocation:
|
||||
if (t->heapIndex + ceiling(sizeInBytes, BytesPerWord)
|
||||
> ThreadHeapSizeInWords)
|
||||
{
|
||||
t->heap = 0;
|
||||
if (t->m->heapPoolIndex < ThreadHeapPoolSize) {
|
||||
t->heap = static_cast<uintptr_t*>
|
||||
(t->m->heap->tryAllocate(ThreadHeapSizeInBytes));
|
||||
|
||||
if (t->heap) {
|
||||
memset(t->heap, 0, ThreadHeapSizeInBytes);
|
||||
if (t->heap) {
|
||||
memset(t->heap, 0, ThreadHeapSizeInBytes);
|
||||
|
||||
t->m->heapPool[t->m->heapPoolIndex++] = t->heap;
|
||||
t->heapOffset += t->heapIndex;
|
||||
t->heapIndex = 0;
|
||||
t->m->heapPool[t->m->heapPoolIndex++] = t->heap;
|
||||
t->heapOffset += t->heapIndex;
|
||||
t->heapIndex = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case Machine::FixedAllocation:
|
||||
if (t->m->fixedFootprint + sizeInBytes > FixedFootprintThresholdInBytes)
|
||||
{
|
||||
t->heap = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case Machine::ImmortalAllocation:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case Machine::FixedAllocation:
|
||||
if (t->m->fixedFootprint + sizeInBytes > FixedFootprintThresholdInBytes) {
|
||||
t->heap = 0;
|
||||
if (t->heap == 0) {
|
||||
// fprintf(stderr, "gc");
|
||||
// vmPrintTrace(t);
|
||||
collect(t, Heap::MinorCollection);
|
||||
}
|
||||
break;
|
||||
|
||||
case Machine::ImmortalAllocation:
|
||||
break;
|
||||
}
|
||||
|
||||
if (t->heap == 0) {
|
||||
// fprintf(stderr, "gc");
|
||||
// vmPrintTrace(t);
|
||||
collect(t, Heap::MinorCollection);
|
||||
}
|
||||
} while (type == Machine::MovableAllocation
|
||||
and t->heapIndex + ceiling(sizeInBytes, BytesPerWord)
|
||||
> ThreadHeapSizeInWords);
|
||||
|
||||
switch (type) {
|
||||
case Machine::MovableAllocation: {
|
||||
|
@ -1519,6 +1519,9 @@ allocate3(Thread* t, Allocator* allocator, Machine::AllocationType type,
|
||||
inline object
|
||||
allocateSmall(Thread* t, unsigned sizeInBytes)
|
||||
{
|
||||
assert(t, t->heapIndex + ceiling(sizeInBytes, BytesPerWord)
|
||||
<= ThreadHeapSizeInWords);
|
||||
|
||||
object o = reinterpret_cast<object>(t->heap + t->heapIndex);
|
||||
t->heapIndex += ceiling(sizeInBytes, BytesPerWord);
|
||||
cast<object>(o, 0) = 0;
|
||||
|
Loading…
Reference in New Issue
Block a user