]> git.ipfire.org Git - thirdparty/postgresql.git/commitdiff
Fix LIKE matching with nondeterministic collations and backslashes.
authorTom Lane <tgl@sss.pgh.pa.us>
Mon, 6 Jul 2026 18:35:21 +0000 (14:35 -0400)
committerTom Lane <tgl@sss.pgh.pa.us>
Mon, 6 Jul 2026 18:35:21 +0000 (14:35 -0400)
Commit 85b7efa1c added support for LIKE with nondeterministic
collations, but it included a bug in the de-escaping logic for
literal pattern substrings.  That unconditionally skipped all
backslashes, but when it encounters '\\' it should emit the second
backslash as a de-escaped character.  That led to acting as though
the escaped backslash was not there.

Bug: #19474
Reported-by: Bowen Shi <zxwsbg12138@gmail.com>
Author: Nitin Motiani <nitinmotiani@google.com>
Reviewed-by: Zsolt Parragi <zsolt.parragi@percona.com>
Reviewed-by: Ewan Young <kdbase.hack@gmail.com>
Reviewed-by: Tom Lane <tgl@sss.pgh.pa.us>
Discussion: https://postgr.es/m/19474-5b86a95f3d9a7ecb@postgresql.org
Discussion: https://postgr.es/m/CAH5HC94yU+K8Gcdy12M5BS8gwD_SXLSHzc9k5tNk7JDnpBiFMA@mail.gmail.com
Backpatch-through: 18

src/backend/utils/adt/like_match.c
src/test/regress/expected/collate.icu.utf8.out
src/test/regress/sql/collate.icu.utf8.sql

index bac6c1824671e3fd1637586dbc9603dce94e0e12..4f74bf3cbcb0e3db8ff3c2591313040739b32960 100644 (file)
@@ -253,9 +253,8 @@ MatchText(const char *t, int tlen, const char *p, int plen, pg_locale_t locale)
                                for (const char *c = p; c < p1; c++)
                                {
                                        if (*c == '\\')
-                                               ;
-                                       else
-                                               *(b++) = *c;
+                                               c++;    /* we already checked this isn't the end */
+                                       *(b++) = *c;
                                }
 
                                subpat = buf;
index f8e6531375206e32f11f0d93213eec1ee5a4c586..2d17d56f6d0a8d27828b42677d0d2f878fb45793 100644 (file)
@@ -2996,6 +2996,37 @@ SELECT U&'\0061\0308bc' LIKE U&'_\00e4bc' COLLATE ignore_accents;
 -- escape character at end of pattern
 SELECT 'foox' LIKE 'foo\' COLLATE ignore_accents;
 ERROR:  LIKE pattern must not end with escape character
+-- literal backslash with nondeterministic collation (bug #19474)
+SELECT 'back\slash' COLLATE ignore_accents LIKE 'back\slash%' ESCAPE '#';
+ ?column? 
+----------
+ t
+(1 row)
+
+SELECT 'aäb' COLLATE ignore_accents LIKE 'a#äb' ESCAPE '#' AS multibyte_escape;
+ multibyte_escape 
+------------------
+ t
+(1 row)
+
+SELECT 'a\äb' COLLATE ignore_accents LIKE 'a\äb%' ESCAPE '#' AS backslash_multibyte;
+ backslash_multibyte 
+---------------------
+ t
+(1 row)
+
+SELECT 'a\b%c' COLLATE ignore_accents LIKE 'a#\b#%%c' ESCAPE '#' AS mixed_escapes;
+ mixed_escapes 
+---------------
+ t
+(1 row)
+
+SELECT 'backslash' COLLATE ignore_accents LIKE 'back\\slash%';
+ ?column? 
+----------
+ f
+(1 row)
+
 -- foreign keys (mixing different nondeterministic collations not allowed)
 CREATE TABLE test10pk (x text COLLATE case_sensitive PRIMARY KEY);
 CREATE TABLE test10fk (x text COLLATE case_insensitive REFERENCES test10pk (x) ON UPDATE CASCADE ON DELETE CASCADE);  -- error
index f4c4271fb34506138b8e2055aa46ab5700dffa60..4fb01a172987f5df760b79776444c3c8b77d668f 100644 (file)
@@ -1079,6 +1079,13 @@ SELECT U&'\0061\0308bc' LIKE U&'_\00e4bc' COLLATE ignore_accents;
 -- escape character at end of pattern
 SELECT 'foox' LIKE 'foo\' COLLATE ignore_accents;
 
+-- literal backslash with nondeterministic collation (bug #19474)
+SELECT 'back\slash' COLLATE ignore_accents LIKE 'back\slash%' ESCAPE '#';
+SELECT 'aäb' COLLATE ignore_accents LIKE 'a#äb' ESCAPE '#' AS multibyte_escape;
+SELECT 'a\äb' COLLATE ignore_accents LIKE 'a\äb%' ESCAPE '#' AS backslash_multibyte;
+SELECT 'a\b%c' COLLATE ignore_accents LIKE 'a#\b#%%c' ESCAPE '#' AS mixed_escapes;
+SELECT 'backslash' COLLATE ignore_accents LIKE 'back\\slash%';
+
 -- foreign keys (mixing different nondeterministic collations not allowed)
 CREATE TABLE test10pk (x text COLLATE case_sensitive PRIMARY KEY);
 CREATE TABLE test10fk (x text COLLATE case_insensitive REFERENCES test10pk (x) ON UPDATE CASCADE ON DELETE CASCADE);  -- error