double_free.c 1.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
  1. #include "test/jemalloc_test.h"
  2. #include "test/san.h"
  3. #include "jemalloc/internal/safety_check.h"
  4. bool fake_abort_called;
  5. void fake_abort(const char *message) {
  6. (void)message;
  7. fake_abort_called = true;
  8. }
  9. void
  10. test_large_double_free_pre(void) {
  11. safety_check_set_abort(&fake_abort);
  12. fake_abort_called = false;
  13. }
  14. void
  15. test_large_double_free_post() {
  16. expect_b_eq(fake_abort_called, true, "Double-free check didn't fire.");
  17. safety_check_set_abort(NULL);
  18. }
  19. TEST_BEGIN(test_large_double_free_tcache) {
  20. test_skip_if(!config_opt_safety_checks);
  21. /*
  22. * Skip debug builds, since too many assertions will be triggered with
  23. * double-free before hitting the one we are interested in.
  24. */
  25. test_skip_if(config_debug);
  26. test_large_double_free_pre();
  27. char *ptr = malloc(SC_LARGE_MINCLASS);
  28. bool guarded = extent_is_guarded(tsdn_fetch(), ptr);
  29. free(ptr);
  30. if (!guarded) {
  31. free(ptr);
  32. } else {
  33. /*
  34. * Skip because guarded extents may unguard immediately on
  35. * deallocation, in which case the second free will crash before
  36. * reaching the intended safety check.
  37. */
  38. fake_abort_called = true;
  39. }
  40. mallctl("thread.tcache.flush", NULL, NULL, NULL, 0);
  41. test_large_double_free_post();
  42. }
  43. TEST_END
  44. TEST_BEGIN(test_large_double_free_no_tcache) {
  45. test_skip_if(!config_opt_safety_checks);
  46. test_skip_if(config_debug);
  47. test_large_double_free_pre();
  48. char *ptr = mallocx(SC_LARGE_MINCLASS, MALLOCX_TCACHE_NONE);
  49. bool guarded = extent_is_guarded(tsdn_fetch(), ptr);
  50. dallocx(ptr, MALLOCX_TCACHE_NONE);
  51. if (!guarded) {
  52. dallocx(ptr, MALLOCX_TCACHE_NONE);
  53. } else {
  54. /*
  55. * Skip because guarded extents may unguard immediately on
  56. * deallocation, in which case the second free will crash before
  57. * reaching the intended safety check.
  58. */
  59. fake_abort_called = true;
  60. }
  61. test_large_double_free_post();
  62. }
  63. TEST_END
  64. int
  65. main(void) {
  66. return test(test_large_double_free_no_tcache,
  67. test_large_double_free_tcache);
  68. }