-
Notifications
You must be signed in to change notification settings - Fork 104
Description
Problem
The global memory block cache does not consider the possibility that operator new could be temporarily overridden.
This means that the global memory block cache can erroneously hold onto pointers from temporary allocators.
Repro
The example below illustrates how disabling the memory block cache fixes the issue.
If you remove the #define that disables the cache, then it crashes with eg. "double free or corruption"
https://coliru.stacked-crooked.com/a/417637f462a33d56
// Remove this line to cause a crash.
#define BOOST_REGEX_MAX_CACHE_BLOCKS 0
#include <boost/regex.hpp>
#include <cstddef>
#include <cstdlib>
struct StackAlloc {
char* buf;
size_t off = 0;
StackAlloc() { buf = (char*)malloc(64 * 1024); }
~StackAlloc() { free(buf); }
void* alloc(size_t n) { off=(off+7)&~7; void* p=buf+off; off+=n; return p; }
void dealloc(void*) {}
};
thread_local StackAlloc* current_alloc;
void* operator new(size_t n) {
return current_alloc ? current_alloc->alloc(n) : malloc(n);
}
void operator delete(void* p) noexcept {
current_alloc ? current_alloc->dealloc(p) : free(p);
}
int main() {
boost::regex rx("(a+)(b*)");
{
StackAlloc a;
current_alloc = &a;
boost::regex_search("aaaaabbbb", rx);
current_alloc = nullptr;
}
boost::regex_search("aaaaabbbb", rx);
}Comparison
This issue does not happen with std::regex because implementations of std::regex don't use a global memory block cache.
Suggestion
My suggestion is to disable the cache by default, and include a warning in the documentation about enabling it.
Alternatively, I suggest to put a clear warning about the std::regex incompatibility in the documentation.