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