Fix bug 8040 - smbclient segfaults when a Cyrillic netbios name or workgroup is confi...
authorJeremy Allison <jra@samba.org>
Fri, 25 Mar 2011 22:12:12 +0000 (15:12 -0700)
committerKarolin Seeger <kseeger@samba.org>
Tue, 14 Jun 2011 10:56:28 +0000 (12:56 +0200)
As discovered by David Disseldorp <ddiss@suse.de>, convert_string_talloc()
doesn't always return consistent results for a zero length string. The
API states an incoming string must *always* contain the terminating null,
but unfotunately too much code expects passing in a zero source length
to return a null terminated string, so at least ensure we return a
correct null string in the required character set and return the
correct length.

Also ensure we cannot return a zero length for a converted string
(we ensure that the returned buffer is always allocated and zero
terminated anyway) as calling code depends on the fact that returning
true from this function will *always* return a non-zero length (as
it must include the terminating null).

Note this is a different fix from what went into master (this is
identical to the fix I'm planning for 3.5.x) as convert_string_talloc()
has diverged between the two.

Jeremy.
(cherry picked from commit bb3ed43584e6d2c4d64b5f7b9e70a7db7f3e859d)

source3/lib/charcnv.c

index 718f8108e57e4b6b4f8e515f4f2735a8c742f530..743f748669ac7d868ae469a16581222bbc56e989 100644 (file)
@@ -573,14 +573,24 @@ bool convert_string_talloc(TALLOC_CTX *ctx, charset_t from, charset_t to,
                errno = EINVAL;
                return false;
        }
+
        if (srclen == 0) {
-               ob = talloc_strdup(ctx, "");
+               /* We really should treat this as an error, but
+                  there are too many callers that need this to
+                  return a NULL terminated string in the correct
+                  character set. */
+               if (to == CH_UTF16LE|| to == CH_UTF16BE || to == CH_UTF16MUNGED) {
+                       destlen = 2;
+               } else {
+                       destlen = 1;
+               }
+               ob = talloc_zero_array(ctx, char, destlen);
                if (ob == NULL) {
                        errno = ENOMEM;
                        return false;
                }
+               *converted_size = destlen;
                *dest = ob;
-               *converted_size = 0;
                return true;
        }
 
@@ -677,6 +687,16 @@ bool convert_string_talloc(TALLOC_CTX *ctx, charset_t from, charset_t to,
        ob[destlen] = '\0';
        ob[destlen+1] = '\0';
 
+       /* Ensure we can never return a *converted_size of zero. */
+       if (destlen == 0) {
+               /* This can happen from a bad iconv "use_as_is:" call. */
+               if (to == CH_UTF16LE|| to == CH_UTF16BE || to == CH_UTF16MUNGED) {
+                       destlen = 2;
+               } else {
+                       destlen = 1;
+               }
+       }
+
        *converted_size = destlen;
        return true;