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