Compare commits

..

12 commits

Author SHA1 Message Date
Daan
f81115d980 Merge branch 'dev' into dev2 2025-05-13 17:46:03 -07:00
Daan
15c917ef15 fix syntax error 2025-05-13 17:45:10 -07:00
Daan
45d984d5d2 Merge branch 'dev' into dev2 2025-05-13 17:43:54 -07:00
daanx
41cc1bfe51 add guarded TLS test for Windows fixed TLS 2025-05-13 17:38:16 -07:00
Daan
df3e191620 make windows fixed TLS opt-in 2025-05-13 16:38:53 -07:00
Daan
0ae310327f fix debug assertion for windows TLS 2025-05-13 16:22:08 -07:00
Daan
d87bcd0027 Merge branch 'dev' into dev2 2025-05-13 16:07:04 -07:00
daanx
72f05e2f07 fix guarded sample rate of 1 (issue #1085) 2025-05-13 15:58:45 -07:00
daanx
a6ecb5c299 fix format specifier (for alpine linux x86, issue #1086) 2025-05-13 15:35:29 -07:00
daanx
341149391f fix include of prctl.h on alpine linux x86 2025-05-13 15:33:29 -07:00
daanx
0184a86eaf add alpine x86 docker file 2025-05-13 15:32:11 -07:00
daanx
c84d996e88 fix TLS initialization for MI_WIN_USE_FIXED_TLS with redirection 2025-05-05 10:23:52 -07:00
10 changed files with 82 additions and 55 deletions

View file

@ -1,6 +1,6 @@
# install from an image # install from an image
# download first an appropriate tar.gz image into the current directory # download first an appropriate tar.gz image into the current directory
# from: <https://github.com/alpinelinux/docker-alpine/tree/edge/armv7> # from <https://github.com/alpinelinux/docker-alpine/tree/edge/armv7>
FROM scratch FROM scratch
# Substitute the image name that was downloaded # Substitute the image name that was downloaded

View file

@ -0,0 +1,28 @@
# install from an image
# download first an appropriate tar.gz image into the current directory
# from <https://github.com/alpinelinux/docker-alpine/tree/edge/x86>
FROM scratch
# Substitute the image name that was downloaded
ADD alpine-minirootfs-20250108-x86.tar.gz /
# Install tools
RUN apk add build-base make cmake
RUN apk add git
RUN apk add vim
RUN mkdir -p /home/dev
WORKDIR /home/dev
# Get mimalloc
RUN git clone https://github.com/microsoft/mimalloc -b dev2
RUN mkdir -p mimalloc/out/release
RUN mkdir -p mimalloc/out/debug
# Build mimalloc debug
WORKDIR /home/dev/mimalloc/out/debug
RUN cmake ../.. -DMI_DEBUG_FULL=ON
# RUN make -j
# RUN make test
CMD ["/bin/sh"]

View file

@ -282,8 +282,8 @@
</ClCompile> </ClCompile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="mimalloc-lib.vcxproj"> <ProjectReference Include="mimalloc-override-dll.vcxproj">
<Project>{abb5eae7-b3e6-432e-b636-333449892ea6}</Project> <Project>{abb5eae7-b3e6-432e-b636-333449892ea7}</Project>
</ProjectReference> </ProjectReference>
</ItemGroup> </ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

View file

@ -118,9 +118,6 @@ void _mi_prim_thread_done_auto_done(void);
void _mi_prim_thread_associate_default_heap(mi_heap_t* heap); void _mi_prim_thread_associate_default_heap(mi_heap_t* heap);
//------------------------------------------------------------------- //-------------------------------------------------------------------
// Access to TLS (thread local storage) slots. // Access to TLS (thread local storage) slots.
// We need fast access to both a unique thread id (in `free.c:mi_free`) and // We need fast access to both a unique thread id (in `free.c:mi_free`) and
@ -211,7 +208,7 @@ static inline void mi_prim_tls_slot_set(size_t slot, void* value) mi_attr_noexce
// thread-local initialization checks in the fast path. // thread-local initialization checks in the fast path.
// We allocate a user TLS slot at process initialization (see `windows/prim.c`) // We allocate a user TLS slot at process initialization (see `windows/prim.c`)
// and store the offset `_mi_win_tls_offset`. // and store the offset `_mi_win_tls_offset`.
#define MI_HAS_TLS_SLOT 2 // 2 = we can reliably initialize the slot (saving a test on each malloc) #define MI_HAS_TLS_SLOT 1 // 2 = we can reliably initialize the slot (saving a test on each malloc)
extern mi_decl_hidden size_t _mi_win_tls_offset; extern mi_decl_hidden size_t _mi_win_tls_offset;

View file

@ -571,7 +571,6 @@ struct mi_heap_s {
size_t guarded_size_min; // minimal size for guarded objects size_t guarded_size_min; // minimal size for guarded objects
size_t guarded_size_max; // maximal size for guarded objects size_t guarded_size_max; // maximal size for guarded objects
size_t guarded_sample_rate; // sample rate (set to 0 to disable guarded pages) size_t guarded_sample_rate; // sample rate (set to 0 to disable guarded pages)
size_t guarded_sample_seed; // starting sample count
size_t guarded_sample_count; // current sample count (counting down to 0) size_t guarded_sample_count; // current sample count (counting down to 0)
#endif #endif
mi_page_t* pages_free_direct[MI_PAGES_DIRECT]; // optimize: array where every entry points a page with possibly free blocks in the corresponding queue for that size. mi_page_t* pages_free_direct[MI_PAGES_DIRECT]; // optimize: array where every entry points a page with possibly free blocks in the corresponding queue for that size.

View file

@ -951,7 +951,7 @@ void mi_debug_show_arenas(void) mi_attr_noexcept {
for (size_t i = 0; i < max_arenas; i++) { for (size_t i = 0; i < max_arenas; i++) {
mi_arena_t* arena = mi_atomic_load_ptr_relaxed(mi_arena_t, &mi_arenas[i]); mi_arena_t* arena = mi_atomic_load_ptr_relaxed(mi_arena_t, &mi_arenas[i]);
if (arena == NULL) break; if (arena == NULL) break;
_mi_message("arena %zu: %zu blocks of size %zuMiB (in %zu fields) %s\n", i, arena->block_count, MI_ARENA_BLOCK_SIZE / MI_MiB, arena->field_count, (arena->memid.is_pinned ? ", pinned" : "")); _mi_message("arena %zu: %zu blocks of size %zuMiB (in %zu fields) %s\n", i, arena->block_count, (size_t)(MI_ARENA_BLOCK_SIZE / MI_MiB), arena->field_count, (arena->memid.is_pinned ? ", pinned" : ""));
if (show_inuse) { if (show_inuse) {
inuse_total += mi_debug_show_bitmap(" ", "inuse blocks", arena->block_count, arena->blocks_inuse, arena->field_count); inuse_total += mi_debug_show_bitmap(" ", "inuse blocks", arena->block_count, arena->blocks_inuse, arena->field_count);
} }

View file

@ -123,7 +123,7 @@ mi_decl_cache_align const mi_heap_t _mi_heap_empty = {
false, // can reclaim false, // can reclaim
0, // tag 0, // tag
#if MI_GUARDED #if MI_GUARDED
0, 0, 0, 0, 1, // count is 1 so we never write to it (see `internal.h:mi_heap_malloc_use_guarded`) 0, 0, 0, 1, // count is 1 so we never write to it (see `internal.h:mi_heap_malloc_use_guarded`)
#endif #endif
MI_SMALL_PAGES_EMPTY, MI_SMALL_PAGES_EMPTY,
MI_PAGE_QUEUES_EMPTY MI_PAGE_QUEUES_EMPTY
@ -172,7 +172,7 @@ mi_decl_cache_align mi_heap_t _mi_heap_main = {
false, // can reclaim false, // can reclaim
0, // tag 0, // tag
#if MI_GUARDED #if MI_GUARDED
0, 0, 0, 0, 0, 0, 0, 0, 0,
#endif #endif
MI_SMALL_PAGES_EMPTY, MI_SMALL_PAGES_EMPTY,
MI_PAGE_QUEUES_EMPTY MI_PAGE_QUEUES_EMPTY
@ -184,15 +184,14 @@ mi_stats_t _mi_stats_main = { MI_STAT_VERSION, MI_STATS_NULL };
#if MI_GUARDED #if MI_GUARDED
mi_decl_export void mi_heap_guarded_set_sample_rate(mi_heap_t* heap, size_t sample_rate, size_t seed) { mi_decl_export void mi_heap_guarded_set_sample_rate(mi_heap_t* heap, size_t sample_rate, size_t seed) {
heap->guarded_sample_seed = seed;
if (heap->guarded_sample_seed == 0) {
heap->guarded_sample_seed = _mi_heap_random_next(heap);
}
heap->guarded_sample_rate = sample_rate; heap->guarded_sample_rate = sample_rate;
if (heap->guarded_sample_rate >= 1) { heap->guarded_sample_count = sample_rate; // count down samples
heap->guarded_sample_seed = heap->guarded_sample_seed % heap->guarded_sample_rate; if (heap->guarded_sample_rate > 1) {
if (seed == 0) {
seed = _mi_heap_random_next(heap);
}
heap->guarded_sample_count = (seed % heap->guarded_sample_rate) + 1; // start at random count between 1 and `sample_rate`
} }
heap->guarded_sample_count = heap->guarded_sample_seed; // count down samples
} }
mi_decl_export void mi_heap_guarded_set_size_bound(mi_heap_t* heap, size_t min, size_t max) { mi_decl_export void mi_heap_guarded_set_size_bound(mi_heap_t* heap, size_t min, size_t max) {
@ -245,7 +244,6 @@ mi_heap_t* _mi_heap_main_get(void) {
return &_mi_heap_main; return &_mi_heap_main;
} }
/* ----------------------------------------------------------- /* -----------------------------------------------------------
Sub process Sub process
----------------------------------------------------------- */ ----------------------------------------------------------- */

View file

@ -32,7 +32,7 @@ terms of the MIT license. A copy of the license can be found in the file
#if defined(__linux__) #if defined(__linux__)
#include <features.h> #include <features.h>
#include <sys/prctl.h> // THP disable, PR_SET_VMA #include <sys/prctl.h> // THP disable, PR_SET_VMA
#if !defined(PR_SET_VMA) #if defined(__GLIBC__) && !defined(PR_SET_VMA)
#include <linux/prctl.h> #include <linux/prctl.h>
#endif #endif
#if defined(__GLIBC__) #if defined(__GLIBC__)

View file

@ -628,32 +628,41 @@ bool _mi_prim_random_buf(void* buf, size_t buf_len) {
//---------------------------------------------------------------- //----------------------------------------------------------------
#if MI_WIN_USE_FIXED_TLS==1 #if MI_WIN_USE_FIXED_TLS==1
mi_decl_cache_align size_t _mi_win_tls_offset = sizeof(void*); // use 2nd slot by default mi_decl_cache_align size_t _mi_win_tls_offset = 0;
#endif #endif
//static void mi_debug_out(const char* s) {
// HANDLE h = GetStdHandle(STD_ERROR_HANDLE);
// WriteConsole(h, s, (DWORD)_mi_strlen(s), NULL, NULL);
//}
static void mi_win_tls_init(DWORD reason) {
if (reason==DLL_PROCESS_ATTACH || reason==DLL_THREAD_ATTACH) {
#if MI_WIN_USE_FIXED_TLS==1 // we must allocate a TLS slot dynamically
if (_mi_win_tls_offset == 0 && reason == DLL_PROCESS_ATTACH) {
const DWORD tls_slot = TlsAlloc(); // usually returns slot 1
if (tls_slot == TLS_OUT_OF_INDEXES) {
_mi_error_message(EFAULT, "unable to allocate the a TLS slot (rebuild without MI_WIN_USE_FIXED_TLS?)\n");
}
_mi_win_tls_offset = (size_t)tls_slot * sizeof(void*);
}
#endif
#if MI_HAS_TLS_SLOT >= 2 // we must initialize the TLS slot before any allocation
if (mi_prim_get_default_heap() == NULL) {
_mi_heap_set_default_direct((mi_heap_t*)&_mi_heap_empty);
#if MI_DEBUG && MI_WIN_USE_FIXED_TLS==1
void* const p = TlsGetValue((DWORD)(_mi_win_tls_offset / sizeof(void*)));
mi_assert_internal(p == (void*)&_mi_heap_empty);
#endif
}
#endif
}
}
static void NTAPI mi_win_main(PVOID module, DWORD reason, LPVOID reserved) { static void NTAPI mi_win_main(PVOID module, DWORD reason, LPVOID reserved) {
MI_UNUSED(reserved); MI_UNUSED(reserved);
MI_UNUSED(module); MI_UNUSED(module);
#if MI_HAS_TLS_SLOT >= 2 // we must initialize the TLS slot before any allocation mi_win_tls_init(reason);
#if MI_WIN_USE_FIXED_TLS==1
if (reason==DLL_PROCESS_ATTACH) {
const DWORD tls_slot = TlsAlloc();
if (tls_slot == TLS_OUT_OF_INDEXES) {
_mi_error_message(EFAULT, "unable to allocate the a TLS slot (rebuild without MI_WIN_USE_FIXED_TLS?)\n");
}
_mi_win_tls_offset = (size_t)tls_slot * sizeof(void*);
}
#endif
if (reason==DLL_PROCESS_ATTACH || reason==DLL_THREAD_ATTACH) {
if (mi_prim_get_default_heap() == NULL) {
_mi_heap_set_default_direct((mi_heap_t*)&_mi_heap_empty);
}
#if MI_DEBUG && MI_WIN_USE_FIXED_TLS==1
void* const p = TlsGetValue((DWORD)(_mi_win_tls_offset / sizeof(void*)));
mi_assert_internal(p == (void*)&_mi_heap_empty);
#endif
}
#endif
if (reason==DLL_PROCESS_ATTACH) { if (reason==DLL_PROCESS_ATTACH) {
_mi_process_load(); _mi_process_load();
} }
@ -815,11 +824,7 @@ static void NTAPI mi_win_main(PVOID module, DWORD reason, LPVOID reserved) {
#endif #endif
mi_decl_export void _mi_redirect_entry(DWORD reason) { mi_decl_export void _mi_redirect_entry(DWORD reason) {
// called on redirection; careful as this may be called before DllMain // called on redirection; careful as this may be called before DllMain
#if MI_HAS_TLS_SLOT >= 2 // we must initialize the TLS slot before any allocation mi_win_tls_init(reason);
if ((reason==DLL_PROCESS_ATTACH || reason==DLL_THREAD_ATTACH) && mi_prim_get_default_heap() == NULL) {
_mi_heap_set_default_direct((mi_heap_t*)&_mi_heap_empty);
}
#endif
if (reason == DLL_PROCESS_ATTACH) { if (reason == DLL_PROCESS_ATTACH) {
mi_redirected = true; mi_redirected = true;
} }

View file

@ -43,7 +43,7 @@ int main() {
// corrupt_free(); // corrupt_free();
// block_overflow1(); // block_overflow1();
// block_overflow2(); // block_overflow2();
// test_canary_leak(); test_canary_leak();
// test_aslr(); // test_aslr();
// invalid_free(); // invalid_free();
// test_reserved(); // test_reserved();