- Simplify the procedure of retrieving XML-data from the kernel.

- Fix a number of potential memory leaks in libgeom related to doing realloc
  without freeing old pointer if things go wrong.
- Fix a number of places in libgeom where malloc and calloc return values
  were not checked.
- Check malloc return value and provide sufficient warning messages when XML
  parsing fails.

PR:		kern/83464
Submitted by:	Dan Lukes <dan - at - obluda.cz>
Approved by:	kib (mentor)
This commit is contained in:
lulf 2008-07-08 17:34:50 +00:00
parent e31c8aa8e5
commit 1547b99716
3 changed files with 67 additions and 28 deletions

View File

@ -45,6 +45,12 @@
#define GCTL_TABLE 1
#include <libgeom.h>
/*
* Global pointer to a string that is used to avoid an errorneous free in
* gctl_free.
*/
static char nomemmsg[] = "Could not allocate memory";
void
gctl_dump(struct gctl_req *req, FILE *f)
{
@ -105,11 +111,12 @@ gctl_set_error(struct gctl_req *req, const char *error, ...)
static void
gctl_check_alloc(struct gctl_req *req, void *ptr)
{
if (ptr != NULL)
return;
gctl_set_error(req, "Could not allocate memory");
gctl_set_error(req, nomemmsg);
if (req->error == NULL)
req->error = "Could not allocate memory";
req->error = nomemmsg;
}
/*
@ -134,7 +141,7 @@ gctl_new_arg(struct gctl_req *req)
struct gctl_req_arg *ap;
req->narg++;
req->arg = realloc(req->arg, sizeof *ap * req->narg);
req->arg = reallocf(req->arg, sizeof *ap * req->narg);
gctl_check_alloc(req, req->arg);
if (req->arg == NULL) {
req->narg = 0;
@ -157,6 +164,8 @@ gctl_ro_param(struct gctl_req *req, const char *name, int len, const void* value
return;
ap->name = strdup(name);
gctl_check_alloc(req, ap->name);
if (ap->name == NULL)
return;
ap->nlen = strlen(ap->name) + 1;
ap->value = __DECONST(void *, value);
ap->flag = GCTL_PARAM_RD;
@ -180,6 +189,8 @@ gctl_rw_param(struct gctl_req *req, const char *name, int len, void* value)
return;
ap->name = strdup(name);
gctl_check_alloc(req, ap->name);
if (ap->name == NULL)
return;
ap->nlen = strlen(ap->name) + 1;
ap->value = value;
ap->flag = GCTL_PARAM_RW;
@ -201,12 +212,11 @@ gctl_issue(struct gctl_req *req)
req->version = GCTL_VERSION;
req->lerror = BUFSIZ; /* XXX: arbitrary number */
req->error = malloc(req->lerror);
req->error = calloc(1, req->lerror);
if (req->error == NULL) {
gctl_check_alloc(req, req->error);
return (req->error);
}
memset(req->error, 0, req->lerror);
req->lerror--;
fd = open(_PATH_DEV PATH_GEOM_CTL, O_RDONLY);
if (fd < 0)
@ -232,7 +242,7 @@ gctl_free(struct gctl_req *req)
free(req->arg[i].name);
}
free(req->arg);
if (req->error != NULL)
if (req->error != NULL && req->error != nomemmsg)
free(req->error);
free(req);
}

View File

@ -39,28 +39,22 @@ char *
geom_getxml()
{
char *p;
size_t l;
int i;
size_t l = 0;
int mib[3];
size_t sizep;
l = 1024 * 1024; /* Start big, realloc back */
p = malloc(l);
if (p) {
i = sysctlbyname("kern.geom.confxml", p, &l, NULL, 0);
if (i == 0) {
p = realloc(p, strlen(p) + 1);
return (p);
}
free(p);
}
l = 0;
i = sysctlbyname("kern.geom.confxml", NULL, &l, NULL, 0);
if (i != 0)
sizep = sizeof(mib) / sizeof(*mib);
if (sysctlnametomib("kern.geom.confxml", mib, &sizep) != 0)
return (NULL);
if (sysctl(mib, sizep, NULL, &l, NULL, 0) != 0)
return (NULL);
l += 4096;
p = malloc(l);
if (p == NULL)
return (NULL);
if (sysctl(mib, sizep, p, &l, NULL, 0) != 0) {
free(p);
return (NULL);
p = malloc(l + 4096);
i = sysctlbyname("kern.geom.confxml", p, &l, NULL, 0);
if (i == 0) {
p = realloc(p, strlen(p) + 1);
return (p);
}
return (NULL);
return (reallocf(p, strlen(p) + 1));
}

View File

@ -84,6 +84,11 @@ StartElement(void *userData, const char *name, const char **attr)
}
if (!strcmp(name, "class") && mt->class == NULL) {
mt->class = calloc(1, sizeof *mt->class);
if (mt->class == NULL) {
warn("Cannot allocate memory during processing of '%s' "
"element", name);
return;
}
mt->class->lg_id = id;
LIST_INSERT_HEAD(&mt->mesh->lg_class, mt->class, lg_class);
LIST_INIT(&mt->class->lg_geom);
@ -92,6 +97,11 @@ StartElement(void *userData, const char *name, const char **attr)
}
if (!strcmp(name, "geom") && mt->geom == NULL) {
mt->geom = calloc(1, sizeof *mt->geom);
if (mt->geom == NULL) {
warn("Cannot allocate memory during processing of '%s' "
"element", name);
return;
}
mt->geom->lg_id = id;
LIST_INSERT_HEAD(&mt->class->lg_geom, mt->geom, lg_geom);
LIST_INIT(&mt->geom->lg_provider);
@ -105,6 +115,11 @@ StartElement(void *userData, const char *name, const char **attr)
}
if (!strcmp(name, "consumer") && mt->consumer == NULL) {
mt->consumer = calloc(1, sizeof *mt->consumer);
if (mt->consumer == NULL) {
warn("Cannot allocate memory during processing of '%s' "
"element", name);
return;
}
mt->consumer->lg_id = id;
LIST_INSERT_HEAD(&mt->geom->lg_consumer, mt->consumer,
lg_consumer);
@ -121,6 +136,11 @@ StartElement(void *userData, const char *name, const char **attr)
}
if (!strcmp(name, "provider") && mt->provider == NULL) {
mt->provider = calloc(1, sizeof *mt->provider);
if (mt->provider == NULL) {
warn("Cannot allocate memory during processing of '%s' "
"element", name);
return;
}
mt->provider->lg_id = id;
LIST_INSERT_HEAD(&mt->geom->lg_provider, mt->provider,
lg_provider);
@ -162,6 +182,11 @@ EndElement(void *userData, const char *name)
mt = userData;
sbuf_finish(mt->sbuf[mt->level]);
p = strdup(sbuf_data(mt->sbuf[mt->level]));
if (p == NULL) {
warn("Cannot allocate memory during processing of '%s' "
"element", name);
return;
}
sbuf_delete(mt->sbuf[mt->level]);
mt->sbuf[mt->level] = NULL;
mt->level--;
@ -212,8 +237,18 @@ EndElement(void *userData, const char *name)
}
if (mt->config != NULL) {
gc = calloc(sizeof *gc, 1);
gc = calloc(1, sizeof *gc);
if (gc == NULL) {
warn("Cannot allocate memory during processing of '%s' "
"element", name);
return;
}
gc->lg_name = strdup(name);
if (gc->lg_name == NULL) {
warn("Cannot allocate memory during processing of '%s' "
"element", name);
return;
}
gc->lg_val = p;
LIST_INSERT_HEAD(mt->config, gc, lg_config);
return;