From: Nathan Bossart <nathan@postgresql.org>
Subject: [PATCH v3] attempt multibyte-aware truncation of database names
Date: Wed, 20 Nov 2024 16:30:11 -0600
---
src/backend/utils/init/postinit.c | 82 +++++++++++++++++++++++++++++--
1 file changed, 79 insertions(+), 3 deletions(-)
100.0% src/backend/utils/init/
inline patch 1: src/backend/utils/init/postinit.c (+79/-3 lines) download inline-1.patchdiff --git a/src/backend/utils/init/postinit.c b/src/backend/utils/init/postinit.cindex 5b657a3f13..ef6fe705c2 100644--- a/src/backend/utils/init/postinit.c+++ b/src/backend/utils/init/postinit.c@@ -1003,14 +1003,90 @@ InitPostgres(const char *in_dbname, Oid dboid,
{
HeapTuple tuple;
Form_pg_database dbform;
+ char trunc_dbname[NAMEDATALEN];+ int curr_len = NAMEDATALEN - 1;- tuple = GetDatabaseTuple(in_dbname);+ /* truncate to NAMEDATALEN-1 bytes first */+ strncpy(trunc_dbname, in_dbname, curr_len);+ trunc_dbname[curr_len] = '\0';++ tuple = GetDatabaseTuple(trunc_dbname);++ if (HeapTupleIsValid(tuple))+ strcpy(dbname, trunc_dbname);++ /*+ * Try shorter lengths to handle potential multibyte character splits.+ * We only need to check back to NAMEDATALEN - MAX_MULTIBYTE_CHAR_LEN+ * since no valid multibyte character can be longer than that.+ */+ while (curr_len > NAMEDATALEN - MAX_MULTIBYTE_CHAR_LEN)+ {+ /*+ * If we've hit an ASCII byte (high bit clear), we know we can't+ * be in the middle of a multibyte character, because all bytes of+ * a multibyte character must have their high bits set.+ */+ if (!IS_HIGHBIT_SET(trunc_dbname[curr_len - 1]))+ break;++ /*+ * Check if we might be splitting a multibyte char by looking at+ * the high bits of the current position and the previous byte in+ * the original string.+ *+ * Note: We must check against in_dbname when looking at curr_len+ * because that byte has been truncated from trunc_dbname.+ */+ if (curr_len < strlen(in_dbname) &&+ IS_HIGHBIT_SET(in_dbname[curr_len]))+ {+ HeapTuple tmp;++ /*+ * Might be splitting a multibyte char, try one byte shorter+ * to find a possible character boundary.+ */+ curr_len--;+ trunc_dbname[curr_len] = '\0';++ tmp = GetDatabaseTuple(trunc_dbname);++ /*+ * If we already had a match then the name is ambiguous and we+ * must fail.+ */+ if (HeapTupleIsValid(tmp))+ {+ if (HeapTupleIsValid(tuple))+ ereport(FATAL,+ (errmsg("ambiguous database name")));+ tuple = tmp;+ strcpy(dbname, trunc_dbname);+ }+ }+ else+ /* not in the middle of a multibyte char */+ break;+ }++ /* If we didn't find any valid database name, report an error */
if (!HeapTupleIsValid(tuple))
ereport(FATAL,
(errcode(ERRCODE_UNDEFINED_DATABASE),
errmsg("database \"%s\" does not exist", in_dbname)));
+
dbform = (Form_pg_database) GETSTRUCT(tuple);
dboid = dbform->oid;
++ if (MyProcPort && MyProcPort->database_name &&+ strcmp(MyProcPort->database_name, dbname) != 0)+ {+ pfree(MyProcPort->database_name);+ MyProcPort->database_name = pstrdup(dbname);++ /* XXX: should we fix process title? */+ }
}
else if (!OidIsValid(dboid))
{
@@ -1067,12 +1143,12 @@ InitPostgres(const char *in_dbname, Oid dboid,
datform = (Form_pg_database) GETSTRUCT(tuple);
if (!HeapTupleIsValid(tuple) ||
- (in_dbname && namestrcmp(&datform->datname, in_dbname)))+ (in_dbname && namestrcmp(&datform->datname, dbname)))
{
if (in_dbname)
ereport(FATAL,
(errcode(ERRCODE_UNDEFINED_DATABASE),
- errmsg("database \"%s\" does not exist", in_dbname),+ errmsg("database \"%s\" does not exist", dbname),
errdetail("It seems to have just been dropped or renamed.")));
else
ereport(FATAL,
--
2.34.1
--1WCno6C1v+Mdlz+A--
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Reply to all the recipients using the --to and --cc options:
reply via email
To: pgsql-bugs@postgresql.org
Cc: nathan@postgresql.org
Subject: Re: [PATCH v3] attempt multibyte-aware truncation of database names
In-Reply-To: <no-message-id-25445@localhost>
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
This inbox is served by DDX for PostgreSQL; see mirroring instructions
for how to clone and mirror all data and code used for this inbox