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