On Sun, Apr 27, 2008 at 08:29:33PM +0100, Daniel P. Berrange wrote:
After updating the virBuffer APIs to protect against improper usage I
have
been thinking about how we might provider safer memory allocation APIs
with protection against common usage errors and compile time validation of
checks for failure.
Here is an updated version which removes the bogus VIR_REALLOC function
and illustrates use in capabilities.c which is a more interesting test
case than hash.c
proxy/Makefile.am | 1
src/capabilities.c | 121 +++++++++++++++++++++++------------------------------
src/hash.c | 113 +++++++++++++++++++++++--------------------------
src/internal.h | 7 ++-
src/memory.c | 117 +++++++++++++++++++++++++++++++++++++++++++++++++++
src/memory.h | 82 +++++++++++++++++++++++++++++++++++
6 files changed, 313 insertions(+), 128 deletions(-)
Dan.
Index: src/capabilities.c
===================================================================
RCS file: /data/cvs/libvirt/src/capabilities.c,v
retrieving revision 1.7
diff -u -p -r1.7 capabilities.c
--- src/capabilities.c 28 Apr 2008 15:14:59 -0000 1.7
+++ src/capabilities.c 28 Apr 2008 16:47:48 -0000
@@ -25,6 +25,7 @@
#include "capabilities.h"
#include "buf.h"
+#include "memory.h"
/**
@@ -42,7 +43,7 @@ virCapabilitiesNew(const char *arch,
{
virCapsPtr caps;
- if ((caps = calloc(1, sizeof(*caps))) == NULL)
+ if (VIR_ALLOC(caps) < 0)
goto no_memory;
if ((caps->host.arch = strdup(arch)) == NULL)
@@ -60,53 +61,53 @@ virCapabilitiesNew(const char *arch,
static void
virCapabilitiesFreeHostNUMACell(virCapsHostNUMACellPtr cell)
{
- free(cell->cpus);
- free(cell);
+ VIR_FREE(cell->cpus);
+ VIR_FREE(cell);
}
static void
virCapabilitiesFreeGuestDomain(virCapsGuestDomainPtr dom)
{
int i;
- free(dom->info.emulator);
- free(dom->info.loader);
+ VIR_FREE(dom->info.emulator);
+ VIR_FREE(dom->info.loader);
for (i = 0 ; i < dom->info.nmachines ; i++)
- free(dom->info.machines[i]);
- free(dom->info.machines);
- free(dom->type);
+ VIR_FREE(dom->info.machines[i]);
+ VIR_FREE(dom->info.machines);
+ VIR_FREE(dom->type);
- free(dom);
+ VIR_FREE(dom);
}
static void
virCapabilitiesFreeGuestFeature(virCapsGuestFeaturePtr feature)
{
- free(feature->name);
- free(feature);
+ VIR_FREE(feature->name);
+ VIR_FREE(feature);
}
static void
virCapabilitiesFreeGuest(virCapsGuestPtr guest)
{
int i;
- free(guest->ostype);
+ VIR_FREE(guest->ostype);
- free(guest->arch.name);
- free(guest->arch.defaultInfo.emulator);
- free(guest->arch.defaultInfo.loader);
+ VIR_FREE(guest->arch.name);
+ VIR_FREE(guest->arch.defaultInfo.emulator);
+ VIR_FREE(guest->arch.defaultInfo.loader);
for (i = 0 ; i < guest->arch.defaultInfo.nmachines ; i++)
- free(guest->arch.defaultInfo.machines[i]);
- free(guest->arch.defaultInfo.machines);
+ VIR_FREE(guest->arch.defaultInfo.machines[i]);
+ VIR_FREE(guest->arch.defaultInfo.machines);
for (i = 0 ; i < guest->arch.ndomains ; i++)
virCapabilitiesFreeGuestDomain(guest->arch.domains[i]);
- free(guest->arch.domains);
+ VIR_FREE(guest->arch.domains);
for (i = 0 ; i < guest->nfeatures ; i++)
virCapabilitiesFreeGuestFeature(guest->features[i]);
- free(guest->features);
+ VIR_FREE(guest->features);
- free(guest);
+ VIR_FREE(guest);
}
@@ -122,21 +123,21 @@ virCapabilitiesFree(virCapsPtr caps) {
for (i = 0 ; i < caps->nguests ; i++)
virCapabilitiesFreeGuest(caps->guests[i]);
- free(caps->guests);
+ VIR_FREE(caps->guests);
for (i = 0 ; i < caps->host.nfeatures ; i++)
- free(caps->host.features[i]);
- free(caps->host.features);
+ VIR_FREE(caps->host.features[i]);
+ VIR_FREE(caps->host.features);
for (i = 0 ; i < caps->host.nnumaCell ; i++)
virCapabilitiesFreeHostNUMACell(caps->host.numaCell[i]);
- free(caps->host.numaCell);
+ VIR_FREE(caps->host.numaCell);
for (i = 0 ; i < caps->host.nmigrateTrans ; i++)
- free(caps->host.migrateTrans[i]);
- free(caps->host.migrateTrans);
+ VIR_FREE(caps->host.migrateTrans[i]);
+ VIR_FREE(caps->host.migrateTrans);
- free(caps->host.arch);
- free(caps);
+ VIR_FREE(caps->host.arch);
+ VIR_FREE(caps);
}
@@ -151,12 +152,9 @@ int
virCapabilitiesAddHostFeature(virCapsPtr caps,
const char *name)
{
- char **features;
-
- if ((features = realloc(caps->host.features,
- sizeof(*features) * (caps->host.nfeatures+1))) == NULL)
+ if (VIR_REALLOC_N(caps->host.features,
+ caps->host.nfeatures + 1) < 0)
return -1;
- caps->host.features = features;
if ((caps->host.features[caps->host.nfeatures] = strdup(name)) == NULL)
return -1;
@@ -177,12 +175,9 @@ int
virCapabilitiesAddHostMigrateTransport(virCapsPtr caps,
const char *name)
{
- char **migrateTrans;
-
- if ((migrateTrans = realloc(caps->host.migrateTrans,
- sizeof(*migrateTrans) * (caps->host.nmigrateTrans+1)))
== NULL)
+ if (VIR_REALLOC_N(caps->host.migrateTrans,
+ caps->host.nmigrateTrans + 1) < 0)
return -1;
- caps->host.migrateTrans = migrateTrans;
if ((caps->host.migrateTrans[caps->host.nmigrateTrans] = strdup(name)) ==
NULL)
return -1;
@@ -208,19 +203,18 @@ virCapabilitiesAddHostNUMACell(virCapsPt
int ncpus,
const int *cpus)
{
- virCapsHostNUMACellPtr cell, *cells;
+ virCapsHostNUMACellPtr cell;
- if ((cells = realloc(caps->host.numaCell,
- sizeof(*cells) * (caps->host.nnumaCell+1))) == NULL)
+ if (VIR_REALLOC_N(caps->host.numaCell,
+ caps->host.nnumaCell + 1) < 0)
return -1;
- caps->host.numaCell = cells;
- if ((cell = calloc(1, sizeof(cell))) == NULL)
+ if (VIR_ALLOC(cell) < 0)
return -1;
caps->host.numaCell[caps->host.nnumaCell] = cell;
- if ((caps->host.numaCell[caps->host.nnumaCell]->cpus =
- malloc(ncpus * sizeof(*cpus))) == NULL)
+ if (VIR_ALLOC_N(caps->host.numaCell[caps->host.nnumaCell]->cpus,
+ ncpus) < 0)
return -1;
memcpy(caps->host.numaCell[caps->host.nnumaCell]->cpus,
cpus,
@@ -259,10 +253,10 @@ virCapabilitiesAddGuest(virCapsPtr caps,
int nmachines,
const char *const *machines)
{
- virCapsGuestPtr guest, *guests;
+ virCapsGuestPtr guest;
int i;
- if ((guest = calloc(1, sizeof(*guest))) == NULL)
+ if (VIR_ALLOC(guest) < 0)
goto no_memory;
if ((guest->ostype = strdup(ostype)) == NULL)
@@ -279,8 +273,8 @@ virCapabilitiesAddGuest(virCapsPtr caps,
(guest->arch.defaultInfo.loader = strdup(loader)) == NULL)
goto no_memory;
if (nmachines) {
- if ((guest->arch.defaultInfo.machines =
- calloc(nmachines, sizeof(*guest->arch.defaultInfo.machines))) == NULL)
+ if (VIR_ALLOC_N(guest->arch.defaultInfo.machines,
+ nmachines) < 0)
goto no_memory;
for (i = 0 ; i < nmachines ; i++) {
if ((guest->arch.defaultInfo.machines[i] = strdup(machines[i])) == NULL)
@@ -289,11 +283,9 @@ virCapabilitiesAddGuest(virCapsPtr caps,
}
}
- if ((guests = realloc(caps->guests,
- sizeof(*guests) *
- (caps->nguests + 1))) == NULL)
+ if (VIR_REALLOC_N(caps->guests,
+ caps->nguests + 1) < 0)
goto no_memory;
- caps->guests = guests;
caps->guests[caps->nguests] = guest;
caps->nguests++;
@@ -325,10 +317,10 @@ virCapabilitiesAddGuestDomain(virCapsGue
int nmachines,
const char *const *machines)
{
- virCapsGuestDomainPtr dom, *doms;
+ virCapsGuestDomainPtr dom;
int i;
- if ((dom = calloc(1, sizeof(*dom))) == NULL)
+ if (VIR_ALLOC(dom) < 0)
goto no_memory;
if ((dom->type = strdup(hvtype)) == NULL)
@@ -341,8 +333,7 @@ virCapabilitiesAddGuestDomain(virCapsGue
(dom->info.loader = strdup(loader)) == NULL)
goto no_memory;
if (nmachines) {
- if ((dom->info.machines =
- calloc(nmachines, sizeof(*dom->info.machines))) == NULL)
+ if (VIR_ALLOC_N(dom->info.machines, nmachines) < 0)
goto no_memory;
for (i = 0 ; i < nmachines ; i++) {
if ((dom->info.machines[i] = strdup(machines[i])) == NULL)
@@ -351,11 +342,9 @@ virCapabilitiesAddGuestDomain(virCapsGue
}
}
- if ((doms = realloc(guest->arch.domains,
- sizeof(*doms) *
- (guest->arch.ndomains + 1))) == NULL)
+ if (VIR_REALLOC_N(guest->arch.domains,
+ guest->arch.ndomains + 1) < 0)
goto no_memory;
- guest->arch.domains = doms;
guest->arch.domains[guest->arch.ndomains] = dom;
guest->arch.ndomains++;
@@ -383,9 +372,9 @@ virCapabilitiesAddGuestFeature(virCapsGu
int defaultOn,
int toggle)
{
- virCapsGuestFeaturePtr feature, *features;
+ virCapsGuestFeaturePtr feature;
- if ((feature = calloc(1, sizeof(*feature))) == NULL)
+ if (VIR_ALLOC(feature) < 0)
goto no_memory;
if ((feature->name = strdup(name)) == NULL)
@@ -393,11 +382,9 @@ virCapabilitiesAddGuestFeature(virCapsGu
feature->defaultOn = defaultOn;
feature->toggle = toggle;
- if ((features = realloc(guest->features,
- sizeof(*features) *
- (guest->nfeatures + 1))) == NULL)
+ if (VIR_REALLOC_N(guest->features,
+ guest->nfeatures + 1) < 0)
goto no_memory;
- guest->features = features;
guest->features[guest->nfeatures] = feature;
guest->nfeatures++;
Index: src/hash.c
===================================================================
RCS file: /data/cvs/libvirt/src/hash.c,v
retrieving revision 1.37
diff -u -p -r1.37 hash.c
--- src/hash.c 18 Apr 2008 08:33:23 -0000 1.37
+++ src/hash.c 28 Apr 2008 16:47:48 -0000
@@ -25,6 +25,7 @@
#include <libxml/threads.h>
#include "internal.h"
#include "hash.h"
+#include "memory.h"
#define MAX_HASH_LEN 8
@@ -85,22 +86,22 @@ virHashComputeKey(virHashTablePtr table,
virHashTablePtr
virHashCreate(int size)
{
- virHashTablePtr table;
+ virHashTablePtr table = NULL;
if (size <= 0)
size = 256;
- table = malloc(sizeof(*table));
- if (table) {
- table->size = size;
- table->nbElems = 0;
- table->table = calloc(1, size * sizeof(*(table->table)));
- if (table->table) {
- return (table);
- }
- free(table);
+ if (VIR_ALLOC(table) < 0)
+ return NULL;
+
+ table->size = size;
+ table->nbElems = 0;
+ if (VIR_ALLOC_N(table->table, size) < 0) {
+ VIR_FREE(table);
+ return NULL;
}
- return (NULL);
+
+ return table;
}
/**
@@ -136,8 +137,7 @@ virHashGrow(virHashTablePtr table, int s
if (oldtable == NULL)
return (-1);
- table->table = calloc(1, size * sizeof(*(table->table)));
- if (table->table == NULL) {
+ if (VIR_ALLOC_N(table->table, size) < 0) {
table->table = oldtable;
return (-1);
}
@@ -170,7 +170,7 @@ virHashGrow(virHashTablePtr table, int s
if (table->table[key].valid == 0) {
memcpy(&(table->table[key]), iter, sizeof(virHashEntry));
table->table[key].next = NULL;
- free(iter);
+ VIR_FREE(iter);
} else {
iter->next = table->table[key].next;
table->table[key].next = iter;
@@ -184,7 +184,7 @@ virHashGrow(virHashTablePtr table, int s
}
}
- free(oldtable);
+ VIR_FREE(oldtable);
#ifdef DEBUG_GROW
xmlGenericError(xmlGenericErrorContext,
@@ -225,19 +225,19 @@ virHashFree(virHashTablePtr table, virHa
next = iter->next;
if ((f != NULL) && (iter->payload != NULL))
f(iter->payload, iter->name);
- free(iter->name);
+ VIR_FREE(iter->name);
iter->payload = NULL;
if (!inside_table)
- free(iter);
+ VIR_FREE(iter);
nbElems--;
inside_table = 0;
iter = next;
}
inside_table = 0;
}
- free(table->table);
+ VIR_FREE(table->table);
}
- free(table);
+ VIR_FREE(table);
}
/**
@@ -281,8 +281,7 @@ virHashAddEntry(virHashTablePtr table, c
if (insert == NULL) {
entry = &(table->table[key]);
} else {
- entry = malloc(sizeof(*entry));
- if (entry == NULL)
+ if (VIR_ALLOC(entry) < 0)
return (-1);
}
@@ -354,8 +353,7 @@ virHashUpdateEntry(virHashTablePtr table
if (insert == NULL) {
entry = &(table->table[key]);
} else {
- entry = malloc(sizeof(*entry));
- if (entry == NULL)
+ if (VIR_ALLOC(entry) < 0)
return (-1);
}
@@ -451,10 +449,10 @@ virHashRemoveEntry(virHashTablePtr table
if ((f != NULL) && (entry->payload != NULL))
f(entry->payload, entry->name);
entry->payload = NULL;
- free(entry->name);
+ VIR_FREE(entry->name);
if (prev) {
prev->next = entry->next;
- free(entry);
+ VIR_FREE(entry);
} else {
if (entry->next == NULL) {
entry->valid = 0;
@@ -462,7 +460,7 @@ virHashRemoveEntry(virHashTablePtr table
entry = entry->next;
memcpy(&(table->table[key]), entry,
sizeof(virHashEntry));
- free(entry);
+ VIR_FREE(entry);
}
}
table->nbElems--;
@@ -535,11 +533,11 @@ int virHashRemoveSet(virHashTablePtr tab
if (iter(entry->payload, entry->name, data)) {
count++;
f(entry->payload, entry->name);
- free(entry->name);
+ VIR_FREE(entry->name);
table->nbElems--;
if (prev) {
prev->next = entry->next;
- free(entry);
+ VIR_FREE(entry);
entry = prev;
} else {
if (entry->next == NULL) {
@@ -549,7 +547,7 @@ int virHashRemoveSet(virHashTablePtr tab
entry = entry->next;
memcpy(&(table->table[i]), entry,
sizeof(virHashEntry));
- free(entry);
+ VIR_FREE(entry);
entry = &(table->table[i]);
continue;
}
@@ -689,8 +687,7 @@ virConnectPtr
virGetConnect(void) {
virConnectPtr ret;
- ret = calloc(1, sizeof(*ret));
- if (ret == NULL) {
+ if (VIR_ALLOC(ret) < 0) {
virHashError(NULL, VIR_ERR_NO_MEMORY, _("allocating connection"));
goto failed;
}
@@ -729,7 +726,7 @@ failed:
virHashFree(ret->storageVols, (virHashDeallocator)
virStorageVolFreeName);
pthread_mutex_destroy(&ret->lock);
- free(ret);
+ VIR_FREE(ret);
}
return(NULL);
}
@@ -759,11 +756,11 @@ virReleaseConnect(virConnectPtr conn) {
if (__lastErr.conn == conn)
__lastErr.conn = NULL;
- free(conn->name);
+ VIR_FREE(conn->name);
pthread_mutex_unlock(&conn->lock);
pthread_mutex_destroy(&conn->lock);
- free(conn);
+ VIR_FREE(conn);
}
/**
@@ -824,8 +821,7 @@ __virGetDomain(virConnectPtr conn, const
ret = (virDomainPtr) virHashLookup(conn->domains, name);
/* TODO check the UUID */
if (ret == NULL) {
- ret = (virDomainPtr) calloc(1, sizeof(*ret));
- if (ret == NULL) {
+ if (VIR_ALLOC(ret) < 0) {
virHashError(conn, VIR_ERR_NO_MEMORY, _("allocating domain"));
goto error;
}
@@ -854,8 +850,8 @@ __virGetDomain(virConnectPtr conn, const
error:
pthread_mutex_unlock(&conn->lock);
if (ret != NULL) {
- free(ret->name );
- free(ret);
+ VIR_FREE(ret->name);
+ VIR_FREE(ret);
}
return(NULL);
}
@@ -888,8 +884,8 @@ virReleaseDomain(virDomainPtr domain) {
__lastErr.dom = NULL;
domain->magic = -1;
domain->id = -1;
- free(domain->name);
- free(domain);
+ VIR_FREE(domain->name);
+ VIR_FREE(domain);
DEBUG("unref connection %p %s %d", conn, conn->name, conn->refs);
conn->refs--;
@@ -962,8 +958,7 @@ __virGetNetwork(virConnectPtr conn, cons
ret = (virNetworkPtr) virHashLookup(conn->networks, name);
/* TODO check the UUID */
if (ret == NULL) {
- ret = (virNetworkPtr) calloc(1, sizeof(*ret));
- if (ret == NULL) {
+ if (VIR_ALLOC(ret) < 0) {
virHashError(conn, VIR_ERR_NO_MEMORY, _("allocating network"));
goto error;
}
@@ -991,8 +986,8 @@ __virGetNetwork(virConnectPtr conn, cons
error:
pthread_mutex_unlock(&conn->lock);
if (ret != NULL) {
- free(ret->name );
- free(ret);
+ VIR_FREE(ret->name);
+ VIR_FREE(ret);
}
return(NULL);
}
@@ -1025,8 +1020,8 @@ virReleaseNetwork(virNetworkPtr network)
__lastErr.net = NULL;
network->magic = -1;
- free(network->name);
- free(network);
+ VIR_FREE(network->name);
+ VIR_FREE(network);
DEBUG("unref connection %p %s %d", conn, conn->name, conn->refs);
conn->refs--;
@@ -1100,8 +1095,7 @@ __virGetStoragePool(virConnectPtr conn,
ret = (virStoragePoolPtr) virHashLookup(conn->storagePools, name);
/* TODO check the UUID */
if (ret == NULL) {
- ret = (virStoragePoolPtr) calloc(1, sizeof(*ret));
- if (ret == NULL) {
+ if (VIR_ALLOC(ret) < 0) {
virHashError(conn, VIR_ERR_NO_MEMORY, _("allocating storage
pool"));
goto error;
}
@@ -1129,8 +1123,8 @@ __virGetStoragePool(virConnectPtr conn,
error:
pthread_mutex_unlock(&conn->lock);
if (ret != NULL) {
- free(ret->name);
- free(ret);
+ VIR_FREE(ret->name);
+ VIR_FREE(ret);
}
return(NULL);
}
@@ -1159,8 +1153,8 @@ virReleaseStoragePool(virStoragePoolPtr
_("pool missing from connection hash table"));
pool->magic = -1;
- free(pool->name);
- free(pool);
+ VIR_FREE(pool->name);
+ VIR_FREE(pool);
DEBUG("unref connection %p %s %d", conn, conn->name, conn->refs);
conn->refs--;
@@ -1232,8 +1226,7 @@ __virGetStorageVol(virConnectPtr conn, c
ret = (virStorageVolPtr) virHashLookup(conn->storageVols, key);
if (ret == NULL) {
- ret = (virStorageVolPtr) calloc(1, sizeof(*ret));
- if (ret == NULL) {
+ if (VIR_ALLOC(ret) < 0) {
virHashError(conn, VIR_ERR_NO_MEMORY, _("allocating storage
vol"));
goto error;
}
@@ -1266,9 +1259,9 @@ __virGetStorageVol(virConnectPtr conn, c
error:
pthread_mutex_unlock(&conn->lock);
if (ret != NULL) {
- free(ret->name);
- free(ret->pool);
- free(ret);
+ VIR_FREE(ret->name);
+ VIR_FREE(ret->pool);
+ VIR_FREE(ret);
}
return(NULL);
}
@@ -1297,9 +1290,9 @@ virReleaseStorageVol(virStorageVolPtr vo
_("vol missing from connection hash table"));
vol->magic = -1;
- free(vol->name);
- free(vol->pool);
- free(vol);
+ VIR_FREE(vol->name);
+ VIR_FREE(vol->pool);
+ VIR_FREE(vol);
DEBUG("unref connection %p %s %d", conn, conn->name, conn->refs);
conn->refs--;
Index: src/internal.h
===================================================================
RCS file: /data/cvs/libvirt/src/internal.h,v
retrieving revision 1.71
diff -u -p -r1.71 internal.h
--- src/internal.h 26 Apr 2008 14:22:02 -0000 1.71
+++ src/internal.h 28 Apr 2008 16:47:49 -0000
@@ -78,7 +78,7 @@ extern int debugFlag;
#define VIR_DEBUG(category, fmt,...) \
do { if (debugFlag) fprintf (stderr, "DEBUG: %s: %s (" fmt ")\n",
category, __func__, __VA_ARGS__); } while (0)
#else
-#define VIR_DEBUG(category, fmt,...)
+#define VIR_DEBUG(category, fmt,...) \
do { } while (0)
#endif /* !ENABLE_DEBUG */
@@ -107,9 +107,14 @@ extern int debugFlag;
#define ATTRIBUTE_FORMAT(args...) __attribute__((__format__ (args)))
#endif
+#ifndef ATTRIBUTE_RETURN_CHECK
+#define ATTRIBUTE_RETURN_CHECK __attribute__((__warn_unused_result__))
+#endif
+
#else
#define ATTRIBUTE_UNUSED
#define ATTRIBUTE_FORMAT(...)
+#define ATTRIBUTE_RETURN_CHECK
#endif /* __GNUC__ */
/**
Index: src/memory.c
===================================================================
RCS file: src/memory.c
diff -N src/memory.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ src/memory.c 28 Apr 2008 16:47:49 -0000
@@ -0,0 +1,117 @@
+/*
+ * memory.c: safer memory allocation
+ *
+ * Copyright (C) 2008 Daniel P. Berrange
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include <stdlib.h>
+
+#include "memory.h"
+
+/**
+ * virAlloc:
+ * @ptrptr: pointer to pointer for address of allocated memory
+ * @size: number of bytes to allocate
+ *
+ * Allocate 'size' bytes of memory. Return the address of the
+ * allocated memory in 'ptrptr'. The newly allocated memory is
+ * filled with zeros.
+ *
+ * Returns -1 on failure to allocate, zero on success
+ */
+int virAlloc(void *ptrptr, size_t size)
+{
+ if (size == 0) {
+ *(void **)ptrptr = NULL;
+ return 0;
+ }
+
+ *(void **)ptrptr = calloc(1, size);
+ if (*(void **)ptrptr == NULL)
+ return -1;
+ return 0;
+}
+
+/**
+ * virAllocN:
+ * @ptrptr: pointer to pointer for address of allocated memory
+ * @size: number of bytes to allocate
+ * @count: number of elements to allocate
+ *
+ * Allocate an array of memory 'count' elements long,
+ * each with 'size' bytes. Return the address of the
+ * allocated memory in 'ptrptr'. The newly allocated
+ * memory is filled with zeros.
+ *
+ * Returns -1 on failure to allocate, zero on success
+ */
+int virAllocN(void *ptrptr, size_t size, size_t count)
+{
+ if (size == 0 || count == 0) {
+ *(void **)ptrptr = NULL;
+ return 0;
+ }
+
+ *(void**)ptrptr = calloc(count, size);
+ if (*(void**)ptrptr == NULL)
+ return -1;
+ return 0;
+}
+
+/**
+ * virReallocN:
+ * @ptrptr: pointer to pointer for address of allocated memory
+ * @size: number of bytes to allocate
+ * @count: number of elements in array
+ *
+ * Resize the block of memory in 'ptrptr' to be an array of
+ * 'count' elements, each 'size' bytes in length. Update
'ptrptr'
+ * with the address of the newly allocated memory. On failure,
+ * 'ptrptr' is not changed and still points to the original memory
+ * block. The newly allocated memory is filled with zeros.
+ *
+ * Returns -1 on failure to allocate, zero on success
+ */
+int virReallocN(void *ptrptr, size_t size, size_t count)
+{
+ void *tmp;
+ if (size == 0 || count == 0) {
+ free(*(void **)ptrptr);
+ *(void **)ptrptr = NULL;
+ return 0;
+ }
+ tmp = realloc(*(void**)ptrptr, size * count);
+ if (!tmp)
+ return -1;
+ *(void**)ptrptr = tmp;
+ return 0;
+}
+
+/**
+ * virFree:
+ * @ptrptr: pointer to pointer for address of memory to be freed
+ *
+ * Release the chunk of memory in the pointer pointed to by
+ * the 'ptrptr' variable. After release, 'ptrptr' will be
+ * updated to point to NULL.
+ */
+void virFree(void *ptrptr)
+{
+ free(*(void**)ptrptr);
+ *(void**)ptrptr = NULL;
+}
Index: src/memory.h
===================================================================
RCS file: src/memory.h
diff -N src/memory.h
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ src/memory.h 28 Apr 2008 16:47:49 -0000
@@ -0,0 +1,82 @@
+/*
+ * memory.c: safer memory allocation
+ *
+ * Copyright (C) 2008 Daniel P. Berrange
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+
+#ifndef __VIR_MEMORY_H_
+#define __VIR_MEMORY_H_
+
+#include "internal.h"
+
+/* Don't call these directly - use the macros below */
+int virAlloc(void *ptrptr, size_t size) ATTRIBUTE_RETURN_CHECK;
+int virAllocN(void *ptrptr, size_t size, size_t count) ATTRIBUTE_RETURN_CHECK;
+int virReallocN(void *ptrptr, size_t size, size_t count) ATTRIBUTE_RETURN_CHECK;
+void virFree(void *ptrptr);
+
+
+/**
+ * VIR_ALLOC:
+ * @ptr: pointer to hold address of allocated memory
+ *
+ * Allocate sizeof(*ptr) bytes of memory and store
+ * the address of allocated memory in 'ptr'. Fill the
+ * newly allocated memory with zeros.
+ *
+ * Returns -1 on failure, 0 on success
+ */
+#define VIR_ALLOC(ptr) virAlloc(&(ptr), sizeof(*(ptr)))
+
+/**
+ * VIR_ALLOC_N:
+ * @ptr: pointer to hold address of allocated memory
+ * @count: number of elements to allocate
+ *
+ * Allocate an array of 'count' elements, each sizeof(*ptr)
+ * bytes long and store the address of allocated memory in
+ * 'ptr'. Fill the newly allocated memory with zeros.
+ *
+ * Returns -1 on failure, 0 on success
+ */
+#define VIR_ALLOC_N(ptr, count) virAllocN(&(ptr), sizeof(*(ptr)), (count))
+
+/**
+ * VIR_REALLOC_N:
+ * @ptr: pointer to hold address of allocated memory
+ * @count: number of elements to allocate
+ *
+ * Re-allocate an array of 'count' elements, each sizeof(*ptr)
+ * bytes long and store the address of allocated memory in
+ * 'ptr'. Fill the newly allocated memory with zeros
+ *
+ * Returns -1 on failure, 0 on success
+ */
+#define VIR_REALLOC_N(ptr, count) virReallocN(&(ptr), sizeof(*(ptr)), (count))
+
+/**
+ * VIR_FREE:
+ * @ptr: pointer holding address to be freed
+ *
+ * Free the memory stored in 'ptr' and update to point
+ * to NULL.
+ */
+#define VIR_FREE(ptr) virFree(&(ptr));
+
+#endif /* __VIR_MEMORY_H_ */
Index: proxy/Makefile.am
===================================================================
RCS file: /data/cvs/libvirt/proxy/Makefile.am,v
retrieving revision 1.16
diff -u -p -r1.16 Makefile.am
--- proxy/Makefile.am 27 Feb 2008 04:35:08 -0000 1.16
+++ proxy/Makefile.am 28 Apr 2008 16:47:49 -0000
@@ -14,6 +14,7 @@ libvirt_proxy_SOURCES = libvirt_proxy.c
@top_srcdir(a)/src/sexpr.c @top_srcdir(a)/src/xml.c \
@top_srcdir(a)/src/xs_internal.c @top_srcdir(a)/src/buf.c \
@top_srcdir(a)/src/capabilities.c \
+ @top_srcdir(a)/src/memory.c \
@top_srcdir(a)/src/util.c \
@top_srcdir(a)/src/uuid.c
libvirt_proxy_LDFLAGS = $(WARN_CFLAGS)
--
|: Red Hat, Engineering, Boston -o-
http://people.redhat.com/berrange/ :|
|:
http://libvirt.org -o-
http://virt-manager.org -o-
http://ovirt.org :|
|:
http://autobuild.org -o-
http://search.cpan.org/~danberr/ :|
|: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|