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; @@ -756,12 +764,18 @@ 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);