aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2015-11-26 13:23:02 -0500
committerTom Lane <tgl@sss.pgh.pa.us>2015-11-26 13:23:02 -0500
commit0da3a9bef7ad36dc640aebf2d0482e18f21561f6 (patch)
treefa6af174b9ec708d3f997519e1bef6e85af5ed37
parentc5ef8ce53d37e276d70593ff0f4b06dd119cd3ff (diff)
downloadpostgresql-0da3a9bef7ad36dc640aebf2d0482e18f21561f6.tar.gz
postgresql-0da3a9bef7ad36dc640aebf2d0482e18f21561f6.zip
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 13bba0227.
-rw-r--r--src/backend/utils/time/combocid.c43
1 files changed, 23 insertions, 20 deletions
diff --git a/src/backend/utils/time/combocid.c b/src/backend/utils/time/combocid.c
index bb2f3295a44..97598aceb3a 100644
--- a/src/backend/utils/time/combocid.c
+++ b/src/backend/utils/time/combocid.c
@@ -217,6 +217,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);
@@ -226,12 +233,20 @@ GetComboCommandId(CommandId cmin, CommandId cmax)
CCID_HASH_SIZE,
&hash_ctl,
HASH_ELEM | HASH_BLOBS | 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 */
@@ -250,20 +265,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;
@@ -327,8 +329,9 @@ SerializeComboCIDState(Size maxsize, char *start_address)
elog(ERROR, "not enough space to serialize ComboCID state");
/* Now, copy the actual cmin/cmax pairs. */
- memcpy(start_address + sizeof(int), comboCids,
- (sizeof(ComboCidKeyData) * usedComboCids));
+ if (usedComboCids > 0)
+ memcpy(start_address + sizeof(int), comboCids,
+ (sizeof(ComboCidKeyData) * usedComboCids));
}
/*