1 #include "test/jemalloc_test.h" 2 3 #include "jemalloc/internal/hook.h" 4 5 static void *arg_extra; 6 static int arg_type; 7 static void *arg_result; 8 static void *arg_address; 9 static size_t arg_old_usize; 10 static size_t arg_new_usize; 11 static uintptr_t arg_result_raw; 12 static uintptr_t arg_args_raw[4]; 13 14 static int call_count = 0; 15 16 static void 17 reset_args() { 18 arg_extra = NULL; 19 arg_type = 12345; 20 arg_result = NULL; 21 arg_address = NULL; 22 arg_old_usize = 0; 23 arg_new_usize = 0; 24 arg_result_raw = 0; 25 memset(arg_args_raw, 77, sizeof(arg_args_raw)); 26 } 27 28 static void 29 alloc_free_size(size_t sz) { 30 void *ptr = mallocx(1, 0); 31 free(ptr); 32 ptr = mallocx(1, 0); 33 free(ptr); 34 ptr = mallocx(1, MALLOCX_TCACHE_NONE); 35 dallocx(ptr, MALLOCX_TCACHE_NONE); 36 } 37 38 /* 39 * We want to support a degree of user reentrancy. This tests a variety of 40 * allocation scenarios. 41 */ 42 static void 43 be_reentrant() { 44 /* Let's make sure the tcache is non-empty if enabled. */ 45 alloc_free_size(1); 46 alloc_free_size(1024); 47 alloc_free_size(64 * 1024); 48 alloc_free_size(256 * 1024); 49 alloc_free_size(1024 * 1024); 50 51 /* Some reallocation. */ 52 void *ptr = mallocx(129, 0); 53 ptr = rallocx(ptr, 130, 0); 54 free(ptr); 55 56 ptr = mallocx(2 * 1024 * 1024, 0); 57 free(ptr); 58 ptr = mallocx(1 * 1024 * 1024, 0); 59 ptr = rallocx(ptr, 2 * 1024 * 1024, 0); 60 free(ptr); 61 62 ptr = mallocx(1, 0); 63 ptr = rallocx(ptr, 1000, 0); 64 free(ptr); 65 } 66 67 static void 68 set_args_raw(uintptr_t *args_raw, int nargs) { 69 memcpy(arg_args_raw, args_raw, sizeof(uintptr_t) * nargs); 70 } 71 72 static void 73 expect_args_raw(uintptr_t *args_raw_expected, int nargs) { 74 int cmp = memcmp(args_raw_expected, arg_args_raw, 75 sizeof(uintptr_t) * nargs); 76 expect_d_eq(cmp, 0, "Raw args mismatch"); 77 } 78 79 static void 80 reset() { 81 call_count = 0; 82 reset_args(); 83 } 84 85 static void 86 test_alloc_hook(void *extra, hook_alloc_t type, void *result, 87 uintptr_t result_raw, uintptr_t args_raw[3]) { 88 call_count++; 89 arg_extra = extra; 90 arg_type = (int)type; 91 arg_result = result; 92 arg_result_raw = result_raw; 93 set_args_raw(args_raw, 3); 94 be_reentrant(); 95 } 96 97 static void 98 test_dalloc_hook(void *extra, hook_dalloc_t type, void *address, 99 uintptr_t args_raw[3]) { 100 call_count++; 101 arg_extra = extra; 102 arg_type = (int)type; 103 arg_address = address; 104 set_args_raw(args_raw, 3); 105 be_reentrant(); 106 } 107 108 static void 109 test_expand_hook(void *extra, hook_expand_t type, void *address, 110 size_t old_usize, size_t new_usize, uintptr_t result_raw, 111 uintptr_t args_raw[4]) { 112 call_count++; 113 arg_extra = extra; 114 arg_type = (int)type; 115 arg_address = address; 116 arg_old_usize = old_usize; 117 arg_new_usize = new_usize; 118 arg_result_raw = result_raw; 119 set_args_raw(args_raw, 4); 120 be_reentrant(); 121 } 122 123 TEST_BEGIN(test_hooks_basic) { 124 /* Just verify that the record their arguments correctly. */ 125 hooks_t hooks = { 126 &test_alloc_hook, &test_dalloc_hook, &test_expand_hook, 127 (void *)111}; 128 void *handle = hook_install(TSDN_NULL, &hooks); 129 uintptr_t args_raw[4] = {10, 20, 30, 40}; 130 131 /* Alloc */ 132 reset_args(); 133 hook_invoke_alloc(hook_alloc_posix_memalign, (void *)222, 333, 134 args_raw); 135 expect_ptr_eq(arg_extra, (void *)111, "Passed wrong user pointer"); 136 expect_d_eq((int)hook_alloc_posix_memalign, arg_type, 137 "Passed wrong alloc type"); 138 expect_ptr_eq((void *)222, arg_result, "Passed wrong result address"); 139 expect_u64_eq(333, arg_result_raw, "Passed wrong result"); 140 expect_args_raw(args_raw, 3); 141 142 /* Dalloc */ 143 reset_args(); 144 hook_invoke_dalloc(hook_dalloc_sdallocx, (void *)222, args_raw); 145 expect_d_eq((int)hook_dalloc_sdallocx, arg_type, 146 "Passed wrong dalloc type"); 147 expect_ptr_eq((void *)111, arg_extra, "Passed wrong user pointer"); 148 expect_ptr_eq((void *)222, arg_address, "Passed wrong address"); 149 expect_args_raw(args_raw, 3); 150 151 /* Expand */ 152 reset_args(); 153 hook_invoke_expand(hook_expand_xallocx, (void *)222, 333, 444, 555, 154 args_raw); 155 expect_d_eq((int)hook_expand_xallocx, arg_type, 156 "Passed wrong expand type"); 157 expect_ptr_eq((void *)111, arg_extra, "Passed wrong user pointer"); 158 expect_ptr_eq((void *)222, arg_address, "Passed wrong address"); 159 expect_zu_eq(333, arg_old_usize, "Passed wrong old usize"); 160 expect_zu_eq(444, arg_new_usize, "Passed wrong new usize"); 161 expect_zu_eq(555, arg_result_raw, "Passed wrong result"); 162 expect_args_raw(args_raw, 4); 163 164 hook_remove(TSDN_NULL, handle); 165 } 166 TEST_END 167 168 TEST_BEGIN(test_hooks_null) { 169 /* Null hooks should be ignored, not crash. */ 170 hooks_t hooks1 = {NULL, NULL, NULL, NULL}; 171 hooks_t hooks2 = {&test_alloc_hook, NULL, NULL, NULL}; 172 hooks_t hooks3 = {NULL, &test_dalloc_hook, NULL, NULL}; 173 hooks_t hooks4 = {NULL, NULL, &test_expand_hook, NULL}; 174 175 void *handle1 = hook_install(TSDN_NULL, &hooks1); 176 void *handle2 = hook_install(TSDN_NULL, &hooks2); 177 void *handle3 = hook_install(TSDN_NULL, &hooks3); 178 void *handle4 = hook_install(TSDN_NULL, &hooks4); 179 180 expect_ptr_ne(handle1, NULL, "Hook installation failed"); 181 expect_ptr_ne(handle2, NULL, "Hook installation failed"); 182 expect_ptr_ne(handle3, NULL, "Hook installation failed"); 183 expect_ptr_ne(handle4, NULL, "Hook installation failed"); 184 185 uintptr_t args_raw[4] = {10, 20, 30, 40}; 186 187 call_count = 0; 188 hook_invoke_alloc(hook_alloc_malloc, NULL, 0, args_raw); 189 expect_d_eq(call_count, 1, "Called wrong number of times"); 190 191 call_count = 0; 192 hook_invoke_dalloc(hook_dalloc_free, NULL, args_raw); 193 expect_d_eq(call_count, 1, "Called wrong number of times"); 194 195 call_count = 0; 196 hook_invoke_expand(hook_expand_realloc, NULL, 0, 0, 0, args_raw); 197 expect_d_eq(call_count, 1, "Called wrong number of times"); 198 199 hook_remove(TSDN_NULL, handle1); 200 hook_remove(TSDN_NULL, handle2); 201 hook_remove(TSDN_NULL, handle3); 202 hook_remove(TSDN_NULL, handle4); 203 } 204 TEST_END 205 206 TEST_BEGIN(test_hooks_remove) { 207 hooks_t hooks = {&test_alloc_hook, NULL, NULL, NULL}; 208 void *handle = hook_install(TSDN_NULL, &hooks); 209 expect_ptr_ne(handle, NULL, "Hook installation failed"); 210 call_count = 0; 211 uintptr_t args_raw[4] = {10, 20, 30, 40}; 212 hook_invoke_alloc(hook_alloc_malloc, NULL, 0, args_raw); 213 expect_d_eq(call_count, 1, "Hook not invoked"); 214 215 call_count = 0; 216 hook_remove(TSDN_NULL, handle); 217 hook_invoke_alloc(hook_alloc_malloc, NULL, 0, NULL); 218 expect_d_eq(call_count, 0, "Hook invoked after removal"); 219 220 } 221 TEST_END 222 223 TEST_BEGIN(test_hooks_alloc_simple) { 224 /* "Simple" in the sense that we're not in a realloc variant. */ 225 hooks_t hooks = {&test_alloc_hook, NULL, NULL, (void *)123}; 226 void *handle = hook_install(TSDN_NULL, &hooks); 227 expect_ptr_ne(handle, NULL, "Hook installation failed"); 228 229 /* Stop malloc from being optimized away. */ 230 volatile int err; 231 void *volatile ptr; 232 233 /* malloc */ 234 reset(); 235 ptr = malloc(1); 236 expect_d_eq(call_count, 1, "Hook not called"); 237 expect_ptr_eq(arg_extra, (void *)123, "Wrong extra"); 238 expect_d_eq(arg_type, (int)hook_alloc_malloc, "Wrong hook type"); 239 expect_ptr_eq(ptr, arg_result, "Wrong result"); 240 expect_u64_eq((uintptr_t)ptr, (uintptr_t)arg_result_raw, 241 "Wrong raw result"); 242 expect_u64_eq((uintptr_t)1, arg_args_raw[0], "Wrong argument"); 243 free(ptr); 244 245 /* posix_memalign */ 246 reset(); 247 err = posix_memalign((void **)&ptr, 1024, 1); 248 expect_d_eq(call_count, 1, "Hook not called"); 249 expect_ptr_eq(arg_extra, (void *)123, "Wrong extra"); 250 expect_d_eq(arg_type, (int)hook_alloc_posix_memalign, 251 "Wrong hook type"); 252 expect_ptr_eq(ptr, arg_result, "Wrong result"); 253 expect_u64_eq((uintptr_t)err, (uintptr_t)arg_result_raw, 254 "Wrong raw result"); 255 expect_u64_eq((uintptr_t)&ptr, arg_args_raw[0], "Wrong argument"); 256 expect_u64_eq((uintptr_t)1024, arg_args_raw[1], "Wrong argument"); 257 expect_u64_eq((uintptr_t)1, arg_args_raw[2], "Wrong argument"); 258 free(ptr); 259 260 /* aligned_alloc */ 261 reset(); 262 ptr = aligned_alloc(1024, 1); 263 expect_d_eq(call_count, 1, "Hook not called"); 264 expect_ptr_eq(arg_extra, (void *)123, "Wrong extra"); 265 expect_d_eq(arg_type, (int)hook_alloc_aligned_alloc, 266 "Wrong hook type"); 267 expect_ptr_eq(ptr, arg_result, "Wrong result"); 268 expect_u64_eq((uintptr_t)ptr, (uintptr_t)arg_result_raw, 269 "Wrong raw result"); 270 expect_u64_eq((uintptr_t)1024, arg_args_raw[0], "Wrong argument"); 271 expect_u64_eq((uintptr_t)1, arg_args_raw[1], "Wrong argument"); 272 free(ptr); 273 274 /* calloc */ 275 reset(); 276 ptr = calloc(11, 13); 277 expect_d_eq(call_count, 1, "Hook not called"); 278 expect_ptr_eq(arg_extra, (void *)123, "Wrong extra"); 279 expect_d_eq(arg_type, (int)hook_alloc_calloc, "Wrong hook type"); 280 expect_ptr_eq(ptr, arg_result, "Wrong result"); 281 expect_u64_eq((uintptr_t)ptr, (uintptr_t)arg_result_raw, 282 "Wrong raw result"); 283 expect_u64_eq((uintptr_t)11, arg_args_raw[0], "Wrong argument"); 284 expect_u64_eq((uintptr_t)13, arg_args_raw[1], "Wrong argument"); 285 free(ptr); 286 287 /* memalign */ 288 #ifdef JEMALLOC_OVERRIDE_MEMALIGN 289 reset(); 290 ptr = memalign(1024, 1); 291 expect_d_eq(call_count, 1, "Hook not called"); 292 expect_ptr_eq(arg_extra, (void *)123, "Wrong extra"); 293 expect_d_eq(arg_type, (int)hook_alloc_memalign, "Wrong hook type"); 294 expect_ptr_eq(ptr, arg_result, "Wrong result"); 295 expect_u64_eq((uintptr_t)ptr, (uintptr_t)arg_result_raw, 296 "Wrong raw result"); 297 expect_u64_eq((uintptr_t)1024, arg_args_raw[0], "Wrong argument"); 298 expect_u64_eq((uintptr_t)1, arg_args_raw[1], "Wrong argument"); 299 free(ptr); 300 #endif /* JEMALLOC_OVERRIDE_MEMALIGN */ 301 302 /* valloc */ 303 #ifdef JEMALLOC_OVERRIDE_VALLOC 304 reset(); 305 ptr = valloc(1); 306 expect_d_eq(call_count, 1, "Hook not called"); 307 expect_ptr_eq(arg_extra, (void *)123, "Wrong extra"); 308 expect_d_eq(arg_type, (int)hook_alloc_valloc, "Wrong hook type"); 309 expect_ptr_eq(ptr, arg_result, "Wrong result"); 310 expect_u64_eq((uintptr_t)ptr, (uintptr_t)arg_result_raw, 311 "Wrong raw result"); 312 expect_u64_eq((uintptr_t)1, arg_args_raw[0], "Wrong argument"); 313 free(ptr); 314 #endif /* JEMALLOC_OVERRIDE_VALLOC */ 315 316 /* mallocx */ 317 reset(); 318 ptr = mallocx(1, MALLOCX_LG_ALIGN(10)); 319 expect_d_eq(call_count, 1, "Hook not called"); 320 expect_ptr_eq(arg_extra, (void *)123, "Wrong extra"); 321 expect_d_eq(arg_type, (int)hook_alloc_mallocx, "Wrong hook type"); 322 expect_ptr_eq(ptr, arg_result, "Wrong result"); 323 expect_u64_eq((uintptr_t)ptr, (uintptr_t)arg_result_raw, 324 "Wrong raw result"); 325 expect_u64_eq((uintptr_t)1, arg_args_raw[0], "Wrong argument"); 326 expect_u64_eq((uintptr_t)MALLOCX_LG_ALIGN(10), arg_args_raw[1], 327 "Wrong flags"); 328 free(ptr); 329 330 hook_remove(TSDN_NULL, handle); 331 } 332 TEST_END 333 334 TEST_BEGIN(test_hooks_dalloc_simple) { 335 /* "Simple" in the sense that we're not in a realloc variant. */ 336 hooks_t hooks = {NULL, &test_dalloc_hook, NULL, (void *)123}; 337 void *handle = hook_install(TSDN_NULL, &hooks); 338 expect_ptr_ne(handle, NULL, "Hook installation failed"); 339 340 void *volatile ptr; 341 342 /* free() */ 343 reset(); 344 ptr = malloc(1); 345 free(ptr); 346 expect_d_eq(call_count, 1, "Hook not called"); 347 expect_ptr_eq(arg_extra, (void *)123, "Wrong extra"); 348 expect_d_eq(arg_type, (int)hook_dalloc_free, "Wrong hook type"); 349 expect_ptr_eq(ptr, arg_address, "Wrong pointer freed"); 350 expect_u64_eq((uintptr_t)ptr, arg_args_raw[0], "Wrong raw arg"); 351 352 /* dallocx() */ 353 reset(); 354 ptr = malloc(1); 355 dallocx(ptr, MALLOCX_TCACHE_NONE); 356 expect_d_eq(call_count, 1, "Hook not called"); 357 expect_ptr_eq(arg_extra, (void *)123, "Wrong extra"); 358 expect_d_eq(arg_type, (int)hook_dalloc_dallocx, "Wrong hook type"); 359 expect_ptr_eq(ptr, arg_address, "Wrong pointer freed"); 360 expect_u64_eq((uintptr_t)ptr, arg_args_raw[0], "Wrong raw arg"); 361 expect_u64_eq((uintptr_t)MALLOCX_TCACHE_NONE, arg_args_raw[1], 362 "Wrong raw arg"); 363 364 /* sdallocx() */ 365 reset(); 366 ptr = malloc(1); 367 sdallocx(ptr, 1, MALLOCX_TCACHE_NONE); 368 expect_d_eq(call_count, 1, "Hook not called"); 369 expect_ptr_eq(arg_extra, (void *)123, "Wrong extra"); 370 expect_d_eq(arg_type, (int)hook_dalloc_sdallocx, "Wrong hook type"); 371 expect_ptr_eq(ptr, arg_address, "Wrong pointer freed"); 372 expect_u64_eq((uintptr_t)ptr, arg_args_raw[0], "Wrong raw arg"); 373 expect_u64_eq((uintptr_t)1, arg_args_raw[1], "Wrong raw arg"); 374 expect_u64_eq((uintptr_t)MALLOCX_TCACHE_NONE, arg_args_raw[2], 375 "Wrong raw arg"); 376 377 hook_remove(TSDN_NULL, handle); 378 } 379 TEST_END 380 381 TEST_BEGIN(test_hooks_expand_simple) { 382 /* "Simple" in the sense that we're not in a realloc variant. */ 383 hooks_t hooks = {NULL, NULL, &test_expand_hook, (void *)123}; 384 void *handle = hook_install(TSDN_NULL, &hooks); 385 expect_ptr_ne(handle, NULL, "Hook installation failed"); 386 387 void *volatile ptr; 388 389 /* xallocx() */ 390 reset(); 391 ptr = malloc(1); 392 size_t new_usize = xallocx(ptr, 100, 200, MALLOCX_TCACHE_NONE); 393 expect_d_eq(call_count, 1, "Hook not called"); 394 expect_ptr_eq(arg_extra, (void *)123, "Wrong extra"); 395 expect_d_eq(arg_type, (int)hook_expand_xallocx, "Wrong hook type"); 396 expect_ptr_eq(ptr, arg_address, "Wrong pointer expanded"); 397 expect_u64_eq(arg_old_usize, nallocx(1, 0), "Wrong old usize"); 398 expect_u64_eq(arg_new_usize, sallocx(ptr, 0), "Wrong new usize"); 399 expect_u64_eq(new_usize, arg_result_raw, "Wrong result"); 400 expect_u64_eq((uintptr_t)ptr, arg_args_raw[0], "Wrong arg"); 401 expect_u64_eq(100, arg_args_raw[1], "Wrong arg"); 402 expect_u64_eq(200, arg_args_raw[2], "Wrong arg"); 403 expect_u64_eq(MALLOCX_TCACHE_NONE, arg_args_raw[3], "Wrong arg"); 404 405 hook_remove(TSDN_NULL, handle); 406 } 407 TEST_END 408 409 TEST_BEGIN(test_hooks_realloc_as_malloc_or_free) { 410 hooks_t hooks = {&test_alloc_hook, &test_dalloc_hook, 411 &test_expand_hook, (void *)123}; 412 void *handle = hook_install(TSDN_NULL, &hooks); 413 expect_ptr_ne(handle, NULL, "Hook installation failed"); 414 415 void *volatile ptr; 416 417 /* realloc(NULL, size) as malloc */ 418 reset(); 419 ptr = realloc(NULL, 1); 420 expect_d_eq(call_count, 1, "Hook not called"); 421 expect_ptr_eq(arg_extra, (void *)123, "Wrong extra"); 422 expect_d_eq(arg_type, (int)hook_alloc_realloc, "Wrong hook type"); 423 expect_ptr_eq(ptr, arg_result, "Wrong result"); 424 expect_u64_eq((uintptr_t)ptr, (uintptr_t)arg_result_raw, 425 "Wrong raw result"); 426 expect_u64_eq((uintptr_t)NULL, arg_args_raw[0], "Wrong argument"); 427 expect_u64_eq((uintptr_t)1, arg_args_raw[1], "Wrong argument"); 428 free(ptr); 429 430 /* realloc(ptr, 0) as free */ 431 if (opt_zero_realloc_action == zero_realloc_action_free) { 432 ptr = malloc(1); 433 reset(); 434 realloc(ptr, 0); 435 expect_d_eq(call_count, 1, "Hook not called"); 436 expect_ptr_eq(arg_extra, (void *)123, "Wrong extra"); 437 expect_d_eq(arg_type, (int)hook_dalloc_realloc, 438 "Wrong hook type"); 439 expect_ptr_eq(ptr, arg_address, 440 "Wrong pointer freed"); 441 expect_u64_eq((uintptr_t)ptr, arg_args_raw[0], 442 "Wrong raw arg"); 443 expect_u64_eq((uintptr_t)0, arg_args_raw[1], 444 "Wrong raw arg"); 445 } 446 447 /* realloc(NULL, 0) as malloc(0) */ 448 reset(); 449 ptr = realloc(NULL, 0); 450 expect_d_eq(call_count, 1, "Hook not called"); 451 expect_ptr_eq(arg_extra, (void *)123, "Wrong extra"); 452 expect_d_eq(arg_type, (int)hook_alloc_realloc, "Wrong hook type"); 453 expect_ptr_eq(ptr, arg_result, "Wrong result"); 454 expect_u64_eq((uintptr_t)ptr, (uintptr_t)arg_result_raw, 455 "Wrong raw result"); 456 expect_u64_eq((uintptr_t)NULL, arg_args_raw[0], "Wrong argument"); 457 expect_u64_eq((uintptr_t)0, arg_args_raw[1], "Wrong argument"); 458 free(ptr); 459 460 hook_remove(TSDN_NULL, handle); 461 } 462 TEST_END 463 464 static void 465 do_realloc_test(void *(*ralloc)(void *, size_t, int), int flags, 466 int expand_type, int dalloc_type) { 467 hooks_t hooks = {&test_alloc_hook, &test_dalloc_hook, 468 &test_expand_hook, (void *)123}; 469 void *handle = hook_install(TSDN_NULL, &hooks); 470 expect_ptr_ne(handle, NULL, "Hook installation failed"); 471 472 void *volatile ptr; 473 void *volatile ptr2; 474 475 /* Realloc in-place, small. */ 476 ptr = malloc(129); 477 reset(); 478 ptr2 = ralloc(ptr, 130, flags); 479 expect_ptr_eq(ptr, ptr2, "Small realloc moved"); 480 481 expect_d_eq(call_count, 1, "Hook not called"); 482 expect_ptr_eq(arg_extra, (void *)123, "Wrong extra"); 483 expect_d_eq(arg_type, expand_type, "Wrong hook type"); 484 expect_ptr_eq(ptr, arg_address, "Wrong address"); 485 expect_u64_eq((uintptr_t)ptr, (uintptr_t)arg_result_raw, 486 "Wrong raw result"); 487 expect_u64_eq((uintptr_t)ptr, arg_args_raw[0], "Wrong argument"); 488 expect_u64_eq((uintptr_t)130, arg_args_raw[1], "Wrong argument"); 489 free(ptr); 490 491 /* 492 * Realloc in-place, large. Since we can't guarantee the large case 493 * across all platforms, we stay resilient to moving results. 494 */ 495 ptr = malloc(2 * 1024 * 1024); 496 free(ptr); 497 ptr2 = malloc(1 * 1024 * 1024); 498 reset(); 499 ptr = ralloc(ptr2, 2 * 1024 * 1024, flags); 500 /* ptr is the new address, ptr2 is the old address. */ 501 if (ptr == ptr2) { 502 expect_d_eq(call_count, 1, "Hook not called"); 503 expect_d_eq(arg_type, expand_type, "Wrong hook type"); 504 } else { 505 expect_d_eq(call_count, 2, "Wrong hooks called"); 506 expect_ptr_eq(ptr, arg_result, "Wrong address"); 507 expect_d_eq(arg_type, dalloc_type, "Wrong hook type"); 508 } 509 expect_ptr_eq(arg_extra, (void *)123, "Wrong extra"); 510 expect_ptr_eq(ptr2, arg_address, "Wrong address"); 511 expect_u64_eq((uintptr_t)ptr, (uintptr_t)arg_result_raw, 512 "Wrong raw result"); 513 expect_u64_eq((uintptr_t)ptr2, arg_args_raw[0], "Wrong argument"); 514 expect_u64_eq((uintptr_t)2 * 1024 * 1024, arg_args_raw[1], 515 "Wrong argument"); 516 free(ptr); 517 518 /* Realloc with move, small. */ 519 ptr = malloc(8); 520 reset(); 521 ptr2 = ralloc(ptr, 128, flags); 522 expect_ptr_ne(ptr, ptr2, "Small realloc didn't move"); 523 524 expect_d_eq(call_count, 2, "Hook not called"); 525 expect_ptr_eq(arg_extra, (void *)123, "Wrong extra"); 526 expect_d_eq(arg_type, dalloc_type, "Wrong hook type"); 527 expect_ptr_eq(ptr, arg_address, "Wrong address"); 528 expect_ptr_eq(ptr2, arg_result, "Wrong address"); 529 expect_u64_eq((uintptr_t)ptr2, (uintptr_t)arg_result_raw, 530 "Wrong raw result"); 531 expect_u64_eq((uintptr_t)ptr, arg_args_raw[0], "Wrong argument"); 532 expect_u64_eq((uintptr_t)128, arg_args_raw[1], "Wrong argument"); 533 free(ptr2); 534 535 /* Realloc with move, large. */ 536 ptr = malloc(1); 537 reset(); 538 ptr2 = ralloc(ptr, 2 * 1024 * 1024, flags); 539 expect_ptr_ne(ptr, ptr2, "Large realloc didn't move"); 540 541 expect_d_eq(call_count, 2, "Hook not called"); 542 expect_ptr_eq(arg_extra, (void *)123, "Wrong extra"); 543 expect_d_eq(arg_type, dalloc_type, "Wrong hook type"); 544 expect_ptr_eq(ptr, arg_address, "Wrong address"); 545 expect_ptr_eq(ptr2, arg_result, "Wrong address"); 546 expect_u64_eq((uintptr_t)ptr2, (uintptr_t)arg_result_raw, 547 "Wrong raw result"); 548 expect_u64_eq((uintptr_t)ptr, arg_args_raw[0], "Wrong argument"); 549 expect_u64_eq((uintptr_t)2 * 1024 * 1024, arg_args_raw[1], 550 "Wrong argument"); 551 free(ptr2); 552 553 hook_remove(TSDN_NULL, handle); 554 } 555 556 static void * 557 realloc_wrapper(void *ptr, size_t size, UNUSED int flags) { 558 return realloc(ptr, size); 559 } 560 561 TEST_BEGIN(test_hooks_realloc) { 562 do_realloc_test(&realloc_wrapper, 0, hook_expand_realloc, 563 hook_dalloc_realloc); 564 } 565 TEST_END 566 567 TEST_BEGIN(test_hooks_rallocx) { 568 do_realloc_test(&rallocx, MALLOCX_TCACHE_NONE, hook_expand_rallocx, 569 hook_dalloc_rallocx); 570 } 571 TEST_END 572 573 int 574 main(void) { 575 /* We assert on call counts. */ 576 return test_no_reentrancy( 577 test_hooks_basic, 578 test_hooks_null, 579 test_hooks_remove, 580 test_hooks_alloc_simple, 581 test_hooks_dalloc_simple, 582 test_hooks_expand_simple, 583 test_hooks_realloc_as_malloc_or_free, 584 test_hooks_realloc, 585 test_hooks_rallocx); 586 } 587