This tracker is deliberately limited to critical, upstream-relevant v3 allocator defects with concrete reproductions and small regression-tested fixes. Feature proposals, CI expansion, observability corrections, debug-build configuration, and platform polish are out of scope and will not be posted upstream from this tracker.
Re-checked against upstream/dev3 at f45596ab on 2026-08-05. No matching open Microsoft issue or PR was found before filing.
Why these are critical
Both retained work items violate allocator lifetime or type-safety invariants inside the C core:
- a public create/destroy lifecycle leaks allocator metadata without bound; and
- the allocator's internal TLS registry can point into freed application heap memory or interpret uninitialized bytes as a
mi_theap_t*.
These are not feature requests. They can cause unbounded process growth, silent allocator-state divergence, invalid pointer dereferences, and writes through a bogus internal heap pointer.
Critical upstream posts
1. mi_subproc_destroy leaks the subproc's own main heap
Current upstream: src/heap.c still guards _mi_heap_force_destroy with !_mi_is_heap_main(heap). That predicate is true for every subproc's heap_main, even though only the process main heap is static. The dynamically allocated subproc main heap is therefore skipped.
Measured detector: 3,000 mi_subproc_new/mi_subproc_destroy cycles retain 21,823,488 bytes (~7.3 KiB per cycle); the fixed build has delta 0. The regression test fails before and passes after the fix.
Why critical: repeated use of the public subproc lifecycle causes deterministic, unbounded allocator-metadata growth and eventual resource exhaustion. The matching mi_heap_free assertion also encodes the same invalid lifetime assumption and blocks the correct free in full-debug/sanitizer configurations.
- Fork fix:
f5bcd7af
- Regression:
test/test-subproc-lifecycle.c
- Upstream issue: pending
- Upstream PR: pending
2. TLS slot growth has two independent memory-safety defects
Current upstream: src/threadlocal.c::mi_thread_locals_expand still uses plain mi_rezalloc and does not explicitly initialize newly added slots.
Defect A ? use-after-free: plain mi_rezalloc allocates from the caller's current default heap. If an application makes a custom heap default and later destroys it, the TLS slot array is freed while mi_thread_locals retains its address. The detector loses 40/40 existing heap/theap bindings before the fix and preserves all 40 afterward.
Defect B ? type confusion: rezalloc cannot guarantee that the old allocation's size-class slack becomes zero in the grown object. A stale slot whose small sequential version happens to match a live key makes adjacent stale bytes get returned as a mi_theap_t*. Allocator code then dereferences and writes through an application-controlled/non-theap pointer.
Why critical: this is allocator-internal use-after-free plus pointer type confusion. It can silently orphan heap state, dereference invalid pointers, or corrupt memory through bogus page-queue/statistics writes. Both defects are fixed at the same growth site: allocate from the non-destroyable process main heap and explicitly zero the new slot range.
- Fork fixes:
590cfe70, 677704e9
- Regressions:
test/test-tls-slots-heap.c, test/test-rezalloc-slack.c
- Upstream issue: pending
- Upstream PR: pending
Filing discipline
- Reproduce on stock upstream at the exact PR base and toolchain before posting.
- Lead with measured failure and allocator invariant, without security/CVE claims the evidence does not establish.
- One logical fix per PR: subproc lifetime and TLS registry safety remain separate.
- Include the regression test and RED -> GREEN evidence in each PR.
This tracker is deliberately limited to critical, upstream-relevant v3 allocator defects with concrete reproductions and small regression-tested fixes. Feature proposals, CI expansion, observability corrections, debug-build configuration, and platform polish are out of scope and will not be posted upstream from this tracker.
Re-checked against
upstream/dev3atf45596abon 2026-08-05. No matching open Microsoft issue or PR was found before filing.Why these are critical
Both retained work items violate allocator lifetime or type-safety invariants inside the C core:
mi_theap_t*.These are not feature requests. They can cause unbounded process growth, silent allocator-state divergence, invalid pointer dereferences, and writes through a bogus internal heap pointer.
Critical upstream posts
1.
mi_subproc_destroyleaks the subproc's own main heapCurrent upstream:
src/heap.cstill guards_mi_heap_force_destroywith!_mi_is_heap_main(heap). That predicate is true for every subproc'sheap_main, even though only the process main heap is static. The dynamically allocated subproc main heap is therefore skipped.Measured detector: 3,000
mi_subproc_new/mi_subproc_destroycycles retain 21,823,488 bytes (~7.3 KiB per cycle); the fixed build has delta 0. The regression test fails before and passes after the fix.Why critical: repeated use of the public subproc lifecycle causes deterministic, unbounded allocator-metadata growth and eventual resource exhaustion. The matching
mi_heap_freeassertion also encodes the same invalid lifetime assumption and blocks the correct free in full-debug/sanitizer configurations.f5bcd7aftest/test-subproc-lifecycle.c2. TLS slot growth has two independent memory-safety defects
Current upstream:
src/threadlocal.c::mi_thread_locals_expandstill uses plainmi_rezallocand does not explicitly initialize newly added slots.Defect A ? use-after-free: plain
mi_rezallocallocates from the caller's current default heap. If an application makes a custom heap default and later destroys it, the TLS slot array is freed whilemi_thread_localsretains its address. The detector loses 40/40 existing heap/theap bindings before the fix and preserves all 40 afterward.Defect B ? type confusion:
rezalloccannot guarantee that the old allocation's size-class slack becomes zero in the grown object. A stale slot whose small sequentialversionhappens to match a live key makes adjacent stale bytes get returned as ami_theap_t*. Allocator code then dereferences and writes through an application-controlled/non-theap pointer.Why critical: this is allocator-internal use-after-free plus pointer type confusion. It can silently orphan heap state, dereference invalid pointers, or corrupt memory through bogus page-queue/statistics writes. Both defects are fixed at the same growth site: allocate from the non-destroyable process main heap and explicitly zero the new slot range.
590cfe70,677704e9test/test-tls-slots-heap.c,test/test-rezalloc-slack.cFiling discipline