• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include "test/jemalloc_test.h"
2 
3 #ifdef JEMALLOC_FILL
4 const char *malloc_conf =
5     "abort:false,junk:true,zero:false,redzone:true,quarantine:0";
6 #endif
7 
8 static arena_dalloc_junk_small_t *arena_dalloc_junk_small_orig;
9 static arena_dalloc_junk_large_t *arena_dalloc_junk_large_orig;
10 static huge_dalloc_junk_t *huge_dalloc_junk_orig;
11 static void *most_recently_junked;
12 
13 static void
arena_dalloc_junk_small_intercept(void * ptr,arena_bin_info_t * bin_info)14 arena_dalloc_junk_small_intercept(void *ptr, arena_bin_info_t *bin_info)
15 {
16 	size_t i;
17 
18 	arena_dalloc_junk_small_orig(ptr, bin_info);
19 	for (i = 0; i < bin_info->reg_size; i++) {
20 		assert_c_eq(((char *)ptr)[i], 0x5a,
21 		    "Missing junk fill for byte %zu/%zu of deallocated region",
22 		    i, bin_info->reg_size);
23 	}
24 	most_recently_junked = ptr;
25 }
26 
27 static void
arena_dalloc_junk_large_intercept(void * ptr,size_t usize)28 arena_dalloc_junk_large_intercept(void *ptr, size_t usize)
29 {
30 	size_t i;
31 
32 	arena_dalloc_junk_large_orig(ptr, usize);
33 	for (i = 0; i < usize; i++) {
34 		assert_c_eq(((char *)ptr)[i], 0x5a,
35 		    "Missing junk fill for byte %zu/%zu of deallocated region",
36 		    i, usize);
37 	}
38 	most_recently_junked = ptr;
39 }
40 
41 static void
huge_dalloc_junk_intercept(void * ptr,size_t usize)42 huge_dalloc_junk_intercept(void *ptr, size_t usize)
43 {
44 
45 	huge_dalloc_junk_orig(ptr, usize);
46 	/*
47 	 * The conditions under which junk filling actually occurs are nuanced
48 	 * enough that it doesn't make sense to duplicate the decision logic in
49 	 * test code, so don't actually check that the region is junk-filled.
50 	 */
51 	most_recently_junked = ptr;
52 }
53 
54 static void
test_junk(size_t sz_min,size_t sz_max)55 test_junk(size_t sz_min, size_t sz_max)
56 {
57 	char *s;
58 	size_t sz_prev, sz, i;
59 
60 	arena_dalloc_junk_small_orig = arena_dalloc_junk_small;
61 	arena_dalloc_junk_small = arena_dalloc_junk_small_intercept;
62 	arena_dalloc_junk_large_orig = arena_dalloc_junk_large;
63 	arena_dalloc_junk_large = arena_dalloc_junk_large_intercept;
64 	huge_dalloc_junk_orig = huge_dalloc_junk;
65 	huge_dalloc_junk = huge_dalloc_junk_intercept;
66 
67 	sz_prev = 0;
68 	s = (char *)mallocx(sz_min, 0);
69 	assert_ptr_not_null((void *)s, "Unexpected mallocx() failure");
70 
71 	for (sz = sallocx(s, 0); sz <= sz_max;
72 	    sz_prev = sz, sz = sallocx(s, 0)) {
73 		if (sz_prev > 0) {
74 			assert_c_eq(s[0], 'a',
75 			    "Previously allocated byte %zu/%zu is corrupted",
76 			    ZU(0), sz_prev);
77 			assert_c_eq(s[sz_prev-1], 'a',
78 			    "Previously allocated byte %zu/%zu is corrupted",
79 			    sz_prev-1, sz_prev);
80 		}
81 
82 		for (i = sz_prev; i < sz; i++) {
83 			assert_c_eq(s[i], 0xa5,
84 			    "Newly allocated byte %zu/%zu isn't junk-filled",
85 			    i, sz);
86 			s[i] = 'a';
87 		}
88 
89 		if (xallocx(s, sz+1, 0, 0) == sz) {
90 			void *junked = (void *)s;
91 
92 			s = (char *)rallocx(s, sz+1, 0);
93 			assert_ptr_not_null((void *)s,
94 			    "Unexpected rallocx() failure");
95 			assert_ptr_eq(most_recently_junked, junked,
96 			    "Expected region of size %zu to be junk-filled",
97 			    sz);
98 		}
99 	}
100 
101 	dallocx(s, 0);
102 	assert_ptr_eq(most_recently_junked, (void *)s,
103 	    "Expected region of size %zu to be junk-filled", sz);
104 
105 	arena_dalloc_junk_small = arena_dalloc_junk_small_orig;
106 	arena_dalloc_junk_large = arena_dalloc_junk_large_orig;
107 	huge_dalloc_junk = huge_dalloc_junk_orig;
108 }
109 
TEST_BEGIN(test_junk_small)110 TEST_BEGIN(test_junk_small)
111 {
112 
113 	test_skip_if(!config_fill);
114 	test_junk(1, SMALL_MAXCLASS-1);
115 }
116 TEST_END
117 
TEST_BEGIN(test_junk_large)118 TEST_BEGIN(test_junk_large)
119 {
120 
121 	test_skip_if(!config_fill);
122 	test_junk(SMALL_MAXCLASS+1, arena_maxclass);
123 }
124 TEST_END
125 
TEST_BEGIN(test_junk_huge)126 TEST_BEGIN(test_junk_huge)
127 {
128 
129 	test_skip_if(!config_fill);
130 	test_junk(arena_maxclass+1, chunksize*2);
131 }
132 TEST_END
133 
134 arena_ralloc_junk_large_t *arena_ralloc_junk_large_orig;
135 static void *most_recently_trimmed;
136 
137 static void
arena_ralloc_junk_large_intercept(void * ptr,size_t old_usize,size_t usize)138 arena_ralloc_junk_large_intercept(void *ptr, size_t old_usize, size_t usize)
139 {
140 
141 	arena_ralloc_junk_large_orig(ptr, old_usize, usize);
142 	assert_zu_eq(old_usize, arena_maxclass, "Unexpected old_usize");
143 	assert_zu_eq(usize, arena_maxclass-PAGE, "Unexpected usize");
144 	most_recently_trimmed = ptr;
145 }
146 
TEST_BEGIN(test_junk_large_ralloc_shrink)147 TEST_BEGIN(test_junk_large_ralloc_shrink)
148 {
149 	void *p1, *p2;
150 
151 	p1 = mallocx(arena_maxclass, 0);
152 	assert_ptr_not_null(p1, "Unexpected mallocx() failure");
153 
154 	arena_ralloc_junk_large_orig = arena_ralloc_junk_large;
155 	arena_ralloc_junk_large = arena_ralloc_junk_large_intercept;
156 
157 	p2 = rallocx(p1, arena_maxclass-PAGE, 0);
158 	assert_ptr_eq(p1, p2, "Unexpected move during shrink");
159 
160 	arena_ralloc_junk_large = arena_ralloc_junk_large_orig;
161 
162 	assert_ptr_eq(most_recently_trimmed, p1,
163 	    "Expected trimmed portion of region to be junk-filled");
164 }
165 TEST_END
166 
167 static bool detected_redzone_corruption;
168 
169 static void
arena_redzone_corruption_replacement(void * ptr,size_t usize,bool after,size_t offset,uint8_t byte)170 arena_redzone_corruption_replacement(void *ptr, size_t usize, bool after,
171     size_t offset, uint8_t byte)
172 {
173 
174 	detected_redzone_corruption = true;
175 }
176 
TEST_BEGIN(test_junk_redzone)177 TEST_BEGIN(test_junk_redzone)
178 {
179 	char *s;
180 	arena_redzone_corruption_t *arena_redzone_corruption_orig;
181 
182 	test_skip_if(!config_fill);
183 
184 	arena_redzone_corruption_orig = arena_redzone_corruption;
185 	arena_redzone_corruption = arena_redzone_corruption_replacement;
186 
187 	/* Test underflow. */
188 	detected_redzone_corruption = false;
189 	s = (char *)mallocx(1, 0);
190 	assert_ptr_not_null((void *)s, "Unexpected mallocx() failure");
191 	s[-1] = 0xbb;
192 	dallocx(s, 0);
193 	assert_true(detected_redzone_corruption,
194 	    "Did not detect redzone corruption");
195 
196 	/* Test overflow. */
197 	detected_redzone_corruption = false;
198 	s = (char *)mallocx(1, 0);
199 	assert_ptr_not_null((void *)s, "Unexpected mallocx() failure");
200 	s[sallocx(s, 0)] = 0xbb;
201 	dallocx(s, 0);
202 	assert_true(detected_redzone_corruption,
203 	    "Did not detect redzone corruption");
204 
205 	arena_redzone_corruption = arena_redzone_corruption_orig;
206 }
207 TEST_END
208 
209 int
main(void)210 main(void)
211 {
212 
213 	return (test(
214 	    test_junk_small,
215 	    test_junk_large,
216 	    test_junk_huge,
217 	    test_junk_large_ralloc_shrink,
218 	    test_junk_redzone));
219 }
220