From 8edbd93e24130ccc1726cbf6a514cd4a9040e874 Mon Sep 17 00:00:00 2001
From: Heikki Linnakangas <heikki.linnakangas@iki.fi>
Date: Thu, 14 Aug 2025 13:45:44 +0300
Subject: [PATCH v4 1/3] libpq: Don't hang on out-of-memory

If an allocation failed while handling an async notification, we
returned EOF, which stopped processing any further data until more
data was received from the server. If more data never arrives,
e.g. because the connection was used just to wait for the
notification, or because the next ReadyForQuery was already received
and buffered, it would get stuck forever. Instead, silently ignore the
notification.

Silently ignoring the notification is not a great way to handle the
situation, but at least the connection doesn't get stuck, and it's
consistent with how the malloc() later in the function is handled, and
with e.g. how pqSaveParameterStatus() handles allocation failures.

Fix the same issue with OOM on receiving BackendKeyData message. That
one is new in v18.

Discussion: https://www.postgresql.org/message-id/df892f9f-5923-4046-9d6f-8c48d8980b50@iki.fi
---
 src/interfaces/libpq/fe-protocol3.c | 16 ++++++++++------
 1 file changed, 10 insertions(+), 6 deletions(-)

diff --git a/src/interfaces/libpq/fe-protocol3.c b/src/interfaces/libpq/fe-protocol3.c
index 1599de757d1..5683229e32e 100644
--- a/src/interfaces/libpq/fe-protocol3.c
+++ b/src/interfaces/libpq/fe-protocol3.c
@@ -1550,9 +1550,8 @@ getBackendKeyData(PGconn *conn, int msgLength)
 	conn->be_cancel_key = malloc(cancel_key_len);
 	if (conn->be_cancel_key == NULL)
 	{
-		libpq_append_conn_error(conn, "out of memory");
-		/* discard the message */
-		return EOF;
+		/* continue without cancel key */
+		return 0;
 	}
 	if (pqGetnchar(conn->be_cancel_key, cancel_key_len, conn))
 	{
@@ -1588,14 +1587,19 @@ getNotify(PGconn *conn)
 		return EOF;
 	/* must save name while getting extra string */
 	svname = strdup(conn->workBuffer.data);
-	if (!svname)
-		return EOF;
 	if (pqGets(&conn->workBuffer, conn))
 	{
-		free(svname);
+		if (svname)
+			free(svname);
 		return EOF;
 	}
 
+	if (!svname)
+	{
+		/* out of memory; silently ignore the notification */
+		return 0;
+	}
+
 	/*
 	 * Store the strings right after the PGnotify structure so it can all be
 	 * freed at once.  We don't use NAMEDATALEN because we don't want to tie
-- 
2.39.5

