summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorbdrewery <bdrewery@FreeBSD.org>2015-10-29 23:02:34 +0000
committerbdrewery <bdrewery@FreeBSD.org>2015-10-29 23:02:34 +0000
commit78af08e72aca2d0d823b51f887eaed8160773b93 (patch)
treea65fe5a3cce8f11fb69e56f881d0b0b0914b34e2 /lib
parentcaa2a6f36aa221602162cf3c48c71b51f3b3b2dd (diff)
downloadFreeBSD-src-78af08e72aca2d0d823b51f887eaed8160773b93.zip
FreeBSD-src-78af08e72aca2d0d823b51f887eaed8160773b93.tar.gz
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
Diffstat (limited to 'lib')
-rw-r--r--lib/libc/iconv/bsd_iconv.c44
1 files changed, 26 insertions, 18 deletions
diff --git a/lib/libc/iconv/bsd_iconv.c b/lib/libc/iconv/bsd_iconv.c
index e032a5b..e9ff688 100644
--- a/lib/libc/iconv/bsd_iconv.c
+++ b/lib/libc/iconv/bsd_iconv.c
@@ -207,43 +207,51 @@ __bsd_iconvlist(int (*do_one) (unsigned int, const char * const *,
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 *
OpenPOWER on IntegriCloud