postgres.git / summary / log / commit / refs
commit dda622edcdba673e90d7b2cafe747ab78249368b
Author: Tom Lane <tgl@sss.pgh.pa.us>
Date: Sun Aug 02 20:49:18 2026 +0000
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
src/backend/utils/cache/ts_cache.c | 29 +++++++++++++++++++++--------
1 file changed, 21 insertions(+), 8 deletions(-)
diff --git a/src/backend/utils/cache/ts_cache.c b/src/backend/utils/cache/ts_cache.c
index 384107b6bac..3885c345975 100644
--- a/src/backend/utils/cache/ts_cache.c
+++ b/src/backend/utils/cache/ts_cache.c
@@ -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))
[parent: cfc720ef4b1d]