Always return a non-NULL pointer for malloc(0).
authorRyan C. Gordon <icculus@icculus.org>
Fri, 04 May 2018 17:45:20 -0400
changeset 1182 179ffe99c57f
parent 1181 b873f3b0f838
child 1183 ec44ee868688
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
mojoshader_assembler.c
mojoshader_compiler.c
mojoshader_opengl.c
mojoshader_preprocessor.c
--- a/mojoshader.c	Fri Oct 13 00:47:22 2017 -0400
+++ b/mojoshader.c	Fri May 04 17:45:20 2018 -0400
@@ -307,9 +307,10 @@
     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 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)
--- a/mojoshader_assembler.c	Fri Oct 13 00:47:22 2017 -0400
+++ b/mojoshader_assembler.c	Fri May 04 17:45:20 2018 -0400
@@ -72,9 +72,10 @@
     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 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)
--- a/mojoshader_compiler.c	Fri Oct 13 00:47:22 2017 -0400
+++ b/mojoshader_compiler.c	Fri May 04 17:45:20 2018 -0400
@@ -160,9 +160,10 @@
     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 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)
--- a/mojoshader_opengl.c	Fri Oct 13 00:47:22 2017 -0400
+++ b/mojoshader_opengl.c	Fri May 04 17:45:20 2018 -0400
@@ -347,9 +347,10 @@
     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 Free(void *ptr)
 {
-    if (ptr != NULL)
+    if ((ptr != &zeromalloc) && (ptr != NULL))
         ctx->free_fn(ptr, ctx->malloc_data);
 } // Free
 
--- a/mojoshader_preprocessor.c	Fri Oct 13 00:47:22 2017 -0400
+++ b/mojoshader_preprocessor.c	Fri May 04 17:45:20 2018 -0400
@@ -68,9 +68,10 @@
     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 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)