2
0

junk.c 5.5 KB

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