diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c index 346a2b39f8..24cf520e57 100644 --- a/src/backend/access/transam/xlog.c +++ b/src/backend/access/transam/xlog.c @@ -1062,8 +1062,11 @@ XLogInsertRecord(XLogRecData *rdata, XLogRecPtr fpw_lsn) if (!debug_reader) debug_reader = XLogReaderAllocate(NULL, NULL); - if (!debug_reader || - !DecodeXLogRecord(debug_reader, (XLogRecord *) recordBuf.data, + if (!debug_reader) + { + appendStringInfo(&buf, "error decoding record: out of memory"); + } + else if (!DecodeXLogRecord(debug_reader, (XLogRecord *) recordBuf.data, &errormsg)) { appendStringInfo(&buf, "error decoding record: %s", diff --git a/src/backend/access/transam/xlogreader.c b/src/backend/access/transam/xlogreader.c index ffdc9753ad..a4124d90d1 100644 --- a/src/backend/access/transam/xlogreader.c +++ b/src/backend/access/transam/xlogreader.c @@ -58,15 +58,18 @@ report_invalid_record(XLogReaderState *state, const char *fmt,...) /* * Allocate and initialize a new XLogReader. * - * The returned XLogReader is palloc'd. (In FRONTEND code, that means that - * running out-of-memory causes an immediate exit(1). + * Returns NULL if the xlogreader couldn't be allocated. */ XLogReaderState * XLogReaderAllocate(XLogPageReadCB pagereadfunc, void *private_data) { XLogReaderState *state; - state = (XLogReaderState *) palloc0(sizeof(XLogReaderState)); + state = (XLogReaderState *) + palloc_extended(sizeof(XLogReaderState), + MCXT_ALLOC_NO_OOM | MCXT_ALLOC_ZERO); + if (!state) + return NULL; state->max_block_id = -1; @@ -74,17 +77,30 @@ XLogReaderAllocate(XLogPageReadCB pagereadfunc, void *private_data) * Permanently allocate readBuf. We do it this way, rather than just * making a static array, for two reasons: (1) no need to waste the * storage in most instantiations of the backend; (2) a static char array - * isn't guaranteed to have any particular alignment, whereas palloc() - * will provide MAXALIGN'd storage. + * isn't guaranteed to have any particular alignment, whereas + * palloc_extended() will provide MAXALIGN'd storage. */ - state->readBuf = (char *) palloc(XLOG_BLCKSZ); + state->readBuf = (char *) palloc_extended(XLOG_BLCKSZ, + MCXT_ALLOC_NO_OOM); + if (!state->readBuf) + { + pfree(state); + return NULL; + } state->read_page = pagereadfunc; /* system_identifier initialized to zeroes above */ state->private_data = private_data; /* ReadRecPtr and EndRecPtr initialized to zeroes above */ /* readSegNo, readOff, readLen, readPageTLI initialized to zeroes above */ - state->errormsg_buf = palloc(MAX_ERRORMSG_LEN + 1); + state->errormsg_buf = palloc_extended(MAX_ERRORMSG_LEN + 1, + MCXT_ALLOC_NO_OOM); + if (!state->errormsg_buf) + { + pfree(state->readBuf); + pfree(state); + return NULL; + } state->errormsg_buf[0] = '\0'; /* diff --git a/src/backend/replication/logical/logical.c b/src/backend/replication/logical/logical.c index 30baa45383..774ebbc749 100644 --- a/src/backend/replication/logical/logical.c +++ b/src/backend/replication/logical/logical.c @@ -163,6 +163,11 @@ StartupDecodingContext(List *output_plugin_options, ctx->slot = slot; ctx->reader = XLogReaderAllocate(read_page, ctx); + if (!ctx->reader) + ereport(ERROR, + (errcode(ERRCODE_OUT_OF_MEMORY), + errmsg("out of memory"))); + ctx->reader->private_data = ctx; ctx->reorder = ReorderBufferAllocate(); diff --git a/src/bin/pg_rewind/parsexlog.c b/src/bin/pg_rewind/parsexlog.c index 0787ca12a7..3cf96abd08 100644 --- a/src/bin/pg_rewind/parsexlog.c +++ b/src/bin/pg_rewind/parsexlog.c @@ -70,6 +70,8 @@ extractPageMap(const char *datadir, XLogRecPtr startpoint, TimeLineID tli, private.datadir = datadir; private.tli = tli; xlogreader = XLogReaderAllocate(&SimpleXLogPageRead, &private); + if (xlogreader == NULL) + pg_fatal("out of memory"); do { @@ -121,6 +123,8 @@ readOneRecord(const char *datadir, XLogRecPtr ptr, TimeLineID tli) private.datadir = datadir; private.tli = tli; xlogreader = XLogReaderAllocate(&SimpleXLogPageRead, &private); + if (xlogreader == NULL) + pg_fatal("out of memory"); record = XLogReadRecord(xlogreader, ptr, &errormsg); if (record == NULL) @@ -171,6 +175,8 @@ findLastCheckpoint(const char *datadir, XLogRecPtr forkptr, TimeLineID tli, private.datadir = datadir; private.tli = tli; xlogreader = XLogReaderAllocate(&SimpleXLogPageRead, &private); + if (xlogreader == NULL) + pg_fatal("out of memory"); searchptr = forkptr; for (;;)