From: Andre Noll Date: Fri, 21 Apr 2017 19:49:20 +0000 (+0200) Subject: wma_afh: Fix two bugs in convert_utf8_to_utf16(). X-Git-Tag: v0.6.0~5^2~3 X-Git-Url: http://git.tuebingen.mpg.de/?p=paraslash.git;a=commitdiff_plain;h=1b9bf429a91f4c9fc1abc6030b02ca0c7739bca8;hp=d193847d4086ce3d3a08d741cb0d93ded9353976 wma_afh: Fix two bugs in convert_utf8_to_utf16(). This function has two issues: * If iconv_open() fails and src is NULL (or *src is NULL) we attempt to close an invalid file descriptor. * On errors, we free *dst but miss to set it to NULL, causing a double free in the caller. This patch addresses both issues. The double free was found by the clang static analyzer. --- diff --git a/wma_afh.c b/wma_afh.c index 4c9d87e0..b4935f0d 100644 --- a/wma_afh.c +++ b/wma_afh.c @@ -316,22 +316,24 @@ static const char top_level_header_object_guid[] = { static int convert_utf8_to_utf16(char *src, char **dst) { - /* - * Without specifying LE (little endian), iconv includes a byte order - * mark (e.g. 0xFFFE) at the beginning. - */ - iconv_t cd = iconv_open("UTF-16LE", "UTF-8"); + iconv_t cd; size_t sz, inbytes, outbytes, inbytesleft, outbytesleft; char *inbuf, *outbuf; int ret; if (!src || !*src) { *dst = para_calloc(2); - ret = 0; - goto out; + return 0; } - if (cd == (iconv_t) -1) + /* + * Without specifying LE (little endian), iconv includes a byte order + * mark (e.g. 0xFFFE) at the beginning. + */ + cd = iconv_open("UTF-16LE", "UTF-8"); + if (cd == (iconv_t)-1) { + *dst = NULL; return -ERRNO_TO_PARA_ERROR(errno); + } inbuf = src; /* even though src is in UTF-8, strlen() should DTRT */ inbytes = inbytesleft = strlen(src); @@ -340,6 +342,8 @@ static int convert_utf8_to_utf16(char *src, char **dst) sz = iconv(cd, ICONV_CAST &inbuf, &inbytesleft, &outbuf, &outbytesleft); if (sz == (size_t)-1) { ret = -ERRNO_TO_PARA_ERROR(errno); + free(*dst); + *dst = NULL; goto out; } assert(outbytes >= outbytesleft); @@ -351,8 +355,6 @@ static int convert_utf8_to_utf16(char *src, char **dst) *dst = outbuf; PARA_INFO_LOG("converted %s to %d UTF-16 bytes\n", src, ret); out: - if (ret < 0) - free(*dst); if (iconv_close(cd) < 0) PARA_WARNING_LOG("iconv_close: %s\n", strerror(errno)); return ret;