aboutsummaryrefslogtreecommitdiff
path: root/src/backend/access/transam/xlogreader.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/access/transam/xlogreader.c')
-rw-r--r--src/backend/access/transam/xlogreader.c23
1 files changed, 23 insertions, 0 deletions
diff --git a/src/backend/access/transam/xlogreader.c b/src/backend/access/transam/xlogreader.c
index b8d62a44967..8e83de6de52 100644
--- a/src/backend/access/transam/xlogreader.c
+++ b/src/backend/access/transam/xlogreader.c
@@ -25,6 +25,10 @@
#include "common/pg_lzcompress.h"
#include "replication/origin.h"
+#ifndef FRONTEND
+#include "utils/memutils.h"
+#endif
+
static bool allocate_recordbuf(XLogReaderState *state, uint32 reclength);
static bool ValidXLogRecordHeader(XLogReaderState *state, XLogRecPtr RecPtr,
@@ -158,6 +162,25 @@ allocate_recordbuf(XLogReaderState *state, uint32 reclength)
newSize += XLOG_BLCKSZ - (newSize % XLOG_BLCKSZ);
newSize = Max(newSize, 5 * Max(BLCKSZ, XLOG_BLCKSZ));
+#ifndef FRONTEND
+
+ /*
+ * Note that in much unlucky circumstances, the random data read from a
+ * recycled segment can cause this routine to be called with a size
+ * causing a hard failure at allocation. For a standby, this would cause
+ * the instance to stop suddenly with a hard failure, preventing it to
+ * retry fetching WAL from one of its sources which could allow it to move
+ * on with replay without a manual restart. If the data comes from a past
+ * recycled segment and is still valid, then the allocation may succeed
+ * but record checks are going to fail so this would be short-lived. If
+ * the allocation fails because of a memory shortage, then this is not a
+ * hard failure either per the guarantee given by MCXT_ALLOC_NO_OOM.
+ */
+ if (!AllocSizeIsValid(newSize))
+ return false;
+
+#endif
+
if (state->readRecordBuf)
pfree(state->readRecordBuf);
state->readRecordBuf =