1 #include "test/jemalloc_test.h"
4 # ifndef JEMALLOC_TEST_JUNK_OPT
5 # define JEMALLOC_TEST_JUNK_OPT "junk:true"
7 const char *malloc_conf
=
8 "abort:false,zero:false,redzone:true,quarantine:0," JEMALLOC_TEST_JUNK_OPT
;
11 static arena_dalloc_junk_small_t
*arena_dalloc_junk_small_orig
;
12 static arena_dalloc_junk_large_t
*arena_dalloc_junk_large_orig
;
13 static huge_dalloc_junk_t
*huge_dalloc_junk_orig
;
14 static void *watch_for_junking
;
15 static bool saw_junking
;
18 watch_junking(void *p
)
21 watch_for_junking
= p
;
26 arena_dalloc_junk_small_intercept(void *ptr
, arena_bin_info_t
*bin_info
)
30 arena_dalloc_junk_small_orig(ptr
, bin_info
);
31 for (i
= 0; i
< bin_info
->reg_size
; i
++) {
32 assert_c_eq(((char *)ptr
)[i
], 0x5a,
33 "Missing junk fill for byte %zu/%zu of deallocated region",
34 i
, bin_info
->reg_size
);
36 if (ptr
== watch_for_junking
)
41 arena_dalloc_junk_large_intercept(void *ptr
, size_t usize
)
45 arena_dalloc_junk_large_orig(ptr
, usize
);
46 for (i
= 0; i
< usize
; i
++) {
47 assert_c_eq(((char *)ptr
)[i
], 0x5a,
48 "Missing junk fill for byte %zu/%zu of deallocated region",
51 if (ptr
== watch_for_junking
)
56 huge_dalloc_junk_intercept(void *ptr
, size_t usize
)
59 huge_dalloc_junk_orig(ptr
, usize
);
61 * The conditions under which junk filling actually occurs are nuanced
62 * enough that it doesn't make sense to duplicate the decision logic in
63 * test code, so don't actually check that the region is junk-filled.
65 if (ptr
== watch_for_junking
)
70 test_junk(size_t sz_min
, size_t sz_max
)
73 size_t sz_prev
, sz
, i
;
76 arena_dalloc_junk_small_orig
= arena_dalloc_junk_small
;
77 arena_dalloc_junk_small
= arena_dalloc_junk_small_intercept
;
78 arena_dalloc_junk_large_orig
= arena_dalloc_junk_large
;
79 arena_dalloc_junk_large
= arena_dalloc_junk_large_intercept
;
80 huge_dalloc_junk_orig
= huge_dalloc_junk
;
81 huge_dalloc_junk
= huge_dalloc_junk_intercept
;
85 s
= (char *)mallocx(sz_min
, 0);
86 assert_ptr_not_null((void *)s
, "Unexpected mallocx() failure");
88 for (sz
= sallocx(s
, 0); sz
<= sz_max
;
89 sz_prev
= sz
, sz
= sallocx(s
, 0)) {
91 assert_c_eq(s
[0], 'a',
92 "Previously allocated byte %zu/%zu is corrupted",
94 assert_c_eq(s
[sz_prev
-1], 'a',
95 "Previously allocated byte %zu/%zu is corrupted",
99 for (i
= sz_prev
; i
< sz
; i
++) {
100 if (opt_junk_alloc
) {
101 assert_c_eq(s
[i
], 0xa5,
102 "Newly allocated byte %zu/%zu isn't "
103 "junk-filled", i
, sz
);
108 if (xallocx(s
, sz
+1, 0, 0) == sz
) {
110 s
= (char *)rallocx(s
, sz
+1, 0);
111 assert_ptr_not_null((void *)s
,
112 "Unexpected rallocx() failure");
113 assert_true(!opt_junk_free
|| saw_junking
,
114 "Expected region of size %zu to be junk-filled",
121 assert_true(!opt_junk_free
|| saw_junking
,
122 "Expected region of size %zu to be junk-filled", sz
);
125 arena_dalloc_junk_small
= arena_dalloc_junk_small_orig
;
126 arena_dalloc_junk_large
= arena_dalloc_junk_large_orig
;
127 huge_dalloc_junk
= huge_dalloc_junk_orig
;
131 TEST_BEGIN(test_junk_small
)
134 test_skip_if(!config_fill
);
135 test_junk(1, SMALL_MAXCLASS
-1);
139 TEST_BEGIN(test_junk_large
)
142 test_skip_if(!config_fill
);
143 test_junk(SMALL_MAXCLASS
+1, large_maxclass
);
147 TEST_BEGIN(test_junk_huge
)
150 test_skip_if(!config_fill
);
151 test_junk(large_maxclass
+1, chunksize
*2);
155 arena_ralloc_junk_large_t
*arena_ralloc_junk_large_orig
;
156 static void *most_recently_trimmed
;
159 shrink_size(size_t size
)
163 for (shrink_size
= size
- 1; nallocx(shrink_size
, 0) == size
;
167 return (shrink_size
);
171 arena_ralloc_junk_large_intercept(void *ptr
, size_t old_usize
, size_t usize
)
174 arena_ralloc_junk_large_orig(ptr
, old_usize
, usize
);
175 assert_zu_eq(old_usize
, large_maxclass
, "Unexpected old_usize");
176 assert_zu_eq(usize
, shrink_size(large_maxclass
), "Unexpected usize");
177 most_recently_trimmed
= ptr
;
180 TEST_BEGIN(test_junk_large_ralloc_shrink
)
184 p1
= mallocx(large_maxclass
, 0);
185 assert_ptr_not_null(p1
, "Unexpected mallocx() failure");
187 arena_ralloc_junk_large_orig
= arena_ralloc_junk_large
;
188 arena_ralloc_junk_large
= arena_ralloc_junk_large_intercept
;
190 p2
= rallocx(p1
, shrink_size(large_maxclass
), 0);
191 assert_ptr_eq(p1
, p2
, "Unexpected move during shrink");
193 arena_ralloc_junk_large
= arena_ralloc_junk_large_orig
;
195 assert_ptr_eq(most_recently_trimmed
, p1
,
196 "Expected trimmed portion of region to be junk-filled");
200 static bool detected_redzone_corruption
;
203 arena_redzone_corruption_replacement(void *ptr
, size_t usize
, bool after
,
204 size_t offset
, uint8_t byte
)
207 detected_redzone_corruption
= true;
210 TEST_BEGIN(test_junk_redzone
)
213 arena_redzone_corruption_t
*arena_redzone_corruption_orig
;
215 test_skip_if(!config_fill
);
216 test_skip_if(!opt_junk_alloc
|| !opt_junk_free
);
218 arena_redzone_corruption_orig
= arena_redzone_corruption
;
219 arena_redzone_corruption
= arena_redzone_corruption_replacement
;
221 /* Test underflow. */
222 detected_redzone_corruption
= false;
223 s
= (char *)mallocx(1, 0);
224 assert_ptr_not_null((void *)s
, "Unexpected mallocx() failure");
227 assert_true(detected_redzone_corruption
,
228 "Did not detect redzone corruption");
231 detected_redzone_corruption
= false;
232 s
= (char *)mallocx(1, 0);
233 assert_ptr_not_null((void *)s
, "Unexpected mallocx() failure");
234 s
[sallocx(s
, 0)] = 0xbb;
236 assert_true(detected_redzone_corruption
,
237 "Did not detect redzone corruption");
239 arena_redzone_corruption
= arena_redzone_corruption_orig
;
247 assert(!config_fill
|| opt_junk_alloc
|| opt_junk_free
);
252 test_junk_large_ralloc_shrink
,