On Fri, Apr 3, 2015 at 6:35 PM, Fujii Masao wrote: > Regarding the second patch, you added the checks of the return value of > XLogReaderAllocate(). But it seems half-baked. XLogReaderAllocate() still > uses palloc(), but don't we need to replace it with palloc_extended(), too?
Doh, you are right. I missed three places. Attached is a new patch completing the fix. -- Michael
From 292012c19805777cf17443eccd9b4ef05c5f42ec Mon Sep 17 00:00:00 2001 From: Michael Paquier <mich...@otacoo.com> Date: Fri, 3 Apr 2015 20:29:39 +0900 Subject: [PATCH] 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, making this routine compatible with previous major versions. --- src/backend/access/transam/xlogreader.c | 23 ++++++++++++++++++++--- src/backend/replication/logical/logical.c | 5 +++++ src/bin/pg_rewind/parsexlog.c | 6 ++++++ 3 files changed, 31 insertions(+), 3 deletions(-) diff --git a/src/backend/access/transam/xlogreader.c b/src/backend/access/transam/xlogreader.c index ffdc975..9047805 100644 --- a/src/backend/access/transam/xlogreader.c +++ b/src/backend/access/transam/xlogreader.c @@ -66,7 +66,11 @@ 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; @@ -77,14 +81,27 @@ XLogReaderAllocate(XLogPageReadCB pagereadfunc, void *private_data) * isn't guaranteed to have any particular alignment, whereas palloc() * 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 30baa45..774ebbc 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 0787ca1..3cf96ab 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 (;;) -- 2.3.5
-- Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-hackers