Skip to content

Commit 1e81cab

Browse files
committed
Destroy global base allocator in the library destructor
The global base allocator should be destroyed in the library destructor in order to avoid use-after-free. Signed-off-by: Lukasz Dorau <[email protected]>
1 parent 73706ea commit 1e81cab

File tree

4 files changed

+25
-8
lines changed

4 files changed

+25
-8
lines changed

src/base_alloc/base_alloc_global.c

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include <stdlib.h>
1010

1111
#include "base_alloc.h"
12+
#include "base_alloc_global.h"
1213
#include "utils_concurrency.h"
1314

1415
#define SIZE_BA_POOL_CHUNK 128
@@ -17,17 +18,20 @@
1718
static umf_ba_pool_t *BA_pool = NULL;
1819
static UTIL_ONCE_FLAG ba_is_initialized = UTIL_ONCE_FLAG_INIT;
1920

20-
static void umf_ba_destroy_global(void) {
21-
assert(BA_pool);
22-
umf_ba_destroy(BA_pool);
23-
BA_pool = NULL;
24-
}
25-
2621
static void umf_ba_create_global(void) {
2722
assert(BA_pool == NULL);
2823
BA_pool = umf_ba_create(SIZE_BA_POOL_CHUNK);
24+
assert(BA_pool);
25+
#if defined(_WIN32) && !defined(UMF_SHARED_LIBRARY)
26+
atexit(umf_ba_destroy_global);
27+
#endif
28+
}
29+
30+
void umf_ba_destroy_global(void) {
2931
if (BA_pool) {
30-
atexit(umf_ba_destroy_global);
32+
umf_ba_pool_t *pool = BA_pool;
33+
BA_pool = NULL;
34+
umf_ba_destroy(pool);
3135
}
3236
}
3337

src/base_alloc/base_alloc_global.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ extern "C" {
1515
#endif
1616

1717
umf_ba_pool_t *umf_ba_get_pool(size_t size);
18+
void umf_ba_destroy_global(void);
1819

1920
#ifdef __cplusplus
2021
}

src/base_alloc/base_alloc_linux.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,15 @@
1212
#include <unistd.h>
1313

1414
#include "base_alloc.h"
15+
#include "base_alloc_global.h"
16+
17+
// The highest possible priority (101) is used, because the constructor should be called
18+
// as the first one and the destructor as the last one in order to avoid use-after-free.
19+
void __attribute__((constructor(101))) umf_ba_constructor(void) {}
20+
21+
void __attribute__((destructor(101))) umf_ba_destructor(void) {
22+
umf_ba_destroy_global();
23+
}
1524

1625
void *ba_os_alloc(size_t size) {
1726
return mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS,

src/libumf_windows.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,10 @@ umf_memory_tracker_handle_t TRACKER = NULL;
1717

1818
static void umfCreate(void) { TRACKER = umfMemoryTrackerCreate(); }
1919

20-
static void umfDestroy(void) { umfMemoryTrackerDestroy(TRACKER); }
20+
static void umfDestroy(void) {
21+
umfMemoryTrackerDestroy(TRACKER);
22+
umf_ba_destroy_global();
23+
}
2124

2225
#if defined(UMF_SHARED_LIBRARY)
2326
BOOL APIENTRY DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) {

0 commit comments

Comments
 (0)