From 336476a959b9ecac75ba3f6de344829563e213ca Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Wed, 12 Jun 2019 19:18:24 +0200 Subject: [PATCH] efi_loader: MetaiMatch() must be case insensitive The MetaiMatch() service of the UnicodeCollationProtocol2 must be case insensitive. Signed-off-by: Heinrich Schuchardt --- lib/efi_loader/efi_unicode_collation.c | 65 ++++++++++++++++---------- 1 file changed, 41 insertions(+), 24 deletions(-) diff --git a/lib/efi_loader/efi_unicode_collation.c b/lib/efi_loader/efi_unicode_collation.c index f293b42397..4fe2362555 100644 --- a/lib/efi_loader/efi_unicode_collation.c +++ b/lib/efi_loader/efi_unicode_collation.c @@ -73,11 +73,22 @@ out: return ret; } +/** + * next_lower() - get next codepoint converted to lower case + * + * @string: pointer to u16 string, on return advanced by one codepoint + * Return: first codepoint of string converted to lower case + */ +static s32 next_lower(const u16 **string) +{ + return utf_to_lower(utf16_get(string)); +} + /** * metai_match() - compare utf-16 string with a pattern string case-insenitively * - * @s: string to compare - * @p: pattern string + * @string: string to compare + * @pattern: pattern string * * The pattern string may use these: * - * matches >= 0 characters @@ -93,61 +104,67 @@ out: * * Return: true if the string is matched. */ -static bool metai_match(const u16 *s, const u16 *p) +static bool metai_match(const u16 *string, const u16 *pattern) { - u16 first; + s32 first, s, p; + + for (; *string && *pattern;) { + const u16 *string_old = string; + + s = next_lower(&string); + p = next_lower(&pattern); - for (; *s && *p; ++s, ++p) { - switch (*p) { + switch (p) { case '*': /* Match 0 or more characters */ - ++p; - for (;; ++s) { - if (metai_match(s, p)) + for (;; s = next_lower(&string)) { + if (metai_match(string_old, pattern)) return true; - if (!*s) + if (!s) return false; + string_old = string; } case '?': /* Match any one character */ break; case '[': /* Match any character in the set */ - ++p; - first = *p; + p = next_lower(&pattern); + first = p; if (first == ']') /* Empty set */ return false; - ++p; - if (*p == '-') { + p = next_lower(&pattern); + if (p == '-') { /* Range */ - ++p; - if (*s < first || *s > *p) + p = next_lower(&pattern); + if (s < first || s > p) return false; - ++p; - if (*p != ']') + p = next_lower(&pattern); + if (p != ']') return false; } else { /* Set */ bool hit = false; - if (*s == first) + if (s == first) hit = true; - for (; *p && *p != ']'; ++p) { - if (*p == *s) + for (; p && p != ']'; + p = next_lower(&pattern)) { + if (p == s) hit = true; } - if (!hit || *p != ']') + if (!hit || p != ']') return false; } break; default: /* Match one character */ - if (*p != *s) + if (p != s) return false; } } - if (!*p && !*s) + if (!*pattern && !*string) return true; return false; } -- 2.30.2