From dfa17bf9673082e658d50369c2a292380cc08a5d Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Fri, 4 May 2018 17:45:20 -0400 Subject: [PATCH] Always return a non-NULL pointer for malloc(0). Some C runtimes, like musl, will return NULL in this case. It's more convenient to not get a NULL (which is meant to be interpreted as a failure), but instead get a non-NULL pointer that can't be dereferenced (because it's a pointer to zero bytes of memory). --- mojoshader.c | 6 ++++-- mojoshader_assembler.c | 6 ++++-- mojoshader_compiler.c | 6 ++++-- mojoshader_opengl.c | 5 +++-- mojoshader_preprocessor.c | 6 ++++-- 5 files changed, 19 insertions(+), 10 deletions(-) diff --git a/mojoshader.c b/mojoshader.c index 255d68a6..36294923 100644 --- a/mojoshader.c +++ b/mojoshader.c @@ -307,9 +307,10 @@ static inline void out_of_memory(Context *ctx) ctx->isfail = ctx->out_of_memory = 1; } // out_of_memory +static char zeromalloc = 0; static inline void *Malloc(Context *ctx, const size_t len) { - void *retval = ctx->malloc((int) len, ctx->malloc_data); + void *retval = (len == 0) ? &zeromalloc : ctx->malloc((int) len, ctx->malloc_data); if (retval == NULL) out_of_memory(ctx); return retval; @@ -325,7 +326,8 @@ static inline char *StrDup(Context *ctx, const char *str) static inline void Free(Context *ctx, void *ptr) { - ctx->free(ptr, ctx->malloc_data); + if ((ptr != &zeromalloc) && (ptr != NULL)) + ctx->free(ptr, ctx->malloc_data); } // Free static void * MOJOSHADERCALL MallocBridge(int bytes, void *data) diff --git a/mojoshader_assembler.c b/mojoshader_assembler.c index c9148410..0621af85 100644 --- a/mojoshader_assembler.c +++ b/mojoshader_assembler.c @@ -72,9 +72,10 @@ static inline void out_of_memory(Context *ctx) ctx->isfail = ctx->out_of_memory = 1; } // out_of_memory +static char zeromalloc = 0; static inline void *Malloc(Context *ctx, const size_t len) { - void *retval = ctx->malloc((int) len, ctx->malloc_data); + void *retval = (len == 0) ? &zeromalloc : ctx->malloc((int) len, ctx->malloc_data); if (retval == NULL) out_of_memory(ctx); return retval; @@ -90,7 +91,8 @@ static inline char *StrDup(Context *ctx, const char *str) static inline void Free(Context *ctx, void *ptr) { - ctx->free(ptr, ctx->malloc_data); + if ((ptr != &zeromalloc) && (ptr != NULL)) + ctx->free(ptr, ctx->malloc_data); } // Free static void *MallocBridge(int bytes, void *data) diff --git a/mojoshader_compiler.c b/mojoshader_compiler.c index 3e49ff64..012997cb 100644 --- a/mojoshader_compiler.c +++ b/mojoshader_compiler.c @@ -160,9 +160,10 @@ static inline void out_of_memory(Context *ctx) ctx->isfail = ctx->out_of_memory = 1; } // out_of_memory +static char zeromalloc = 0; static inline void *Malloc(Context *ctx, const size_t len) { - void *retval = ctx->malloc((int) len, ctx->malloc_data); + void *retval = (len == 0) ? &zeromalloc : ctx->malloc((int) len, ctx->malloc_data); if (retval == NULL) out_of_memory(ctx); return retval; @@ -178,7 +179,8 @@ static inline char *StrDup(Context *ctx, const char *str) static inline void Free(Context *ctx, void *ptr) { - ctx->free(ptr, ctx->malloc_data); + if ((ptr != &zeromalloc) && (ptr != NULL)) + ctx->free(ptr, ctx->malloc_data); } // Free static void *MallocBridge(int bytes, void *data) diff --git a/mojoshader_opengl.c b/mojoshader_opengl.c index 08b9773f..2e88e358 100644 --- a/mojoshader_opengl.c +++ b/mojoshader_opengl.c @@ -347,9 +347,10 @@ static inline void out_of_memory(void) set_error("out of memory"); } // out_of_memory +static char zeromalloc = 0; static inline void *Malloc(const size_t len) { - void *retval = ctx->malloc_fn((int) len, ctx->malloc_data); + void *retval = (len == 0) ? &zeromalloc : ctx->malloc_fn((int) len, ctx->malloc_data); if (retval == NULL) out_of_memory(); return retval; @@ -357,7 +358,7 @@ static inline void *Malloc(const size_t len) static inline void Free(void *ptr) { - if (ptr != NULL) + if ((ptr != &zeromalloc) && (ptr != NULL)) ctx->free_fn(ptr, ctx->malloc_data); } // Free diff --git a/mojoshader_preprocessor.c b/mojoshader_preprocessor.c index 5b5090ba..664b530e 100644 --- a/mojoshader_preprocessor.c +++ b/mojoshader_preprocessor.c @@ -68,9 +68,10 @@ static inline void out_of_memory(Context *ctx) ctx->out_of_memory = 1; } // out_of_memory +static char zeromalloc = 0; static inline void *Malloc(Context *ctx, const size_t len) { - void *retval = ctx->malloc((int) len, ctx->malloc_data); + void *retval = (len == 0) ? &zeromalloc : ctx->malloc((int) len, ctx->malloc_data); if (retval == NULL) out_of_memory(ctx); return retval; @@ -78,7 +79,8 @@ static inline void *Malloc(Context *ctx, const size_t len) static inline void Free(Context *ctx, void *ptr) { - ctx->free(ptr, ctx->malloc_data); + if ((ptr != &zeromalloc) && (ptr != NULL)) + ctx->free(ptr, ctx->malloc_data); } // Free static void *MallocBridge(int bytes, void *data)