summaryrefslogtreecommitdiff
path: root/deps/jemalloc/test/unit/double_free.c
diff options
context:
space:
mode:
Diffstat (limited to 'deps/jemalloc/test/unit/double_free.c')
-rw-r--r--deps/jemalloc/test/unit/double_free.c77
1 files changed, 77 insertions, 0 deletions
diff --git a/deps/jemalloc/test/unit/double_free.c b/deps/jemalloc/test/unit/double_free.c
new file mode 100644
index 000000000..12122c1b7
--- /dev/null
+++ b/deps/jemalloc/test/unit/double_free.c
@@ -0,0 +1,77 @@
+#include "test/jemalloc_test.h"
+#include "test/san.h"
+
+#include "jemalloc/internal/safety_check.h"
+
+bool fake_abort_called;
+void fake_abort(const char *message) {
+ (void)message;
+ fake_abort_called = true;
+}
+
+void
+test_large_double_free_pre(void) {
+ safety_check_set_abort(&fake_abort);
+ fake_abort_called = false;
+}
+
+void
+test_large_double_free_post() {
+ expect_b_eq(fake_abort_called, true, "Double-free check didn't fire.");
+ safety_check_set_abort(NULL);
+}
+
+TEST_BEGIN(test_large_double_free_tcache) {
+ test_skip_if(!config_opt_safety_checks);
+ /*
+ * Skip debug builds, since too many assertions will be triggered with
+ * double-free before hitting the one we are interested in.
+ */
+ test_skip_if(config_debug);
+
+ test_large_double_free_pre();
+ char *ptr = malloc(SC_LARGE_MINCLASS);
+ bool guarded = extent_is_guarded(tsdn_fetch(), ptr);
+ free(ptr);
+ if (!guarded) {
+ free(ptr);
+ } else {
+ /*
+ * Skip because guarded extents may unguard immediately on
+ * deallocation, in which case the second free will crash before
+ * reaching the intended safety check.
+ */
+ fake_abort_called = true;
+ }
+ mallctl("thread.tcache.flush", NULL, NULL, NULL, 0);
+ test_large_double_free_post();
+}
+TEST_END
+
+TEST_BEGIN(test_large_double_free_no_tcache) {
+ test_skip_if(!config_opt_safety_checks);
+ test_skip_if(config_debug);
+
+ test_large_double_free_pre();
+ char *ptr = mallocx(SC_LARGE_MINCLASS, MALLOCX_TCACHE_NONE);
+ bool guarded = extent_is_guarded(tsdn_fetch(), ptr);
+ dallocx(ptr, MALLOCX_TCACHE_NONE);
+ if (!guarded) {
+ dallocx(ptr, MALLOCX_TCACHE_NONE);
+ } else {
+ /*
+ * Skip because guarded extents may unguard immediately on
+ * deallocation, in which case the second free will crash before
+ * reaching the intended safety check.
+ */
+ fake_abort_called = true;
+ }
+ test_large_double_free_post();
+}
+TEST_END
+
+int
+main(void) {
+ return test(test_large_double_free_no_tcache,
+ test_large_double_free_tcache);
+}