Use explicit buffer length field in the reply reader
This commit is contained in:
parent
adb0895e99
commit
5cf292cdd0
55
hiredis.c
55
hiredis.c
@ -44,7 +44,8 @@ typedef struct redisReader {
|
|||||||
void *reply; /* holds temporary reply */
|
void *reply; /* holds temporary reply */
|
||||||
|
|
||||||
sds buf; /* read buffer */
|
sds buf; /* read buffer */
|
||||||
unsigned int pos; /* buffer cursor */
|
size_t pos; /* buffer cursor */
|
||||||
|
size_t len; /* buffer length */
|
||||||
|
|
||||||
redisReadTask rstack[3]; /* stack of read tasks */
|
redisReadTask rstack[3]; /* stack of read tasks */
|
||||||
int ridx; /* index of stack */
|
int ridx; /* index of stack */
|
||||||
@ -163,20 +164,31 @@ static char *readBytes(redisReader *r, unsigned int bytes) {
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *seekNewline(char *s) {
|
/* Find pointer to \r\n. */
|
||||||
/* Find pointer to \r\n without strstr */
|
static char *seekNewline(char *s, size_t len) {
|
||||||
while (s != NULL) {
|
int pos = 0;
|
||||||
s = strchr(s,'\r');
|
int _len = len-1;
|
||||||
if (s != NULL) {
|
|
||||||
if (s[1] == '\n')
|
/* Position should be < len-1 because the character at "pos" should be
|
||||||
break;
|
* followed by a \n. Note that strchr cannot be used because it doesn't
|
||||||
else
|
* allow to search a limited length and the buffer that is being searched
|
||||||
s++;
|
* might not have a trailing NULL character. */
|
||||||
|
while (pos < _len) {
|
||||||
|
while(pos < _len && s[pos] != '\r') pos++;
|
||||||
|
if (s[pos] != '\r') {
|
||||||
|
/* Not found. */
|
||||||
|
return NULL;
|
||||||
} else {
|
} else {
|
||||||
break;
|
if (s[pos+1] == '\n') {
|
||||||
|
/* Found. */
|
||||||
|
return s+pos;
|
||||||
|
} else {
|
||||||
|
/* Continue searching. */
|
||||||
|
pos++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return s;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *readLine(redisReader *r, int *_len) {
|
static char *readLine(redisReader *r, int *_len) {
|
||||||
@ -184,7 +196,7 @@ static char *readLine(redisReader *r, int *_len) {
|
|||||||
int len;
|
int len;
|
||||||
|
|
||||||
p = r->buf+r->pos;
|
p = r->buf+r->pos;
|
||||||
s = seekNewline(p);
|
s = seekNewline(p,(r->len-r->pos));
|
||||||
if (s != NULL) {
|
if (s != NULL) {
|
||||||
len = s-(r->buf+r->pos);
|
len = s-(r->buf+r->pos);
|
||||||
r->pos += len+2; /* skip \r\n */
|
r->pos += len+2; /* skip \r\n */
|
||||||
@ -253,7 +265,7 @@ static int processBulkItem(redisReader *r) {
|
|||||||
int success = 0;
|
int success = 0;
|
||||||
|
|
||||||
p = r->buf+r->pos;
|
p = r->buf+r->pos;
|
||||||
s = seekNewline(p);
|
s = seekNewline(p,r->len-r->pos);
|
||||||
if (s != NULL) {
|
if (s != NULL) {
|
||||||
p = r->buf+r->pos;
|
p = r->buf+r->pos;
|
||||||
bytelen = s-(r->buf+r->pos)+2; /* include \r\n */
|
bytelen = s-(r->buf+r->pos)+2; /* include \r\n */
|
||||||
@ -267,7 +279,7 @@ static int processBulkItem(redisReader *r) {
|
|||||||
} else {
|
} else {
|
||||||
/* Only continue when the buffer contains the entire bulk item. */
|
/* Only continue when the buffer contains the entire bulk item. */
|
||||||
bytelen += len+2; /* include \r\n */
|
bytelen += len+2; /* include \r\n */
|
||||||
if (r->pos+bytelen <= sdslen(r->buf)) {
|
if (r->pos+bytelen <= r->len) {
|
||||||
obj = r->fn ? r->fn->createString(cur,s+2,len) :
|
obj = r->fn ? r->fn->createString(cur,s+2,len) :
|
||||||
(void*)REDIS_REPLY_STRING;
|
(void*)REDIS_REPLY_STRING;
|
||||||
success = 1;
|
success = 1;
|
||||||
@ -463,8 +475,10 @@ void redisReplyReaderFeed(void *reader, char *buf, size_t len) {
|
|||||||
redisReader *r = reader;
|
redisReader *r = reader;
|
||||||
|
|
||||||
/* Copy the provided buffer. */
|
/* Copy the provided buffer. */
|
||||||
if (buf != NULL && len >= 1)
|
if (buf != NULL && len >= 1) {
|
||||||
r->buf = sdscatlen(r->buf,buf,len);
|
r->buf = sdscatlen(r->buf,buf,len);
|
||||||
|
r->len = sdslen(r->buf);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int redisReplyReaderGetReply(void *reader, void **reply) {
|
int redisReplyReaderGetReply(void *reader, void **reply) {
|
||||||
@ -472,7 +486,7 @@ int redisReplyReaderGetReply(void *reader, void **reply) {
|
|||||||
if (reply != NULL) *reply = NULL;
|
if (reply != NULL) *reply = NULL;
|
||||||
|
|
||||||
/* When the buffer is empty, there will never be a reply. */
|
/* When the buffer is empty, there will never be a reply. */
|
||||||
if (sdslen(r->buf) == 0)
|
if (r->len == 0)
|
||||||
return REDIS_OK;
|
return REDIS_OK;
|
||||||
|
|
||||||
/* Set first item to process when the stack is empty. */
|
/* Set first item to process when the stack is empty. */
|
||||||
@ -493,14 +507,15 @@ int redisReplyReaderGetReply(void *reader, void **reply) {
|
|||||||
|
|
||||||
/* Discard the consumed part of the buffer. */
|
/* Discard the consumed part of the buffer. */
|
||||||
if (r->pos > 0) {
|
if (r->pos > 0) {
|
||||||
if (r->pos == sdslen(r->buf)) {
|
if (r->pos == r->len) {
|
||||||
/* sdsrange has a quirck on this edge case. */
|
/* sdsrange has a quirck on this edge case. */
|
||||||
sdsfree(r->buf);
|
sdsfree(r->buf);
|
||||||
r->buf = sdsempty();
|
r->buf = sdsempty();
|
||||||
} else {
|
} else {
|
||||||
r->buf = sdsrange(r->buf,r->pos,sdslen(r->buf));
|
r->buf = sdsrange(r->buf,r->pos,r->len);
|
||||||
}
|
}
|
||||||
r->pos = 0;
|
r->pos = 0;
|
||||||
|
r->len = sdslen(r->buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Emit a reply when there is one. */
|
/* Emit a reply when there is one. */
|
||||||
@ -509,7 +524,7 @@ int redisReplyReaderGetReply(void *reader, void **reply) {
|
|||||||
r->reply = NULL;
|
r->reply = NULL;
|
||||||
|
|
||||||
/* Destroy the buffer when it is empty and is quite large. */
|
/* Destroy the buffer when it is empty and is quite large. */
|
||||||
if (sdslen(r->buf) == 0 && sdsavail(r->buf) > 16*1024) {
|
if (r->len == 0 && sdsavail(r->buf) > 16*1024) {
|
||||||
sdsfree(r->buf);
|
sdsfree(r->buf);
|
||||||
r->buf = sdsempty();
|
r->buf = sdsempty();
|
||||||
r->pos = 0;
|
r->pos = 0;
|
||||||
|
Loading…
Reference in New Issue
Block a user