svn commit: r290168 - head/lib/libc/iconv
Bryan Drewery
bdrewery at FreeBSD.org
Thu Oct 29 23:02:35 UTC 2015
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 *
More information about the svn-src-all
mailing list