@@ -147,6 +147,7 @@ static void update_stat_cas(conn *c, ENGINE_ERROR_CODE ret);
147147static void process_stats_prefixes(conn *c, const size_t ntokens);
148148static void process_stats_prefixlist(conn *c, token_t *tokens, const size_t ntokens);
149149static void process_stats_engine(conn *c, token_t *tokens, const size_t ntokens);
150+ static size_t count_remained_tokens(const token_t *tokens);
150151static void write_ascii_stats_buffer(conn *c);
151152
152153/* defaults */
@@ -8608,7 +8609,7 @@ static void process_stats_prefixlist(conn *c, token_t *tokens, const size_t ntok
86088609 int len;
86098610 char *stats;
86108611 token_t *prefixes = ntokens > 4 ? &tokens[3] : NULL;
8611- size_t nprefixes = ntokens > 4 ? ntokens- 4 : 0;
8612+ size_t nprefixes = ntokens > 4 ? ntokens - 4 : 0;
86128613 size_t prefix_cnt = nprefixes;
86138614
86148615 if (ntokens < 4) {
@@ -8631,16 +8632,39 @@ static void process_stats_prefixlist(conn *c, token_t *tokens, const size_t ntok
86318632 return;
86328633 }
86338634
8635+ /* untokenized command reserved */
8636+ if (ntokens >= MAX_TOKENS) {
8637+ prefix_cnt += count_remained_tokens(&tokens[ntokens - 1]);
8638+ }
8639+
86348640 if (prefix_cnt > settings.max_stats_prefixes) {
86358641 out_string(c, "CLIENT_ERROR invalid: too many prefixes");
86368642 return;
86378643 }
86388644
8645+ if (ntokens >= MAX_TOKENS && prefix_cnt > nprefixes) {
8646+ token_t *temp = (token_t *)malloc(sizeof(token_t) * (prefix_cnt + 2));
8647+ if (temp == NULL) {
8648+ out_string(c, "SERVER_ERROR no more memory");
8649+ return;
8650+ }
8651+ memcpy(temp, prefixes, sizeof(token_t) * nprefixes);
8652+ tokenize_command(prefixes[nprefixes].value, prefixes[nprefixes + 1].length,
8653+ temp + nprefixes, (prefix_cnt - nprefixes + 1));
8654+ prefixes = temp;
8655+ nprefixes = prefix_cnt;
8656+ }
8657+
86398658 if (item_cmd == true) { /* item */
86408659 stats = mc_engine.v1->prefix_dump_stats(mc_engine.v0, c, prefixes, nprefixes, &len);
86418660 } else { /* operation */
86428661 stats = stats_prefix_dump(prefixes, nprefixes, &len);
86438662 }
8663+
8664+ if (ntokens > MAX_TOKENS && prefix_cnt > nprefixes) {
8665+ free(prefixes);
8666+ }
8667+
86448668 if (stats != NULL) {
86458669 write_and_free(c, stats, len);
86468670 } else {
@@ -8682,6 +8706,27 @@ static void process_stats_engine(conn *c, token_t *tokens, const size_t ntokens)
86828706 }
86838707}
86848708
8709+ static size_t count_remained_tokens(const token_t *remained)
8710+ {
8711+ assert(remained != NULL);
8712+ if (remained->value == NULL) return 0;
8713+
8714+ size_t count = 0;
8715+ const char *s = remained->value;
8716+ const char *e = s + (remained+1)->length;
8717+
8718+ while (s < e) {
8719+ if (*s == ' ') {
8720+ s++;
8721+ } else {
8722+ count++;
8723+ while (s < e && *s != ' ') s++;
8724+ }
8725+ }
8726+
8727+ return count;
8728+ }
8729+
86858730static void write_ascii_stats_buffer(conn *c)
86868731{
86878732 append_ascii_stats(NULL, 0, NULL, 0, c);
@@ -14014,12 +14059,11 @@ static int try_read_command_ascii(conn *c)
1401414059 conn_set_state(c, conn_closing);
1401514060 return 1;
1401614061 }
14017- /* Check KEY_MAX_LENGTH and eflag filter length
14018- * - KEY_MAX_LENGTH : 16000
14019- * - IN eflag filter : > 6400 (64* 100)
14062+ /* Check < KEY_MAX_LENGTH and IN eflag filter> or prefixlist max length : 26KB
14063+ * - KEY_MAX_LENGTH(16000) + IN eflag filter(64*100) : 24KB
14064+ * - prefixlist max length : max prefix count( 100) * MAX_PREFIX_LENGTH(250) : 25KB
1402014065 */
14021- if (c->rbytes > ((16+8)*1024)) {
14022- /* The length of "stats prefixes" command cannot exceed 24 KB. */
14066+ if (c->rbytes > (26*1024)) {
1402314067 if (strncmp(ptr, "get ", 4) && strncmp(ptr, "gets ", 5)) {
1402414068 char buffer[16];
1402514069 memcpy(buffer, ptr, 15); buffer[15] = '\0';
0 commit comments