mirror of
https://github.com/postgres/postgres.git
synced 2026-10-23 13:29:09 +03:00
Tighten up TS dictionary cache entry creation.
In the not-too-likely scenario where we successfully created a hash table entry for a TS dictionary, but then failed to make a small memory context for it, we left the hash entry in existence but with a garbage value for dictCtx. This confused the code the next time through, leading to a crash. Rearrange things so that we leave the hash entry in a well-defined state with dictCtx == NULL, and then the next try knows it still needs to make a memory context. Reported-by: Alexander Lakhin <exclusion@gmail.com> Author: Tom Lane <tgl@sss.pgh.pa.us> Discussion: https://postgr.es/m/0f3ddeb5-0dbd-479c-9d0e-ae254758e624@gmail.com Backpatch-through: 14
This commit is contained in:
29
src/backend/utils/cache/ts_cache.c
vendored
29
src/backend/utils/cache/ts_cache.c
vendored
@@ -279,37 +279,50 @@ lookup_ts_dictionary_cache(Oid dictId)
|
||||
elog(ERROR, "text search template %u has no lexize method",
|
||||
template->tmpllexize);
|
||||
|
||||
/*
|
||||
* OK, create or clear out the hashtable entry
|
||||
*/
|
||||
if (entry == NULL)
|
||||
{
|
||||
bool found;
|
||||
|
||||
/* Now make the cache entry */
|
||||
entry = (TSDictionaryCacheEntry *)
|
||||
hash_search(TSDictionaryCacheHash,
|
||||
(void *) &dictId,
|
||||
HASH_ENTER, &found);
|
||||
Assert(!found); /* it wasn't there a moment ago */
|
||||
|
||||
/* Create private memory context the first time through */
|
||||
memset(entry, 0, sizeof(TSDictionaryCacheEntry));
|
||||
entry->dictId = dictId;
|
||||
saveCtx = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
saveCtx = entry->dictCtx; /* could be NULL if we failed before */
|
||||
memset(entry, 0, sizeof(TSDictionaryCacheEntry));
|
||||
entry->dictId = dictId;
|
||||
entry->dictCtx = saveCtx;
|
||||
}
|
||||
|
||||
/*
|
||||
* Create or clear the entry's private memory context
|
||||
*/
|
||||
if (saveCtx == NULL)
|
||||
{
|
||||
saveCtx = AllocSetContextCreate(CacheMemoryContext,
|
||||
"TS dictionary",
|
||||
ALLOCSET_SMALL_SIZES);
|
||||
entry->dictCtx = saveCtx;
|
||||
MemoryContextCopyAndSetIdentifier(saveCtx, NameStr(dict->dictname));
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Clear the existing entry's private context */
|
||||
saveCtx = entry->dictCtx;
|
||||
/* Don't let context's ident pointer dangle while we reset it */
|
||||
MemoryContextSetIdentifier(saveCtx, NULL);
|
||||
MemoryContextReset(saveCtx);
|
||||
MemoryContextCopyAndSetIdentifier(saveCtx, NameStr(dict->dictname));
|
||||
}
|
||||
|
||||
MemSet(entry, 0, sizeof(TSDictionaryCacheEntry));
|
||||
entry->dictId = dictId;
|
||||
entry->dictCtx = saveCtx;
|
||||
|
||||
entry->lexizeOid = template->tmpllexize;
|
||||
|
||||
if (OidIsValid(template->tmplinit))
|
||||
|
||||
Reference in New Issue
Block a user