diff --git a/src/backend/access/transam/xlogreader.c b/src/backend/access/transam/xlogreader.c
index 946907a..5fc859d 100644
--- a/src/backend/access/transam/xlogreader.c
+++ b/src/backend/access/transam/xlogreader.c
@@ -31,6 +31,7 @@
 #include "access/xlogrecord.h"
 #include "catalog/pg_control.h"
 #include "common/pg_lzcompress.h"
+#include "common/relpath.h"
 #include "replication/origin.h"
 
 #ifndef FRONTEND
@@ -1800,6 +1801,14 @@ DecodeXLogRecord(XLogReaderState *state,
 
 			COPY_HEADER_FIELD(&fork_flags, sizeof(uint8));
 			blk->forknum = fork_flags & BKPBLOCK_FORK_MASK;
+			if (blk->forknum > MAX_FORKNUM)
+			{
+				report_invalid_record(state,
+									  "invalid fork number %u at %X/%08X",
+									  blk->forknum,
+									  LSN_FORMAT_ARGS(state->ReadRecPtr));
+				goto err;
+			}
 			blk->flags = fork_flags;
 			blk->has_image = ((fork_flags & BKPBLOCK_HAS_IMAGE) != 0);
 			blk->has_data = ((fork_flags & BKPBLOCK_HAS_DATA) != 0);
diff --git a/src/common/relpath.c b/src/common/relpath.c
index 8fb3bed..7fdbd76 100644
--- a/src/common/relpath.c
+++ b/src/common/relpath.c
@@ -145,6 +145,14 @@ GetRelationPath(Oid dbOid, Oid spcOid, RelFileNumber relNumber,
 {
 	RelPathStr	rp;
 
+	/*
+	 * WAL decode/display paths can reach here with unvalidated fork
+	 * numbers; clamp as defense in depth so we never index forkNames[]
+	 * out of bounds.  Callers that can ereport should validate first.
+	 */
+	if (forkNumber < MAIN_FORKNUM || forkNumber > MAX_FORKNUM)
+		forkNumber = MAIN_FORKNUM;
+
 	if (spcOid == GLOBALTABLESPACE_OID)
 	{
 		/* Shared system relations live in {datadir}/global */
