From 816cfd5398488b0989bbb72a0fd9f03570185ef6 Mon Sep 17 00:00:00 2001
From: s1ko <s1ko@riseup.net>
Date: Sun, 8 Nov 2026 18:35:22 +0100
Subject: [PATCH v1 1/2] libpq: check column count before reading
 target_session_attrs probe result

PQconnectPoll trusted the shape of the result set returned for the
internal "SHOW transaction_read_only" and "SELECT pg_is_in_recovery()"
queries, checking PQntuples() but not PQnfields() before calling
PQgetvalue(res, 0, 0).  A server that answers with one row and zero
columns makes PQgetvalue() return NULL, which is then passed to
strncmp() and crashes the client.

Require exactly one column as well, so that a malformed reply falls
through to the existing error path and the connection attempt fails
instead.
---
 src/interfaces/libpq/fe-connect.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/interfaces/libpq/fe-connect.c b/src/interfaces/libpq/fe-connect.c
index 9e17a8f1c6..b30585c74c 100644
--- a/src/interfaces/libpq/fe-connect.c
+++ b/src/interfaces/libpq/fe-connect.c
@@ -4596,7 +4596,7 @@ keep_going:						/* We will come back to here until there is
 
 				res = PQgetResult(conn);
 				if (res && PQresultStatus(res) == PGRES_TUPLES_OK &&
-					PQntuples(res) == 1)
+					PQntuples(res) == 1 && PQnfields(res) == 1)
 				{
 					char	   *val = PQgetvalue(res, 0, 0);
 
@@ -4664,7 +4664,7 @@ keep_going:						/* We will come back to here until there is
 
 				res = PQgetResult(conn);
 				if (res && PQresultStatus(res) == PGRES_TUPLES_OK &&
-					PQntuples(res) == 1)
+					PQntuples(res) == 1 && PQnfields(res) == 1)
 				{
 					char	   *val = PQgetvalue(res, 0, 0);
 
-- 
2.53.0

