ldb:utf8: ldb_ascii_toupper() avoids real toupper()
authorDouglas Bagnall <douglas.bagnall@catalyst.net.nz>
Fri, 19 Apr 2024 21:57:15 +0000 (09:57 +1200)
committerAndrew Bartlett <abartlet@samba.org>
Tue, 23 Apr 2024 02:37:25 +0000 (02:37 +0000)
If a non-lowercase ASCII character has an uppercase counterpart in
some locale, toupper() will convert it to an int codepoint. Probably
that codepoint is too big to fit in our char return type, so we would
truncate it to 8 bit. So it becomes an arbitrary mapping.

It would also behave strangely with a byte with the top bit set, say
0xE2. If char is unsigned on this system, that is 'â', which
uppercases to 'Â', with the codepoint 0xC2. That seems fine in
isolation, but remember this is ldb_utf8.c, and that byte was not a
codepoint but a piece of a long utf-8 encoding. In the more likely
case where char is signed, toupper() is being passed a negative
number, the result of which is undefined.

Signed-off-by: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
Autobuild-User(master): Andrew Bartlett <abartlet@samba.org>
Autobuild-Date(master): Tue Apr 23 02:37:25 UTC 2024 on atb-devel-224

lib/ldb/common/ldb_utf8.c

index f45b72dde50053444e446705a2ce6b60a2955263..178bdd86de109e8267b19fcc5a7ee6d9b8036f07 100644 (file)
@@ -136,5 +136,15 @@ int ldb_attr_dn(const char *attr)
 }
 
 _PRIVATE_ char ldb_ascii_toupper(char c) {
-       return ('a' <= c && c <= 'z') ? c ^ 0x20 : toupper(c);
+       /*
+        * We are aiming for a 1970s C-locale toupper(), when all letters
+        * were 7-bit and behaved with true American spirit.
+        *
+        * For example, we don't want the "i" in "<guid=" to be upper-cased to
+        * "İ" as would happen in some locales, or we won't be able to parse
+        * that properly. This is unfortunate for cases where we are dealing
+        * with real text; a search for the name "Ali" would need to be
+        * written "Alİ" to match.
+        */
+       return ('a' <= c && c <= 'z') ? c ^ 0x20 : c;
 }