Skip to content

Commit

Permalink
Issue 102: Piping null to the server will crash it
Browse files Browse the repository at this point in the history
  • Loading branch information
Trond Norbye authored and dustin committed Oct 29, 2009
1 parent 0731dc8 commit 75cc836
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 2 deletions.
31 changes: 29 additions & 2 deletions memcached.c
Original file line number Diff line number Diff line change
Expand Up @@ -3127,9 +3127,27 @@ static int try_read_command(conn *c) {

if (c->rbytes == 0)
return 0;

el = memchr(c->rcurr, '\n', c->rbytes);
if (!el)
if (!el) {
if (c->rbytes > 1024) {
/*
* We didn't have a '\n' in the first k. This _has_ to be a
* large multiget, if not we should just nuke the connection.
*/
char *ptr = c->rcurr;
while (*ptr == ' ') { /* ignore leading whitespaces */
++ptr;
}

if (strcmp(ptr, "get ") && strcmp(ptr, "gets ")) {
conn_set_state(c, conn_closing);
return 1;
}
}

return 0;
}
cont = el + 1;
if ((el - c->rcurr) > 1 && *(el - 1) == '\r') {
el--;
Expand Down Expand Up @@ -3191,12 +3209,17 @@ static enum try_read_result try_read_udp(conn *c) {
* close.
* before reading, move the remaining incomplete fragment of a command
* (if any) to the beginning of the buffer.
*
* To protect us from someone flooding a connection with bogus data causing
* the connection to eat up all available memory, break out and start looking
* at the data I've got after a number of reallocs...
*
* @return enum try_read_result
*/
static enum try_read_result try_read_network(conn *c) {
enum try_read_result gotdata = READ_NO_DATA_RECEIVED;
int res;

int num_allocs = 0;
assert(c != NULL);

if (c->rcurr != c->rbuf) {
Expand All @@ -3207,6 +3230,10 @@ static enum try_read_result try_read_network(conn *c) {

while (1) {
if (c->rbytes >= c->rsize) {
if (num_allocs == 4) {
return gotdata;
}
++num_allocs;
char *new_rbuf = realloc(c->rbuf, c->rsize * 2);
if (!new_rbuf) {
if (settings.verbose > 0)
Expand Down
17 changes: 17 additions & 0 deletions testapp.c
Original file line number Diff line number Diff line change
Expand Up @@ -538,6 +538,22 @@ static enum test_return test_issue_92(void) {
return TEST_PASS;
}

static enum test_return test_issue_102(void) {
char buffer[4096];
memset(buffer, ' ', sizeof(buffer));
buffer[sizeof(buffer) - 1] = '\0';

close(sock);
sock = connect_server("127.0.0.1", port, false);

send_ascii_command(buffer);
/* verify that the server closed the connection */
assert(read(sock, buffer, sizeof(buffer)) == 0);
close(sock);
sock = connect_server("127.0.0.1", port, false);
return TEST_PASS;
}

static enum test_return start_memcached_server(void) {
server_pid = start_server(&port, false, 600);
sock = connect_server("127.0.0.1", port, false);
Expand Down Expand Up @@ -1676,6 +1692,7 @@ struct testcase testcases[] = {
/* The following tests all run towards the same server */
{ "start_server", start_memcached_server },
{ "issue_92", test_issue_92 },
{ "issue_102", test_issue_102 },
{ "binary_noop", test_binary_noop },
{ "binary_quit", test_binary_quit },
{ "binary_quitq", test_binary_quitq },
Expand Down

0 comments on commit 75cc836

Please sign in to comment.