postgres.git / summary / log / commit / refs
commit 8993bf0991d876c878fe3739d6d4e200a1e122f3
Author: Jeff Davis <jdavis@postgresql.org>
Date: Tue Jan 27 16:16:07 2026 +0000
First released in: 18.2
Fix crash introduced by incorrect backport 806555e300.
Commit 7f007e4a04 in master depends on 1476028225, but the latter was
not backported. Therefore 806555e300 (the backport of commit
7f007e4a04) incorrectly used pg_strfold() in a locale where
ctype_is_c.
The fix is to simply have the callers check for ctype_is_c.
Because 7f007e4a04 was only backported to version 18, and because the
commit in master is fine, this fix only exists in version 18.
Reported-by: Александр Кожемякин <a.kozhemyakin@postgrespro.ru>
Discussion: https://postgr.es/m/456f7143-51ea-4342-b4a1-85f0d9b6c79f@postgrespro.ru
contrib/ltree/crc32.c | 34 ++++++++++++++++++++++++----------
contrib/ltree/lquery_op.c | 21 +++++++++++++++++++--
2 files changed, 43 insertions(+), 12 deletions(-)
diff --git a/contrib/ltree/crc32.c b/contrib/ltree/crc32.c
index ce1b0f28e21..1eeda14651e 100644
--- a/contrib/ltree/crc32.c
+++ b/contrib/ltree/crc32.c
@@ -30,20 +30,34 @@ ltree_crc32_sz(const char *buf, int size)
locale = pg_newlocale_from_collation(DEFAULT_COLLATION_OID);
INIT_TRADITIONAL_CRC32(crc);
- while (size > 0)
+ if (locale->ctype_is_c)
+ {
+ while (size > 0)
+ {
+ char c = pg_ascii_tolower(*p);
+
+ COMP_TRADITIONAL_CRC32(crc, &c, 1);
+ size--;
+ p++;
+ }
+ }
+ else
{
- char foldstr[UNICODE_CASEMAP_BUFSZ];
- int srclen = pg_mblen(p);
- size_t foldlen;
+ while (size > 0)
+ {
+ char foldstr[UNICODE_CASEMAP_BUFSZ];
+ int srclen = pg_mblen(p);
+ size_t foldlen;
- /* fold one codepoint at a time */
- foldlen = pg_strfold(foldstr, UNICODE_CASEMAP_BUFSZ, p, srclen,
- locale);
+ /* fold one codepoint at a time */
+ foldlen = pg_strfold(foldstr, UNICODE_CASEMAP_BUFSZ, p, srclen,
+ locale);
- COMP_TRADITIONAL_CRC32(crc, foldstr, foldlen);
+ COMP_TRADITIONAL_CRC32(crc, foldstr, foldlen);
- size -= srclen;
- p += srclen;
+ size -= srclen;
+ p += srclen;
+ }
}
FIN_TRADITIONAL_CRC32(crc);
return (unsigned int) crc;
diff --git a/contrib/ltree/lquery_op.c b/contrib/ltree/lquery_op.c
index 9b1de101213..f4a507a27c7 100644
--- a/contrib/ltree/lquery_op.c
+++ b/contrib/ltree/lquery_op.c
@@ -96,15 +96,32 @@ ltree_prefix_eq_ci(const char *a, size_t a_sz, const char *b, size_t b_sz)
static pg_locale_t locale = NULL;
size_t al_sz = a_sz + 1;
size_t al_len;
- char *al = palloc(al_sz);
+ char *al;
size_t bl_sz = b_sz + 1;
size_t bl_len;
- char *bl = palloc(bl_sz);
+ char *bl;
bool res;
if (!locale)
locale = pg_newlocale_from_collation(DEFAULT_COLLATION_OID);
+ if (locale->ctype_is_c)
+ {
+ if (a_sz > b_sz)
+ return false;
+
+ for (int i = 0; i < a_sz; i++)
+ {
+ if (pg_ascii_tolower(a[i]) != pg_ascii_tolower(b[i]))
+ return false;
+ }
+
+ return true;
+ }
+
+ al = palloc(al_sz);
+ bl = palloc(bl_sz);
+
/* casefold both a and b */
al_len = pg_strfold(al, al_sz, a, a_sz, locale);
[parent: 919c9fa13cd0]