Because nvp wasn't initialized on every loop iteration once we jumped

to 'fail' on error it was treated as success, because nvp!=NULL. Fix this
by not handling success under 'fail' label and by using separate variable
for parent nvpair.

If we succeeded to allocate nvlist, but failed to allocated nvpair we
would leak nvls[ii] on return. Destroy it when we cannot allocate nvpair,
before we goto fail.

Submitted by:	pjd@ and oshogbo@ (minor changes)
Found by:       scan-build
MFC after:	1 month
Sponsored by:	Wheel Systems
This commit is contained in:
Mariusz Zaborski 2017-09-21 10:10:42 +00:00
parent a3c485d38d
commit c696dd0687

View File

@ -1407,10 +1407,9 @@ nvpair_create_nvlist_array(const char *name, const nvlist_t * const *value,
{
unsigned int ii;
nvlist_t **nvls;
nvpair_t *nvp;
nvpair_t *parent;
int flags;
nvp = NULL;
nvls = NULL;
if (value == NULL || nitems == 0) {
@ -1433,33 +1432,40 @@ nvpair_create_nvlist_array(const char *name, const nvlist_t * const *value,
goto fail;
if (ii > 0) {
nvpair_t *nvp;
nvp = nvpair_allocv(" ", NV_TYPE_NVLIST,
(uint64_t)(uintptr_t)nvls[ii], 0, 0);
if (nvp == NULL)
if (nvp == NULL) {
ERRNO_SAVE();
nvlist_destroy(nvls[ii]);
ERRNO_RESTORE();
goto fail;
}
nvlist_set_array_next(nvls[ii - 1], nvp);
}
}
flags = nvlist_flags(nvls[nitems - 1]) | NV_FLAG_IN_ARRAY;
nvlist_set_flags(nvls[nitems - 1], flags);
nvp = nvpair_allocv(name, NV_TYPE_NVLIST_ARRAY,
parent = nvpair_allocv(name, NV_TYPE_NVLIST_ARRAY,
(uint64_t)(uintptr_t)nvls, 0, nitems);
if (parent == NULL)
goto fail;
for (ii = 0; ii < nitems; ii++)
nvlist_set_parent(nvls[ii], parent);
return (parent);
fail:
if (nvp == NULL) {
ERRNO_SAVE();
for (; ii > 0; ii--)
nvlist_destroy(nvls[ii - 1]);
ERRNO_SAVE();
for (; ii > 0; ii--)
nvlist_destroy(nvls[ii - 1]);
nv_free(nvls);
ERRNO_RESTORE();
nv_free(nvls);
ERRNO_RESTORE();
} else {
for (ii = 0; ii < nitems; ii++)
nvlist_set_parent(nvls[ii], nvp);
}
return (nvp);
return (NULL);
}
#ifndef _KERNEL