1a0698ed9Schristos #include "test/jemalloc_test.h" 2a0698ed9Schristos 3a0698ed9Schristos static unsigned 4a0698ed9Schristos get_nsizes_impl(const char *cmd) { 5a0698ed9Schristos unsigned ret; 6a0698ed9Schristos size_t z; 7a0698ed9Schristos 8a0698ed9Schristos z = sizeof(unsigned); 9*7bdf38e5Schristos expect_d_eq(mallctl(cmd, (void *)&ret, &z, NULL, 0), 0, 10a0698ed9Schristos "Unexpected mallctl(\"%s\", ...) failure", cmd); 11a0698ed9Schristos 12a0698ed9Schristos return ret; 13a0698ed9Schristos } 14a0698ed9Schristos 15a0698ed9Schristos static unsigned 16a0698ed9Schristos get_nlarge(void) { 17a0698ed9Schristos return get_nsizes_impl("arenas.nlextents"); 18a0698ed9Schristos } 19a0698ed9Schristos 20a0698ed9Schristos static size_t 21a0698ed9Schristos get_size_impl(const char *cmd, size_t ind) { 22a0698ed9Schristos size_t ret; 23a0698ed9Schristos size_t z; 24a0698ed9Schristos size_t mib[4]; 25a0698ed9Schristos size_t miblen = 4; 26a0698ed9Schristos 27a0698ed9Schristos z = sizeof(size_t); 28*7bdf38e5Schristos expect_d_eq(mallctlnametomib(cmd, mib, &miblen), 29a0698ed9Schristos 0, "Unexpected mallctlnametomib(\"%s\", ...) failure", cmd); 30a0698ed9Schristos mib[2] = ind; 31a0698ed9Schristos z = sizeof(size_t); 32*7bdf38e5Schristos expect_d_eq(mallctlbymib(mib, miblen, (void *)&ret, &z, NULL, 0), 33a0698ed9Schristos 0, "Unexpected mallctlbymib([\"%s\", %zu], ...) failure", cmd, ind); 34a0698ed9Schristos 35a0698ed9Schristos return ret; 36a0698ed9Schristos } 37a0698ed9Schristos 38a0698ed9Schristos static size_t 39a0698ed9Schristos get_large_size(size_t ind) { 40a0698ed9Schristos return get_size_impl("arenas.lextent.0.size", ind); 41a0698ed9Schristos } 42a0698ed9Schristos 43a0698ed9Schristos TEST_BEGIN(test_grow_and_shrink) { 44*7bdf38e5Schristos /* 45*7bdf38e5Schristos * Use volatile to workaround buffer overflow false positives 46*7bdf38e5Schristos * (-D_FORTIFY_SOURCE=3). 47*7bdf38e5Schristos */ 48*7bdf38e5Schristos void *volatile p, *volatile q; 49a0698ed9Schristos size_t tsz; 50a0698ed9Schristos #define NCYCLES 3 51a0698ed9Schristos unsigned i, j; 52a0698ed9Schristos #define NSZS 1024 53a0698ed9Schristos size_t szs[NSZS]; 54a0698ed9Schristos #define MAXSZ ZU(12 * 1024 * 1024) 55a0698ed9Schristos 56a0698ed9Schristos p = mallocx(1, 0); 57*7bdf38e5Schristos expect_ptr_not_null(p, "Unexpected mallocx() error"); 58a0698ed9Schristos szs[0] = sallocx(p, 0); 59a0698ed9Schristos 60a0698ed9Schristos for (i = 0; i < NCYCLES; i++) { 61a0698ed9Schristos for (j = 1; j < NSZS && szs[j-1] < MAXSZ; j++) { 62a0698ed9Schristos q = rallocx(p, szs[j-1]+1, 0); 63*7bdf38e5Schristos expect_ptr_not_null(q, 64a0698ed9Schristos "Unexpected rallocx() error for size=%zu-->%zu", 65a0698ed9Schristos szs[j-1], szs[j-1]+1); 66a0698ed9Schristos szs[j] = sallocx(q, 0); 67*7bdf38e5Schristos expect_zu_ne(szs[j], szs[j-1]+1, 68a0698ed9Schristos "Expected size to be at least: %zu", szs[j-1]+1); 69a0698ed9Schristos p = q; 70a0698ed9Schristos } 71a0698ed9Schristos 72a0698ed9Schristos for (j--; j > 0; j--) { 73a0698ed9Schristos q = rallocx(p, szs[j-1], 0); 74*7bdf38e5Schristos expect_ptr_not_null(q, 75a0698ed9Schristos "Unexpected rallocx() error for size=%zu-->%zu", 76a0698ed9Schristos szs[j], szs[j-1]); 77a0698ed9Schristos tsz = sallocx(q, 0); 78*7bdf38e5Schristos expect_zu_eq(tsz, szs[j-1], 79a0698ed9Schristos "Expected size=%zu, got size=%zu", szs[j-1], tsz); 80a0698ed9Schristos p = q; 81a0698ed9Schristos } 82a0698ed9Schristos } 83a0698ed9Schristos 84a0698ed9Schristos dallocx(p, 0); 85a0698ed9Schristos #undef MAXSZ 86a0698ed9Schristos #undef NSZS 87a0698ed9Schristos #undef NCYCLES 88a0698ed9Schristos } 89a0698ed9Schristos TEST_END 90a0698ed9Schristos 91a0698ed9Schristos static bool 92*7bdf38e5Schristos validate_fill(void *p, uint8_t c, size_t offset, size_t len) { 93a0698ed9Schristos bool ret = false; 94*7bdf38e5Schristos /* 95*7bdf38e5Schristos * Use volatile to workaround buffer overflow false positives 96*7bdf38e5Schristos * (-D_FORTIFY_SOURCE=3). 97*7bdf38e5Schristos */ 98*7bdf38e5Schristos uint8_t *volatile buf = (uint8_t *)p; 99a0698ed9Schristos size_t i; 100a0698ed9Schristos 101a0698ed9Schristos for (i = 0; i < len; i++) { 102a0698ed9Schristos uint8_t b = buf[offset+i]; 103a0698ed9Schristos if (b != c) { 104a0698ed9Schristos test_fail("Allocation at %p (len=%zu) contains %#x " 105a0698ed9Schristos "rather than %#x at offset %zu", p, len, b, c, 106a0698ed9Schristos offset+i); 107a0698ed9Schristos ret = true; 108a0698ed9Schristos } 109a0698ed9Schristos } 110a0698ed9Schristos 111a0698ed9Schristos return ret; 112a0698ed9Schristos } 113a0698ed9Schristos 114a0698ed9Schristos TEST_BEGIN(test_zero) { 115*7bdf38e5Schristos /* 116*7bdf38e5Schristos * Use volatile to workaround buffer overflow false positives 117*7bdf38e5Schristos * (-D_FORTIFY_SOURCE=3). 118*7bdf38e5Schristos */ 119*7bdf38e5Schristos void *volatile p, *volatile q; 120a0698ed9Schristos size_t psz, qsz, i, j; 121a0698ed9Schristos size_t start_sizes[] = {1, 3*1024, 63*1024, 4095*1024}; 122a0698ed9Schristos #define FILL_BYTE 0xaaU 123a0698ed9Schristos #define RANGE 2048 124a0698ed9Schristos 125a0698ed9Schristos for (i = 0; i < sizeof(start_sizes)/sizeof(size_t); i++) { 126a0698ed9Schristos size_t start_size = start_sizes[i]; 127a0698ed9Schristos p = mallocx(start_size, MALLOCX_ZERO); 128*7bdf38e5Schristos expect_ptr_not_null(p, "Unexpected mallocx() error"); 129a0698ed9Schristos psz = sallocx(p, 0); 130a0698ed9Schristos 131*7bdf38e5Schristos expect_false(validate_fill(p, 0, 0, psz), 132a0698ed9Schristos "Expected zeroed memory"); 133a0698ed9Schristos memset(p, FILL_BYTE, psz); 134*7bdf38e5Schristos expect_false(validate_fill(p, FILL_BYTE, 0, psz), 135a0698ed9Schristos "Expected filled memory"); 136a0698ed9Schristos 137a0698ed9Schristos for (j = 1; j < RANGE; j++) { 138a0698ed9Schristos q = rallocx(p, start_size+j, MALLOCX_ZERO); 139*7bdf38e5Schristos expect_ptr_not_null(q, "Unexpected rallocx() error"); 140a0698ed9Schristos qsz = sallocx(q, 0); 141a0698ed9Schristos if (q != p || qsz != psz) { 142*7bdf38e5Schristos expect_false(validate_fill(q, FILL_BYTE, 0, 143a0698ed9Schristos psz), "Expected filled memory"); 144*7bdf38e5Schristos expect_false(validate_fill(q, 0, psz, qsz-psz), 145a0698ed9Schristos "Expected zeroed memory"); 146a0698ed9Schristos } 147a0698ed9Schristos if (psz != qsz) { 148a0698ed9Schristos memset((void *)((uintptr_t)q+psz), FILL_BYTE, 149a0698ed9Schristos qsz-psz); 150a0698ed9Schristos psz = qsz; 151a0698ed9Schristos } 152a0698ed9Schristos p = q; 153a0698ed9Schristos } 154*7bdf38e5Schristos expect_false(validate_fill(p, FILL_BYTE, 0, psz), 155a0698ed9Schristos "Expected filled memory"); 156a0698ed9Schristos dallocx(p, 0); 157a0698ed9Schristos } 158a0698ed9Schristos #undef FILL_BYTE 159a0698ed9Schristos } 160a0698ed9Schristos TEST_END 161a0698ed9Schristos 162a0698ed9Schristos TEST_BEGIN(test_align) { 163a0698ed9Schristos void *p, *q; 164a0698ed9Schristos size_t align; 165a0698ed9Schristos #define MAX_ALIGN (ZU(1) << 25) 166a0698ed9Schristos 167a0698ed9Schristos align = ZU(1); 168a0698ed9Schristos p = mallocx(1, MALLOCX_ALIGN(align)); 169*7bdf38e5Schristos expect_ptr_not_null(p, "Unexpected mallocx() error"); 170a0698ed9Schristos 171a0698ed9Schristos for (align <<= 1; align <= MAX_ALIGN; align <<= 1) { 172a0698ed9Schristos q = rallocx(p, 1, MALLOCX_ALIGN(align)); 173*7bdf38e5Schristos expect_ptr_not_null(q, 174a0698ed9Schristos "Unexpected rallocx() error for align=%zu", align); 175*7bdf38e5Schristos expect_ptr_null( 176a0698ed9Schristos (void *)((uintptr_t)q & (align-1)), 177a0698ed9Schristos "%p inadequately aligned for align=%zu", 178a0698ed9Schristos q, align); 179a0698ed9Schristos p = q; 180a0698ed9Schristos } 181a0698ed9Schristos dallocx(p, 0); 182a0698ed9Schristos #undef MAX_ALIGN 183a0698ed9Schristos } 184a0698ed9Schristos TEST_END 185a0698ed9Schristos 186*7bdf38e5Schristos TEST_BEGIN(test_align_enum) { 187*7bdf38e5Schristos /* Span both small sizes and large sizes. */ 188*7bdf38e5Schristos #define LG_MIN 12 189*7bdf38e5Schristos #define LG_MAX 15 190*7bdf38e5Schristos for (size_t lg_align = LG_MIN; lg_align <= LG_MAX; ++lg_align) { 191*7bdf38e5Schristos for (size_t lg_size = LG_MIN; lg_size <= LG_MAX; ++lg_size) { 192*7bdf38e5Schristos size_t size = 1 << lg_size; 193*7bdf38e5Schristos for (size_t lg_align_next = LG_MIN; 194*7bdf38e5Schristos lg_align_next <= LG_MAX; ++lg_align_next) { 195*7bdf38e5Schristos int flags = MALLOCX_LG_ALIGN(lg_align); 196*7bdf38e5Schristos void *p = mallocx(1, flags); 197*7bdf38e5Schristos assert_ptr_not_null(p, 198*7bdf38e5Schristos "Unexpected mallocx() error"); 199*7bdf38e5Schristos assert_zu_eq(nallocx(1, flags), 200*7bdf38e5Schristos TEST_MALLOC_SIZE(p), 201*7bdf38e5Schristos "Wrong mallocx() usable size"); 202*7bdf38e5Schristos int flags_next = 203*7bdf38e5Schristos MALLOCX_LG_ALIGN(lg_align_next); 204*7bdf38e5Schristos p = rallocx(p, size, flags_next); 205*7bdf38e5Schristos assert_ptr_not_null(p, 206*7bdf38e5Schristos "Unexpected rallocx() error"); 207*7bdf38e5Schristos expect_zu_eq(nallocx(size, flags_next), 208*7bdf38e5Schristos TEST_MALLOC_SIZE(p), 209*7bdf38e5Schristos "Wrong rallocx() usable size"); 210*7bdf38e5Schristos free(p); 211*7bdf38e5Schristos } 212*7bdf38e5Schristos } 213*7bdf38e5Schristos } 214*7bdf38e5Schristos #undef LG_MAX 215*7bdf38e5Schristos #undef LG_MIN 216*7bdf38e5Schristos } 217*7bdf38e5Schristos TEST_END 218*7bdf38e5Schristos 219a0698ed9Schristos TEST_BEGIN(test_lg_align_and_zero) { 220*7bdf38e5Schristos /* 221*7bdf38e5Schristos * Use volatile to workaround buffer overflow false positives 222*7bdf38e5Schristos * (-D_FORTIFY_SOURCE=3). 223*7bdf38e5Schristos */ 224*7bdf38e5Schristos void *volatile p, *volatile q; 225a0698ed9Schristos unsigned lg_align; 226a0698ed9Schristos size_t sz; 227a0698ed9Schristos #define MAX_LG_ALIGN 25 228a0698ed9Schristos #define MAX_VALIDATE (ZU(1) << 22) 229a0698ed9Schristos 230a0698ed9Schristos lg_align = 0; 231a0698ed9Schristos p = mallocx(1, MALLOCX_LG_ALIGN(lg_align)|MALLOCX_ZERO); 232*7bdf38e5Schristos expect_ptr_not_null(p, "Unexpected mallocx() error"); 233a0698ed9Schristos 234a0698ed9Schristos for (lg_align++; lg_align <= MAX_LG_ALIGN; lg_align++) { 235a0698ed9Schristos q = rallocx(p, 1, MALLOCX_LG_ALIGN(lg_align)|MALLOCX_ZERO); 236*7bdf38e5Schristos expect_ptr_not_null(q, 237a0698ed9Schristos "Unexpected rallocx() error for lg_align=%u", lg_align); 238*7bdf38e5Schristos expect_ptr_null( 239a0698ed9Schristos (void *)((uintptr_t)q & ((ZU(1) << lg_align)-1)), 240a0698ed9Schristos "%p inadequately aligned for lg_align=%u", q, lg_align); 241a0698ed9Schristos sz = sallocx(q, 0); 242a0698ed9Schristos if ((sz << 1) <= MAX_VALIDATE) { 243*7bdf38e5Schristos expect_false(validate_fill(q, 0, 0, sz), 244a0698ed9Schristos "Expected zeroed memory"); 245a0698ed9Schristos } else { 246*7bdf38e5Schristos expect_false(validate_fill(q, 0, 0, MAX_VALIDATE), 247a0698ed9Schristos "Expected zeroed memory"); 248*7bdf38e5Schristos expect_false(validate_fill( 249a0698ed9Schristos (void *)((uintptr_t)q+sz-MAX_VALIDATE), 250a0698ed9Schristos 0, 0, MAX_VALIDATE), "Expected zeroed memory"); 251a0698ed9Schristos } 252a0698ed9Schristos p = q; 253a0698ed9Schristos } 254a0698ed9Schristos dallocx(p, 0); 255a0698ed9Schristos #undef MAX_VALIDATE 256a0698ed9Schristos #undef MAX_LG_ALIGN 257a0698ed9Schristos } 258a0698ed9Schristos TEST_END 259a0698ed9Schristos 260*7bdf38e5Schristos /* 261*7bdf38e5Schristos * GCC "-Walloc-size-larger-than" warning detects when one of the memory 262*7bdf38e5Schristos * allocation functions is called with a size larger than the maximum size that 263*7bdf38e5Schristos * they support. Here we want to explicitly test that the allocation functions 264*7bdf38e5Schristos * do indeed fail properly when this is the case, which triggers the warning. 265*7bdf38e5Schristos * Therefore we disable the warning for these tests. 266*7bdf38e5Schristos */ 267*7bdf38e5Schristos JEMALLOC_DIAGNOSTIC_PUSH 268*7bdf38e5Schristos JEMALLOC_DIAGNOSTIC_IGNORE_ALLOC_SIZE_LARGER_THAN 269*7bdf38e5Schristos 270a0698ed9Schristos TEST_BEGIN(test_overflow) { 271a0698ed9Schristos size_t largemax; 272a0698ed9Schristos void *p; 273a0698ed9Schristos 274a0698ed9Schristos largemax = get_large_size(get_nlarge()-1); 275a0698ed9Schristos 276a0698ed9Schristos p = mallocx(1, 0); 277*7bdf38e5Schristos expect_ptr_not_null(p, "Unexpected mallocx() failure"); 278a0698ed9Schristos 279*7bdf38e5Schristos expect_ptr_null(rallocx(p, largemax+1, 0), 280a0698ed9Schristos "Expected OOM for rallocx(p, size=%#zx, 0)", largemax+1); 281a0698ed9Schristos 282*7bdf38e5Schristos expect_ptr_null(rallocx(p, ZU(PTRDIFF_MAX)+1, 0), 283a0698ed9Schristos "Expected OOM for rallocx(p, size=%#zx, 0)", ZU(PTRDIFF_MAX)+1); 284a0698ed9Schristos 285*7bdf38e5Schristos expect_ptr_null(rallocx(p, SIZE_T_MAX, 0), 286a0698ed9Schristos "Expected OOM for rallocx(p, size=%#zx, 0)", SIZE_T_MAX); 287a0698ed9Schristos 288*7bdf38e5Schristos expect_ptr_null(rallocx(p, 1, MALLOCX_ALIGN(ZU(PTRDIFF_MAX)+1)), 289a0698ed9Schristos "Expected OOM for rallocx(p, size=1, MALLOCX_ALIGN(%#zx))", 290a0698ed9Schristos ZU(PTRDIFF_MAX)+1); 291a0698ed9Schristos 292a0698ed9Schristos dallocx(p, 0); 293a0698ed9Schristos } 294a0698ed9Schristos TEST_END 295a0698ed9Schristos 296*7bdf38e5Schristos /* Re-enable the "-Walloc-size-larger-than=" warning */ 297*7bdf38e5Schristos JEMALLOC_DIAGNOSTIC_POP 298*7bdf38e5Schristos 299a0698ed9Schristos int 300a0698ed9Schristos main(void) { 301a0698ed9Schristos return test( 302a0698ed9Schristos test_grow_and_shrink, 303a0698ed9Schristos test_zero, 304a0698ed9Schristos test_align, 305*7bdf38e5Schristos test_align_enum, 306a0698ed9Schristos test_lg_align_and_zero, 307a0698ed9Schristos test_overflow); 308a0698ed9Schristos } 309