Home | History | Annotate | Download | only in integration
      1 #include "test/jemalloc_test.h"
      2 
      3 /*
      4  * Use a separate arena for xallocx() extension/contraction tests so that
      5  * internal allocation e.g. by heap profiling can't interpose allocations where
      6  * xallocx() would ordinarily be able to extend.
      7  */
      8 static unsigned
      9 arena_ind(void)
     10 {
     11 	static unsigned ind = 0;
     12 
     13 	if (ind == 0) {
     14 		size_t sz = sizeof(ind);
     15 		assert_d_eq(mallctl("arenas.extend", &ind, &sz, NULL, 0), 0,
     16 		    "Unexpected mallctl failure creating arena");
     17 	}
     18 
     19 	return (ind);
     20 }
     21 
     22 TEST_BEGIN(test_same_size)
     23 {
     24 	void *p;
     25 	size_t sz, tsz;
     26 
     27 	p = mallocx(42, 0);
     28 	assert_ptr_not_null(p, "Unexpected mallocx() error");
     29 	sz = sallocx(p, 0);
     30 
     31 	tsz = xallocx(p, sz, 0, 0);
     32 	assert_zu_eq(tsz, sz, "Unexpected size change: %zu --> %zu", sz, tsz);
     33 
     34 	dallocx(p, 0);
     35 }
     36 TEST_END
     37 
     38 TEST_BEGIN(test_extra_no_move)
     39 {
     40 	void *p;
     41 	size_t sz, tsz;
     42 
     43 	p = mallocx(42, 0);
     44 	assert_ptr_not_null(p, "Unexpected mallocx() error");
     45 	sz = sallocx(p, 0);
     46 
     47 	tsz = xallocx(p, sz, sz-42, 0);
     48 	assert_zu_eq(tsz, sz, "Unexpected size change: %zu --> %zu", sz, tsz);
     49 
     50 	dallocx(p, 0);
     51 }
     52 TEST_END
     53 
     54 TEST_BEGIN(test_no_move_fail)
     55 {
     56 	void *p;
     57 	size_t sz, tsz;
     58 
     59 	p = mallocx(42, 0);
     60 	assert_ptr_not_null(p, "Unexpected mallocx() error");
     61 	sz = sallocx(p, 0);
     62 
     63 	tsz = xallocx(p, sz + 5, 0, 0);
     64 	assert_zu_eq(tsz, sz, "Unexpected size change: %zu --> %zu", sz, tsz);
     65 
     66 	dallocx(p, 0);
     67 }
     68 TEST_END
     69 
     70 static unsigned
     71 get_nsizes_impl(const char *cmd)
     72 {
     73 	unsigned ret;
     74 	size_t z;
     75 
     76 	z = sizeof(unsigned);
     77 	assert_d_eq(mallctl(cmd, &ret, &z, NULL, 0), 0,
     78 	    "Unexpected mallctl(\"%s\", ...) failure", cmd);
     79 
     80 	return (ret);
     81 }
     82 
     83 static unsigned
     84 get_nsmall(void)
     85 {
     86 
     87 	return (get_nsizes_impl("arenas.nbins"));
     88 }
     89 
     90 static unsigned
     91 get_nlarge(void)
     92 {
     93 
     94 	return (get_nsizes_impl("arenas.nlruns"));
     95 }
     96 
     97 static unsigned
     98 get_nhuge(void)
     99 {
    100 
    101 	return (get_nsizes_impl("arenas.nhchunks"));
    102 }
    103 
    104 static size_t
    105 get_size_impl(const char *cmd, size_t ind)
    106 {
    107 	size_t ret;
    108 	size_t z;
    109 	size_t mib[4];
    110 	size_t miblen = 4;
    111 
    112 	z = sizeof(size_t);
    113 	assert_d_eq(mallctlnametomib(cmd, mib, &miblen),
    114 	    0, "Unexpected mallctlnametomib(\"%s\", ...) failure", cmd);
    115 	mib[2] = ind;
    116 	z = sizeof(size_t);
    117 	assert_d_eq(mallctlbymib(mib, miblen, &ret, &z, NULL, 0),
    118 	    0, "Unexpected mallctlbymib([\"%s\", %zu], ...) failure", cmd, ind);
    119 
    120 	return (ret);
    121 }
    122 
    123 static size_t
    124 get_small_size(size_t ind)
    125 {
    126 
    127 	return (get_size_impl("arenas.bin.0.size", ind));
    128 }
    129 
    130 static size_t
    131 get_large_size(size_t ind)
    132 {
    133 
    134 	return (get_size_impl("arenas.lrun.0.size", ind));
    135 }
    136 
    137 static size_t
    138 get_huge_size(size_t ind)
    139 {
    140 
    141 	return (get_size_impl("arenas.hchunk.0.size", ind));
    142 }
    143 
    144 TEST_BEGIN(test_size)
    145 {
    146 	size_t small0, hugemax;
    147 	void *p;
    148 
    149 	/* Get size classes. */
    150 	small0 = get_small_size(0);
    151 	hugemax = get_huge_size(get_nhuge()-1);
    152 
    153 	p = mallocx(small0, 0);
    154 	assert_ptr_not_null(p, "Unexpected mallocx() error");
    155 
    156 	/* Test smallest supported size. */
    157 	assert_zu_eq(xallocx(p, 1, 0, 0), small0,
    158 	    "Unexpected xallocx() behavior");
    159 
    160 	/* Test largest supported size. */
    161 	assert_zu_le(xallocx(p, hugemax, 0, 0), hugemax,
    162 	    "Unexpected xallocx() behavior");
    163 
    164 	/* Test size overflow. */
    165 	assert_zu_le(xallocx(p, hugemax+1, 0, 0), hugemax,
    166 	    "Unexpected xallocx() behavior");
    167 	assert_zu_le(xallocx(p, SIZE_T_MAX, 0, 0), hugemax,
    168 	    "Unexpected xallocx() behavior");
    169 
    170 	dallocx(p, 0);
    171 }
    172 TEST_END
    173 
    174 TEST_BEGIN(test_size_extra_overflow)
    175 {
    176 	size_t small0, hugemax;
    177 	void *p;
    178 
    179 	/* Get size classes. */
    180 	small0 = get_small_size(0);
    181 	hugemax = get_huge_size(get_nhuge()-1);
    182 
    183 	p = mallocx(small0, 0);
    184 	assert_ptr_not_null(p, "Unexpected mallocx() error");
    185 
    186 	/* Test overflows that can be resolved by clamping extra. */
    187 	assert_zu_le(xallocx(p, hugemax-1, 2, 0), hugemax,
    188 	    "Unexpected xallocx() behavior");
    189 	assert_zu_le(xallocx(p, hugemax, 1, 0), hugemax,
    190 	    "Unexpected xallocx() behavior");
    191 
    192 	/* Test overflow such that hugemax-size underflows. */
    193 	assert_zu_le(xallocx(p, hugemax+1, 2, 0), hugemax,
    194 	    "Unexpected xallocx() behavior");
    195 	assert_zu_le(xallocx(p, hugemax+2, 3, 0), hugemax,
    196 	    "Unexpected xallocx() behavior");
    197 	assert_zu_le(xallocx(p, SIZE_T_MAX-2, 2, 0), hugemax,
    198 	    "Unexpected xallocx() behavior");
    199 	assert_zu_le(xallocx(p, SIZE_T_MAX-1, 1, 0), hugemax,
    200 	    "Unexpected xallocx() behavior");
    201 
    202 	dallocx(p, 0);
    203 }
    204 TEST_END
    205 
    206 TEST_BEGIN(test_extra_small)
    207 {
    208 	size_t small0, small1, hugemax;
    209 	void *p;
    210 
    211 	/* Get size classes. */
    212 	small0 = get_small_size(0);
    213 	small1 = get_small_size(1);
    214 	hugemax = get_huge_size(get_nhuge()-1);
    215 
    216 	p = mallocx(small0, 0);
    217 	assert_ptr_not_null(p, "Unexpected mallocx() error");
    218 
    219 	assert_zu_eq(xallocx(p, small1, 0, 0), small0,
    220 	    "Unexpected xallocx() behavior");
    221 
    222 	assert_zu_eq(xallocx(p, small1, 0, 0), small0,
    223 	    "Unexpected xallocx() behavior");
    224 
    225 	assert_zu_eq(xallocx(p, small0, small1 - small0, 0), small0,
    226 	    "Unexpected xallocx() behavior");
    227 
    228 	/* Test size+extra overflow. */
    229 	assert_zu_eq(xallocx(p, small0, hugemax - small0 + 1, 0), small0,
    230 	    "Unexpected xallocx() behavior");
    231 	assert_zu_eq(xallocx(p, small0, SIZE_T_MAX - small0, 0), small0,
    232 	    "Unexpected xallocx() behavior");
    233 
    234 	dallocx(p, 0);
    235 }
    236 TEST_END
    237 
    238 TEST_BEGIN(test_extra_large)
    239 {
    240 	int flags = MALLOCX_ARENA(arena_ind());
    241 	size_t smallmax, large0, large1, large2, huge0, hugemax;
    242 	void *p;
    243 
    244 	/* Get size classes. */
    245 	smallmax = get_small_size(get_nsmall()-1);
    246 	large0 = get_large_size(0);
    247 	large1 = get_large_size(1);
    248 	large2 = get_large_size(2);
    249 	huge0 = get_huge_size(0);
    250 	hugemax = get_huge_size(get_nhuge()-1);
    251 
    252 	p = mallocx(large2, flags);
    253 	assert_ptr_not_null(p, "Unexpected mallocx() error");
    254 
    255 	assert_zu_eq(xallocx(p, large2, 0, flags), large2,
    256 	    "Unexpected xallocx() behavior");
    257 	/* Test size decrease with zero extra. */
    258 	assert_zu_eq(xallocx(p, large0, 0, flags), large0,
    259 	    "Unexpected xallocx() behavior");
    260 	assert_zu_eq(xallocx(p, smallmax, 0, flags), large0,
    261 	    "Unexpected xallocx() behavior");
    262 
    263 	assert_zu_eq(xallocx(p, large2, 0, flags), large2,
    264 	    "Unexpected xallocx() behavior");
    265 	/* Test size decrease with non-zero extra. */
    266 	assert_zu_eq(xallocx(p, large0, large2 - large0, flags), large2,
    267 	    "Unexpected xallocx() behavior");
    268 	assert_zu_eq(xallocx(p, large1, large2 - large1, flags), large2,
    269 	    "Unexpected xallocx() behavior");
    270 	assert_zu_eq(xallocx(p, large0, large1 - large0, flags), large1,
    271 	    "Unexpected xallocx() behavior");
    272 	assert_zu_eq(xallocx(p, smallmax, large0 - smallmax, flags), large0,
    273 	    "Unexpected xallocx() behavior");
    274 
    275 	assert_zu_eq(xallocx(p, large0, 0, flags), large0,
    276 	    "Unexpected xallocx() behavior");
    277 	/* Test size increase with zero extra. */
    278 	assert_zu_eq(xallocx(p, large2, 0, flags), large2,
    279 	    "Unexpected xallocx() behavior");
    280 	assert_zu_eq(xallocx(p, huge0, 0, flags), large2,
    281 	    "Unexpected xallocx() behavior");
    282 
    283 	assert_zu_eq(xallocx(p, large0, 0, flags), large0,
    284 	    "Unexpected xallocx() behavior");
    285 	/* Test size increase with non-zero extra. */
    286 	assert_zu_lt(xallocx(p, large0, huge0 - large0, flags), huge0,
    287 	    "Unexpected xallocx() behavior");
    288 
    289 	assert_zu_eq(xallocx(p, large0, 0, flags), large0,
    290 	    "Unexpected xallocx() behavior");
    291 	/* Test size increase with non-zero extra. */
    292 	assert_zu_eq(xallocx(p, large0, large2 - large0, flags), large2,
    293 	    "Unexpected xallocx() behavior");
    294 
    295 	assert_zu_eq(xallocx(p, large2, 0, flags), large2,
    296 	    "Unexpected xallocx() behavior");
    297 	/* Test size+extra overflow. */
    298 	assert_zu_lt(xallocx(p, large2, hugemax - large2 + 1, flags), huge0,
    299 	    "Unexpected xallocx() behavior");
    300 
    301 	dallocx(p, flags);
    302 }
    303 TEST_END
    304 
    305 TEST_BEGIN(test_extra_huge)
    306 {
    307 	int flags = MALLOCX_ARENA(arena_ind());
    308 	size_t largemax, huge1, huge2, huge3, hugemax;
    309 	void *p;
    310 
    311 	/* Get size classes. */
    312 	largemax = get_large_size(get_nlarge()-1);
    313 	huge1 = get_huge_size(1);
    314 	huge2 = get_huge_size(2);
    315 	huge3 = get_huge_size(3);
    316 	hugemax = get_huge_size(get_nhuge()-1);
    317 
    318 	p = mallocx(huge3, flags);
    319 	assert_ptr_not_null(p, "Unexpected mallocx() error");
    320 
    321 	assert_zu_eq(xallocx(p, huge3, 0, flags), huge3,
    322 	    "Unexpected xallocx() behavior");
    323 	/* Test size decrease with zero extra. */
    324 	assert_zu_ge(xallocx(p, huge1, 0, flags), huge1,
    325 	    "Unexpected xallocx() behavior");
    326 	assert_zu_ge(xallocx(p, largemax, 0, flags), huge1,
    327 	    "Unexpected xallocx() behavior");
    328 
    329 	assert_zu_eq(xallocx(p, huge3, 0, flags), huge3,
    330 	    "Unexpected xallocx() behavior");
    331 	/* Test size decrease with non-zero extra. */
    332 	assert_zu_eq(xallocx(p, huge1, huge3 - huge1, flags), huge3,
    333 	    "Unexpected xallocx() behavior");
    334 	assert_zu_eq(xallocx(p, huge2, huge3 - huge2, flags), huge3,
    335 	    "Unexpected xallocx() behavior");
    336 	assert_zu_eq(xallocx(p, huge1, huge2 - huge1, flags), huge2,
    337 	    "Unexpected xallocx() behavior");
    338 	assert_zu_ge(xallocx(p, largemax, huge1 - largemax, flags), huge1,
    339 	    "Unexpected xallocx() behavior");
    340 
    341 	assert_zu_ge(xallocx(p, huge1, 0, flags), huge1,
    342 	    "Unexpected xallocx() behavior");
    343 	/* Test size increase with zero extra. */
    344 	assert_zu_le(xallocx(p, huge3, 0, flags), huge3,
    345 	    "Unexpected xallocx() behavior");
    346 	assert_zu_le(xallocx(p, hugemax+1, 0, flags), huge3,
    347 	    "Unexpected xallocx() behavior");
    348 
    349 	assert_zu_ge(xallocx(p, huge1, 0, flags), huge1,
    350 	    "Unexpected xallocx() behavior");
    351 	/* Test size increase with non-zero extra. */
    352 	assert_zu_le(xallocx(p, huge1, SIZE_T_MAX - huge1, flags), hugemax,
    353 	    "Unexpected xallocx() behavior");
    354 
    355 	assert_zu_ge(xallocx(p, huge1, 0, flags), huge1,
    356 	    "Unexpected xallocx() behavior");
    357 	/* Test size increase with non-zero extra. */
    358 	assert_zu_le(xallocx(p, huge1, huge3 - huge1, flags), huge3,
    359 	    "Unexpected xallocx() behavior");
    360 
    361 	assert_zu_eq(xallocx(p, huge3, 0, flags), huge3,
    362 	    "Unexpected xallocx() behavior");
    363 	/* Test size+extra overflow. */
    364 	assert_zu_le(xallocx(p, huge3, hugemax - huge3 + 1, flags), hugemax,
    365 	    "Unexpected xallocx() behavior");
    366 
    367 	dallocx(p, flags);
    368 }
    369 TEST_END
    370 
    371 static void
    372 print_filled_extents(const void *p, uint8_t c, size_t len)
    373 {
    374 	const uint8_t *pc = (const uint8_t *)p;
    375 	size_t i, range0;
    376 	uint8_t c0;
    377 
    378 	malloc_printf("  p=%p, c=%#x, len=%zu:", p, c, len);
    379 	range0 = 0;
    380 	c0 = pc[0];
    381 	for (i = 0; i < len; i++) {
    382 		if (pc[i] != c0) {
    383 			malloc_printf(" %#x[%zu..%zu)", c0, range0, i);
    384 			range0 = i;
    385 			c0 = pc[i];
    386 		}
    387 	}
    388 	malloc_printf(" %#x[%zu..%zu)\n", c0, range0, i);
    389 }
    390 
    391 static bool
    392 validate_fill(const void *p, uint8_t c, size_t offset, size_t len)
    393 {
    394 	const uint8_t *pc = (const uint8_t *)p;
    395 	bool err;
    396 	size_t i;
    397 
    398 	for (i = offset, err = false; i < offset+len; i++) {
    399 		if (pc[i] != c)
    400 			err = true;
    401 	}
    402 
    403 	if (err)
    404 		print_filled_extents(p, c, offset + len);
    405 
    406 	return (err);
    407 }
    408 
    409 static void
    410 test_zero(size_t szmin, size_t szmax)
    411 {
    412 	int flags = MALLOCX_ARENA(arena_ind()) | MALLOCX_ZERO;
    413 	size_t sz, nsz;
    414 	void *p;
    415 #define	FILL_BYTE 0x7aU
    416 
    417 	sz = szmax;
    418 	p = mallocx(sz, flags);
    419 	assert_ptr_not_null(p, "Unexpected mallocx() error");
    420 	assert_false(validate_fill(p, 0x00, 0, sz), "Memory not filled: sz=%zu",
    421 	    sz);
    422 
    423 	/*
    424 	 * Fill with non-zero so that non-debug builds are more likely to detect
    425 	 * errors.
    426 	 */
    427 	memset(p, FILL_BYTE, sz);
    428 	assert_false(validate_fill(p, FILL_BYTE, 0, sz),
    429 	    "Memory not filled: sz=%zu", sz);
    430 
    431 	/* Shrink in place so that we can expect growing in place to succeed. */
    432 	sz = szmin;
    433 	assert_zu_eq(xallocx(p, sz, 0, flags), sz,
    434 	    "Unexpected xallocx() error");
    435 	assert_false(validate_fill(p, FILL_BYTE, 0, sz),
    436 	    "Memory not filled: sz=%zu", sz);
    437 
    438 	for (sz = szmin; sz < szmax; sz = nsz) {
    439 		nsz = nallocx(sz+1, flags);
    440 		assert_zu_eq(xallocx(p, sz+1, 0, flags), nsz,
    441 		    "Unexpected xallocx() failure");
    442 		assert_false(validate_fill(p, FILL_BYTE, 0, sz),
    443 		    "Memory not filled: sz=%zu", sz);
    444 		assert_false(validate_fill(p, 0x00, sz, nsz-sz),
    445 		    "Memory not filled: sz=%zu, nsz-sz=%zu", sz, nsz-sz);
    446 		memset((void *)((uintptr_t)p + sz), FILL_BYTE, nsz-sz);
    447 		assert_false(validate_fill(p, FILL_BYTE, 0, nsz),
    448 		    "Memory not filled: nsz=%zu", nsz);
    449 	}
    450 
    451 	dallocx(p, flags);
    452 }
    453 
    454 TEST_BEGIN(test_zero_large)
    455 {
    456 	size_t large0, largemax;
    457 
    458 	/* Get size classes. */
    459 	large0 = get_large_size(0);
    460 	largemax = get_large_size(get_nlarge()-1);
    461 
    462 	test_zero(large0, largemax);
    463 }
    464 TEST_END
    465 
    466 TEST_BEGIN(test_zero_huge)
    467 {
    468 	size_t huge0, huge1;
    469 
    470 	/* Get size classes. */
    471 	huge0 = get_huge_size(0);
    472 	huge1 = get_huge_size(1);
    473 
    474 	test_zero(huge1, huge0 * 2);
    475 }
    476 TEST_END
    477 
    478 int
    479 main(void)
    480 {
    481 
    482 	return (test(
    483 	    test_same_size,
    484 	    test_extra_no_move,
    485 	    test_no_move_fail,
    486 	    test_size,
    487 	    test_size_extra_overflow,
    488 	    test_extra_small,
    489 	    test_extra_large,
    490 	    test_extra_huge,
    491 	    test_zero_large,
    492 	    test_zero_huge));
    493 }
    494