devinfo: fix memory leak on error paths

Refactor to create devinfo_free_dev().  Call it to plug a memory leak
on two error paths in devinfo_init_devices().

Reported by:	Coverity
MFC after:	2 weeks
Sponsored by:	Dell EMC Isilon
This commit is contained in:
Eric van Gyzen 2020-08-04 21:05:53 +00:00
parent b64dca2b6f
commit 32592d86df
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=363866

View File

@ -76,6 +76,7 @@ __FBSDID("$FreeBSD$");
static int devinfo_init_devices(int generation);
static int devinfo_init_resources(int generation);
static void devinfo_free_dev(struct devinfo_i_dev *dd);
TAILQ_HEAD(,devinfo_i_dev) devinfo_dev;
TAILQ_HEAD(,devinfo_i_rman) devinfo_rman;
@ -225,7 +226,7 @@ devinfo_init_devices(int generation)
rlen, sizeof(udev));
return (EINVAL);
}
if ((dd = malloc(sizeof(*dd))) == NULL)
if ((dd = calloc(1, sizeof(*dd))) == NULL)
return(ENOMEM);
dd->dd_dev.dd_handle = udev.dv_handle;
dd->dd_dev.dd_parent = udev.dv_parent;
@ -242,10 +243,14 @@ devinfo_init_devices(int generation)
dd->dd_location = NULL;
#define UNPACK(x) \
dd->dd_dev.x = dd->x = strdup(walker); \
if (dd->x == NULL) \
if (dd->x == NULL) { \
devinfo_free_dev(dd); \
return(ENOMEM); \
if (walker + strnlen(walker, ep - walker) >= ep) \
} \
if (walker + strnlen(walker, ep - walker) >= ep) { \
devinfo_free_dev(dd); \
return(EINVAL); \
} \
walker += strlen(walker) + 1;
UNPACK(dd_name);
@ -364,6 +369,20 @@ devinfo_init_resources(int generation)
return(0);
}
/*
* Free an individual dev.
*/
static void
devinfo_free_dev(struct devinfo_i_dev *dd)
{
free(dd->dd_name);
free(dd->dd_desc);
free(dd->dd_drivername);
free(dd->dd_pnpinfo);
free(dd->dd_location);
free(dd);
}
/*
* Free the list contents.
*/
@ -376,12 +395,7 @@ devinfo_free(void)
while ((dd = TAILQ_FIRST(&devinfo_dev)) != NULL) {
TAILQ_REMOVE(&devinfo_dev, dd, dd_link);
free(dd->dd_name);
free(dd->dd_desc);
free(dd->dd_drivername);
free(dd->dd_pnpinfo);
free(dd->dd_location);
free(dd);
devinfo_free_dev(dd);
}
while ((dm = TAILQ_FIRST(&devinfo_rman)) != NULL) {
TAILQ_REMOVE(&devinfo_rman, dm, dm_link);