1 #include "test/jemalloc_test.h" 2 #include "test/san.h" 3 4 #include "jemalloc/internal/safety_check.h" 5 6 bool fake_abort_called; 7 void fake_abort(const char *message) { 8 (void)message; 9 fake_abort_called = true; 10 } 11 12 void 13 test_large_double_free_pre(void) { 14 safety_check_set_abort(&fake_abort); 15 fake_abort_called = false; 16 } 17 18 void 19 test_large_double_free_post() { 20 expect_b_eq(fake_abort_called, true, "Double-free check didn't fire."); 21 safety_check_set_abort(NULL); 22 } 23 24 TEST_BEGIN(test_large_double_free_tcache) { 25 test_skip_if(!config_opt_safety_checks); 26 /* 27 * Skip debug builds, since too many assertions will be triggered with 28 * double-free before hitting the one we are interested in. 29 */ 30 test_skip_if(config_debug); 31 32 test_large_double_free_pre(); 33 char *ptr = malloc(SC_LARGE_MINCLASS); 34 bool guarded = extent_is_guarded(tsdn_fetch(), ptr); 35 free(ptr); 36 if (!guarded) { 37 free(ptr); 38 } else { 39 /* 40 * Skip because guarded extents may unguard immediately on 41 * deallocation, in which case the second free will crash before 42 * reaching the intended safety check. 43 */ 44 fake_abort_called = true; 45 } 46 mallctl("thread.tcache.flush", NULL, NULL, NULL, 0); 47 test_large_double_free_post(); 48 } 49 TEST_END 50 51 TEST_BEGIN(test_large_double_free_no_tcache) { 52 test_skip_if(!config_opt_safety_checks); 53 test_skip_if(config_debug); 54 55 test_large_double_free_pre(); 56 char *ptr = mallocx(SC_LARGE_MINCLASS, MALLOCX_TCACHE_NONE); 57 bool guarded = extent_is_guarded(tsdn_fetch(), ptr); 58 dallocx(ptr, MALLOCX_TCACHE_NONE); 59 if (!guarded) { 60 dallocx(ptr, MALLOCX_TCACHE_NONE); 61 } else { 62 /* 63 * Skip because guarded extents may unguard immediately on 64 * deallocation, in which case the second free will crash before 65 * reaching the intended safety check. 66 */ 67 fake_abort_called = true; 68 } 69 test_large_double_free_post(); 70 } 71 TEST_END 72 73 int 74 main(void) { 75 return test(test_large_double_free_no_tcache, 76 test_large_double_free_tcache); 77 } 78