Hooks: hook the realloc paths that act as pure malloc/free.
This commit is contained in:
parent
83e516154c
commit
67270040a5
@ -16,9 +16,13 @@
|
|||||||
*
|
*
|
||||||
* For realloc and rallocx, if the expansion happens in place, the expansion
|
* For realloc and rallocx, if the expansion happens in place, the expansion
|
||||||
* hook is called. If it is moved, then the alloc hook is called on the new
|
* hook is called. If it is moved, then the alloc hook is called on the new
|
||||||
* location, and then the free hook is called on the old location.
|
* location, and then the free hook is called on the old location (i.e. both
|
||||||
|
* hooks are invoked in between the alloc and the dalloc).
|
||||||
*
|
*
|
||||||
* If we return NULL from OOM, then usize might not be trustworthy.
|
* If we return NULL from OOM, then usize might not be trustworthy. Calling
|
||||||
|
* realloc(NULL, size) only calls the alloc hook, and calling realloc(ptr, 0)
|
||||||
|
* only calls the free hook. (Calling realloc(NULL, 0) is treated as malloc(0),
|
||||||
|
* and only calls the alloc hook).
|
||||||
*
|
*
|
||||||
* Reentrancy:
|
* Reentrancy:
|
||||||
* Is not protected against. If your hooks allocate, then the hooks will be
|
* Is not protected against. If your hooks allocate, then the hooks will be
|
||||||
|
@ -2311,11 +2311,12 @@ isfree(tsd_t *tsd, void *ptr, size_t usize, tcache_t *tcache, bool slow_path) {
|
|||||||
JEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN
|
JEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN
|
||||||
void JEMALLOC_NOTHROW *
|
void JEMALLOC_NOTHROW *
|
||||||
JEMALLOC_ALLOC_SIZE(2)
|
JEMALLOC_ALLOC_SIZE(2)
|
||||||
je_realloc(void *ptr, size_t size) {
|
je_realloc(void *ptr, size_t arg_size) {
|
||||||
void *ret;
|
void *ret;
|
||||||
tsdn_t *tsdn JEMALLOC_CC_SILENCE_INIT(NULL);
|
tsdn_t *tsdn JEMALLOC_CC_SILENCE_INIT(NULL);
|
||||||
size_t usize JEMALLOC_CC_SILENCE_INIT(0);
|
size_t usize JEMALLOC_CC_SILENCE_INIT(0);
|
||||||
size_t old_usize = 0;
|
size_t old_usize = 0;
|
||||||
|
size_t size = arg_size;
|
||||||
|
|
||||||
LOG("core.realloc.entry", "ptr: %p, size: %zu\n", ptr, size);
|
LOG("core.realloc.entry", "ptr: %p, size: %zu\n", ptr, size);
|
||||||
|
|
||||||
@ -2331,6 +2332,9 @@ je_realloc(void *ptr, size_t size) {
|
|||||||
tcache = NULL;
|
tcache = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uintptr_t args[3] = {(uintptr_t)ptr, size};
|
||||||
|
hook_invoke_dalloc(hook_dalloc_realloc, ptr, args);
|
||||||
|
|
||||||
ifree(tsd, ptr, tcache, true);
|
ifree(tsd, ptr, tcache, true);
|
||||||
|
|
||||||
LOG("core.realloc.exit", "result: %p", NULL);
|
LOG("core.realloc.exit", "result: %p", NULL);
|
||||||
@ -2386,6 +2390,12 @@ je_realloc(void *ptr, size_t size) {
|
|||||||
dopts.item_size = size;
|
dopts.item_size = size;
|
||||||
|
|
||||||
imalloc(&sopts, &dopts);
|
imalloc(&sopts, &dopts);
|
||||||
|
if (sopts.slow) {
|
||||||
|
uintptr_t args[3] = {(uintptr_t)ptr, arg_size};
|
||||||
|
hook_invoke_alloc(hook_alloc_realloc, ret,
|
||||||
|
(uintptr_t)ret, args);
|
||||||
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -179,7 +179,6 @@ TEST_END
|
|||||||
|
|
||||||
TEST_BEGIN(test_hooks_alloc_simple) {
|
TEST_BEGIN(test_hooks_alloc_simple) {
|
||||||
/* "Simple" in the sense that we're not in a realloc variant. */
|
/* "Simple" in the sense that we're not in a realloc variant. */
|
||||||
|
|
||||||
hooks_t hooks = {&test_alloc_hook, NULL, NULL};
|
hooks_t hooks = {&test_alloc_hook, NULL, NULL};
|
||||||
void *handle = hook_install(TSDN_NULL, &hooks, (void *)123);
|
void *handle = hook_install(TSDN_NULL, &hooks, (void *)123);
|
||||||
assert_ptr_ne(handle, NULL, "Hook installation failed");
|
assert_ptr_ne(handle, NULL, "Hook installation failed");
|
||||||
@ -364,6 +363,54 @@ TEST_BEGIN(test_hooks_expand_simple) {
|
|||||||
}
|
}
|
||||||
TEST_END
|
TEST_END
|
||||||
|
|
||||||
|
TEST_BEGIN(test_hooks_realloc_as_malloc_or_free) {
|
||||||
|
hooks_t hooks = {&test_alloc_hook, &test_dalloc_hook,
|
||||||
|
&test_expand_hook};
|
||||||
|
void *handle = hook_install(TSDN_NULL, &hooks, (void *)123);
|
||||||
|
assert_ptr_ne(handle, NULL, "Hook installation failed");
|
||||||
|
|
||||||
|
void *volatile ptr;
|
||||||
|
|
||||||
|
/* realloc(NULL, size) as malloc */
|
||||||
|
reset();
|
||||||
|
ptr = realloc(NULL, 1);
|
||||||
|
assert_d_eq(call_count, 1, "Hook not called");
|
||||||
|
assert_ptr_eq(arg_extra, (void *)123, "Wrong extra");
|
||||||
|
assert_d_eq(arg_type, (int)hook_alloc_realloc, "Wrong hook type");
|
||||||
|
assert_ptr_eq(ptr, arg_result, "Wrong result");
|
||||||
|
assert_u64_eq((uintptr_t)ptr, (uintptr_t)arg_result_raw,
|
||||||
|
"Wrong raw result");
|
||||||
|
assert_u64_eq((uintptr_t)NULL, arg_args_raw[0], "Wrong argument");
|
||||||
|
assert_u64_eq((uintptr_t)1, arg_args_raw[1], "Wrong argument");
|
||||||
|
free(ptr);
|
||||||
|
|
||||||
|
/* realloc(ptr, 0) as free */
|
||||||
|
ptr = malloc(1);
|
||||||
|
reset();
|
||||||
|
realloc(ptr, 0);
|
||||||
|
assert_d_eq(call_count, 1, "Hook not called");
|
||||||
|
assert_ptr_eq(arg_extra, (void *)123, "Wrong extra");
|
||||||
|
assert_d_eq(arg_type, (int)hook_dalloc_realloc, "Wrong hook type");
|
||||||
|
assert_ptr_eq(ptr, arg_address, "Wrong pointer freed");
|
||||||
|
assert_u64_eq((uintptr_t)ptr, arg_args_raw[0], "Wrong raw arg");
|
||||||
|
assert_u64_eq((uintptr_t)0, arg_args_raw[1], "Wrong raw arg");
|
||||||
|
|
||||||
|
/* realloc(NULL, 0) as malloc(0) */
|
||||||
|
reset();
|
||||||
|
ptr = realloc(NULL, 0);
|
||||||
|
assert_d_eq(call_count, 1, "Hook not called");
|
||||||
|
assert_ptr_eq(arg_extra, (void *)123, "Wrong extra");
|
||||||
|
assert_d_eq(arg_type, (int)hook_alloc_realloc, "Wrong hook type");
|
||||||
|
assert_ptr_eq(ptr, arg_result, "Wrong result");
|
||||||
|
assert_u64_eq((uintptr_t)ptr, (uintptr_t)arg_result_raw,
|
||||||
|
"Wrong raw result");
|
||||||
|
assert_u64_eq((uintptr_t)NULL, arg_args_raw[0], "Wrong argument");
|
||||||
|
assert_u64_eq((uintptr_t)0, arg_args_raw[1], "Wrong argument");
|
||||||
|
free(ptr);
|
||||||
|
|
||||||
|
hook_remove(TSDN_NULL, handle);
|
||||||
|
}
|
||||||
|
TEST_END
|
||||||
|
|
||||||
int
|
int
|
||||||
main(void) {
|
main(void) {
|
||||||
@ -374,5 +421,6 @@ main(void) {
|
|||||||
test_hooks_remove,
|
test_hooks_remove,
|
||||||
test_hooks_alloc_simple,
|
test_hooks_alloc_simple,
|
||||||
test_hooks_dalloc_simple,
|
test_hooks_dalloc_simple,
|
||||||
test_hooks_expand_simple);
|
test_hooks_expand_simple,
|
||||||
|
test_hooks_realloc_as_malloc_or_free);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user