Fail cleanly on allocation failures
Previously code in the SWIG tool didn't handle allocation failures well. Most places didn't check for NULL return from malloc()/realloc()/calloc() at all, typically resulting in undefined behaviour, and some places used assert() to check for a NULL return (which is a misuse of assert() and such checks disappear if built with NDEBUG defined leaving us back with undefined behaviour). All C allocations are now done via wrapper functions (Malloc(), Realloc() and Calloc()) which emit and error and exit with non-zero status on failure, so a non-NULL return can be relied upon. Fixes #1901.
This commit is contained in:
parent
9eb75a0c07
commit
e38847f7e1
14 changed files with 83 additions and 65 deletions
|
|
@ -122,6 +122,10 @@
|
|||
#define DohIterator DOH_NAMESPACE(Iterator)
|
||||
#define DohFirst DOH_NAMESPACE(First)
|
||||
#define DohNext DOH_NAMESPACE(Next)
|
||||
#define DohMalloc DOH_NAMESPACE(Malloc)
|
||||
#define DohRealloc DOH_NAMESPACE(Realloc)
|
||||
#define DohCalloc DOH_NAMESPACE(Calloc)
|
||||
#define DohFree DOH_NAMESPACE(Free)
|
||||
#endif
|
||||
|
||||
#define DOH_MAJOR_VERSION 0
|
||||
|
|
@ -163,12 +167,11 @@ typedef struct {
|
|||
|
||||
/* Memory management */
|
||||
|
||||
#ifndef DohMalloc
|
||||
#define DohMalloc malloc
|
||||
#endif
|
||||
#ifndef DohRealloc
|
||||
#define DohRealloc realloc
|
||||
#endif
|
||||
/* Wrappers around malloc(), realloc() and calloc() which never return NULL. */
|
||||
extern void *DohMalloc(size_t size);
|
||||
extern void *DohRealloc(void *ptr, size_t size);
|
||||
extern void *DohCalloc(size_t n, size_t size);
|
||||
|
||||
#ifndef DohFree
|
||||
#define DohFree free
|
||||
#endif
|
||||
|
|
@ -440,6 +443,10 @@ extern void DohMemoryDebug(void);
|
|||
#define Next DohNext
|
||||
#define Iterator DohIterator
|
||||
#define SortList DohSortList
|
||||
#define Malloc DohMalloc
|
||||
#define Realloc DohRealloc
|
||||
#define Calloc DohCalloc
|
||||
#define Free DohFree
|
||||
#endif
|
||||
|
||||
#ifdef NIL
|
||||
|
|
|
|||
|
|
@ -291,10 +291,6 @@ DOH *DohNewFile(DOHString *filename, const char *mode, DOHList *newfiles) {
|
|||
return 0;
|
||||
|
||||
f = (DohFile *) DohMalloc(sizeof(DohFile));
|
||||
if (!f) {
|
||||
fclose(file);
|
||||
return 0;
|
||||
}
|
||||
if (newfiles)
|
||||
Append(newfiles, filename);
|
||||
f->filep = file;
|
||||
|
|
@ -314,8 +310,6 @@ DOH *DohNewFile(DOHString *filename, const char *mode, DOHList *newfiles) {
|
|||
DOH *DohNewFileFromFile(FILE *file) {
|
||||
DohFile *f;
|
||||
f = (DohFile *) DohMalloc(sizeof(DohFile));
|
||||
if (!f)
|
||||
return 0;
|
||||
f->filep = file;
|
||||
f->fd = 0;
|
||||
f->closeondel = 0;
|
||||
|
|
@ -331,8 +325,6 @@ DOH *DohNewFileFromFile(FILE *file) {
|
|||
DOH *DohNewFileFromFd(int fd) {
|
||||
DohFile *f;
|
||||
f = (DohFile *) DohMalloc(sizeof(DohFile));
|
||||
if (!f)
|
||||
return 0;
|
||||
f->filep = 0;
|
||||
f->fd = fd;
|
||||
f->closeondel = 0;
|
||||
|
|
|
|||
|
|
@ -173,10 +173,7 @@ static void resize(Hash *h) {
|
|||
p = p + 2;
|
||||
}
|
||||
|
||||
table = (HashNode **) DohMalloc(newsize * sizeof(HashNode *));
|
||||
for (i = 0; i < newsize; i++) {
|
||||
table[i] = 0;
|
||||
}
|
||||
table = (HashNode **) DohCalloc(newsize, sizeof(HashNode *));
|
||||
|
||||
/* Walk down the old set of nodes and re-place */
|
||||
h->hashsize = newsize;
|
||||
|
|
|
|||
|
|
@ -27,7 +27,6 @@ extern DohObjInfo DohListType;
|
|||
static
|
||||
void more(List *l) {
|
||||
l->items = (void **) DohRealloc(l->items, l->maxitems * 2 * sizeof(void *));
|
||||
assert(l->items);
|
||||
l->maxitems *= 2;
|
||||
}
|
||||
|
||||
|
|
@ -346,15 +345,10 @@ DohObjInfo DohListType = {
|
|||
#define MAXLISTITEMS 8
|
||||
|
||||
DOH *DohNewList(void) {
|
||||
List *l;
|
||||
int i;
|
||||
l = (List *) DohMalloc(sizeof(List));
|
||||
List *l = (List *) DohMalloc(sizeof(List));
|
||||
l->nitems = 0;
|
||||
l->maxitems = MAXLISTITEMS;
|
||||
l->items = (void **) DohMalloc(l->maxitems * sizeof(void *));
|
||||
for (i = 0; i < MAXLISTITEMS; i++) {
|
||||
l->items[i] = 0;
|
||||
}
|
||||
l->items = (void **) DohCalloc(l->maxitems, sizeof(void *));
|
||||
l->file = 0;
|
||||
l->line = 0;
|
||||
return DohObjMalloc(&DohListType, l);
|
||||
|
|
|
|||
|
|
@ -14,6 +14,9 @@
|
|||
|
||||
#include "dohint.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifndef DOH_POOL_SIZE
|
||||
#define DOH_POOL_SIZE 4194304
|
||||
#endif
|
||||
|
|
@ -48,10 +51,7 @@ static int pools_initialized = 0;
|
|||
static void CreatePool() {
|
||||
Pool *p = 0;
|
||||
p = (Pool *) DohMalloc(sizeof(Pool));
|
||||
assert(p);
|
||||
p->ptr = (DohBase *) DohMalloc(sizeof(DohBase) * PoolSize);
|
||||
assert(p->ptr);
|
||||
memset(p->ptr, 0, sizeof(DohBase) * PoolSize);
|
||||
p->ptr = (DohBase *) DohCalloc(PoolSize, sizeof(DohBase));
|
||||
p->len = PoolSize;
|
||||
p->blen = PoolSize * sizeof(DohBase);
|
||||
p->current = 0;
|
||||
|
|
@ -234,3 +234,40 @@ void DohMemoryDebug(void) {
|
|||
#endif
|
||||
|
||||
}
|
||||
|
||||
static void allocation_failed(size_t n, size_t size) {
|
||||
/* Report and exit as directly as possible to try to avoid further issues due
|
||||
* to lack of memory. */
|
||||
if (n == 1) {
|
||||
#if defined __STDC_VERSION__ && __STDC_VERSION__-0 >= 19901L
|
||||
fprintf(stderr, "Failed to allocate %zu bytes\n", size);
|
||||
#else
|
||||
fprintf(stderr, "Failed to allocate %lu bytes\n", (unsigned long)size);
|
||||
#endif
|
||||
} else {
|
||||
#if defined __STDC_VERSION__ && __STDC_VERSION__-0 >= 19901L
|
||||
fprintf(stderr, "Failed to allocate %zu*%zu bytes\n", n, size);
|
||||
#else
|
||||
fprintf(stderr, "Failed to allocate %lu*%lu bytes\n", (unsigned long)n, (unsigned long)size);
|
||||
#endif
|
||||
}
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
void *DohMalloc(size_t size) {
|
||||
void *p = malloc(size);
|
||||
if (!p) allocation_failed(1, size);
|
||||
return p;
|
||||
}
|
||||
|
||||
void *DohRealloc(void *ptr, size_t size) {
|
||||
void *p = realloc(ptr, size);
|
||||
if (!p) allocation_failed(1, size);
|
||||
return p;
|
||||
}
|
||||
|
||||
void *DohCalloc(size_t n, size_t size) {
|
||||
void *p = calloc(n, size);
|
||||
if (!p) allocation_failed(n, size);
|
||||
return p;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -229,7 +229,6 @@ static void DohString_append(DOH *so, const DOHString_or_char *str) {
|
|||
if (newlen >= newmaxsize - 1)
|
||||
newmaxsize = newlen + 1;
|
||||
s->str = (char *) DohRealloc(s->str, newmaxsize);
|
||||
assert(s->str);
|
||||
s->maxsize = newmaxsize;
|
||||
}
|
||||
tc = s->str;
|
||||
|
|
@ -296,7 +295,6 @@ static int String_insert(DOH *so, int pos, DOH *str) {
|
|||
while (s->maxsize <= s->len + len) {
|
||||
int newsize = 2 * s->maxsize;
|
||||
s->str = (char *) DohRealloc(s->str, newsize);
|
||||
assert(s->str);
|
||||
s->maxsize = newsize;
|
||||
}
|
||||
memmove(s->str + pos + len, s->str + pos, (s->len - pos));
|
||||
|
|
@ -424,7 +422,6 @@ static int String_write(DOH *so, const void *buffer, int len) {
|
|||
newlen = s->sp + len + 1;
|
||||
if (newlen > s->maxsize) {
|
||||
s->str = (char *) DohRealloc(s->str, newlen);
|
||||
assert(s->str);
|
||||
s->maxsize = newlen;
|
||||
s->len = s->sp + len;
|
||||
}
|
||||
|
|
@ -517,7 +514,6 @@ static int String_putc(DOH *so, int ch) {
|
|||
if (len > (maxsize - 2)) {
|
||||
maxsize *= 2;
|
||||
tc = (char *) DohRealloc(tc, maxsize);
|
||||
assert(tc);
|
||||
s->maxsize = (int) maxsize;
|
||||
s->str = tc;
|
||||
}
|
||||
|
|
@ -923,7 +919,6 @@ static int replace_simple(String *str, char *token, char *rep, int flags, int co
|
|||
newsize *= 2;
|
||||
|
||||
ns = (char *) DohMalloc(newsize);
|
||||
assert(ns);
|
||||
t = ns;
|
||||
s = first;
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue