From e5cddef8845715c55592e5f9786b524c668d83d1 Mon Sep 17 00:00:00 2001
From: Zhang Mingli <avamingli@gmail.com>
Date: Tue, 30 Jul 2024 11:10:32 +0800
Subject: [PATCH] Fix COPY FROM crash due to buffer flush.

We may call CopyMultiInsertInfoFlush() to flush buffer during COPY
tuples, ex: COPY a partitioned table with mass data.

To reproduce it easily, change the Macros to:
define MAX_BUFFERED_TUPLES	1
define MAX_PARTITION_BUFFERS	0

Config and make install, initdb will get a coredump.

When inserting from next tuple CopyMultiInsertInfoNextFreeSlot()
will get a crash due to null pointer of buffer.

Instead of call CopyMultiInsertInfoSetupBuffer() outside, put it
into CopyMultiInsertInfoNextFreeSlot() to avoid such issues.

Authored-by: Zhang Mingli avamingli@gmail.com
---
 src/backend/commands/copyfrom.c | 11 +++++++++--
 1 file changed, 9 insertions(+), 2 deletions(-)

diff --git a/src/backend/commands/copyfrom.c b/src/backend/commands/copyfrom.c
index ce4d62e707..ef42b4d523 100644
--- a/src/backend/commands/copyfrom.c
+++ b/src/backend/commands/copyfrom.c
@@ -586,8 +586,15 @@ static inline TupleTableSlot *
 CopyMultiInsertInfoNextFreeSlot(CopyMultiInsertInfo *miinfo,
 								ResultRelInfo *rri)
 {
-	CopyMultiInsertBuffer *buffer = rri->ri_CopyMultiInsertBuffer;
-	int			nused = buffer->nused;
+	CopyMultiInsertBuffer *buffer;
+	int			nused;
+
+	/* Setup buffer in case it's flushed. */
+	if (rri->ri_CopyMultiInsertBuffer == NULL)
+		CopyMultiInsertInfoSetupBuffer(miinfo, rri);
+
+	buffer = rri->ri_CopyMultiInsertBuffer;
+	nused = buffer->nused;
 
 	Assert(buffer != NULL);
 	Assert(nused < MAX_BUFFERED_TUPLES);
-- 
2.34.1

