diff options
Diffstat (limited to 'source4')
-rw-r--r-- | source4/lib/charcnv.c | 34 |
1 files changed, 17 insertions, 17 deletions
diff --git a/source4/lib/charcnv.c b/source4/lib/charcnv.c index 392ad3cc72..e5331b973e 100644 --- a/source4/lib/charcnv.c +++ b/source4/lib/charcnv.c @@ -168,7 +168,7 @@ ssize_t convert_string(charset_t from, charset_t to, **/ ssize_t convert_string_talloc(TALLOC_CTX *ctx, charset_t from, charset_t to, - void const *src, size_t srclen, void **dest) + void const *src, size_t srclen, void **dest) { size_t i_len, o_len, destlen; size_t retval; @@ -189,20 +189,25 @@ ssize_t convert_string_talloc(TALLOC_CTX *ctx, charset_t from, charset_t to, return -1; } - destlen = MAX(srclen, 512); + /* it is _very_ rare that a conversion increases the size by + more than 3x */ + destlen = srclen; outbuf = NULL; convert: - destlen = destlen * 2; + destlen = 2 + (destlen*3); ob = (char *)talloc_realloc(ctx, outbuf, destlen); if (!ob) { DEBUG(0, ("convert_string_talloc: realloc failed!\n")); talloc_free(outbuf); return (size_t)-1; - } - else + } else { outbuf = ob; + } + + /* we give iconv 2 less bytes to allow us to terminate at the + end */ i_len = srclen; - o_len = destlen; + o_len = destlen-2; retval = smb_iconv(descriptor, &inbuf, &i_len, &outbuf, &o_len); @@ -220,20 +225,15 @@ convert: } DEBUG(0,("Conversion error: %s(%s)\n",reason,inbuf)); talloc_free(ob); - /* smb_panic(reason); */ return (size_t)-1; } - destlen = destlen - o_len; - /* +2 for mandetory null termination, UTF8 or UTF16 */ - *dest = (char *)talloc_realloc(ctx, ob, destlen+2); - if (!*dest) { - DEBUG(0, ("convert_string_talloc: out of memory!\n")); - talloc_free(ob); - return (size_t)-1; - } - ((char *)*dest)[destlen] = '\0'; - ((char *)*dest)[destlen+1] = '\0'; + destlen = (destlen-2) - o_len; + + /* guarantee null termination in all charsets */ + SSVAL(ob, destlen, 0); + + *dest = ob; return destlen; } |