From 1dc9f8d67545afe02d9b11e36633ae315d03a79c Mon Sep 17 00:00:00 2001
From: roman khapov <r.khapov@ya.ru>
Date: Thu, 29 Oct 2026 16:15:17 +0500
Subject: [PATCH] libpq: guard select() fallback against fds >= FD_SETSIZE

On platforms without poll(2), PQsocketPoll() calls FD_SET() on the
connection socket without checking the fd number first.  If the
application has opened enough files that socket() returns an fd at or
above FD_SETSIZE, FD_SET() writes out of bounds, silently corrupting
the fd_sets on the stack.  Fail cleanly with EINVAL instead.
---
 src/interfaces/libpq/fe-misc.c | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/src/interfaces/libpq/fe-misc.c b/src/interfaces/libpq/fe-misc.c
index 73d10e5..4a741ee 100644
--- a/src/interfaces/libpq/fe-misc.c
+++ b/src/interfaces/libpq/fe-misc.c
@@ -1328,6 +1328,16 @@ PQsocketPoll(int sock, int forRead, int forWrite, pg_usec_time_t end_time)
 	if (!forRead && !forWrite)
 		return 0;
 
+	/*
+	 * On platforms where we must use select(2), fail cleanly instead of
+	 * overrunning the fd_set if the socket's descriptor is too large.
+	 */
+	if ((int) sock >= FD_SETSIZE)
+	{
+		SOCK_ERRNO_SET(EINVAL);
+		return -1;
+	}
+
 	FD_ZERO(&input_mask);
 	FD_ZERO(&output_mask);
 	FD_ZERO(&except_mask);
-- 
2.50.1 (Apple Git-155)

