Fix StrCaseCmp() to avoid calling smb_panic() on invalid multibyte strings.
authorAndrew Bartlett <abartlet@samba.org>
Sat, 19 Jul 2003 00:36:43 +0000 (00:36 +0000)
committerAndrew Bartlett <abartlet@samba.org>
Sat, 19 Jul 2003 00:36:43 +0000 (00:36 +0000)
This fix results in
 - we no longer use fixed-size buffers in StrCaseCmp (previously limited to
   a pstring)
 - we return strcmp(s, t) if either of the strings is invalid
 - for non-ascii cases, we call iconv twice, not 4 times.

The basic idea with this fix is that if a string is not valid in the currnet
charset, then (unless it is byte-equivilant) it cannot be case-equivilant
to any other string.

This should address the majority of our smb_panic() cases on this matter.  It
will not fix them all - we still call unix_strupper(), aka strupper_m()
elsewhere, but this was being called on every file in the directory when
we performed unix_convert().

Tested with the stf unit tests for this routine.

Andrew Bartlett

source/lib/util_str.c

index 96fbc3f1247d81a4d185d856bd09d532e5f73fdb..7bf43de5f33bc0b60738b47ad4390459f593683b 100644 (file)
@@ -181,7 +181,9 @@ int StrCaseCmp(const char *s, const char *t)
 {
 
        const char * ps, * pt;
-       pstring buf1, buf2;
+       size_t size;
+       smb_ucs2_t *buffer_s, *buffer_t;
+       int ret;
 
        for (ps = s, pt = t; ; ps++, pt++) {
                char us, ut;
@@ -206,16 +208,27 @@ int StrCaseCmp(const char *s, const char *t)
                        return +1;
        }
 
-       /* TODO: Don't do this with a fixed-length buffer.  This could
-        * still be much more efficient. */
-       /* TODO: Hardcode a char-by-char comparison for UTF-8, which
-        * can be much faster. */
-       /* TODO: Test case for this! */
-
-       unix_strupper(ps, strlen(ps)+1, buf1, sizeof(buf1));
-       unix_strupper(pt, strlen(pt)+1, buf2, sizeof(buf2));
-
-       return strcmp(buf1, buf2);
+       size = convert_string_allocate(CH_UNIX, CH_UCS2, s, strlen(s),
+                                      (void **) &buffer_s);
+       if (size == -1) {
+               return strcmp(s, t); 
+               /* Not quite the right answer, but finding the right one
+                  under this failure case is expensive, and it's pretty close */
+       }
+       
+       size = convert_string_allocate(CH_UNIX, CH_UCS2, t, strlen(t),
+                                      (void **) &buffer_t);
+       if (size == -1) {
+               SAFE_FREE(buffer_s);
+               return strcmp(s, t); 
+               /* Not quite the right answer, but finding the right one
+                  under this failure case is expensive, and it's pretty close */
+       }
+       
+       ret = strcasecmp_w(buffer_s, buffer_t);
+       SAFE_FREE(buffer_s);
+       SAFE_FREE(buffer_t);
+       return ret;
 }