From 1b9bf429a91f4c9fc1abc6030b02ca0c7739bca8 Mon Sep 17 00:00:00 2001 From: Andre Noll Date: Fri, 21 Apr 2017 21:49:20 +0200 Subject: [PATCH] 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. --- wma_afh.c | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) 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; -- 2.39.2