diff options
Diffstat (limited to 'nsswitch/libwbclient/wbclient.c')
-rw-r--r-- | nsswitch/libwbclient/wbclient.c | 53 |
1 files changed, 51 insertions, 2 deletions
diff --git a/nsswitch/libwbclient/wbclient.c b/nsswitch/libwbclient/wbclient.c index cd5ffa876a..6b076ad499 100644 --- a/nsswitch/libwbclient/wbclient.c +++ b/nsswitch/libwbclient/wbclient.c @@ -147,12 +147,61 @@ const char *wbcErrorString(wbcErr error) return "unknown wbcErr value"; } +#define WBC_MAGIC (0x7a2b0e1e) + +struct wbcMemPrefix { + uint32_t magic; + void (*destructor)(void *ptr); +}; + +static size_t wbcPrefixLen(void) +{ + size_t result = sizeof(struct wbcMemPrefix); + return (result + 15) & ~15; +} + +static struct wbcMemPrefix *wbcMemToPrefix(void *ptr) +{ + return (struct wbcMemPrefix *)(((char *)ptr) - wbcPrefixLen()); +} + +void *wbcAllocateMemory(size_t nelem, size_t elsize, + void (*destructor)(void *ptr)) +{ + struct wbcMemPrefix *result; + + if (nelem >= (2<<24)/elsize) { + /* basic protection against integer wrap */ + return NULL; + } + + result = (struct wbcMemPrefix *)calloc( + 1, nelem*elsize + wbcPrefixLen()); + if (result == NULL) { + return NULL; + } + result->magic = WBC_MAGIC; + result->destructor = destructor; + return ((char *)result) + wbcPrefixLen(); +} + /* Free library allocated memory */ void wbcFreeMemory(void *p) { - if (p) - talloc_free(p); + struct wbcMemPrefix *wbcMem; + if (p == NULL) { + return; + } + wbcMem = wbcMemToPrefix(p); + if (wbcMem->magic != WBC_MAGIC) { + talloc_free(p); + return; + } + if (wbcMem->destructor != NULL) { + wbcMem->destructor(p); + } + free(wbcMem); return; } |