Skip to content

Commit c521b76

Browse files
6unYoungjhpark816
authored andcommitted
FIX: Add handling for tokens exceeding max_stats_prefixes in process_stats_prefixlist()
1 parent da6931c commit c521b76

File tree

1 file changed

+50
-6
lines changed

1 file changed

+50
-6
lines changed

memcached.c

Lines changed: 50 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,7 @@ static void update_stat_cas(conn *c, ENGINE_ERROR_CODE ret);
147147
static void process_stats_prefixes(conn *c, const size_t ntokens);
148148
static void process_stats_prefixlist(conn *c, token_t *tokens, const size_t ntokens);
149149
static void process_stats_engine(conn *c, token_t *tokens, const size_t ntokens);
150+
static size_t count_remained_tokens(const token_t *tokens);
150151
static 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+
86858730
static 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

Comments
 (0)