Skip to content

Commit 8fecc4b

Browse files
committed
Fix crash in pthread_tsd_cleanup on macOS ARM64 (#1177)
Complete the NULL handling fix from commit 515047b by also checking for NULL page entries in the 2-level page map lookup. The issue occurs on macOS ARM64 during pthread TSD (thread-specific data) cleanup when thread_local C++ objects are destroyed. During this late cleanup phase, the TLS for mimalloc may already be invalidated, causing _mi_checked_ptr_page to return NULL for valid pointers. Commit 515047b ('improve free on macos') changed the sub==NULL case to return _mi_page_empty instead of NULL, but missed the case where sub[sub_idx] is NULL. This commit adds the same NULL check for the page entry itself. Includes a regression test that reproduces the crash scenario.
1 parent 7a2a411 commit 8fecc4b

File tree

3 files changed

+27
-1
lines changed

3 files changed

+27
-1
lines changed

CMakeLists.txt

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -767,6 +767,18 @@ if (MI_BUILD_TESTS)
767767
add_test(NAME test-stress-dynamic COMMAND ${CMAKE_COMMAND} -E env MIMALLOC_VERBOSE=1 ${LD_PRELOAD}=$<TARGET_FILE:mimalloc> $<TARGET_FILE:mimalloc-test-stress-dynamic>)
768768
endif()
769769
endif()
770+
771+
# issue 1177: test thread_local cleanup on macOS
772+
add_executable(test-issue-1177 test/test-issue-1177.cpp)
773+
target_compile_definitions(test-issue-1177 PRIVATE ${mi_defines})
774+
target_compile_options(test-issue-1177 PRIVATE ${mi_cflags})
775+
target_include_directories(test-issue-1177 PRIVATE include)
776+
if(MI_BUILD_SHARED)
777+
target_link_libraries(test-issue-1177 PRIVATE mimalloc ${mi_libraries})
778+
elseif(MI_BUILD_STATIC)
779+
target_link_libraries(test-issue-1177 PRIVATE mimalloc-static ${mi_libraries})
780+
endif()
781+
add_test(NAME test-issue-1177 COMMAND test-issue-1177)
770782
endif()
771783

772784
# -----------------------------------------------------------------------------

include/mimalloc/internal.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -578,7 +578,9 @@ static inline mi_page_t* _mi_checked_ptr_page(const void* p) {
578578
const size_t idx = _mi_page_map_index(p, &sub_idx);
579579
mi_submap_t const sub = _mi_page_map[idx];
580580
if mi_unlikely(sub == NULL) return (mi_page_t*)&_mi_page_empty;
581-
return sub[sub_idx];
581+
mi_page_t* const page = sub[sub_idx];
582+
if mi_unlikely(page == NULL) return (mi_page_t*)&_mi_page_empty;
583+
return page;
582584
}
583585

584586
#endif

test/test-issue-1177.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
#include <thread>
2+
#include <cstdlib>
3+
4+
thread_local void* s_ptr = malloc(1);
5+
6+
int main()
7+
{
8+
std::thread thread([]() { free(s_ptr); });
9+
thread.join();
10+
free(s_ptr);
11+
return 0;
12+
}

0 commit comments

Comments
 (0)