diff options
author | Fujii Masao <fujii@postgresql.org> | 2015-04-03 21:55:37 +0900 |
---|---|---|
committer | Fujii Masao <fujii@postgresql.org> | 2015-04-03 21:55:37 +0900 |
commit | 6e4bf4ecd3c2a266870139462a079809dfe7ab8c (patch) | |
tree | 8e363162645de6b1826003944e3b9a93e1a28e26 /src/backend/access/transam | |
parent | f85155e18cb71a599724536e598e8d6f5e140454 (diff) | |
download | postgresql-6e4bf4ecd3c2a266870139462a079809dfe7ab8c.tar.gz postgresql-6e4bf4ecd3c2a266870139462a079809dfe7ab8c.zip |
Fix error handling of XLogReaderAllocate in case of OOM
Similarly to previous fix 9b8d478, commit 2c03216 has switched
XLogReaderAllocate() to use a set of palloc calls instead of malloc,
causing any callers of this function to fail with an error instead of
receiving a NULL pointer in case of out-of-memory error. Fix this by
using palloc_extended with MCXT_ALLOC_NO_OOM that will safely return
NULL in case of an OOM.
Michael Paquier, slightly modified by me.
Diffstat (limited to 'src/backend/access/transam')
-rw-r--r-- | src/backend/access/transam/xlog.c | 7 | ||||
-rw-r--r-- | src/backend/access/transam/xlogreader.c | 30 |
2 files changed, 28 insertions, 9 deletions
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c index 346a2b39f85..24cf520e579 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 ffdc9753ad7..a4124d90d1b 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'; /* |