| #include "test/jemalloc_test.h" |
| |
| #define QUARANTINE_SIZE 8192 |
| #define STRINGIFY_HELPER(x) #x |
| #define STRINGIFY(x) STRINGIFY_HELPER(x) |
| |
| #ifdef JEMALLOC_FILL |
| const char *malloc_conf = "abort:false,junk:true,redzone:true,quarantine:" |
| STRINGIFY(QUARANTINE_SIZE); |
| #endif |
| |
| void |
| quarantine_clear(void) |
| { |
| void *p; |
| |
| p = mallocx(QUARANTINE_SIZE*2, 0); |
| assert_ptr_not_null(p, "Unexpected mallocx() failure"); |
| dallocx(p, 0); |
| } |
| |
| TEST_BEGIN(test_quarantine) |
| { |
| #define SZ ZU(256) |
| #define NQUARANTINED (QUARANTINE_SIZE/SZ) |
| void *quarantined[NQUARANTINED+1]; |
| size_t i, j; |
| |
| test_skip_if(!config_fill); |
| |
| assert_zu_eq(nallocx(SZ, 0), SZ, |
| "SZ=%zu does not precisely equal a size class", SZ); |
| |
| quarantine_clear(); |
| |
| /* |
| * Allocate enough regions to completely fill the quarantine, plus one |
| * more. The last iteration occurs with a completely full quarantine, |
| * but no regions should be drained from the quarantine until the last |
| * deallocation occurs. Therefore no region recycling should occur |
| * until after this loop completes. |
| */ |
| for (i = 0; i < NQUARANTINED+1; i++) { |
| void *p = mallocx(SZ, 0); |
| assert_ptr_not_null(p, "Unexpected mallocx() failure"); |
| quarantined[i] = p; |
| dallocx(p, 0); |
| for (j = 0; j < i; j++) { |
| assert_ptr_ne(p, quarantined[j], |
| "Quarantined region recycled too early; " |
| "i=%zu, j=%zu", i, j); |
| } |
| } |
| #undef NQUARANTINED |
| #undef SZ |
| } |
| TEST_END |
| |
| static bool detected_redzone_corruption; |
| |
| static void |
| arena_redzone_corruption_replacement(void *ptr, size_t usize, bool after, |
| size_t offset, uint8_t byte) |
| { |
| |
| detected_redzone_corruption = true; |
| } |
| |
| TEST_BEGIN(test_quarantine_redzone) |
| { |
| char *s; |
| arena_redzone_corruption_t *arena_redzone_corruption_orig; |
| |
| test_skip_if(!config_fill); |
| |
| arena_redzone_corruption_orig = arena_redzone_corruption; |
| arena_redzone_corruption = arena_redzone_corruption_replacement; |
| |
| /* Test underflow. */ |
| detected_redzone_corruption = false; |
| s = (char *)mallocx(1, 0); |
| assert_ptr_not_null((void *)s, "Unexpected mallocx() failure"); |
| s[-1] = 0xbb; |
| dallocx(s, 0); |
| assert_true(detected_redzone_corruption, |
| "Did not detect redzone corruption"); |
| |
| /* Test overflow. */ |
| detected_redzone_corruption = false; |
| s = (char *)mallocx(1, 0); |
| assert_ptr_not_null((void *)s, "Unexpected mallocx() failure"); |
| s[sallocx(s, 0)] = 0xbb; |
| dallocx(s, 0); |
| assert_true(detected_redzone_corruption, |
| "Did not detect redzone corruption"); |
| |
| arena_redzone_corruption = arena_redzone_corruption_orig; |
| } |
| TEST_END |
| |
| int |
| main(void) |
| { |
| |
| return (test( |
| test_quarantine, |
| test_quarantine_redzone)); |
| } |