1 #include "test/jemalloc_test.h"
2
3 #ifdef JEMALLOC_FILL
4 # ifndef JEMALLOC_TEST_JUNK_OPT
5 # define JEMALLOC_TEST_JUNK_OPT "junk:true"
6 # endif
7 const char *malloc_conf =
8 "abort:false,zero:false," JEMALLOC_TEST_JUNK_OPT;
9 #endif
10
11 static arena_dalloc_junk_small_t *arena_dalloc_junk_small_orig;
12 static large_dalloc_junk_t *large_dalloc_junk_orig;
13 static large_dalloc_maybe_junk_t *large_dalloc_maybe_junk_orig;
14 static void *watch_for_junking;
15 static bool saw_junking;
16
17 static void
watch_junking(void * p)18 watch_junking(void *p)
19 {
20 watch_for_junking = p;
21 saw_junking = false;
22 }
23
24 static void
arena_dalloc_junk_small_intercept(void * ptr,const arena_bin_info_t * bin_info)25 arena_dalloc_junk_small_intercept(void *ptr, const arena_bin_info_t *bin_info)
26 {
27 size_t i;
28
29 arena_dalloc_junk_small_orig(ptr, bin_info);
30 for (i = 0; i < bin_info->reg_size; i++) {
31 assert_u_eq(((uint8_t *)ptr)[i], JEMALLOC_FREE_JUNK,
32 "Missing junk fill for byte %zu/%zu of deallocated region",
33 i, bin_info->reg_size);
34 }
35 if (ptr == watch_for_junking)
36 saw_junking = true;
37 }
38
39 static void
large_dalloc_junk_intercept(void * ptr,size_t usize)40 large_dalloc_junk_intercept(void *ptr, size_t usize)
41 {
42 size_t i;
43
44 large_dalloc_junk_orig(ptr, usize);
45 for (i = 0; i < usize; i++) {
46 assert_u_eq(((uint8_t *)ptr)[i], JEMALLOC_FREE_JUNK,
47 "Missing junk fill for byte %zu/%zu of deallocated region",
48 i, usize);
49 }
50 if (ptr == watch_for_junking)
51 saw_junking = true;
52 }
53
54 static void
large_dalloc_maybe_junk_intercept(void * ptr,size_t usize)55 large_dalloc_maybe_junk_intercept(void *ptr, size_t usize)
56 {
57 large_dalloc_maybe_junk_orig(ptr, usize);
58 if (ptr == watch_for_junking)
59 saw_junking = true;
60 }
61
62 static void
test_junk(size_t sz_min,size_t sz_max)63 test_junk(size_t sz_min, size_t sz_max)
64 {
65 uint8_t *s;
66 size_t sz_prev, sz, i;
67
68 if (opt_junk_free) {
69 arena_dalloc_junk_small_orig = arena_dalloc_junk_small;
70 arena_dalloc_junk_small = arena_dalloc_junk_small_intercept;
71 large_dalloc_junk_orig = large_dalloc_junk;
72 large_dalloc_junk = large_dalloc_junk_intercept;
73 large_dalloc_maybe_junk_orig = large_dalloc_maybe_junk;
74 large_dalloc_maybe_junk = large_dalloc_maybe_junk_intercept;
75 }
76
77 sz_prev = 0;
78 s = (uint8_t *)mallocx(sz_min, 0);
79 assert_ptr_not_null((void *)s, "Unexpected mallocx() failure");
80
81 for (sz = sallocx(s, 0); sz <= sz_max;
82 sz_prev = sz, sz = sallocx(s, 0)) {
83 if (sz_prev > 0) {
84 assert_u_eq(s[0], 'a',
85 "Previously allocated byte %zu/%zu is corrupted",
86 ZU(0), sz_prev);
87 assert_u_eq(s[sz_prev-1], 'a',
88 "Previously allocated byte %zu/%zu is corrupted",
89 sz_prev-1, sz_prev);
90 }
91
92 for (i = sz_prev; i < sz; i++) {
93 if (opt_junk_alloc) {
94 assert_u_eq(s[i], JEMALLOC_ALLOC_JUNK,
95 "Newly allocated byte %zu/%zu isn't "
96 "junk-filled", i, sz);
97 }
98 s[i] = 'a';
99 }
100
101 if (xallocx(s, sz+1, 0, 0) == sz) {
102 uint8_t *t;
103 watch_junking(s);
104 t = (uint8_t *)rallocx(s, sz+1, 0);
105 assert_ptr_not_null((void *)t,
106 "Unexpected rallocx() failure");
107 assert_ptr_ne(s, t, "Unexpected in-place rallocx()");
108 assert_zu_ge(sallocx(t, 0), sz+1,
109 "Unexpectedly small rallocx() result");
110 assert_true(!opt_junk_free || saw_junking,
111 "Expected region of size %zu to be junk-filled",
112 sz);
113 s = t;
114 }
115 }
116
117 watch_junking(s);
118 dallocx(s, 0);
119 assert_true(!opt_junk_free || saw_junking,
120 "Expected region of size %zu to be junk-filled", sz);
121
122 if (opt_junk_free) {
123 arena_dalloc_junk_small = arena_dalloc_junk_small_orig;
124 large_dalloc_junk = large_dalloc_junk_orig;
125 large_dalloc_maybe_junk = large_dalloc_maybe_junk_orig;
126 }
127 }
128
TEST_BEGIN(test_junk_small)129 TEST_BEGIN(test_junk_small)
130 {
131 test_skip_if(!config_fill);
132 test_junk(1, SMALL_MAXCLASS-1);
133 }
134 TEST_END
135
TEST_BEGIN(test_junk_large)136 TEST_BEGIN(test_junk_large)
137 {
138 test_skip_if(!config_fill);
139 test_junk(SMALL_MAXCLASS+1, (1U << (LG_LARGE_MINCLASS+1)));
140 }
141 TEST_END
142
143 int
main(void)144 main(void)
145 {
146 return (test(
147 test_junk_small,
148 test_junk_large));
149 }
150