Home | History | Annotate | Line # | Download | only in unit
      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