Merge pull request #147 from hdoreau/d7e3268f48b457cb52336d264f8860b336faea9f

Prevent hiredis from crashing on memory allocation failure
This commit is contained in:
Pieter Noordhuis 2013-01-26 11:18:45 -08:00
commit f05909cd53
5 changed files with 78 additions and 15 deletions

View File

@ -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: check the `err` field to see if establishing the connection was successful:
redisContext *c = redisConnect("127.0.0.1", 6379); redisContext *c = redisConnect("127.0.0.1", 6379);
if (c->err) { if (c != NULL && c->err) {
printf("Error: %s\n", c->errstr); printf("Error: %s\n", c->errstr);
// handle error // handle error
} }

35
async.c
View File

@ -102,7 +102,12 @@ static dictType callbackDict = {
}; };
static redisAsyncContext *redisAsyncInitialize(redisContext *c) { 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); c = &(ac->c);
/* The regular connect functions will always set the flag REDIS_CONNECTED. /* 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) { redisAsyncContext *redisAsyncConnect(const char *ip, int port) {
redisContext *c = redisConnectNonBlock(ip,port); redisContext *c;
redisAsyncContext *ac = redisAsyncInitialize(c); redisAsyncContext *ac;
c = redisConnectNonBlock(ip,port);
if (c == NULL)
return NULL;
ac = redisAsyncInitialize(c);
if (ac == NULL) {
redisFree(c);
return NULL;
}
__redisAsyncCopyError(ac); __redisAsyncCopyError(ac);
return ac; return ac;
} }
redisAsyncContext *redisAsyncConnectUnix(const char *path) { redisAsyncContext *redisAsyncConnectUnix(const char *path) {
redisContext *c = redisConnectUnixNonBlock(path); redisContext *c;
redisAsyncContext *ac = redisAsyncInitialize(c); redisAsyncContext *ac;
c = redisConnectUnixNonBlock(path);
if (c == NULL)
return NULL;
ac = redisAsyncInitialize(c);
__redisAsyncCopyError(ac); __redisAsyncCopyError(ac);
return ac; return ac;
} }
@ -182,6 +204,9 @@ static int __redisPushCallback(redisCallbackList *list, redisCallback *source) {
/* Copy callback from stack to heap */ /* Copy callback from stack to heap */
cb = malloc(sizeof(*cb)); cb = malloc(sizeof(*cb));
if (cb == NULL)
return REDIS_ERR_OOM;
if (source != NULL) { if (source != NULL) {
memcpy(cb,source,sizeof(*cb)); memcpy(cb,source,sizeof(*cb));
cb->next = NULL; cb->next = NULL;

View File

@ -11,8 +11,13 @@ int main(void) {
struct timeval timeout = { 1, 500000 }; // 1.5 seconds struct timeval timeout = { 1, 500000 }; // 1.5 seconds
c = redisConnectWithTimeout((char*)"127.0.0.1", 6379, timeout); c = redisConnectWithTimeout((char*)"127.0.0.1", 6379, timeout);
if (c->err) { if (c == NULL || c->err) {
printf("Connection error: %s\n", c->errstr); if (c) {
printf("Connection error: %s\n", c->errstr);
redisFree(c);
} else {
printf("Connection error: can't allocate redis context\n");
}
exit(1); exit(1);
} }

View File

@ -1014,42 +1014,72 @@ void redisFree(redisContext *c) {
* context will be set to the return value of the error function. * 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. */ * When no set of reply functions is given, the default set will be used. */
redisContext *redisConnect(const char *ip, int port) { redisContext *redisConnect(const char *ip, int port) {
redisContext *c = redisContextInit(); redisContext *c;
c = redisContextInit();
if (c == NULL)
return NULL;
c->flags |= REDIS_BLOCK; c->flags |= REDIS_BLOCK;
redisContextConnectTcp(c,ip,port,NULL); redisContextConnectTcp(c,ip,port,NULL);
return c; return c;
} }
redisContext *redisConnectWithTimeout(const char *ip, int port, struct timeval tv) { 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; c->flags |= REDIS_BLOCK;
redisContextConnectTcp(c,ip,port,&tv); redisContextConnectTcp(c,ip,port,&tv);
return c; return c;
} }
redisContext *redisConnectNonBlock(const char *ip, int port) { redisContext *redisConnectNonBlock(const char *ip, int port) {
redisContext *c = redisContextInit(); redisContext *c;
c = redisContextInit();
if (c == NULL)
return NULL;
c->flags &= ~REDIS_BLOCK; c->flags &= ~REDIS_BLOCK;
redisContextConnectTcp(c,ip,port,NULL); redisContextConnectTcp(c,ip,port,NULL);
return c; return c;
} }
redisContext *redisConnectUnix(const char *path) { redisContext *redisConnectUnix(const char *path) {
redisContext *c = redisContextInit(); redisContext *c;
c = redisContextInit();
if (c == NULL)
return NULL;
c->flags |= REDIS_BLOCK; c->flags |= REDIS_BLOCK;
redisContextConnectUnix(c,path,NULL); redisContextConnectUnix(c,path,NULL);
return c; return c;
} }
redisContext *redisConnectUnixWithTimeout(const char *path, struct timeval tv) { redisContext *redisConnectUnixWithTimeout(const char *path, struct timeval tv) {
redisContext *c = redisContextInit(); redisContext *c;
c = redisContextInit();
if (c == NULL)
return NULL;
c->flags |= REDIS_BLOCK; c->flags |= REDIS_BLOCK;
redisContextConnectUnix(c,path,&tv); redisContextConnectUnix(c,path,&tv);
return c; return c;
} }
redisContext *redisConnectUnixNonBlock(const char *path) { redisContext *redisConnectUnixNonBlock(const char *path) {
redisContext *c = redisContextInit(); redisContext *c;
c = redisContextInit();
if (c == NULL)
return NULL;
c->flags &= ~REDIS_BLOCK; c->flags &= ~REDIS_BLOCK;
redisContextConnectUnix(c,path,NULL); redisContextConnectUnix(c,path,NULL);
return c; return c;

5
test.c
View File

@ -88,7 +88,10 @@ static redisContext *connect(struct config config) {
assert(NULL); 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); printf("Connection error: %s\n", c->errstr);
exit(1); exit(1);
} }