Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 29 Oct 2015 23:02:34 +0000 (UTC)
From:      Bryan Drewery <bdrewery@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r290168 - head/lib/libc/iconv
Message-ID:  <201510292302.t9TN2YEp074734@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: bdrewery
Date: Thu Oct 29 23:02:34 2015
New Revision: 290168
URL: https://svnweb.freebsd.org/changeset/base/290168

Log:
  Fix several memory leaks, and crashes, in iconvlist(3).
  
  - Both curitem and curitem (via the names list) was always leaked.
  - malloc(3) failures lead to some leaks.
  - __bsd___iconv_get_list() failure lead to a crash since its error was not
    handles and __bsd___iconv_free_list() is not NULL-safe.
  
  I have slightly refactored this to avoid extra malloc and free logic in cases
  of malloc(3) failing.
  
  There are still bad assumptions here that I did not deal with.  One of which is
  that the data will always have a '/' so the strchr(3) will not return NULL.
  
  Coverity CID:	1130055 1130054 1130053

Modified:
  head/lib/libc/iconv/bsd_iconv.c

Modified: head/lib/libc/iconv/bsd_iconv.c
==============================================================================
--- head/lib/libc/iconv/bsd_iconv.c	Thu Oct 29 22:12:03 2015	(r290167)
+++ head/lib/libc/iconv/bsd_iconv.c	Thu Oct 29 23:02:34 2015	(r290168)
@@ -207,43 +207,51 @@ __bsd_iconvlist(int (*do_one) (unsigned 
 	const char * const *np;
 	char *curitem, *curkey, *slashpos;
 	size_t sz;
-	unsigned int i, j;
+	unsigned int i, j, n;
 
 	i = 0;
+	names = NULL;
 
-	if (__bsd___iconv_get_list(&list, &sz, true))
+	if (__bsd___iconv_get_list(&list, &sz, true)) {
 		list = NULL;
+		goto out;
+	}
 	qsort((void *)list, sz, sizeof(char *), qsort_helper);
 	while (i < sz) {
 		j = 0;
 		slashpos = strchr(list[i], '/');
-		curkey = (char *)malloc(slashpos - list[i] + 2);
-		names = (char **)malloc(sz * sizeof(char *));
-		if ((curkey == NULL) || (names == NULL)) {
-			__bsd___iconv_free_list(list, sz);
-			return;
-		}
-		strlcpy(curkey, list[i], slashpos - list[i] + 1);
+		names = malloc(sz * sizeof(char *));
+		if (names == NULL)
+			goto out;
+		curkey = strndup(list[i], slashpos - list[i]);
+		if (curkey == NULL)
+			goto out;
 		names[j++] = curkey;
 		for (; (i < sz) && (memcmp(curkey, list[i], strlen(curkey)) == 0); i++) {
 			slashpos = strchr(list[i], '/');
-			curitem = (char *)malloc(strlen(slashpos) + 1);
-			if (curitem == NULL) {
-				__bsd___iconv_free_list(list, sz);
-				return;
-			}
-			strlcpy(curitem, &slashpos[1], strlen(slashpos) + 1);
-			if (strcmp(curkey, curitem) == 0) {
+			if (strcmp(curkey, &slashpos[1]) == 0)
 				continue;
-			}
+			curitem = strdup(&slashpos[1]);
+			if (curitem == NULL)
+				goto out;
 			names[j++] = curitem;
 		}
 		np = (const char * const *)names;
 		do_one(j, np, data);
+		for (n = 0; n < j; n++)
+			free(names[n]);
 		free(names);
+		names = NULL;
 	}
 
-	__bsd___iconv_free_list(list, sz);
+out:
+	if (names != NULL) {
+		for (n = 0; n < j; n++)
+			free(names[n]);
+		free(names);
+	}
+	if (list != NULL)
+		__bsd___iconv_free_list(list, sz);
 }
 
 __inline const char *



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201510292302.t9TN2YEp074734>