From 080241946ec542ada349fced93936e2aebb51c75 Mon Sep 17 00:00:00 2001 From: "Dr. David Alan Gilbert" Date: Mon, 9 Jun 2025 02:19:21 +0100 Subject: [PATCH 1/2] utf8: Remove unused utf8_normalize utf8_normalize() was added in 2019 as part of commit 9d53690f0d4e ("unicode: implement higher level API for string handling") but has remained unused. (I think because the other higher level routines added by that patch normalise as part of their operations) Remove it. Signed-off-by: Dr. David Alan Gilbert Signed-off-by: Gabriel Krisman Bertazi --- fs/unicode/utf8-core.c | 22 ---------------------- include/linux/unicode.h | 3 --- 2 files changed, 25 deletions(-) diff --git a/fs/unicode/utf8-core.c b/fs/unicode/utf8-core.c index 543c60c12461..8c4b8e27e956 100644 --- a/fs/unicode/utf8-core.c +++ b/fs/unicode/utf8-core.c @@ -138,28 +138,6 @@ int utf8_casefold_hash(const struct unicode_map *um, const void *salt, } EXPORT_SYMBOL(utf8_casefold_hash); -int utf8_normalize(const struct unicode_map *um, const struct qstr *str, - unsigned char *dest, size_t dlen) -{ - struct utf8cursor cur; - ssize_t nlen = 0; - - if (utf8ncursor(&cur, um, UTF8_NFDI, str->name, str->len) < 0) - return -EINVAL; - - for (nlen = 0; nlen < dlen; nlen++) { - int c = utf8byte(&cur); - - dest[nlen] = c; - if (!c) - return nlen; - if (c == -1) - break; - } - return -EINVAL; -} -EXPORT_SYMBOL(utf8_normalize); - static const struct utf8data *find_table_version(const struct utf8data *table, size_t nr_entries, unsigned int version) { diff --git a/include/linux/unicode.h b/include/linux/unicode.h index 5e6b212a2aed..64fa44fe180c 100644 --- a/include/linux/unicode.h +++ b/include/linux/unicode.h @@ -66,9 +66,6 @@ int utf8_strncasecmp_folded(const struct unicode_map *um, const struct qstr *cf, const struct qstr *s1); -int utf8_normalize(const struct unicode_map *um, const struct qstr *str, - unsigned char *dest, size_t dlen); - int utf8_casefold(const struct unicode_map *um, const struct qstr *str, unsigned char *dest, size_t dlen); From a511442085c140da9cdbe60e3f0fab1c71480801 Mon Sep 17 00:00:00 2001 From: Gabriel Krisman Bertazi Date: Fri, 31 Jul 2026 15:54:45 -0400 Subject: [PATCH 2/2] unicode: Properly reject invalid encoding version strings Casefolding filesystems can request a specific version of UTF-8 at mount-time. utf8_parse_version then assembles the "major.minor.rev" string into an unsigned int. There were two issues with the parser logic: first, individual fields are read as signed int, allowing negative numbers, second, an overflowed field will result in unexpected results. Something like the below actually succeeds to mount using utf8-12.1.0. mount -t tmpfs -o casefold=utf8-12.0.256 none /mnt [ 10.867859] tmpfs: Using encoding : utf8-12.1.0 Signed-off-by: Gabriel Krisman Bertazi --- fs/unicode/utf8-core.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/fs/unicode/utf8-core.c b/fs/unicode/utf8-core.c index 8c4b8e27e956..f313532f5e80 100644 --- a/fs/unicode/utf8-core.c +++ b/fs/unicode/utf8-core.c @@ -204,17 +204,19 @@ int utf8_parse_version(char *version) substring_t args[3]; unsigned int maj, min, rev; static const struct match_token token[] = { - {1, "%d.%d.%d"}, + {1, "%u.%u.%u"}, {0, NULL} }; if (match_token(version, token, args) != 1) return -EINVAL; - if (match_int(&args[0], &maj) || match_int(&args[1], &min) || - match_int(&args[2], &rev)) + if (match_uint(&args[0], &maj) || match_uint(&args[1], &min) || + match_uint(&args[2], &rev)) return -EINVAL; + if (maj > U8_MAX || min > U8_MAX || rev > U8_MAX) + return -EINVAL; return UNICODE_AGE(maj, min, rev); } EXPORT_SYMBOL(utf8_parse_version);