summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/backend/access/transam/xloginsert.c22
-rw-r--r--src/include/access/xloginsert.h4
2 files changed, 20 insertions, 6 deletions
diff --git a/src/backend/access/transam/xloginsert.c b/src/backend/access/transam/xloginsert.c
index f3c29fa9091..24f9755e5d8 100644
--- a/src/backend/access/transam/xloginsert.c
+++ b/src/backend/access/transam/xloginsert.c
@@ -348,7 +348,7 @@ XLogRegisterBlock(uint8 block_id, RelFileLocator *rlocator, ForkNumber forknum,
* XLogRecGetData().
*/
void
-XLogRegisterData(char *data, int len)
+XLogRegisterData(char *data, uint32 len)
{
XLogRecData *rdata;
@@ -386,7 +386,7 @@ XLogRegisterData(char *data, int len)
* limited)
*/
void
-XLogRegisterBufData(uint8 block_id, char *data, int len)
+XLogRegisterBufData(uint8 block_id, char *data, uint32 len)
{
registered_buffer *regbuf;
XLogRecData *rdata;
@@ -399,8 +399,16 @@ XLogRegisterBufData(uint8 block_id, char *data, int len)
elog(ERROR, "no block with id %d registered with WAL insertion",
block_id);
- if (num_rdatas >= max_rdatas)
+ /*
+ * Check against max_rdatas and ensure we do not register more data per
+ * buffer than can be handled by the physical data format; i.e. that
+ * regbuf->rdata_len does not grow beyond what
+ * XLogRecordBlockHeader->data_length can hold.
+ */
+ if (num_rdatas >= max_rdatas ||
+ regbuf->rdata_len + len > UINT16_MAX)
elog(ERROR, "too much WAL data");
+
rdata = &rdatas[num_rdatas++];
rdata->data = data;
@@ -757,11 +765,17 @@ XLogRecordAssemble(RmgrId rmid, uint8 info,
if (needs_data)
{
/*
+ * When copying to XLogRecordBlockHeader, the length is narrowed
+ * to an uint16. Double-check that it is still correct.
+ */
+ Assert(regbuf->rdata_len <= UINT16_MAX);
+
+ /*
* Link the caller-supplied rdata chain for this buffer to the
* overall list.
*/
bkpb.fork_flags |= BKPBLOCK_HAS_DATA;
- bkpb.data_length = regbuf->rdata_len;
+ bkpb.data_length = (uint16) regbuf->rdata_len;
total_len += regbuf->rdata_len;
rdt_datas_last->next = regbuf->rdata_head;
diff --git a/src/include/access/xloginsert.h b/src/include/access/xloginsert.h
index c04f77b173a..aed4643d1c5 100644
--- a/src/include/access/xloginsert.h
+++ b/src/include/access/xloginsert.h
@@ -43,12 +43,12 @@ extern void XLogBeginInsert(void);
extern void XLogSetRecordFlags(uint8 flags);
extern XLogRecPtr XLogInsert(RmgrId rmid, uint8 info);
extern void XLogEnsureRecordSpace(int max_block_id, int ndatas);
-extern void XLogRegisterData(char *data, int len);
+extern void XLogRegisterData(char *data, uint32 len);
extern void XLogRegisterBuffer(uint8 block_id, Buffer buffer, uint8 flags);
extern void XLogRegisterBlock(uint8 block_id, RelFileLocator *rlocator,
ForkNumber forknum, BlockNumber blknum, char *page,
uint8 flags);
-extern void XLogRegisterBufData(uint8 block_id, char *data, int len);
+extern void XLogRegisterBufData(uint8 block_id, char *data, uint32 len);
extern void XLogResetInsertion(void);
extern bool XLogCheckBufferNeedsBackup(Buffer buffer);