Blame SOURCES/0001-lib-write-improve-key-collation-compatibility-with-Windows.patch

6a74ba
From d5a522c0bb738efdd7cc1e762840b579fc9ea3de Mon Sep 17 00:00:00 2001
6a74ba
From: Laszlo Ersek <lersek@redhat.com>
6a74ba
Date: Fri, 10 Sep 2021 01:06:17 +0200
6a74ba
Subject: [PATCH] lib: write: improve key collation compatibility with Windows
6a74ba
6a74ba
There are multiple problems with using strcasecmp() for ordering registry
6a74ba
keys:
6a74ba
6a74ba
(1) strcasecmp() is influenced by LC_CTYPE.
6a74ba
6a74ba
(2) strcasecmp() cannot implement case conversion for multibyte UTF-8
6a74ba
    sequences.
6a74ba
6a74ba
(3) Even with LC_CTYPE=POSIX and key names consisting solely of ASCII
6a74ba
    characters, strcasecmp() converts characters to lowercase, for
6a74ba
    comparison. But on Windows, the CompareStringOrdinal() function
6a74ba
    converts characters to uppercase. This makes a difference when
6a74ba
    comparing a letter to one of the characters that fall between 'Z'
6a74ba
    (0x5A) and 'a' (0x61), namely {'[', '\\', ']', '^', '_', '`'}. For
6a74ba
    example,
6a74ba
6a74ba
      'c' (0x63) > '_' (0x5F)
6a74ba
      'C' (0x43) < '_' (0x5F)
6a74ba
6a74ba
Compare key names byte for byte, eliminating problems (1) and (3).
6a74ba
6a74ba
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1648520
6a74ba
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
6a74ba
Message-Id: <20210909230617.31256-1-lersek@redhat.com>
6a74ba
Acked-by: Richard W.M. Jones <rjones@redhat.com>
6a74ba
---
6a74ba
 lib/write.c | 32 +++++++++++++++++++++++++++++++-
6a74ba
 1 file changed, 31 insertions(+), 1 deletion(-)
6a74ba
6a74ba
diff --git a/lib/write.c b/lib/write.c
6a74ba
index 70105c9d9907..d9a13a3c18b6 100644
6a74ba
--- a/lib/write.c
6a74ba
+++ b/lib/write.c
6a74ba
@@ -462,7 +462,37 @@ compare_name_with_nk_name (hive_h *h, const char *name, hive_node_h nk_offs)
6a74ba
     return 0;
6a74ba
   }
6a74ba
 
6a74ba
-  int r = strcasecmp (name, nname);
6a74ba
+  /* Perform a limited case-insensitive comparison. ASCII letters will be
6a74ba
+   * *upper-cased*. Multibyte sequences will produce nonsensical orderings.
6a74ba
+   */
6a74ba
+  int r = 0;
6a74ba
+  const char *s1 = name;
6a74ba
+  const char *s2 = nname;
6a74ba
+
6a74ba
+  for (;;) {
6a74ba
+    unsigned char c1 = *(s1++);
6a74ba
+    unsigned char c2 = *(s2++);
6a74ba
+
6a74ba
+    if (c1 >= 'a' && c1 <= 'z')
6a74ba
+      c1 = 'A' + (c1 - 'a');
6a74ba
+    if (c2 >= 'a' && c2 <= 'z')
6a74ba
+      c2 = 'A' + (c2 - 'a');
6a74ba
+    if (c1 < c2) {
6a74ba
+      /* Also covers the case when "name" is a prefix of "nname". */
6a74ba
+      r = -1;
6a74ba
+      break;
6a74ba
+    }
6a74ba
+    if (c1 > c2) {
6a74ba
+      /* Also covers the case when "nname" is a prefix of "name". */
6a74ba
+      r = 1;
6a74ba
+      break;
6a74ba
+    }
6a74ba
+    if (c1 == '\0') {
6a74ba
+      /* Both strings end. */
6a74ba
+      break;
6a74ba
+    }
6a74ba
+  }
6a74ba
+
6a74ba
   free (nname);
6a74ba
 
6a74ba
   return r;
6a74ba
-- 
6a74ba
2.19.1.3.g30247aa5d201
6a74ba