2013-12-18 07:14:36 +08:00
|
|
|
#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 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);
|
|
|
|
|
2014-01-08 08:47:56 +08:00
|
|
|
arena_redzone_corruption_orig = arena_redzone_corruption;
|
|
|
|
arena_redzone_corruption = arena_redzone_corruption_replacement;
|
2013-12-18 07:14:36 +08:00
|
|
|
|
|
|
|
/* 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");
|
|
|
|
|
2014-01-08 08:47:56 +08:00
|
|
|
arena_redzone_corruption = arena_redzone_corruption_orig;
|
2013-12-18 07:14:36 +08:00
|
|
|
}
|
|
|
|
TEST_END
|
|
|
|
|
|
|
|
int
|
|
|
|
main(void)
|
|
|
|
{
|
|
|
|
|
|
|
|
return (test(
|
|
|
|
test_quarantine,
|
|
|
|
test_quarantine_redzone));
|
|
|
|
}
|