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
|
||||
* 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:
|
||||
* 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
|
||||
void JEMALLOC_NOTHROW *
|
||||
JEMALLOC_ALLOC_SIZE(2)
|
||||
je_realloc(void *ptr, size_t size) {
|
||||
je_realloc(void *ptr, size_t arg_size) {
|
||||
void *ret;
|
||||
tsdn_t *tsdn JEMALLOC_CC_SILENCE_INIT(NULL);
|
||||
size_t usize JEMALLOC_CC_SILENCE_INIT(0);
|
||||
size_t old_usize = 0;
|
||||
size_t size = arg_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;
|
||||
}
|
||||
|
||||
uintptr_t args[3] = {(uintptr_t)ptr, size};
|
||||
hook_invoke_dalloc(hook_dalloc_realloc, ptr, args);
|
||||
|
||||
ifree(tsd, ptr, tcache, true);
|
||||
|
||||
LOG("core.realloc.exit", "result: %p", NULL);
|
||||
@ -2386,6 +2390,12 @@ je_realloc(void *ptr, size_t size) {
|
||||
dopts.item_size = size;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -179,7 +179,6 @@ TEST_END
|
||||
|
||||
TEST_BEGIN(test_hooks_alloc_simple) {
|
||||
/* "Simple" in the sense that we're not in a realloc variant. */
|
||||
|
||||
hooks_t hooks = {&test_alloc_hook, NULL, NULL};
|
||||
void *handle = hook_install(TSDN_NULL, &hooks, (void *)123);
|
||||
assert_ptr_ne(handle, NULL, "Hook installation failed");
|
||||
@ -364,6 +363,54 @@ TEST_BEGIN(test_hooks_expand_simple) {
|
||||
}
|
||||
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
|
||||
main(void) {
|
||||
@ -374,5 +421,6 @@ main(void) {
|
||||
test_hooks_remove,
|
||||
test_hooks_alloc_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