Skip to content

Commit 0da3a9b

Browse files
committed
Fix failure to consider failure cases in GetComboCommandId().
Failure to initially palloc the comboCids array, or to realloc it bigger when needed, left combocid's data structures in an inconsistent state that would cause trouble if the top transaction continues to execute. Noted while examining a user complaint about the amount of memory used for this. (There's not much we can do about that, but it does point up that repalloc failure has a non-negligible chance of occurring here.) In HEAD/9.5, also avoid possible invocation of memcpy() with a null pointer in SerializeComboCIDState; cf commit 13bba02.
1 parent c5ef8ce commit 0da3a9b

File tree

1 file changed

+23
-20
lines changed

1 file changed

+23
-20
lines changed

src/backend/utils/time/combocid.c

Lines changed: 23 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,13 @@ GetComboCommandId(CommandId cmin, CommandId cmax)
217217
{
218218
HASHCTL hash_ctl;
219219

220+
/* Make array first; existence of hash table asserts array exists */
221+
comboCids = (ComboCidKeyData *)
222+
MemoryContextAlloc(TopTransactionContext,
223+
sizeof(ComboCidKeyData) * CCID_ARRAY_SIZE);
224+
sizeComboCids = CCID_ARRAY_SIZE;
225+
usedComboCids = 0;
226+
220227
memset(&hash_ctl, 0, sizeof(hash_ctl));
221228
hash_ctl.keysize = sizeof(ComboCidKeyData);
222229
hash_ctl.entrysize = sizeof(ComboCidEntryData);
@@ -226,12 +233,20 @@ GetComboCommandId(CommandId cmin, CommandId cmax)
226233
CCID_HASH_SIZE,
227234
&hash_ctl,
228235
HASH_ELEM | HASH_BLOBS | HASH_CONTEXT);
236+
}
237+
238+
/*
239+
* Grow the array if there's not at least one free slot. We must do this
240+
* before possibly entering a new hashtable entry, else failure to
241+
* repalloc would leave a corrupt hashtable entry behind.
242+
*/
243+
if (usedComboCids >= sizeComboCids)
244+
{
245+
int newsize = sizeComboCids * 2;
229246

230247
comboCids = (ComboCidKeyData *)
231-
MemoryContextAlloc(TopTransactionContext,
232-
sizeof(ComboCidKeyData) * CCID_ARRAY_SIZE);
233-
sizeComboCids = CCID_ARRAY_SIZE;
234-
usedComboCids = 0;
248+
repalloc(comboCids, sizeof(ComboCidKeyData) * newsize);
249+
sizeComboCids = newsize;
235250
}
236251

237252
/* Lookup or create a hash entry with the desired cmin/cmax */
@@ -250,20 +265,7 @@ GetComboCommandId(CommandId cmin, CommandId cmax)
250265
return entry->combocid;
251266
}
252267

253-
/*
254-
* We have to create a new combo cid. Check that there's room for it in
255-
* the array, and grow it if there isn't.
256-
*/
257-
if (usedComboCids >= sizeComboCids)
258-
{
259-
/* We need to grow the array */
260-
int newsize = sizeComboCids * 2;
261-
262-
comboCids = (ComboCidKeyData *)
263-
repalloc(comboCids, sizeof(ComboCidKeyData) * newsize);
264-
sizeComboCids = newsize;
265-
}
266-
268+
/* We have to create a new combo cid; we already made room in the array */
267269
combocid = usedComboCids;
268270

269271
comboCids[combocid].cmin = cmin;
@@ -327,8 +329,9 @@ SerializeComboCIDState(Size maxsize, char *start_address)
327329
elog(ERROR, "not enough space to serialize ComboCID state");
328330

329331
/* Now, copy the actual cmin/cmax pairs. */
330-
memcpy(start_address + sizeof(int), comboCids,
331-
(sizeof(ComboCidKeyData) * usedComboCids));
332+
if (usedComboCids > 0)
333+
memcpy(start_address + sizeof(int), comboCids,
334+
(sizeof(ComboCidKeyData) * usedComboCids));
332335
}
333336

334337
/*

0 commit comments

Comments
 (0)