diff --git a/src/backend/utils/time/combocid.c b/src/backend/utils/time/combocid.c index 85de85adf86d382fbb6b98e50588817011b0f5b9..12bc2eedfeb12b8e56a57aa66118b3e4205e4909 100644 --- a/src/backend/utils/time/combocid.c +++ b/src/backend/utils/time/combocid.c @@ -208,6 +208,13 @@ GetComboCommandId(CommandId cmin, CommandId cmax) { HASHCTL hash_ctl; + /* Make array first; existence of hash table asserts array exists */ + comboCids = (ComboCidKeyData *) + MemoryContextAlloc(TopTransactionContext, + sizeof(ComboCidKeyData) * CCID_ARRAY_SIZE); + sizeComboCids = CCID_ARRAY_SIZE; + usedComboCids = 0; + memset(&hash_ctl, 0, sizeof(hash_ctl)); hash_ctl.keysize = sizeof(ComboCidKeyData); hash_ctl.entrysize = sizeof(ComboCidEntryData); @@ -218,12 +225,20 @@ GetComboCommandId(CommandId cmin, CommandId cmax) CCID_HASH_SIZE, &hash_ctl, HASH_ELEM | HASH_FUNCTION | HASH_CONTEXT); + } + + /* + * Grow the array if there's not at least one free slot. We must do this + * before possibly entering a new hashtable entry, else failure to + * repalloc would leave a corrupt hashtable entry behind. + */ + if (usedComboCids >= sizeComboCids) + { + int newsize = sizeComboCids * 2; comboCids = (ComboCidKeyData *) - MemoryContextAlloc(TopTransactionContext, - sizeof(ComboCidKeyData) * CCID_ARRAY_SIZE); - sizeComboCids = CCID_ARRAY_SIZE; - usedComboCids = 0; + repalloc(comboCids, sizeof(ComboCidKeyData) * newsize); + sizeComboCids = newsize; } /* Lookup or create a hash entry with the desired cmin/cmax */ @@ -242,20 +257,7 @@ GetComboCommandId(CommandId cmin, CommandId cmax) return entry->combocid; } - /* - * We have to create a new combo cid. Check that there's room for it in - * the array, and grow it if there isn't. - */ - if (usedComboCids >= sizeComboCids) - { - /* We need to grow the array */ - int newsize = sizeComboCids * 2; - - comboCids = (ComboCidKeyData *) - repalloc(comboCids, sizeof(ComboCidKeyData) * newsize); - sizeComboCids = newsize; - } - + /* We have to create a new combo cid; we already made room in the array */ combocid = usedComboCids; comboCids[combocid].cmin = cmin;