From 1d8015ef6adebc113e99aa9cd972381dc2048b3e Mon Sep 17 00:00:00 2001
From: "Chao Li (Evan)" <lic@highgo.com>
Date: Tue, 25 Nov 2025 10:26:16 +0800
Subject: [PATCH v1] Fixes bug in strlower_libc_sb()

Fixed a no-impact bug in strlower_libc_sb(), where is lenght check
is useless, thus removed the check.

Author: Chao Li <lic@highgo.com>
---
 src/backend/utils/adt/pg_locale_libc.c | 163 +++++++++++++------------
 1 file changed, 82 insertions(+), 81 deletions(-)

diff --git a/src/backend/utils/adt/pg_locale_libc.c b/src/backend/utils/adt/pg_locale_libc.c
index 716f005066a..877fdedf079 100644
--- a/src/backend/utils/adt/pg_locale_libc.c
+++ b/src/backend/utils/adt/pg_locale_libc.c
@@ -426,39 +426,37 @@ static size_t
 strlower_libc_sb(char *dest, size_t destsize, const char *src, ssize_t srclen,
 				 pg_locale_t locale)
 {
+	ssize_t		reallen;
+	locale_t	loc = locale->lt;
+
 	if (srclen < 0)
 		srclen = strlen(src);
 
-	if (srclen + 1 <= destsize)
-	{
-		locale_t	loc = locale->lt;
-		char	   *p;
-
-		if (srclen + 1 > destsize)
-			return srclen;
+	reallen = srclen + 1;
+	if (reallen > destsize)
+		reallen = destsize;
 
-		memcpy(dest, src, srclen);
-		dest[srclen] = '\0';
+	memcpy(dest, src, reallen);
+	if (reallen < destsize)
+		dest[reallen] = '\0';
 
-		/*
-		 * Note: we assume that tolower_l() will not be so broken as to need
-		 * an isupper_l() guard test.  When using the default collation, we
-		 * apply the traditional Postgres behavior that forces ASCII-style
-		 * treatment of I/i, but in non-default collations you get exactly
-		 * what the collation says.
-		 */
-		for (p = dest; *p; p++)
+	/*
+	 * Note: we assume that tolower_l() will not be so broken as to need an
+	 * isupper_l() guard test.  When using the default collation, we apply the
+	 * traditional Postgres behavior that forces ASCII-style treatment of I/i,
+	 * but in non-default collations you get exactly what the collation says.
+	 */
+	for (char *p = dest; *p; p++)
+	{
+		if (locale->is_default)
 		{
-			if (locale->is_default)
-			{
-				if (*p >= 'A' && *p <= 'Z')
-					*p += 'a' - 'A';
-				else if (IS_HIGHBIT_SET(*p) && isupper_l(*p, loc))
-					*p = tolower_l((unsigned char) *p, loc);
-			}
-			else
+			if (*p >= 'A' && *p <= 'Z')
+				*p += 'a' - 'A';
+			else if (IS_HIGHBIT_SET(*p) && isupper_l(*p, loc))
 				*p = tolower_l((unsigned char) *p, loc);
 		}
+		else
+			*p = tolower_l((unsigned char) *p, loc);
 	}
 
 	return srclen;
@@ -516,55 +514,57 @@ static size_t
 strtitle_libc_sb(char *dest, size_t destsize, const char *src, ssize_t srclen,
 				 pg_locale_t locale)
 {
+	ssize_t		reallen;
+	locale_t	loc = locale->lt;
+	int			wasalnum = false;
+
 	if (srclen < 0)
 		srclen = strlen(src);
 
-	if (srclen + 1 <= destsize)
-	{
-		locale_t	loc = locale->lt;
-		int			wasalnum = false;
-		char	   *p;
+	reallen = srclen + 1;
+	if (reallen > destsize)
+		reallen = destsize;
 
-		memcpy(dest, src, srclen);
-		dest[srclen] = '\0';
+	memcpy(dest, src, reallen);
+	if (reallen < destsize)
+		dest[reallen] = '\0';
 
-		/*
-		 * Note: we assume that toupper_l()/tolower_l() will not be so broken
-		 * as to need guard tests.  When using the default collation, we apply
-		 * the traditional Postgres behavior that forces ASCII-style treatment
-		 * of I/i, but in non-default collations you get exactly what the
-		 * collation says.
-		 */
-		for (p = dest; *p; p++)
+	/*
+	 * Note: we assume that toupper_l()/tolower_l() will not be so broken as
+	 * to need guard tests.  When using the default collation, we apply the
+	 * traditional Postgres behavior that forces ASCII-style treatment of I/i,
+	 * but in non-default collations you get exactly what the collation says.
+	 */
+	for (char *p = dest; *p; p++)
+	{
+		if (locale->is_default)
 		{
-			if (locale->is_default)
+			if (wasalnum)
 			{
-				if (wasalnum)
-				{
-					if (*p >= 'A' && *p <= 'Z')
-						*p += 'a' - 'A';
-					else if (IS_HIGHBIT_SET(*p) && isupper_l(*p, loc))
-						*p = tolower_l((unsigned char) *p, loc);
-				}
-				else
-				{
-					if (*p >= 'a' && *p <= 'z')
-						*p -= 'a' - 'A';
-					else if (IS_HIGHBIT_SET(*p) && islower_l(*p, loc))
-						*p = toupper_l((unsigned char) *p, loc);
-				}
+				if (*p >= 'A' && *p <= 'Z')
+					*p += 'a' - 'A';
+				else if (IS_HIGHBIT_SET(*p) && isupper_l(*p, loc))
+					*p = tolower_l((unsigned char) *p, loc);
 			}
 			else
 			{
-				if (wasalnum)
-					*p = tolower_l((unsigned char) *p, loc);
-				else
+				if (*p >= 'a' && *p <= 'z')
+					*p -= 'a' - 'A';
+				else if (IS_HIGHBIT_SET(*p) && islower_l(*p, loc))
 					*p = toupper_l((unsigned char) *p, loc);
 			}
-			wasalnum = isalnum_l((unsigned char) *p, loc);
 		}
+		else
+		{
+			if (wasalnum)
+				*p = tolower_l((unsigned char) *p, loc);
+			else
+				*p = toupper_l((unsigned char) *p, loc);
+		}
+		wasalnum = isalnum_l((unsigned char) *p, loc);
 	}
 
+
 	return srclen;
 }
 
@@ -627,36 +627,37 @@ static size_t
 strupper_libc_sb(char *dest, size_t destsize, const char *src, ssize_t srclen,
 				 pg_locale_t locale)
 {
+	ssize_t		reallen;
+	locale_t	loc = locale->lt;
+
 	if (srclen < 0)
 		srclen = strlen(src);
 
-	if (srclen + 1 <= destsize)
-	{
-		locale_t	loc = locale->lt;
-		char	   *p;
+	reallen = srclen + 1;
+	if (reallen > destsize)
+		reallen = destsize;
 
-		memcpy(dest, src, srclen);
-		dest[srclen] = '\0';
+	memcpy(dest, src, reallen);
+	if (reallen < destsize)
+		dest[reallen] = '\0';
 
-		/*
-		 * Note: we assume that toupper_l() will not be so broken as to need
-		 * an islower_l() guard test.  When using the default collation, we
-		 * apply the traditional Postgres behavior that forces ASCII-style
-		 * treatment of I/i, but in non-default collations you get exactly
-		 * what the collation says.
-		 */
-		for (p = dest; *p; p++)
+	/*
+	 * Note: we assume that toupper_l() will not be so broken as to need an
+	 * islower_l() guard test.  When using the default collation, we apply the
+	 * traditional Postgres behavior that forces ASCII-style treatment of I/i,
+	 * but in non-default collations you get exactly what the collation says.
+	 */
+	for (char *p = dest; *p; p++)
+	{
+		if (locale->is_default)
 		{
-			if (locale->is_default)
-			{
-				if (*p >= 'a' && *p <= 'z')
-					*p -= 'a' - 'A';
-				else if (IS_HIGHBIT_SET(*p) && islower_l(*p, loc))
-					*p = toupper_l((unsigned char) *p, loc);
-			}
-			else
+			if (*p >= 'a' && *p <= 'z')
+				*p -= 'a' - 'A';
+			else if (IS_HIGHBIT_SET(*p) && islower_l(*p, loc))
 				*p = toupper_l((unsigned char) *p, loc);
 		}
+		else
+			*p = toupper_l((unsigned char) *p, loc);
 	}
 
 	return srclen;
-- 
2.39.5 (Apple Git-154)

