Merge pull request #147 from hdoreau/d7e3268f48b457cb52336d264f8860b336faea9f
Prevent hiredis from crashing on memory allocation failure
This commit is contained in:
commit
f05909cd53
@ -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
35
async.c
@ -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;
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
42
hiredis.c
42
hiredis.c
@ -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
5
test.c
@ -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);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user