v1-0001-multibyte-truncation-for-database-and-user-name.patch

text/plain

Filename: v1-0001-multibyte-truncation-for-database-and-user-name.patch
Type: text/plain
Part: 0
Message: ProcessStartupPacket(): database_name and user_name truncation

Patch

Format: format-patch
Series: patch v1-0001
Subject: multibyte truncation for database and user name
File+
src/backend/postmaster/postmaster.c 44 4
From 6ccb4f03f56dda9e9a2616c6e0875a97a8711d72 Mon Sep 17 00:00:00 2001
From: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Date: Tue, 20 Jun 2023 10:26:16 +0000
Subject: [PATCH v1] multibyte truncation for database and user name

database_name and user_name truncation done in ProcessStartupPacket() do not
take care of multibyte character boundary. In case of multibyte, this somehow
breaks the initial goal to avoid lookup failures when overlength names are given.
---
 src/backend/postmaster/postmaster.c | 48 ++++++++++++++++++++++++++---
 1 file changed, 44 insertions(+), 4 deletions(-)
 100.0% src/backend/postmaster/

diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c
index 4c49393fc5..72991c4eab 100644
--- a/src/backend/postmaster/postmaster.c
+++ b/src/backend/postmaster/postmaster.c
@@ -1951,6 +1951,7 @@ ProcessStartupPacket(Port *port, bool ssl_done, bool gss_done)
 	char	   *buf;
 	ProtocolVersion proto;
 	MemoryContext oldcontext;
+	int			client_encoding = -1;
 
 	pq_startmsgread();
 
@@ -2238,6 +2239,18 @@ retry1:
 				{
 					port->application_name = pg_clean_ascii(valptr, 0);
 				}
+				/* Record the client_encoding if we come across it */
+				else if (strcmp(nameptr, "client_encoding") == 0)
+				{
+					client_encoding = pg_valid_client_encoding(valptr);
+
+					if (client_encoding < 0)
+						ereport(FATAL,
+								(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+								 errmsg("invalid value for parameter \"%s\": \"%s\"",
+										"client_encoding",
+										valptr)));
+				}
 			}
 			offset = valoffset + strlen(valptr) + 1;
 		}
@@ -2291,13 +2304,40 @@ retry1:
 	}
 
 	/*
-	 * Truncate given database and user names to length of a Postgres name.
-	 * This avoids lookup failures when overlength names are given.
+	 * Given the client encoding, truncate given database and user names to
+	 * length of a Postgres name. This avoids lookup failures when overlength
+	 * names are given.
 	 */
+	if (client_encoding < 0)
+	{
+		/*
+		 * client_encoding has not been found in the startup packet so let's
+		 * try to get it from locale.
+		 */
+		client_encoding = pg_get_encoding_from_locale(NULL, true);
+
+		if (client_encoding < 0)
+			client_encoding = PG_SQL_ASCII;
+	}
+
 	if (strlen(port->database_name) >= NAMEDATALEN)
-		port->database_name[NAMEDATALEN - 1] = '\0';
+	{
+		int			newlen;
+
+		newlen = pg_encoding_mbcliplen(client_encoding, port->database_name,
+									   strlen(port->database_name),
+									   NAMEDATALEN - 1);
+		port->database_name[newlen] = '\0';
+	}
 	if (strlen(port->user_name) >= NAMEDATALEN)
-		port->user_name[NAMEDATALEN - 1] = '\0';
+	{
+		int			newlen;
+
+		newlen = pg_encoding_mbcliplen(client_encoding, port->user_name,
+									   strlen(port->user_name),
+									   NAMEDATALEN - 1);
+		port->user_name[newlen] = '\0';
+	}
 
 	if (am_walsender)
 		MyBackendType = B_WAL_SENDER;
-- 
2.34.1