From 77727d5612698cbc919cb1f1c359931a30819c93 Mon Sep 17 00:00:00 2001 From: Nikos Mavrogiannopoulos Date: Tue, 20 Nov 2012 19:16:44 +0100 Subject: [PATCH] improved iconv support. --- NEWS | 2 +- lib/system.c | 40 ++++++++++++++++++++++++++++++++++------ 2 files changed, 35 insertions(+), 7 deletions(-) diff --git a/NEWS b/NEWS index 367e94823..e516d04dd 100644 --- a/NEWS +++ b/NEWS @@ -8,7 +8,7 @@ See the end for copying conditions. extension. ** libgnutls: Handle BMPString (UCS-2) encoding in the Distinguished -Name by translating it to UTF-8 (works on windows or systems with libiconv). +Name by translating it to UTF-8 (works on windows or systems with iconv). ** libgnutls: Added PKCS #11 key generation function that returns the public key on generation. diff --git a/lib/system.c b/lib/system.c index dcca1450c..899598dbd 100644 --- a/lib/system.c +++ b/lib/system.c @@ -477,13 +477,15 @@ gnutls_x509_trust_list_add_system_trust(gnutls_x509_trust_list_t list, # include +#define INC(x) (2*x) + int _gnutls_ucs2_to_utf8(const void* data, size_t size, gnutls_datum_t *output) { iconv_t conv; int ret; -size_t orig, dstlen = size*2; +size_t orig, dstlen = INC(size), tmp; char* src = (void*)data; -char* dst, *pdst; +char* dst = NULL, *pdst; if (size == 0) return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); @@ -496,23 +498,49 @@ char* dst, *pdst; if (dst == NULL) { ret = gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); - goto cleanup; + goto fail; } orig = dstlen; ret = iconv(conv, &src, &size, &pdst, &dstlen); if (ret == -1) { - ret = gnutls_assert_val(GNUTLS_E_PARSING_ERROR); - goto cleanup; + if (dstlen != 0 || size == 0) + { + ret = gnutls_assert_val(GNUTLS_E_PARSING_ERROR); + goto fail; + } + + /* otherwise the buffer wasn't sufficient */ + tmp = orig + INC(orig); + dstlen += INC(orig); + + dst = gnutls_realloc_fast(dst, tmp); + if (dst == NULL) + { + ret = gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); + goto fail; + } + pdst = dst + orig; + orig = tmp; + + ret = iconv(conv, &src, &size, &pdst, &dstlen); + if (ret == -1) + { + ret = gnutls_assert_val(GNUTLS_E_PARSING_ERROR); + goto fail; + } } - output->data = (void*)dst; output->size = orig-dstlen; output->data[output->size] = 0; ret = 0; + goto cleanup; + +fail: + gnutls_free(dst); cleanup: iconv_close(conv); -- 2.11.4.GIT