summaryrefslogtreecommitdiff
path: root/ssl.c
diff options
context:
space:
mode:
authorMichael Grunder <michael.grunder@gmail.com>2020-05-22 09:27:49 -0700
committerGitHub <noreply@github.com>2020-05-22 09:27:49 -0700
commit8e0264cfd6889b73c241b60736fe96ba1322ee6e (patch)
treec7a8f050a2e6966c45f7af919056b9653f831579 /ssl.c
parent83bba659b9dbd6c77baf2ff27ff6342317869a3e (diff)
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.
Diffstat (limited to 'ssl.c')
-rw-r--r--ssl.c33
1 files changed, 25 insertions, 8 deletions
diff --git a/ssl.c b/ssl.c
index 502814d..8cb133a 100644
--- a/ssl.c
+++ b/ssl.c
@@ -163,18 +163,22 @@ static void opensslDoLock(int mode, int lkid, const char *f, int line) {
(void)line;
}
-static void initOpensslLocks(void) {
+static int initOpensslLocks(void) {
unsigned ii, nlocks;
if (CRYPTO_get_locking_callback() != NULL) {
/* Someone already set the callback before us. Don't destroy it! */
- return;
+ return REDIS_OK;
}
nlocks = CRYPTO_num_locks();
ossl_locks = hi_malloc(sizeof(*ossl_locks) * nlocks);
+ if (ossl_locks == NULL)
+ return REDIS_ERR;
+
for (ii = 0; ii < nlocks; ii++) {
sslLockInit(ossl_locks + ii);
}
CRYPTO_set_locking_callback(opensslDoLock);
+ return REDIS_OK;
}
#endif /* HIREDIS_USE_CRYPTO_LOCKS */
@@ -183,15 +187,20 @@ static void initOpensslLocks(void) {
*/
static int redisSSLConnect(redisContext *c, SSL_CTX *ssl_ctx, SSL *ssl) {
+ redisSSLContext *rssl;
+
if (c->privdata) {
__redisSetError(c, REDIS_ERR_OTHER, "redisContext was already associated");
return REDIS_ERR;
}
- c->privdata = calloc(1, sizeof(redisSSLContext));
- c->funcs = &redisContextSSLFuncs;
- redisSSLContext *rssl = c->privdata;
+ rssl = hi_calloc(1, sizeof(redisSSLContext));
+ if (rssl == NULL) {
+ __redisSetError(c, REDIS_ERR_OOM, "Out of memory");
+ return REDIS_ERR;
+ }
+ c->funcs = &redisContextSSLFuncs;
rssl->ssl_ctx = ssl_ctx;
rssl->ssl = ssl;
@@ -202,12 +211,14 @@ static int redisSSLConnect(redisContext *c, SSL_CTX *ssl_ctx, SSL *ssl) {
ERR_clear_error();
int rv = SSL_connect(rssl->ssl);
if (rv == 1) {
+ c->privdata = rssl;
return REDIS_OK;
}
rv = SSL_get_error(rssl->ssl, rv);
if (((c->flags & REDIS_BLOCK) == 0) &&
(rv == SSL_ERROR_WANT_READ || rv == SSL_ERROR_WANT_WRITE)) {
+ c->privdata = rssl;
return REDIS_OK;
}
@@ -222,6 +233,8 @@ static int redisSSLConnect(redisContext *c, SSL_CTX *ssl_ctx, SSL *ssl) {
}
__redisSetError(c, REDIS_ERR_IO, err);
}
+
+ hi_free(rssl);
return REDIS_ERR;
}
@@ -241,7 +254,10 @@ int redisSecureConnection(redisContext *c, const char *capath,
isInit = 1;
SSL_library_init();
#ifdef HIREDIS_USE_CRYPTO_LOCKS
- initOpensslLocks();
+ if (initOpensslLocks() == REDIS_ERR) {
+ __redisSetError(c, REDIS_ERR_OOM, "Out of memory");
+ goto error;
+ }
#endif
}
@@ -290,7 +306,8 @@ int redisSecureConnection(redisContext *c, const char *capath,
}
}
- return redisSSLConnect(c, ssl_ctx, ssl);
+ if (redisSSLConnect(c, ssl_ctx, ssl) == REDIS_OK)
+ return REDIS_OK;
error:
if (ssl) SSL_free(ssl);
@@ -330,7 +347,7 @@ static void redisSSLFreeContext(void *privdata){
SSL_CTX_free(rsc->ssl_ctx);
rsc->ssl_ctx = NULL;
}
- free(rsc);
+ hi_free(rsc);
}
static int redisSSLRead(redisContext *c, char *buf, size_t bufcap) {