The branch, master has been updated
       via  790ab3e lib/util/charset Add copyright headers
       via  d17f435 lib/util/charset Make fast path from UTF16 to '8 bit' 
charsets clearer
       via  eee1ff2 lib/util/charset Add tests for srclen=-1 behaviour.
       via  4081ea5 lib/util/charset use convert_string.c in common
       via  75d5ba4 lib/util/charset Fix string termination conditions for 
UTF16 strings
      from  240465f Remove another fstring in this code.

http://gitweb.samba.org/?p=samba.git;a=shortlog;h=master


- Log -----------------------------------------------------------------
commit 790ab3e0dbd77ba2d08ef9c39d00f542fbe01358
Author: Andrew Bartlett <[email protected]>
Date:   Thu Apr 28 10:56:36 2011 +1000

    lib/util/charset Add copyright headers
    
    Autobuild-User: Andrew Bartlett <[email protected]>
    Autobuild-Date: Thu Apr 28 04:13:44 CEST 2011 on sn-devel-104

commit d17f4352fe2493be433a21e2f47453968aafdc4d
Author: Andrew Tridgell <[email protected]>
Date:   Thu Apr 28 10:50:06 2011 +1000

    lib/util/charset Make fast path from UTF16 to '8 bit' charsets clearer
    
    This breaks the fast path into handling for -1 and handling for
    specified lenghts, avoding branch operations on each character.
    
    Pair-Programmed-With: Andrew Bartlett <[email protected]>
    Signed-off-by: Andrew Tridgell <[email protected]>

commit eee1ff2fb56f46fb3c6aa7dfe51583e3b489fb5d
Author: Andrew Bartlett <[email protected]>
Date:   Thu Apr 28 10:48:43 2011 +1000

    lib/util/charset Add tests for srclen=-1 behaviour.
    
    This confirms that we do include a null terminator in all non-failed
    conversions.
    
    Andrew Bartlett
    
    Signed-off-by: Andrew Tridgell <[email protected]>

commit 4081ea5b49c6b882174d633a1eb03436341c4e63
Author: Andrew Bartlett <[email protected]>
Date:   Tue Apr 12 14:49:41 2011 +1000

    lib/util/charset use convert_string.c in common
    
    This brings another layer of the charcnv library in common.
    
    Andrew Bartlett
    
    Signed-off-by: Andrew Tridgell <[email protected]>

commit 75d5ba4109801957eef590b601cce61a6e67064f
Author: Andrew Bartlett <[email protected]>
Date:   Thu Apr 14 17:23:25 2011 +1000

    lib/util/charset Fix string termination conditions for UTF16 strings
    
    This punts partial UTF16 strings to iconv() to deal with, as it's not
    a fast path any longer if it's got an odd length.
    
    Andrew Bartlett
    
    Signed-off-by: Andrew Tridgell <[email protected]>

-----------------------------------------------------------------------

Summary of changes:
 lib/util/charset/charcnv.c              |  135 ----------
 lib/util/charset/convert_string.c       |   54 +++--
 lib/util/charset/tests/convert_string.c |  443 +++++++++++++++++++++++++++++++
 lib/util/charset/util_unistr.c          |   65 -----
 lib/util/charset/wscript_build          |    4 +-
 source3/wscript_build                   |    2 +-
 6 files changed, 481 insertions(+), 222 deletions(-)


Changeset truncated at 500 lines:

diff --git a/lib/util/charset/charcnv.c b/lib/util/charset/charcnv.c
index 998bb08..076795a 100644
--- a/lib/util/charset/charcnv.c
+++ b/lib/util/charset/charcnv.c
@@ -113,138 +113,3 @@ convert:
        return destlen;
 
 }
-
-/**
- * Convert string from one encoding to another, making error checking etc
- *
- * @param src pointer to source string (multibyte or singlebyte)
- * @param srclen length of the source string in bytes
- * @param dest pointer to destination string (multibyte or singlebyte)
- * @param destlen maximal length allowed for string
- * @returns the number of bytes occupied in the destination
- * on error, returns -1, and sets errno
- **/
-_PUBLIC_ bool convert_string_error_handle(struct smb_iconv_handle *ic,
-                                         charset_t from, charset_t to,
-                                         void const *src, size_t srclen,
-                                         void *dest, size_t destlen,
-                                         size_t *converted_size)
-{
-       size_t i_len, o_len;
-       ssize_t retval;
-       const char* inbuf = (const char*)src;
-       char* outbuf = (char*)dest;
-       smb_iconv_t descriptor;
-
-       if (srclen == (size_t)-1)
-               srclen = strlen(inbuf)+1;
-
-       descriptor = get_conv_handle(ic, from, to);
-       if (descriptor == (smb_iconv_t)-1 || descriptor == (smb_iconv_t)0) {
-               if (converted_size) {
-                       *converted_size = 0;
-               }
-               errno = EINVAL;
-               return -1;
-       }
-
-       i_len=srclen;
-       o_len=destlen;
-
-       retval = smb_iconv(descriptor,  &inbuf, &i_len, &outbuf, &o_len);
-
-       if (converted_size != NULL)
-               *converted_size = destlen-o_len;
-       return (retval != (ssize_t)-1);
-}
-
-
-/**
- * Convert string from one encoding to another, making error checking etc
- *
- * @param src pointer to source string (multibyte or singlebyte)
- * @param srclen length of the source string in bytes
- * @param dest pointer to destination string (multibyte or singlebyte)
- * @param destlen maximal length allowed for string
- * @returns the number of bytes occupied in the destination
- **/
-_PUBLIC_ bool convert_string_handle(struct smb_iconv_handle *ic,
-                                        charset_t from, charset_t to,
-                                        void const *src, size_t srclen,
-                                        void *dest, size_t destlen, size_t 
*converted_size)
-{
-       bool retval;
-
-       retval = convert_string_error_handle(ic, from, to, src, srclen, dest, 
destlen, converted_size);
-       if(retval==false) {
-               const char *reason;
-               switch(errno) {
-               case EINVAL:
-                       reason="Incomplete multibyte sequence";
-                       return false;
-               case E2BIG:
-                       reason="No more room";
-                       if (from == CH_UNIX) {
-                               DEBUG(0,("E2BIG: convert_string_handle(%s,%s): 
srclen=%d destlen=%d - '%s'\n",
-                                        charset_name(ic, from), 
charset_name(ic, to),
-                                        (int)srclen, (int)destlen,
-                                        (const char *)src));
-                       } else {
-                               DEBUG(0,("E2BIG: convert_string_handle(%s,%s): 
srclen=%d destlen=%d\n",
-                                        charset_name(ic, from), 
charset_name(ic, to),
-                                        (int)srclen, (int)destlen));
-                       }
-                       return false;
-               case EILSEQ:
-                       reason="Illegal multibyte sequence";
-                       return false;
-               default:
-                       return false;
-               }
-       }
-       return true;
-}
-       
-/**
- * Convert between character sets, allocating a new buffer using talloc for 
the result.
- *
- * @param srclen length of source buffer.
- * @param dest always set at least to NULL
- * @note -1 is not accepted for srclen.
- *
- * @returns Size in bytes of the converted string; or -1 in case of error.
- **/
-
-_PUBLIC_ bool convert_string_talloc_handle(TALLOC_CTX *ctx,
-                                               struct smb_iconv_handle *ic,
-                                               charset_t from, charset_t to, 
-                                               void const *src, size_t srclen, 
-                                               void *dst, size_t 
*converted_size)
-{
-       void **dest = (void **)dst;
-       smb_iconv_t descriptor;
-       ssize_t ret;
-
-       *dest = NULL;
-
-       if (src == NULL || srclen == (size_t)-1 || srclen == 0)
-               return false;
-
-       descriptor = get_conv_handle(ic, from, to);
-
-       if (descriptor == (smb_iconv_t)-1 || descriptor == (smb_iconv_t)0) {
-               /* conversion not supported, return -1*/
-               DEBUG(3, ("convert_string_talloc_handle: conversion from %s to 
%s not supported!\n",
-                         charset_name(ic, from), 
-                         charset_name(ic, to)));
-               return false;
-       }
-
-       ret = iconv_talloc(ctx, descriptor, src, srclen, dest);
-       if (ret == -1)
-               return false;
-       if (converted_size != NULL)
-               *converted_size = ret;
-       return true;
-}
-
diff --git a/lib/util/charset/convert_string.c 
b/lib/util/charset/convert_string.c
index e51add2..51f9fec 100644
--- a/lib/util/charset/convert_string.c
+++ b/lib/util/charset/convert_string.c
@@ -2,7 +2,8 @@
    Unix SMB/CIFS implementation.
    Character set conversion Extensions
    Copyright (C) Igor Vergeichik <[email protected]> 2001
-   Copyright (C) Andrew Tridgell 2001
+   Copyright (C) Andrew Tridgell 2001-2011
+   Copyright (C) Andrew Bartlett 2011
    Copyright (C) Simo Sorce 2001
    Copyright (C) Martin Pool 2003
 
@@ -21,6 +22,7 @@
 
 */
 #include "includes.h"
+#include "system/iconv.h"
 
 /**
  * @file
@@ -177,28 +179,29 @@ bool convert_string_error_handle(struct smb_iconv_handle 
*ic,
                size_t slen = srclen;
                size_t dlen = destlen;
                unsigned char lastp = '\0';
+               bool ret;
 
-               /* If all characters are ascii, fast path here. */
-               while (((slen == (size_t)-1) || (slen >= 2)) && dlen) {
-                       if (((lastp = *p) <= 0x7f) && (p[1] == 0)) {
+               if (slen == (size_t)-1) {
+                       while (dlen &&
+                              ((lastp = *p) <= 0x7f) && (p[1] == 0)) {
                                *q++ = *p;
-                               if (slen != (size_t)-1) {
-                                       slen -= 2;
-                               }
                                p += 2;
                                dlen--;
                                retval++;
                                if (!lastp)
                                        break;
-                       } else {
-#ifdef BROKEN_UNICODE_COMPOSE_CHARACTERS
-                               goto general_case;
-#else
-                               bool ret = convert_string_internal(ic, from, 
to, p, slen, q, dlen, converted_size);
-                               *converted_size += retval;
-                               return ret;
-#endif
                        }
+                       if (lastp != 0) goto slow_path;
+               } else {
+                       while (slen >= 2 && dlen &&
+                              (*p <= 0x7f) && (p[1] == 0)) {
+                               *q++ = *p;
+                               slen -= 2;
+                               p += 2;
+                               dlen--;
+                               retval++;
+                       }
+                       if (slen != 0) goto slow_path;
                }
 
                *converted_size = retval;
@@ -212,6 +215,19 @@ bool convert_string_error_handle(struct smb_iconv_handle 
*ic,
                        }
                }
                return true;
+
+       slow_path:
+               /* come here when we hit a character we can't deal
+                * with in the fast path
+                */
+#ifdef BROKEN_UNICODE_COMPOSE_CHARACTERS
+               goto general_case;
+#else
+               ret = convert_string_internal(ic, from, to, p, slen, q, dlen, 
converted_size);
+               *converted_size += retval;
+               return ret;
+#endif
+
        } else if (from != CH_UTF16LE && from != CH_UTF16BE && to == 
CH_UTF16LE) {
                const unsigned char *p = (const unsigned char *)src;
                unsigned char *q = (unsigned char *)dest;
@@ -221,8 +237,8 @@ bool convert_string_error_handle(struct smb_iconv_handle 
*ic,
                unsigned char lastp = '\0';
 
                /* If all characters are ascii, fast path here. */
-               while (slen && (dlen >= 2)) {
-                       if ((lastp = *p) <= 0x7F) {
+               while (slen && (dlen >= 1)) {
+                       if (dlen >=2 && (lastp = *p) <= 0x7F) {
                                *q++ = *p++;
                                *q++ = '\0';
                                if (slen != (size_t)-1) {
@@ -387,7 +403,7 @@ bool convert_string_talloc_handle(TALLOC_CTX *ctx, struct 
smb_iconv_handle *ic,
        }
 
        /* +2 is for ucs2 null termination. */
-       ob = (char *)TALLOC_REALLOC(ctx, ob, destlen + 2);
+       ob = talloc_realloc(ctx, ob, char, destlen + 2);
 
        if (!ob) {
                DEBUG(0, ("convert_string_talloc: realloc failed!\n"));
@@ -428,7 +444,7 @@ bool convert_string_talloc_handle(TALLOC_CTX *ctx, struct 
smb_iconv_handle *ic,
         */
        if (o_len > 1024) {
                /* We're shrinking here so we know the +2 is safe from wrap. */
-               ob = (char *)TALLOC_REALLOC(ctx,ob,destlen + 2);
+               ob = talloc_realloc(ctx,ob, char, destlen + 2);
        }
 
        if (destlen && !ob) {
diff --git a/lib/util/charset/tests/convert_string.c 
b/lib/util/charset/tests/convert_string.c
index 32fc11f..bd140d5 100644
--- a/lib/util/charset/tests/convert_string.c
+++ b/lib/util/charset/tests/convert_string.c
@@ -282,6 +282,191 @@ static bool test_gd_iso8859_cp850_handle(struct 
torture_context *tctx)
        return true;
 }
 
+static bool test_gd_minus_1_handle(struct torture_context *tctx)
+{
+       struct smb_iconv_handle *iconv_handle;
+       DATA_BLOB gd_utf8 = base64_decode_data_blob(gd_utf8_base64);
+       DATA_BLOB gd_cp850 = base64_decode_data_blob(gd_cp850_base64);
+       DATA_BLOB gd_utf16le = base64_decode_data_blob(gd_utf16le_base64);
+       DATA_BLOB gd_output;
+       DATA_BLOB gd_utf8_terminated;
+       DATA_BLOB gd_cp850_terminated;
+       DATA_BLOB gd_utf16le_terminated;
+       
+       talloc_steal(tctx, gd_utf8.data);
+       talloc_steal(tctx, gd_cp850.data);
+       talloc_steal(tctx, gd_utf16le.data);
+
+       iconv_handle = get_iconv_testing_handle(tctx, "CP850", "CP850", "UTF8");
+       torture_assert(tctx, iconv_handle, "getting iconv handle");
+
+       gd_utf8_terminated = data_blob_talloc(tctx, NULL, gd_utf8.length + 1);
+       memcpy(gd_utf8_terminated.data, gd_utf8.data, gd_utf8.length);
+       gd_utf8_terminated.data[gd_utf8.length] = '\0';
+
+       gd_cp850_terminated = data_blob_talloc(tctx, NULL, gd_cp850.length + 1);
+       memcpy(gd_cp850_terminated.data, gd_cp850.data, gd_cp850.length);
+       gd_cp850_terminated.data[gd_cp850.length] = '\0';
+
+       gd_utf16le_terminated = data_blob_talloc(tctx, NULL, gd_utf16le.length 
+ 2);
+       memcpy(gd_utf16le_terminated.data, gd_utf16le.data, gd_utf16le.length);
+       gd_utf16le_terminated.data[gd_utf16le.length] = '\0';
+       gd_utf16le_terminated.data[gd_utf16le.length + 1] = '\0';
+
+       gd_output = data_blob_talloc(tctx, NULL, gd_utf16le.length + 10);
+
+       torture_assert(tctx, convert_string_error_handle(iconv_handle,
+                                                         CH_UTF8, CH_UTF16LE,
+                                                         
gd_utf8_terminated.data, -1,
+                                                        (void 
*)gd_output.data, gd_output.length, &gd_output.length),
+                      "conversion from UTF8 to UTF16LE null terminated");
+       torture_assert_data_blob_equal(tctx, gd_output, gd_utf16le_terminated, 
"conversion from UTF8 to UTF16LE null terminated");
+
+       gd_output = data_blob_talloc(tctx, NULL, gd_utf16le.length + 10);
+       torture_assert(tctx, convert_string_error_handle(iconv_handle,
+                                                         CH_UTF8, CH_UTF16LE,
+                                                         
gd_utf8_terminated.data, -1,
+                                                         (void 
*)gd_output.data, gd_utf16le.length, &gd_output.length) == false,
+                      "conversion from UTF8 to UTF16LE null terminated should 
fail");
+       torture_assert_errno_equal(tctx, E2BIG, "conversion from UTF8 to 
UTF16LE should fail E2BIG");
+       torture_assert_data_blob_equal(tctx, gd_output, gd_utf16le, "conversion 
from UTF8 to UTF16LE null terminated");
+
+       gd_output = data_blob_talloc(tctx, NULL, gd_utf16le.length + 10);
+       torture_assert(tctx, convert_string_error_handle(iconv_handle,
+                                                         CH_UTF8, CH_UTF16LE,
+                                                         
gd_utf8_terminated.data, -1,
+                                                         (void 
*)gd_output.data, gd_utf16le.length - 1, &gd_output.length) == false,
+                      "conversion from UTF8 to UTF16LE null terminated should 
fail");
+       torture_assert_errno_equal(tctx, E2BIG, "conversion from UTF8 to 
UTF16LE should fail E2BIG");
+
+       gd_output = data_blob_talloc(tctx, NULL, gd_utf16le.length + 10);
+       torture_assert(tctx, convert_string_error_handle(iconv_handle,
+                                                         CH_UTF8, CH_UTF16LE,
+                                                         
gd_utf8_terminated.data, -1,
+                                                         (void 
*)gd_output.data, gd_utf16le.length - 2, &gd_output.length) == false,
+                      "conversion from UTF8 to UTF16LE null terminated should 
fail");
+       torture_assert_errno_equal(tctx, E2BIG, "conversion from UTF8 to 
UTF16LE should fail E2BIG");
+
+       gd_output = data_blob_talloc(tctx, NULL, gd_utf8.length + 10);
+       torture_assert(tctx, convert_string_error_handle(iconv_handle,
+                                                        CH_UTF16LE, CH_UTF8,
+                                                        
gd_utf16le_terminated.data, -1,
+                                                        (void 
*)gd_output.data, gd_output.length, &gd_output.length),
+                      "conversion from UTF16LE to UTF8 null terminated");
+       torture_assert_data_blob_equal(tctx, gd_output, gd_utf8_terminated, 
"conversion from UTF16LE to UTF8 null terminated");
+
+       gd_output = data_blob_talloc(tctx, NULL, gd_utf8.length + 10);
+
+       torture_assert(tctx, convert_string_error_handle(iconv_handle,
+                                                        CH_UTF16LE, CH_UTF8,
+                                                        
gd_utf16le_terminated.data, -1,
+                                                        (void 
*)gd_output.data, gd_utf8.length, &gd_output.length) == false,
+                      "conversion from UTF16LE to UTF8 null terminated should 
fail");
+       torture_assert_errno_equal(tctx, E2BIG, "conversion from UTF16LE to 
UTF8 should fail E2BIG");
+       torture_assert_data_blob_equal(tctx, gd_output, gd_utf8, "conversion 
from UTF16LE to UTF8 null terminated");
+
+       gd_output = data_blob_talloc(tctx, NULL, gd_utf8.length + 10);
+
+       torture_assert(tctx, convert_string_error_handle(iconv_handle,
+                                                        CH_UTF16LE, CH_UTF8,
+                                                        
gd_utf16le_terminated.data, -1,
+                                                        (void 
*)gd_output.data, gd_utf8.length - 1, &gd_output.length) == false,
+                      "conversion from UTF16LE to UTF8 null terminated should 
fail");
+       torture_assert_errno_equal(tctx, E2BIG, "conversion from UTF16LE to 
UTF8 should fail E2BIG");
+
+       gd_output = data_blob_talloc(tctx, NULL, gd_utf8.length + 10);
+
+       torture_assert(tctx, convert_string_error_handle(iconv_handle,
+                                                        CH_UTF16LE, CH_UTF8,
+                                                        
gd_utf16le_terminated.data, -1,
+                                                        (void 
*)gd_output.data, gd_utf8.length - 2, &gd_output.length) == false,
+                      "conversion from UTF16LE to UTF8 null terminated should 
fail");
+       torture_assert_errno_equal(tctx, E2BIG, "conversion from UTF16LE to 
UTF8 should fail E2BIG");
+
+       gd_output = data_blob_talloc(tctx, NULL, gd_cp850.length + 10);
+
+       torture_assert(tctx, convert_string_error_handle(iconv_handle,
+                                                        CH_UTF16LE, CH_DOS,
+                                                        
gd_utf16le_terminated.data, -1,
+                                                        (void 
*)gd_output.data, gd_output.length, &gd_output.length),
+                      "conversion from UTF16LE to CP850 (dos) null 
terminated");
+       torture_assert_data_blob_equal(tctx, gd_output, gd_cp850_terminated, 
"conversion from UTF16LE to CP850 (dos) null terminated");
+
+       /* Now null terminate the string early, the confirm we don't skip the 
NULL and convert any further */
+       gd_utf8_terminated.data[3] = '\0';
+       gd_utf8_terminated.length = 4; /* used for the comparison only */
+
+       gd_cp850_terminated.data[2] = '\0';
+       gd_cp850_terminated.length = 3; /* used for the comparison only */
+
+       gd_utf16le_terminated.data[4] = '\0';
+       gd_utf16le_terminated.data[5] = '\0';
+       gd_utf16le_terminated.length = 6; /* used for the comparison only */
+
+       gd_output = data_blob_talloc(tctx, NULL, gd_utf16le.length + 10);
+
+       torture_assert(tctx, convert_string_error_handle(iconv_handle,
+                                                         CH_UTF8, CH_UTF16LE,
+                                                         
gd_utf8_terminated.data, -1,
+                                                         (void 
*)gd_output.data, gd_output.length, &gd_output.length),
+                      "conversion from UTF8 to UTF16LE null terminated");
+       torture_assert_data_blob_equal(tctx, gd_output, gd_utf16le_terminated, 
"conversion from UTF8 to UTF16LE null terminated early");
+
+       gd_output = data_blob_talloc(tctx, NULL, gd_utf8.length + 10);
+
+       torture_assert(tctx, convert_string_error_handle(iconv_handle,
+                                                         CH_UTF16LE, CH_UTF8,
+                                                         
gd_utf16le_terminated.data, -1,
+                                                        (void 
*)gd_output.data, gd_output.length, &gd_output.length),
+                      "conversion from UTF16LE to UTF8 null terminated");
+       torture_assert_data_blob_equal(tctx, gd_output, gd_utf8_terminated, 
"conversion from UTF16LE to UTF8 null terminated early");
+
+       gd_output = data_blob_talloc(tctx, NULL, gd_utf16le.length + 10);
+
+       torture_assert(tctx, convert_string_error_handle(iconv_handle,
+                                                         CH_DOS, CH_UTF16LE,
+                                                         
gd_cp850_terminated.data, -1,
+                                                         (void 
*)gd_output.data, gd_output.length, &gd_output.length),
+                      "conversion from CP850 to UTF16LE null terminated");
+       torture_assert_data_blob_equal(tctx, gd_output, gd_utf16le_terminated, 
"conversion from UTF8 to UTF16LE null terminated early");
+
+       gd_output = data_blob_talloc(tctx, NULL, gd_cp850.length + 10);
+
+       torture_assert(tctx, convert_string_error_handle(iconv_handle,
+                                                         CH_UTF16LE, CH_DOS,
+                                                         
gd_utf16le_terminated.data, -1,
+                                                        (void 
*)gd_output.data, gd_output.length, &gd_output.length),
+                      "conversion from UTF16LE to UTF8 null terminated");
+       torture_assert_data_blob_equal(tctx, gd_output, gd_cp850_terminated, 
"conversion from UTF16LE to UTF8 null terminated early");
+       
+       /* Now null terminate the string particularly early, the confirm we 
don't skip the NULL and convert any further */
+       gd_utf8_terminated.data[1] = '\0';
+       gd_utf8_terminated.length = 2; /* used for the comparison only */
+       
+       gd_utf16le_terminated.data[2] = '\0';
+       gd_utf16le_terminated.data[3] = '\0';
+       gd_utf16le_terminated.length = 4; /* used for the comparison only */
+
+       gd_output = data_blob_talloc(tctx, NULL, gd_utf16le.length + 10);
+
+       torture_assert(tctx, convert_string_error_handle(iconv_handle, CH_UTF8, 
CH_UTF16LE,
+                                                         
gd_utf8_terminated.data, -1,
+                                                        (void 
*)gd_output.data, gd_output.length, &gd_output.length),
+                      "conversion from UTF8 to UTF16LE null terminated");
+       torture_assert_data_blob_equal(tctx, gd_output, gd_utf16le_terminated, 
"conversion from UTF8 to UTF16LE null terminated very early");
+
+       gd_output = data_blob_talloc(tctx, NULL, gd_utf8.length + 10);
+
+       torture_assert(tctx, convert_string_error_handle(iconv_handle,
+                                                         CH_UTF16LE, CH_UTF8,
+                                                         
gd_utf16le_terminated.data, -1,
+                                                        (void 
*)gd_output.data, gd_output.length, &gd_output.length),
+                      "conversion from UTF16LE to UTF8 null terminated");
+       torture_assert_data_blob_equal(tctx, gd_output, gd_utf8_terminated, 
"conversion from UTF16LE to UTF8 null terminated very early");
+
+       return true;
+}
+
 static bool test_gd_ascii_handle(struct torture_context *tctx)
 {
        struct smb_iconv_handle *iconv_handle;
@@ -472,6 +657,261 @@ static bool 
test_plato_english_iso8859_cp850_handle(struct torture_context *tctx
        return true;
 }
 
+static bool test_plato_english_minus_1_handle(struct torture_context *tctx)
+{
+       struct smb_iconv_handle *iconv_handle;
+       DATA_BLOB plato_english_utf8 = 
data_blob_string_const(plato_english_ascii);
+       DATA_BLOB plato_english_utf16le = 
base64_decode_data_blob(plato_english_utf16le_base64);
+       DATA_BLOB plato_english_output;
+       DATA_BLOB plato_english_utf8_terminated;
+       DATA_BLOB plato_english_utf16le_terminated;
+       
+       talloc_steal(tctx, plato_english_utf16le.data);
+
+       iconv_handle = get_iconv_testing_handle(tctx, "ISO8859-1", "CP850", 
"UTF8");
+       torture_assert(tctx, iconv_handle, "getting iconv handle");
+
+       plato_english_utf8_terminated = data_blob_talloc(tctx, NULL, 
plato_english_utf8.length + 1);
+       memcpy(plato_english_utf8_terminated.data, plato_english_utf8.data, 
plato_english_utf8.length);
+       plato_english_utf8_terminated.data[plato_english_utf8.length] = '\0';
+
+       plato_english_utf16le_terminated = data_blob_talloc(tctx, NULL, 
plato_english_utf16le.length + 2);
+       memcpy(plato_english_utf16le_terminated.data, 
plato_english_utf16le.data, plato_english_utf16le.length);
+       plato_english_utf16le_terminated.data[plato_english_utf16le.length] = 
'\0';
+       plato_english_utf16le_terminated.data[plato_english_utf16le.length + 1] 
= '\0';
+               
+       plato_english_output = data_blob_talloc(tctx, NULL, 
plato_english_utf16le.length + 10);
+
+       torture_assert(tctx, convert_string_error_handle(iconv_handle,
+                                                         CH_UTF8, CH_UTF16LE,
+                                                         
plato_english_utf8_terminated.data, -1,
+                                                        (void 
*)plato_english_output.data, plato_english_output.length, 
&plato_english_output.length),
+                      "conversion from UTF8 to UTF16LE null terminated");
+       torture_assert_data_blob_equal(tctx, plato_english_output, 
plato_english_utf16le_terminated, "conversion from UTF8 to UTF16LE null 
terminated");
+
+       torture_assert(tctx, convert_string_error_handle(iconv_handle,
+                                                         CH_UTF8, CH_UTF16LE,
+                                                         
plato_english_utf8_terminated.data, -1,
+                                                         (void 
*)plato_english_output.data, plato_english_utf16le.length, 
&plato_english_output.length) == false,
+                      "conversion from UTF8 to UTF16LE null terminated should 
fail");
+       torture_assert_errno_equal(tctx, E2BIG, "conversion from UTF8 to 
UTF16LE should fail E2BIG");
+       torture_assert_data_blob_equal(tctx, plato_english_output, 
plato_english_utf16le, "conversion from UTF8 to UTF16LE null terminated");
+
+       torture_assert(tctx, convert_string_error_handle(iconv_handle,
+                                                         CH_UTF8, CH_UTF16LE,


-- 
Samba Shared Repository

Reply via email to