1
0
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:
Tom Lane
2026-08-02 16:49:18 -04:00
parent 5fdea3aa32
commit 634a8dcb8f

View File

@@ -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,
&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))