Commit 11e0c4c5 authored by antirez's avatar antirez
Browse files

Protections against protocol desyncs, leading to infinite query buffer...

Protections against protocol desyncs, leading to infinite query buffer growing, due to nul-terms in specific bytes of the request or indefinitely long multi bulk or bulk count strings without newlines. This bug is related to Issue #141 as well.
parent f42e2f1b
#include "redis.h" #include "redis.h"
#include <sys/uio.h> #include <sys/uio.h>
static void setProtocolError(redisClient *c, int pos);
void *dupClientReplyValue(void *o) { void *dupClientReplyValue(void *o) {
incrRefCount((robj*)o); incrRefCount((robj*)o);
return o; return o;
...@@ -675,8 +677,13 @@ int processInlineBuffer(redisClient *c) { ...@@ -675,8 +677,13 @@ int processInlineBuffer(redisClient *c) {
size_t querylen; size_t querylen;
/* Nothing to do without a \r\n */ /* Nothing to do without a \r\n */
if (newline == NULL) if (newline == NULL) {
if (sdslen(c->querybuf) > REDIS_INLINE_MAX_SIZE) {
addReplyError(c,"Protocol error: too big inline request");
setProtocolError(c,0);
}
return REDIS_ERR; return REDIS_ERR;
}
/* Split the input buffer up to the \r\n */ /* Split the input buffer up to the \r\n */
querylen = newline-(c->querybuf); querylen = newline-(c->querybuf);
...@@ -726,8 +733,13 @@ int processMultibulkBuffer(redisClient *c) { ...@@ -726,8 +733,13 @@ int processMultibulkBuffer(redisClient *c) {
/* Multi bulk length cannot be read without a \r\n */ /* Multi bulk length cannot be read without a \r\n */
newline = strchr(c->querybuf,'\r'); newline = strchr(c->querybuf,'\r');
if (newline == NULL) if (newline == NULL) {
if (sdslen(c->querybuf) > REDIS_INLINE_MAX_SIZE) {
addReplyError(c,"Protocol error: too big mbulk count string");
setProtocolError(c,0);
}
return REDIS_ERR; return REDIS_ERR;
}
/* Buffer should also contain \n */ /* Buffer should also contain \n */
if (newline-(c->querybuf) > ((signed)sdslen(c->querybuf)-2)) if (newline-(c->querybuf) > ((signed)sdslen(c->querybuf)-2))
...@@ -761,8 +773,13 @@ int processMultibulkBuffer(redisClient *c) { ...@@ -761,8 +773,13 @@ int processMultibulkBuffer(redisClient *c) {
/* Read bulk length if unknown */ /* Read bulk length if unknown */
if (c->bulklen == -1) { if (c->bulklen == -1) {
newline = strchr(c->querybuf+pos,'\r'); newline = strchr(c->querybuf+pos,'\r');
if (newline == NULL) if (newline == NULL) {
if (sdslen(c->querybuf) > REDIS_INLINE_MAX_SIZE) {
addReplyError(c,"Protocol error: too big bulk count string");
setProtocolError(c,0);
}
break; break;
}
/* Buffer should also contain \n */ /* Buffer should also contain \n */
if (newline-(c->querybuf) > ((signed)sdslen(c->querybuf)-2)) if (newline-(c->querybuf) > ((signed)sdslen(c->querybuf)-2))
...@@ -831,9 +848,9 @@ int processMultibulkBuffer(redisClient *c) { ...@@ -831,9 +848,9 @@ int processMultibulkBuffer(redisClient *c) {
if (pos) c->querybuf = sdsrange(c->querybuf,pos,-1); if (pos) c->querybuf = sdsrange(c->querybuf,pos,-1);
/* We're done when c->multibulk == 0 */ /* We're done when c->multibulk == 0 */
if (c->multibulklen == 0) { if (c->multibulklen == 0) return REDIS_OK;
return REDIS_OK;
} /* Still not read to process the command */
return REDIS_ERR; return REDIS_ERR;
} }
......
...@@ -60,6 +60,7 @@ ...@@ -60,6 +60,7 @@
#define REDIS_MAX_QUERYBUF_LEN (1024*1024*1024) /* 1GB max query buffer. */ #define REDIS_MAX_QUERYBUF_LEN (1024*1024*1024) /* 1GB max query buffer. */
#define REDIS_IOBUF_LEN (1024*16) /* Generic I/O buffer size */ #define REDIS_IOBUF_LEN (1024*16) /* Generic I/O buffer size */
#define REDIS_REPLY_CHUNK_BYTES (16*1024) /* 16k output buffer */ #define REDIS_REPLY_CHUNK_BYTES (16*1024) /* 16k output buffer */
#define REDIS_INLINE_MAX_SIZE (1024*64) /* Max size of inline reads */
#define REDIS_MBULK_BIG_ARG (1024*32) #define REDIS_MBULK_BIG_ARG (1024*32)
/* Hash table parameters */ /* Hash table parameters */
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment