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