forked from lix-project/lix
allocate a GC root value for the Value cache pointer
keeping it as a simple data member means it won't be scanned by the GC, so eventually the GC will collect a cache that is still referenced (resulting in use-after-free of cache elements). fixes #5962
This commit is contained in:
parent
5f08db69d1
commit
fd5aa6ee3e
|
@ -435,6 +435,11 @@ EvalState::EvalState(
|
||||||
, store(store)
|
, store(store)
|
||||||
, buildStore(buildStore ? buildStore : store)
|
, buildStore(buildStore ? buildStore : store)
|
||||||
, regexCache(makeRegexCache())
|
, regexCache(makeRegexCache())
|
||||||
|
#if HAVE_BOEHMGC
|
||||||
|
, valueAllocCache(std::allocate_shared<void *>(traceable_allocator<void *>(), nullptr))
|
||||||
|
#else
|
||||||
|
, valueAllocCache(std::make_shared<void *>(nullptr))
|
||||||
|
#endif
|
||||||
, baseEnv(allocEnv(128))
|
, baseEnv(allocEnv(128))
|
||||||
, staticBaseEnv(false, 0)
|
, staticBaseEnv(false, 0)
|
||||||
{
|
{
|
||||||
|
@ -852,15 +857,15 @@ Value * EvalState::allocValue()
|
||||||
GC_malloc_many returns a linked list of objects of the given size, where the first word
|
GC_malloc_many returns a linked list of objects of the given size, where the first word
|
||||||
of each object is also the pointer to the next object in the list. This also means that we
|
of each object is also the pointer to the next object in the list. This also means that we
|
||||||
have to explicitly clear the first word of every object we take. */
|
have to explicitly clear the first word of every object we take. */
|
||||||
if (!valueAllocCache) {
|
if (!*valueAllocCache) {
|
||||||
valueAllocCache = GC_malloc_many(sizeof(Value));
|
*valueAllocCache = GC_malloc_many(sizeof(Value));
|
||||||
if (!valueAllocCache) throw std::bad_alloc();
|
if (!*valueAllocCache) throw std::bad_alloc();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* GC_NEXT is a convenience macro for accessing the first word of an object.
|
/* GC_NEXT is a convenience macro for accessing the first word of an object.
|
||||||
Take the first list item, advance the list to the next item, and clear the next pointer. */
|
Take the first list item, advance the list to the next item, and clear the next pointer. */
|
||||||
void * p = valueAllocCache;
|
void * p = *valueAllocCache;
|
||||||
GC_PTR_STORE_AND_DIRTY(&valueAllocCache, GC_NEXT(p));
|
GC_PTR_STORE_AND_DIRTY(&*valueAllocCache, GC_NEXT(p));
|
||||||
GC_NEXT(p) = nullptr;
|
GC_NEXT(p) = nullptr;
|
||||||
|
|
||||||
nrValues++;
|
nrValues++;
|
||||||
|
|
|
@ -133,7 +133,7 @@ private:
|
||||||
std::shared_ptr<RegexCache> regexCache;
|
std::shared_ptr<RegexCache> regexCache;
|
||||||
|
|
||||||
/* Allocation cache for GC'd Value objects. */
|
/* Allocation cache for GC'd Value objects. */
|
||||||
void * valueAllocCache = nullptr;
|
std::shared_ptr<void *> valueAllocCache;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue