mirror of
https://github.com/postgres/postgres.git
synced 2025-06-23 14:01:44 +03:00
Fix assign_record_type_typmod().
If an error occurred in the wrong place, it was possible to leave an
unintialized entry in the hash table, leading to a crash. Fixed.
Also, be more careful about the order of operations so that an
allocation error doesn't leak memory in CacheMemoryContext or
unnecessarily advance NextRecordTypmod.
Backpatch through version 11. Earlier versions (prior to 35ea75632a
)
do not exhibit the problem, because an uninitialized hash entry
contains a valid empty list.
Author: Sait Talha Nisanci <Sait.Nisanci@microsoft.com>
Reviewed-by: Andres Freund
Discussion: https://postgr.es/m/HE1PR8303MB009069D476225B9A9E194B8891779@HE1PR8303MB0090.EURPRD83.prod.outlook.com
Backpatch-through: 11
This commit is contained in:
26
src/backend/utils/cache/typcache.c
vendored
26
src/backend/utils/cache/typcache.c
vendored
@ -1786,10 +1786,14 @@ assign_record_type_typmod(TupleDesc tupDesc)
|
|||||||
CreateCacheMemoryContext();
|
CreateCacheMemoryContext();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Find or create a hashtable entry for this tuple descriptor */
|
/*
|
||||||
|
* Find a hashtable entry for this tuple descriptor. We don't use
|
||||||
|
* HASH_ENTER yet, because if it's missing, we need to make sure that all
|
||||||
|
* the allocations succeed before we create the new entry.
|
||||||
|
*/
|
||||||
recentry = (RecordCacheEntry *) hash_search(RecordCacheHash,
|
recentry = (RecordCacheEntry *) hash_search(RecordCacheHash,
|
||||||
(void *) &tupDesc,
|
(void *) &tupDesc,
|
||||||
HASH_ENTER, &found);
|
HASH_FIND, &found);
|
||||||
if (found && recentry->tupdesc != NULL)
|
if (found && recentry->tupdesc != NULL)
|
||||||
{
|
{
|
||||||
tupDesc->tdtypmod = recentry->tupdesc->tdtypmod;
|
tupDesc->tdtypmod = recentry->tupdesc->tdtypmod;
|
||||||
@ -1797,25 +1801,39 @@ assign_record_type_typmod(TupleDesc tupDesc)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Not present, so need to manufacture an entry */
|
/* Not present, so need to manufacture an entry */
|
||||||
recentry->tupdesc = NULL;
|
|
||||||
oldcxt = MemoryContextSwitchTo(CacheMemoryContext);
|
oldcxt = MemoryContextSwitchTo(CacheMemoryContext);
|
||||||
|
|
||||||
/* Look in the SharedRecordTypmodRegistry, if attached */
|
/* Look in the SharedRecordTypmodRegistry, if attached */
|
||||||
entDesc = find_or_make_matching_shared_tupledesc(tupDesc);
|
entDesc = find_or_make_matching_shared_tupledesc(tupDesc);
|
||||||
if (entDesc == NULL)
|
if (entDesc == NULL)
|
||||||
{
|
{
|
||||||
|
/*
|
||||||
|
* Make sure we have room before we CreateTupleDescCopy() or advance
|
||||||
|
* NextRecordTypmod.
|
||||||
|
*/
|
||||||
|
ensure_record_cache_typmod_slot_exists(NextRecordTypmod);
|
||||||
|
|
||||||
/* Reference-counted local cache only. */
|
/* Reference-counted local cache only. */
|
||||||
entDesc = CreateTupleDescCopy(tupDesc);
|
entDesc = CreateTupleDescCopy(tupDesc);
|
||||||
entDesc->tdrefcount = 1;
|
entDesc->tdrefcount = 1;
|
||||||
entDesc->tdtypmod = NextRecordTypmod++;
|
entDesc->tdtypmod = NextRecordTypmod++;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
ensure_record_cache_typmod_slot_exists(entDesc->tdtypmod);
|
ensure_record_cache_typmod_slot_exists(entDesc->tdtypmod);
|
||||||
|
}
|
||||||
|
|
||||||
RecordCacheArray[entDesc->tdtypmod] = entDesc;
|
RecordCacheArray[entDesc->tdtypmod] = entDesc;
|
||||||
recentry->tupdesc = entDesc;
|
|
||||||
|
|
||||||
/* Assign a unique tupdesc identifier, too. */
|
/* Assign a unique tupdesc identifier, too. */
|
||||||
RecordIdentifierArray[entDesc->tdtypmod] = ++tupledesc_id_counter;
|
RecordIdentifierArray[entDesc->tdtypmod] = ++tupledesc_id_counter;
|
||||||
|
|
||||||
|
/* Fully initialized; create the hash table entry */
|
||||||
|
recentry = (RecordCacheEntry *) hash_search(RecordCacheHash,
|
||||||
|
(void *) &tupDesc,
|
||||||
|
HASH_ENTER, NULL);
|
||||||
|
recentry->tupdesc = entDesc;
|
||||||
|
|
||||||
/* Update the caller's tuple descriptor. */
|
/* Update the caller's tuple descriptor. */
|
||||||
tupDesc->tdtypmod = entDesc->tdtypmod;
|
tupDesc->tdtypmod = entDesc->tdtypmod;
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user