Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit dd0e37c

Browse files
committed
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 35ea756) 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
1 parent 9f6be2e commit dd0e37c

File tree

1 file changed

+23
-5
lines changed

1 file changed

+23
-5
lines changed

src/backend/utils/cache/typcache.c

+23-5
Original file line numberDiff line numberDiff line change
@@ -1968,36 +1968,54 @@ assign_record_type_typmod(TupleDesc tupDesc)
19681968
CreateCacheMemoryContext();
19691969
}
19701970

1971-
/* Find or create a hashtable entry for this tuple descriptor */
1971+
/*
1972+
* Find a hashtable entry for this tuple descriptor. We don't use
1973+
* HASH_ENTER yet, because if it's missing, we need to make sure that all
1974+
* the allocations succeed before we create the new entry.
1975+
*/
19721976
recentry = (RecordCacheEntry *) hash_search(RecordCacheHash,
19731977
(void *) &tupDesc,
1974-
HASH_ENTER, &found);
1978+
HASH_FIND, &found);
19751979
if (found && recentry->tupdesc != NULL)
19761980
{
19771981
tupDesc->tdtypmod = recentry->tupdesc->tdtypmod;
19781982
return;
19791983
}
19801984

19811985
/* Not present, so need to manufacture an entry */
1982-
recentry->tupdesc = NULL;
19831986
oldcxt = MemoryContextSwitchTo(CacheMemoryContext);
19841987

19851988
/* Look in the SharedRecordTypmodRegistry, if attached */
19861989
entDesc = find_or_make_matching_shared_tupledesc(tupDesc);
19871990
if (entDesc == NULL)
19881991
{
1992+
/*
1993+
* Make sure we have room before we CreateTupleDescCopy() or advance
1994+
* NextRecordTypmod.
1995+
*/
1996+
ensure_record_cache_typmod_slot_exists(NextRecordTypmod);
1997+
19891998
/* Reference-counted local cache only. */
19901999
entDesc = CreateTupleDescCopy(tupDesc);
19912000
entDesc->tdrefcount = 1;
19922001
entDesc->tdtypmod = NextRecordTypmod++;
19932002
}
1994-
ensure_record_cache_typmod_slot_exists(entDesc->tdtypmod);
2003+
else
2004+
{
2005+
ensure_record_cache_typmod_slot_exists(entDesc->tdtypmod);
2006+
}
2007+
19952008
RecordCacheArray[entDesc->tdtypmod] = entDesc;
1996-
recentry->tupdesc = entDesc;
19972009

19982010
/* Assign a unique tupdesc identifier, too. */
19992011
RecordIdentifierArray[entDesc->tdtypmod] = ++tupledesc_id_counter;
20002012

2013+
/* Fully initialized; create the hash table entry */
2014+
recentry = (RecordCacheEntry *) hash_search(RecordCacheHash,
2015+
(void *) &tupDesc,
2016+
HASH_ENTER, NULL);
2017+
recentry->tupdesc = entDesc;
2018+
20012019
/* Update the caller's tuple descriptor. */
20022020
tupDesc->tdtypmod = entDesc->tdtypmod;
20032021

0 commit comments

Comments
 (0)