lib: strings: Simplify strcasecmp
authorVolker Lendecke <vl@samba.org>
Tue, 5 Aug 2014 09:21:07 +0000 (09:21 +0000)
committerKarolin Seeger <kseeger@samba.org>
Mon, 1 Sep 2014 19:34:11 +0000 (21:34 +0200)
This makes us fallback to strcasecmp early if any INVALID_CODEPOINT
appears. Without this patch we just continue to compare if both strings
happen to have an INVALID_CODEPOINT in the same spot.

Signed-off-by: Volker Lendecke <vl@samba.org>
Reviewed-by: Jeremy Allison <jra@samba.org>
Bug: https://bugzilla.samba.org/show_bug.cgi?id=10716
smbd constantly crashes when filename contains non-ascii character

lib/util/charset/util_str.c

index f62c9998b33f2422a8e1cc61b3fe6f4688f1a7a2..d2e6cbbc620e09102e203b293f538a1e3b8bf474 100644 (file)
@@ -47,6 +47,11 @@ _PUBLIC_ int strcasecmp_m_handle(struct smb_iconv_handle *iconv_handle,
                c1 = next_codepoint_handle(iconv_handle, s1, &size1);
                c2 = next_codepoint_handle(iconv_handle, s2, &size2);
 
+               if (c1 == INVALID_CODEPOINT ||
+                   c2 == INVALID_CODEPOINT) {
+                       return strcasecmp(s1, s2);
+               }
+
                s1 += size1;
                s2 += size2;
 
@@ -54,22 +59,6 @@ _PUBLIC_ int strcasecmp_m_handle(struct smb_iconv_handle *iconv_handle,
                        continue;
                }
 
-               if (c1 == INVALID_CODEPOINT ||
-                   c2 == INVALID_CODEPOINT) {
-                       /*
-                        * Fall back to byte
-                        * comparison. We must
-                        * step back by the codepoint
-                        * length we just incremented
-                        * - otherwise we are not
-                        * checking the bytes that
-                        * failed the conversion.
-                        */
-                       s1 -= size1;
-                       s2 -= size2;
-                       return strcasecmp(s1, s2);
-               }
-
                if (toupper_m(c1) != toupper_m(c2)) {
                        return c1 - c2;
                }
@@ -107,26 +96,8 @@ _PUBLIC_ int strncasecmp_m_handle(struct smb_iconv_handle *iconv_handle,
                c1 = next_codepoint_handle(iconv_handle, s1, &size1);
                c2 = next_codepoint_handle(iconv_handle, s2, &size2);
 
-               s1 += size1;
-               s2 += size2;
-
-               if (c1 == c2) {
-                       continue;
-               }
-
                if (c1 == INVALID_CODEPOINT ||
                    c2 == INVALID_CODEPOINT) {
-                       /*
-                        * Fall back to byte
-                        * comparison. We must
-                        * step back by the codepoint
-                        * length we just incremented
-                        * by - otherwise we are not
-                        * checking the bytes that
-                        * failed the conversion.
-                        */
-                       s1 -= size1;
-                       s2 -= size2;
                        /*
                         * n was specified in characters,
                         * now we must convert it to bytes.
@@ -139,12 +110,19 @@ _PUBLIC_ int strncasecmp_m_handle(struct smb_iconv_handle *iconv_handle,
                         * to be n characters long, so we are
                         * guaranteed to be able to look at the
                         * (n remaining + size1) bytes from the
-                        * new (s1 - size1) position).
+                        * s1 position).
                         */
                        n += size1;
                        return strncasecmp(s1, s2, n);
                }
 
+               s1 += size1;
+               s2 += size2;
+
+               if (c1 == c2) {
+                       continue;
+               }
+
                if (toupper_m(c1) != toupper_m(c2)) {
                        return c1 - c2;
                }