summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPieter Noordhuis <pcnoordhuis@gmail.com>2013-01-26 11:18:45 -0800
committerPieter Noordhuis <pcnoordhuis@gmail.com>2013-01-26 11:18:45 -0800
commitf05909cd53b1c0f983e2d645205d036784f0b39b (patch)
tree8738a33e728a53c7b521f2f87bec569245650fc3
parent9df327e8fddef1e17b2136b5f42be58f46cdbc08 (diff)
parentd7e3268f48b457cb52336d264f8860b336faea9f (diff)
Merge pull request #147 from hdoreau/d7e3268f48b457cb52336d264f8860b336faea9f
Prevent hiredis from crashing on memory allocation failure
-rw-r--r--README.md2
-rw-r--r--async.c35
-rw-r--r--example.c9
-rw-r--r--hiredis.c42
-rw-r--r--test.c5
5 files changed, 78 insertions, 15 deletions
diff --git a/README.md b/README.md
index 62fe106..8d788f2 100644
--- a/README.md
+++ b/README.md
@@ -44,7 +44,7 @@ After trying to connect to Redis using `redisConnect` you should
check the `err` field to see if establishing the connection was successful:
redisContext *c = redisConnect("127.0.0.1", 6379);
- if (c->err) {
+ if (c != NULL && c->err) {
printf("Error: %s\n", c->errstr);
// handle error
}
diff --git a/async.c b/async.c
index f65f869..83d88ec 100644
--- a/async.c
+++ b/async.c
@@ -102,7 +102,12 @@ static dictType callbackDict = {
};
static redisAsyncContext *redisAsyncInitialize(redisContext *c) {
- redisAsyncContext *ac = realloc(c,sizeof(redisAsyncContext));
+ redisAsyncContext *ac;
+
+ ac = realloc(c,sizeof(redisAsyncContext));
+ if (ac == NULL)
+ return NULL;
+
c = &(ac->c);
/* The regular connect functions will always set the flag REDIS_CONNECTED.
@@ -142,15 +147,32 @@ static void __redisAsyncCopyError(redisAsyncContext *ac) {
}
redisAsyncContext *redisAsyncConnect(const char *ip, int port) {
- redisContext *c = redisConnectNonBlock(ip,port);
- redisAsyncContext *ac = redisAsyncInitialize(c);
+ redisContext *c;
+ redisAsyncContext *ac;
+
+ c = redisConnectNonBlock(ip,port);
+ if (c == NULL)
+ return NULL;
+
+ ac = redisAsyncInitialize(c);
+ if (ac == NULL) {
+ redisFree(c);
+ return NULL;
+ }
+
__redisAsyncCopyError(ac);
return ac;
}
redisAsyncContext *redisAsyncConnectUnix(const char *path) {
- redisContext *c = redisConnectUnixNonBlock(path);
- redisAsyncContext *ac = redisAsyncInitialize(c);
+ redisContext *c;
+ redisAsyncContext *ac;
+
+ c = redisConnectUnixNonBlock(path);
+ if (c == NULL)
+ return NULL;
+
+ ac = redisAsyncInitialize(c);
__redisAsyncCopyError(ac);
return ac;
}
@@ -182,6 +204,9 @@ static int __redisPushCallback(redisCallbackList *list, redisCallback *source) {
/* Copy callback from stack to heap */
cb = malloc(sizeof(*cb));
+ if (cb == NULL)
+ return REDIS_ERR_OOM;
+
if (source != NULL) {
memcpy(cb,source,sizeof(*cb));
cb->next = NULL;
diff --git a/example.c b/example.c
index 378ef71..d9d7271 100644
--- a/example.c
+++ b/example.c
@@ -11,8 +11,13 @@ int main(void) {
struct timeval timeout = { 1, 500000 }; // 1.5 seconds
c = redisConnectWithTimeout((char*)"127.0.0.1", 6379, timeout);
- if (c->err) {
- printf("Connection error: %s\n", c->errstr);
+ if (c == NULL || c->err) {
+ if (c) {
+ printf("Connection error: %s\n", c->errstr);
+ redisFree(c);
+ } else {
+ printf("Connection error: can't allocate redis context\n");
+ }
exit(1);
}
diff --git a/hiredis.c b/hiredis.c
index 50028ee..958f58b 100644
--- a/hiredis.c
+++ b/hiredis.c
@@ -1014,42 +1014,72 @@ void redisFree(redisContext *c) {
* context will be set to the return value of the error function.
* When no set of reply functions is given, the default set will be used. */
redisContext *redisConnect(const char *ip, int port) {
- redisContext *c = redisContextInit();
+ redisContext *c;
+
+ c = redisContextInit();
+ if (c == NULL)
+ return NULL;
+
c->flags |= REDIS_BLOCK;
redisContextConnectTcp(c,ip,port,NULL);
return c;
}
redisContext *redisConnectWithTimeout(const char *ip, int port, struct timeval tv) {
- redisContext *c = redisContextInit();
+ redisContext *c;
+
+ c = redisContextInit();
+ if (c == NULL)
+ return NULL;
+
c->flags |= REDIS_BLOCK;
redisContextConnectTcp(c,ip,port,&tv);
return c;
}
redisContext *redisConnectNonBlock(const char *ip, int port) {
- redisContext *c = redisContextInit();
+ redisContext *c;
+
+ c = redisContextInit();
+ if (c == NULL)
+ return NULL;
+
c->flags &= ~REDIS_BLOCK;
redisContextConnectTcp(c,ip,port,NULL);
return c;
}
redisContext *redisConnectUnix(const char *path) {
- redisContext *c = redisContextInit();
+ redisContext *c;
+
+ c = redisContextInit();
+ if (c == NULL)
+ return NULL;
+
c->flags |= REDIS_BLOCK;
redisContextConnectUnix(c,path,NULL);
return c;
}
redisContext *redisConnectUnixWithTimeout(const char *path, struct timeval tv) {
- redisContext *c = redisContextInit();
+ redisContext *c;
+
+ c = redisContextInit();
+ if (c == NULL)
+ return NULL;
+
c->flags |= REDIS_BLOCK;
redisContextConnectUnix(c,path,&tv);
return c;
}
redisContext *redisConnectUnixNonBlock(const char *path) {
- redisContext *c = redisContextInit();
+ redisContext *c;
+
+ c = redisContextInit();
+ if (c == NULL)
+ return NULL;
+
c->flags &= ~REDIS_BLOCK;
redisContextConnectUnix(c,path,NULL);
return c;
diff --git a/test.c b/test.c
index 737ad1c..6786003 100644
--- a/test.c
+++ b/test.c
@@ -88,7 +88,10 @@ static redisContext *connect(struct config config) {
assert(NULL);
}
- if (c->err) {
+ if (c == NULL) {
+ printf("Connection error: can't allocate redis context\n");
+ exit(1);
+ } else if (c->err) {
printf("Connection error: %s\n", c->errstr);
exit(1);
}