summary |
shortlog |
log |
commit | commitdiff |
tree
raw |
patch |
inline | side by side (from parent 1:
d193847)
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.
static int convert_utf8_to_utf16(char *src, char **dst)
{
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");
size_t sz, inbytes, outbytes, inbytesleft, outbytesleft;
char *inbuf, *outbuf;
int ret;
if (!src || !*src) {
*dst = para_calloc(2);
size_t sz, inbytes, outbytes, inbytesleft, outbytesleft;
char *inbuf, *outbuf;
int ret;
if (!src || !*src) {
*dst = para_calloc(2);
- 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);
return -ERRNO_TO_PARA_ERROR(errno);
inbuf = src;
/* even though src is in UTF-8, strlen() should DTRT */
inbytes = inbytesleft = strlen(src);
inbuf = src;
/* even though src is in UTF-8, strlen() should DTRT */
inbytes = inbytesleft = strlen(src);
sz = iconv(cd, ICONV_CAST &inbuf, &inbytesleft, &outbuf, &outbytesleft);
if (sz == (size_t)-1) {
ret = -ERRNO_TO_PARA_ERROR(errno);
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);
goto out;
}
assert(outbytes >= outbytesleft);
*dst = outbuf;
PARA_INFO_LOG("converted %s to %d UTF-16 bytes\n", src, ret);
out:
*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;
if (iconv_close(cd) < 0)
PARA_WARNING_LOG("iconv_close: %s\n", strerror(errno));
return ret;