From 8e0264cfd6889b73c241b60736fe96ba1322ee6e Mon Sep 17 00:00:00 2001 From: Michael Grunder Date: Fri, 22 May 2020 09:27:49 -0700 Subject: Allow users to replace allocator and handle OOM everywhere. (#800) * Adds an indirection to every allocation/deallocation to allow users to plug in ones of their choosing (use custom functions, jemalloc, etc). * Gracefully handle OOM everywhere in hiredis. This should make it possible for users of the library to have more flexibility in how they handle such situations. * Changes `redisReaderTask->elements` from an `int` to a `long long` to prevent a possible overflow when transferring the task elements into a `redisReply`. * Adds a configurable `max elements` member to `redisReader` that defaults to 2^32 - 1. This can be set to "unlimited" by setting the value to zero. --- adapters/ae.h | 5 ++++- adapters/glib.h | 3 +++ adapters/ivykis.h | 5 ++++- adapters/libev.h | 5 ++++- adapters/libevent.h | 5 ++++- adapters/libuv.h | 10 ++++------ adapters/macosx.h | 7 ++++--- 7 files changed, 27 insertions(+), 13 deletions(-) (limited to 'adapters') diff --git a/adapters/ae.h b/adapters/ae.h index 0393992..660d82e 100644 --- a/adapters/ae.h +++ b/adapters/ae.h @@ -96,7 +96,7 @@ static void redisAeCleanup(void *privdata) { redisAeEvents *e = (redisAeEvents*)privdata; redisAeDelRead(privdata); redisAeDelWrite(privdata); - free(e); + hi_free(e); } static int redisAeAttach(aeEventLoop *loop, redisAsyncContext *ac) { @@ -109,6 +109,9 @@ static int redisAeAttach(aeEventLoop *loop, redisAsyncContext *ac) { /* Create container for context and r/w events */ e = (redisAeEvents*)hi_malloc(sizeof(*e)); + if (e == NULL) + return REDIS_ERR; + e->context = ac; e->loop = loop; e->fd = c->fd; diff --git a/adapters/glib.h b/adapters/glib.h index e0a6411..ad59dd1 100644 --- a/adapters/glib.h +++ b/adapters/glib.h @@ -134,6 +134,9 @@ redis_source_new (redisAsyncContext *ac) g_return_val_if_fail(ac != NULL, NULL); source = (RedisSource *)g_source_new(&source_funcs, sizeof *source); + if (source == NULL) + return NULL; + source->ac = ac; source->poll_fd.fd = c->fd; source->poll_fd.events = 0; diff --git a/adapters/ivykis.h b/adapters/ivykis.h index 75616ee..179f6ab 100644 --- a/adapters/ivykis.h +++ b/adapters/ivykis.h @@ -43,7 +43,7 @@ static void redisIvykisCleanup(void *privdata) { redisIvykisEvents *e = (redisIvykisEvents*)privdata; iv_fd_unregister(&e->fd); - free(e); + hi_free(e); } static int redisIvykisAttach(redisAsyncContext *ac) { @@ -56,6 +56,9 @@ static int redisIvykisAttach(redisAsyncContext *ac) { /* Create container for context and r/w events */ e = (redisIvykisEvents*)hi_malloc(sizeof(*e)); + if (e == NULL) + return REDIS_ERR; + e->context = ac; /* Register functions to start/stop listening for events */ diff --git a/adapters/libev.h b/adapters/libev.h index 1520923..7057dbd 100644 --- a/adapters/libev.h +++ b/adapters/libev.h @@ -116,7 +116,7 @@ static void redisLibevCleanup(void *privdata) { redisLibevDelRead(privdata); redisLibevDelWrite(privdata); redisLibevStopTimer(privdata); - free(e); + hi_free(e); } static void redisLibevTimeout(EV_P_ ev_timer *timer, int revents) { @@ -149,6 +149,9 @@ static int redisLibevAttach(EV_P_ redisAsyncContext *ac) { /* Create container for context and r/w events */ e = (redisLibevEvents*)hi_calloc(1, sizeof(*e)); + if (e == NULL) + return REDIS_ERR; + e->context = ac; #if EV_MULTIPLICITY e->loop = loop; diff --git a/adapters/libevent.h b/adapters/libevent.h index 0674ca6..9150979 100644 --- a/adapters/libevent.h +++ b/adapters/libevent.h @@ -47,7 +47,7 @@ typedef struct redisLibeventEvents { } redisLibeventEvents; static void redisLibeventDestroy(redisLibeventEvents *e) { - free(e); + hi_free(e); } static void redisLibeventHandler(int fd, short event, void *arg) { @@ -153,6 +153,9 @@ static int redisLibeventAttach(redisAsyncContext *ac, struct event_base *base) { /* Create container for context and r/w events */ e = (redisLibeventEvents*)hi_calloc(1, sizeof(*e)); + if (e == NULL) + return REDIS_ERR; + e->context = ac; /* Register functions to start/stop listening for events */ diff --git a/adapters/libuv.h b/adapters/libuv.h index 7aac127..c120b1b 100644 --- a/adapters/libuv.h +++ b/adapters/libuv.h @@ -73,7 +73,7 @@ static void redisLibuvDelWrite(void *privdata) { static void on_close(uv_handle_t* handle) { redisLibuvEvents* p = (redisLibuvEvents*)handle->data; - free(p); + hi_free(p); } @@ -98,11 +98,9 @@ static int redisLibuvAttach(redisAsyncContext* ac, uv_loop_t* loop) { ac->ev.delWrite = redisLibuvDelWrite; ac->ev.cleanup = redisLibuvCleanup; - redisLibuvEvents* p = (redisLibuvEvents*)malloc(sizeof(*p)); - - if (!p) { - return REDIS_ERR; - } + redisLibuvEvents* p = (redisLibuvEvents*)hi_malloc(sizeof(*p)); + if (p == NULL) + return REDIS_ERR; memset(p, 0, sizeof(*p)); diff --git a/adapters/macosx.h b/adapters/macosx.h index 72121f6..3c87f1b 100644 --- a/adapters/macosx.h +++ b/adapters/macosx.h @@ -27,7 +27,7 @@ static int freeRedisRunLoop(RedisRunLoop* redisRunLoop) { CFSocketInvalidate(redisRunLoop->socketRef); CFRelease(redisRunLoop->socketRef); } - free(redisRunLoop); + hi_free(redisRunLoop); } return REDIS_ERR; } @@ -80,8 +80,9 @@ static int redisMacOSAttach(redisAsyncContext *redisAsyncCtx, CFRunLoopRef runLo /* Nothing should be attached when something is already attached */ if( redisAsyncCtx->ev.data != NULL ) return REDIS_ERR; - RedisRunLoop* redisRunLoop = (RedisRunLoop*) calloc(1, sizeof(RedisRunLoop)); - if( !redisRunLoop ) return REDIS_ERR; + RedisRunLoop* redisRunLoop = (RedisRunLoop*) hi_calloc(1, sizeof(RedisRunLoop)); + if (redisRunLoop == NULL) + return REDIS_ERR; /* Setup redis stuff */ redisRunLoop->context = redisAsyncCtx; -- cgit v1.2.3