fix: prevent corruption of the small allocator state (#13548)

This PR fixes possible corruption when recovering from memory
exhaustion.

This code threw an `std::bad_alloc` in the case of memory exhaustion,
but left the small allocator in an inconsistent state when doing so.
This would mean any code catching and recovering from the allocation
failure would likely find itself with a corrupt small allocator.

While we could try and make this code exception safe in future, simply
making it panic is better than the status quo, and is consistent with
how we handle most other allocation failures.

changelog-please-rerun-the-changelog-ci
This commit is contained in:
Eric Wieser 2026-05-06 06:46:03 -07:00 committed by GitHub
parent e3eb9aa832
commit 56fe75eef4
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -270,8 +270,8 @@ void heap::export_objs() {
}
void heap::alloc_segment() {
LEAN_RUNTIME_STAT_CODE(g_num_segments++);
segment * s = new segment();
LEAN_RUNTIME_STAT_CODE(g_num_segments++);
s->m_next = m_curr_segment;
m_curr_segment = s;
}
@ -283,8 +283,13 @@ static page * alloc_page(heap * h, unsigned obj_size) {
page * p = new (s->m_next_page_mem) page();
s->m_next_page_mem += LEAN_PAGE_SIZE;
if (s->is_full()) {
/* s is full, we need to allocate a new one. */
h->alloc_segment();
try {
/* s is full, we need to allocate a new one. */
h->alloc_segment();
} catch (std::bad_alloc const&) {
/* `s` is now in an inconsistent state so it would be unsafe to propagate the exception */
lean_internal_panic_out_of_memory();
}
}
unsigned slot_idx = lean_get_slot_idx(obj_size);
p->m_header.m_heap = h;