Skip to content

Block cache holds dangling pointers from custom new, then regex_search corrupts memory #258

@nlguillemot

Description

@nlguillemot

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions