libnv: fix memory leaks

nvpair_create_stringv: free the temporary string; this fix affects
nvlist_add_stringf() and nvlist_add_stringv().

nvpair_remove_nvlist_array (NV_TYPE_NVLIST_ARRAY case): free the chain
of nvpairs (as resetting it prevents nvlist_destroy() from freeing it).
Note: freeing the chain in nvlist_destroy() is not sufficient, because
it would still leak through nvlist_take_nvlist_array().  This affects
all nvlist_*_nvlist_array() use

Submitted by:	Mindaugas Rasiukevicius <rmind@netbsd.org>
Reported by:	clang/gcc ASAN
MFC after:	2 weeks
This commit is contained in:
oshogbo 2019-02-10 23:28:55 +00:00
parent a7ab0783e1
commit 1790653b1d
4 changed files with 23 additions and 4 deletions

View File

@ -304,6 +304,8 @@ parent(int sock)
name = nvlist_next(nvl, &type, &cookie);
CHECK(name == NULL);
nvlist_destroy(nvl);
}
static void

View File

@ -103,6 +103,7 @@ bool nvlist_move_nvpair(nvlist_t *nvl, nvpair_t *nvp);
void nvlist_set_parent(nvlist_t *nvl, nvpair_t *parent);
void nvlist_set_array_next(nvlist_t *nvl, nvpair_t *ele);
nvpair_t *nvlist_get_array_next_nvpair(nvlist_t *nvl);
const nvpair_t *nvlist_get_nvpair(const nvlist_t *nvl, const char *name);

View File

@ -247,6 +247,15 @@ nvlist_set_array_next(nvlist_t *nvl, nvpair_t *ele)
nvl->nvl_array_next = ele;
}
nvpair_t *
nvlist_get_array_next_nvpair(nvlist_t *nvl)
{
NVLIST_ASSERT(nvl);
return (nvl->nvl_array_next);
}
bool
nvlist_in_array(const nvlist_t *nvl)
{

View File

@ -229,8 +229,16 @@ nvpair_remove_nvlist_array(nvpair_t *nvp)
nvlarray = __DECONST(nvlist_t **,
nvpair_get_nvlist_array(nvp, &count));
for (i = 0; i < count; i++) {
nvlist_set_array_next(nvlarray[i], NULL);
nvlist_set_parent(nvlarray[i], NULL);
nvlist_t *nvl;
nvpair_t *nnvp;
nvl = nvlarray[i];
nnvp = nvlist_get_array_next_nvpair(nvl);
if (nnvp != NULL) {
nvpair_free_structure(nnvp);
}
nvlist_set_array_next(nvl, NULL);
nvlist_set_parent(nvl, NULL);
}
}
@ -1193,8 +1201,7 @@ nvpair_create_stringv(const char *name, const char *valuefmt, va_list valueap)
if (len < 0)
return (NULL);
nvp = nvpair_create_string(name, str);
if (nvp == NULL)
nv_free(str);
nv_free(str);
return (nvp);
}