From 89f4c4563b89b5ffd1bd656720df0f12497c4690 Mon Sep 17 00:00:00 2001 From: "clark.kang" Date: Thu, 27 Nov 2014 08:51:13 +0900 Subject: [PATCH] fix delete parsing for memcache --- src/proto/nc_memcache.c | 44 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 43 insertions(+), 1 deletion(-) diff --git a/src/proto/nc_memcache.c b/src/proto/nc_memcache.c index 1b1bae7f..990ca8db 100644 --- a/src/proto/nc_memcache.c +++ b/src/proto/nc_memcache.c @@ -127,6 +127,8 @@ memcache_parse_req(struct msg *r) struct mbuf *b; uint8_t *p, *m; uint8_t ch; + uint8_t *last_num; + int last_num_size; enum { SW_START, SW_REQ_TYPE, @@ -147,12 +149,16 @@ memcache_parse_req(struct msg *r) SW_NUM, SW_RUNTO_CRLF, SW_CRLF, + SW_RUNTO_DELETE_CRLF, SW_NOREPLY, SW_AFTER_NOREPLY, SW_ALMOST_DONE, SW_SENTINEL } state; + last_num = NULL; + last_num_size = 0; + state = r->state; b = STAILQ_LAST(&r->mhdr, mbuf, next); @@ -345,7 +351,7 @@ memcache_parse_req(struct msg *r) } else if (memcache_arithmetic(r)) { state = SW_SPACES_BEFORE_NUM; } else if (memcache_delete(r)) { - state = SW_RUNTO_CRLF; + state = SW_RUNTO_DELETE_CRLF; } else if (memcache_retrieval(r)) { state = SW_SPACES_BEFORE_KEYS; } else { @@ -536,6 +542,7 @@ memcache_parse_req(struct msg *r) } /* num_start <- p; num <- ch - '0' */ r->token = p; + last_num = p; state = SW_NUM; } @@ -546,6 +553,7 @@ memcache_parse_req(struct msg *r) /* num <- num * 10 + (ch - '0') */ ; } else if (ch == ' ' || ch == CR) { + last_num_size = (int)(p - r->token); r->token = NULL; /* num_end <- p - 1 */ p = p - 1; /* go back by 1 byte */ @@ -556,6 +564,32 @@ memcache_parse_req(struct msg *r) break; + case SW_RUNTO_DELETE_CRLF: + if (isdigit(ch)) { + state = SW_SPACES_BEFORE_NUM; + p = p - 1; + break; + } + + switch (ch) { + case ' ': + break; + + case CR: + state = SW_ALMOST_DONE; + break; + + case 'n': + r->token = p; + state = SW_NOREPLY; + break; + + default: + goto error; + } + + break; + case SW_RUNTO_CRLF: switch (ch) { case ' ': @@ -599,6 +633,8 @@ memcache_parse_req(struct msg *r) r->noreply = 1; state = SW_AFTER_NOREPLY; p = p - 1; /* go back by 1 byte */ + last_num = NULL; + last_num_size = 0; } else { goto error; } @@ -641,6 +677,12 @@ memcache_parse_req(struct msg *r) break; case SW_ALMOST_DONE: + if (memcache_delete(r) && last_num != NULL) { + if (last_num_size != 1 || last_num[0] != '0') { + goto error; + } + } + switch (ch) { case LF: /* req_end <- p */