From a46bf328e6c3a58734e6d0e15c678a9d2857497c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Mah=C3=A9?= Date: Thu, 10 Nov 2022 11:17:38 +0100 Subject: [PATCH] bug fix: bloomflex std::bad_alloc for large (2^32?) allocations when using the fastidious option, swarm crashes when it tries to allocate the bloomfilter (at least for allocations of 5 GB, could also be the case for smaller allocations). Our current tests are not able to trigger this bug. I've introduced the bug on January 28th while replacing malloc with new and delete. Sadly, the bug is present in main branch and in the v3.1.1 release, so I think an urgent v3.1.2 release is necessary. Other replacements of malloc made in January may have introduced so-far undetected bugs. I will do my best to test large datasets before future releases. --- src/bloomflex.cc | 16 +++++++--------- src/util.cc | 22 +++++++++++++++++++++- src/util.h | 1 + 3 files changed, 29 insertions(+), 10 deletions(-) diff --git a/src/bloomflex.cc b/src/bloomflex.cc index d60b5347..9feb0d12 100644 --- a/src/bloomflex.cc +++ b/src/bloomflex.cc @@ -35,6 +35,7 @@ #include #include "bloomflex.h" #include "pseudo_rng.h" +#include "util.h" auto bloomflex_patterns_generate(struct bloomflex_s * b) -> void @@ -64,7 +65,7 @@ auto bloomflex_init(uint64_t size, unsigned int k) -> struct bloomflex_s * constexpr unsigned int multiplier {16}; // multiply by 65,536 constexpr unsigned int divider {3}; // divide by 8 - auto * b = new struct bloomflex_s; + auto * b = static_cast(xmalloc(sizeof(struct bloomflex_s))); b->size = size >> divider; b->pattern_shift = multiplier; @@ -72,10 +73,10 @@ auto bloomflex_init(uint64_t size, unsigned int k) -> struct bloomflex_s * b->pattern_mask = b->pattern_count - 1; b->pattern_k = k; - b->patterns = new uint64_t[b->pattern_count]; + b->patterns = static_cast(xmalloc(b->pattern_count * sizeof(uint64_t))); bloomflex_patterns_generate(b); - b->bitmap = new uint64_t[size]; + b->bitmap = static_cast(xmalloc(size)); memset(b->bitmap, UINT8_MAX, size); return b; @@ -84,10 +85,7 @@ auto bloomflex_init(uint64_t size, unsigned int k) -> struct bloomflex_s * auto bloomflex_exit(struct bloomflex_s * b) -> void { - delete [] b->bitmap; - b->bitmap = nullptr; - delete [] b->patterns; - b->patterns = nullptr; - delete b; - b = nullptr; + xfree(b->bitmap); + xfree(b->patterns); + xfree(b); } diff --git a/src/util.cc b/src/util.cc index 6d1a00cf..2b55140c 100644 --- a/src/util.cc +++ b/src/util.cc @@ -28,6 +28,7 @@ static const char * progress_prompt; static uint64_t progress_next; static uint64_t progress_size; static uint64_t progress_chunk; +constexpr size_t memalignment = 16; auto progress_init(const char * prompt, const uint64_t size) -> void @@ -70,13 +71,32 @@ auto progress_done() -> void } +auto xmalloc(size_t size) -> void * +{ + if (size == 0) { + size = 1; + } + void * t {nullptr}; +#ifdef _WIN32 + t = _aligned_malloc(size, memalignment); +#else + if (posix_memalign(& t, memalignment, size) != 0) { + t = nullptr; + } +#endif + if (t == nullptr) { + fatal(error_prefix, "Unable to allocate enough memory."); + } + return t; +} + + auto xrealloc(void *ptr, size_t size) -> void * { if (size == 0) { size = 1; } #ifdef _WIN32 - constexpr size_t memalignment = 16; void * t = _aligned_realloc(ptr, size, memalignment); #else void * t = realloc(ptr, size); diff --git a/src/util.h b/src/util.h index ffcfcfbb..d0620130 100644 --- a/src/util.h +++ b/src/util.h @@ -25,6 +25,7 @@ #include +auto xmalloc(size_t size) -> void *; auto xrealloc(void * ptr, size_t size) -> void *; auto xfree(void * ptr) -> void; auto xgetline(char ** linep, size_t * linecapp, FILE * stream) -> ssize_t;