Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 6e4bf4e

Browse files
committed
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.
1 parent f85155e commit 6e4bf4e

File tree

4 files changed

+39
-9
lines changed

4 files changed

+39
-9
lines changed

src/backend/access/transam/xlog.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1062,8 +1062,11 @@ XLogInsertRecord(XLogRecData *rdata, XLogRecPtr fpw_lsn)
10621062
if (!debug_reader)
10631063
debug_reader = XLogReaderAllocate(NULL, NULL);
10641064

1065-
if (!debug_reader ||
1066-
!DecodeXLogRecord(debug_reader, (XLogRecord *) recordBuf.data,
1065+
if (!debug_reader)
1066+
{
1067+
appendStringInfo(&buf, "error decoding record: out of memory");
1068+
}
1069+
else if (!DecodeXLogRecord(debug_reader, (XLogRecord *) recordBuf.data,
10671070
&errormsg))
10681071
{
10691072
appendStringInfo(&buf, "error decoding record: %s",

src/backend/access/transam/xlogreader.c

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -58,33 +58,49 @@ report_invalid_record(XLogReaderState *state, const char *fmt,...)
5858
/*
5959
* Allocate and initialize a new XLogReader.
6060
*
61-
* The returned XLogReader is palloc'd. (In FRONTEND code, that means that
62-
* running out-of-memory causes an immediate exit(1).
61+
* Returns NULL if the xlogreader couldn't be allocated.
6362
*/
6463
XLogReaderState *
6564
XLogReaderAllocate(XLogPageReadCB pagereadfunc, void *private_data)
6665
{
6766
XLogReaderState *state;
6867

69-
state = (XLogReaderState *) palloc0(sizeof(XLogReaderState));
68+
state = (XLogReaderState *)
69+
palloc_extended(sizeof(XLogReaderState),
70+
MCXT_ALLOC_NO_OOM | MCXT_ALLOC_ZERO);
71+
if (!state)
72+
return NULL;
7073

7174
state->max_block_id = -1;
7275

7376
/*
7477
* Permanently allocate readBuf. We do it this way, rather than just
7578
* making a static array, for two reasons: (1) no need to waste the
7679
* storage in most instantiations of the backend; (2) a static char array
77-
* isn't guaranteed to have any particular alignment, whereas palloc()
78-
* will provide MAXALIGN'd storage.
80+
* isn't guaranteed to have any particular alignment, whereas
81+
* palloc_extended() will provide MAXALIGN'd storage.
7982
*/
80-
state->readBuf = (char *) palloc(XLOG_BLCKSZ);
83+
state->readBuf = (char *) palloc_extended(XLOG_BLCKSZ,
84+
MCXT_ALLOC_NO_OOM);
85+
if (!state->readBuf)
86+
{
87+
pfree(state);
88+
return NULL;
89+
}
8190

8291
state->read_page = pagereadfunc;
8392
/* system_identifier initialized to zeroes above */
8493
state->private_data = private_data;
8594
/* ReadRecPtr and EndRecPtr initialized to zeroes above */
8695
/* readSegNo, readOff, readLen, readPageTLI initialized to zeroes above */
87-
state->errormsg_buf = palloc(MAX_ERRORMSG_LEN + 1);
96+
state->errormsg_buf = palloc_extended(MAX_ERRORMSG_LEN + 1,
97+
MCXT_ALLOC_NO_OOM);
98+
if (!state->errormsg_buf)
99+
{
100+
pfree(state->readBuf);
101+
pfree(state);
102+
return NULL;
103+
}
88104
state->errormsg_buf[0] = '\0';
89105

90106
/*

src/backend/replication/logical/logical.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,11 @@ StartupDecodingContext(List *output_plugin_options,
163163
ctx->slot = slot;
164164

165165
ctx->reader = XLogReaderAllocate(read_page, ctx);
166+
if (!ctx->reader)
167+
ereport(ERROR,
168+
(errcode(ERRCODE_OUT_OF_MEMORY),
169+
errmsg("out of memory")));
170+
166171
ctx->reader->private_data = ctx;
167172

168173
ctx->reorder = ReorderBufferAllocate();

src/bin/pg_rewind/parsexlog.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,8 @@ extractPageMap(const char *datadir, XLogRecPtr startpoint, TimeLineID tli,
7070
private.datadir = datadir;
7171
private.tli = tli;
7272
xlogreader = XLogReaderAllocate(&SimpleXLogPageRead, &private);
73+
if (xlogreader == NULL)
74+
pg_fatal("out of memory");
7375

7476
do
7577
{
@@ -121,6 +123,8 @@ readOneRecord(const char *datadir, XLogRecPtr ptr, TimeLineID tli)
121123
private.datadir = datadir;
122124
private.tli = tli;
123125
xlogreader = XLogReaderAllocate(&SimpleXLogPageRead, &private);
126+
if (xlogreader == NULL)
127+
pg_fatal("out of memory");
124128

125129
record = XLogReadRecord(xlogreader, ptr, &errormsg);
126130
if (record == NULL)
@@ -171,6 +175,8 @@ findLastCheckpoint(const char *datadir, XLogRecPtr forkptr, TimeLineID tli,
171175
private.datadir = datadir;
172176
private.tli = tli;
173177
xlogreader = XLogReaderAllocate(&SimpleXLogPageRead, &private);
178+
if (xlogreader == NULL)
179+
pg_fatal("out of memory");
174180

175181
searchptr = forkptr;
176182
for (;;)

0 commit comments

Comments
 (0)