smalloc: add pre and post redzone checks to pointers
Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
diff --git a/smalloc.c b/smalloc.c
index 7b30ce7..17c57a8 100644
--- a/smalloc.c
+++ b/smalloc.c
@@ -14,10 +14,15 @@
#include "mutex.h"
#define MP_SAFE /* define to made allocator thread safe */
+#define SMALLOC_REDZONE /* define to detect memory corruption */
-#define INITIAL_SIZE 32*1048576 /* new pool size */
+#define INITIAL_SIZE 32768 /* new pool size */
#define MAX_POOLS 4 /* maximum number of pools to setup */
+#define SMALLOC_PRE_RED 0xdeadbeefU
+#define SMALLOC_POST_RED 0x5aa55aa5U
+#define SMALLOC_REDZONE_SZ (2 * sizeof(unsigned int))
+
unsigned int smalloc_pool_size = INITIAL_SIZE;
struct pool {
@@ -181,6 +186,10 @@
goto out_close;
alloc_size += sizeof(*hdr);
+#ifdef SMALLOC_REDZONE
+ alloc_size += SMALLOC_REDZONE_SZ;
+#endif
+
if (alloc_size > smalloc_pool_size)
pool->size = alloc_size;
else
@@ -254,6 +263,29 @@
fio_mutex_remove(lock);
}
+static void sfree_check_redzone(struct mem_hdr *hdr, void *ptr)
+{
+#ifdef SMALLOC_REDZONE
+ unsigned int *prered, *postred;
+
+ prered = (unsigned int *) ptr;
+ postred = (unsigned int *) (ptr + hdr_size(hdr) - sizeof(unsigned int));
+
+ if (*prered != SMALLOC_PRE_RED) {
+ fprintf(stderr, "smalloc pre redzone destroyed!\n");
+ fprintf(stderr, " ptr=%p, prered=%x, expected %x\n",
+ ptr, *prered, SMALLOC_PRE_RED);
+ assert(0);
+ }
+ if (*postred != SMALLOC_POST_RED) {
+ fprintf(stderr, "smalloc post redzone destroyed!\n");
+ fprintf(stderr, " ptr=%p, postred=%x, expected %x\n",
+ ptr, *postred, SMALLOC_POST_RED);
+ assert(0);
+ }
+#endif
+}
+
static void sfree_pool(struct pool *pool, void *ptr)
{
struct mem_hdr *hdr, *nxt;
@@ -261,10 +293,15 @@
if (!ptr)
return;
+#ifdef SMALLOC_REDZONE
+ ptr -= sizeof(unsigned int);
+#endif
+
assert(ptr_valid(pool, ptr));
pool_lock(pool);
hdr = ptr - sizeof(*hdr);
+ sfree_check_redzone(hdr, ptr);
assert(!hdr_free(hdr));
hdr_mark_free(hdr);
pool->room -= hdr_size(hdr);
@@ -303,7 +340,7 @@
sfree_pool(pool, ptr);
}
-static void *smalloc_pool(struct pool *pool, unsigned int size)
+static void *__smalloc_pool(struct pool *pool, unsigned int size)
{
struct mem_hdr *hdr, *prv;
int did_restart = 0;
@@ -380,6 +417,28 @@
return NULL;
}
+static void *smalloc_pool(struct pool *pool, unsigned int size)
+{
+#ifdef SMALLOC_REDZONE
+ unsigned int *prered, *postred;
+ void *ptr;
+
+ ptr = __smalloc_pool(pool, size + 2 * sizeof(unsigned int));
+ if (!ptr)
+ return NULL;
+
+ prered = ptr;
+ *prered = SMALLOC_PRE_RED;
+ ptr += sizeof(unsigned int);
+ postred = ptr + size;
+ *postred = SMALLOC_POST_RED;
+
+ return ptr;
+#else
+ return __smalloc_pool(pool, size);
+#endif
+}
+
void *smalloc(unsigned int size)
{
unsigned int i;