From 8993bf0991d876c878fe3739d6d4e200a1e122f3 Mon Sep 17 00:00:00 2001 From: Jeff Davis Date: Tue, 27 Jan 2026 08:16:07 -0800 Subject: [PATCH] Fix crash introduced by incorrect backport 806555e300. MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit 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: Александр Кожемякин 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); -- 2.47.3