From: Brian Aker Date: Fri, 9 Nov 2007 18:11:09 +0000 (-0800) Subject: Fixed bug reported by Stuart Midgley about what happens when there are no X-Git-Tag: 0.10~23 X-Git-Url: https://git.m6w6.name/?a=commitdiff_plain;h=131622cdc2710ecd9ad554ce7d08c6003fbdcf6e;p=m6w6%2Flibmemcached Fixed bug reported by Stuart Midgley about what happens when there are no servers and you try to set/get values. --- diff --git a/lib/memcached_auto.c b/lib/memcached_auto.c index 69b975c1..25f9aaf9 100644 --- a/lib/memcached_auto.c +++ b/lib/memcached_auto.c @@ -11,6 +11,9 @@ static memcached_return memcached_auto(memcached_st *ptr, char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE]; unsigned int server_key; + if (ptr->hosts == NULL || ptr->number_of_hosts == 0) + return MEMCACHED_NO_SERVERS; + server_key= memcached_generate_hash(ptr, key, key_length); if ((rc= memcached_connect(ptr, server_key)) != MEMCACHED_SUCCESS) diff --git a/lib/memcached_connect.c b/lib/memcached_connect.c index 68b9c939..025fdf6e 100644 --- a/lib/memcached_connect.c +++ b/lib/memcached_connect.c @@ -134,10 +134,10 @@ memcached_return memcached_connect(memcached_st *ptr, unsigned int server_key) memcached_return rc= MEMCACHED_NO_SERVERS; LIBMEMCACHED_MEMCACHED_CONNECT_START(); - if (ptr->connected == ptr->number_of_hosts) + if (ptr->connected == ptr->number_of_hosts && ptr->number_of_hosts) return MEMCACHED_SUCCESS; - if (!ptr->hosts) + if (ptr->hosts == NULL || ptr->number_of_hosts == 0) return MEMCACHED_NO_SERVERS; /* We need to clean up the multi startup piece */ diff --git a/lib/memcached_delete.c b/lib/memcached_delete.c index 6a849533..0ed6092a 100644 --- a/lib/memcached_delete.c +++ b/lib/memcached_delete.c @@ -11,6 +11,9 @@ memcached_return memcached_delete(memcached_st *ptr, char *key, size_t key_lengt LIBMEMCACHED_MEMCACHED_DELETE_START(); + if (ptr->hosts == NULL || ptr->number_of_hosts == 0) + return MEMCACHED_NO_SERVERS; + server_key= memcached_generate_hash(ptr, key, key_length); if ((rc= memcached_connect(ptr, server_key)) != MEMCACHED_SUCCESS) diff --git a/lib/memcached_flush.c b/lib/memcached_flush.c index 8538aaa0..58f5bff2 100644 --- a/lib/memcached_flush.c +++ b/lib/memcached_flush.c @@ -10,6 +10,9 @@ memcached_return memcached_flush(memcached_st *ptr, time_t expiration) rc= memcached_connect(ptr, 0); + if (rc == MEMCACHED_NO_SERVERS) + return rc; + if (rc != MEMCACHED_SUCCESS) rc= MEMCACHED_SOME_ERRORS; diff --git a/lib/memcached_get.c b/lib/memcached_get.c index 01f388c9..c0da409d 100644 --- a/lib/memcached_get.c +++ b/lib/memcached_get.c @@ -143,6 +143,12 @@ char *memcached_get(memcached_st *ptr, char *key, size_t key_length, memcached_string_st *result_buffer; LIBMEMCACHED_MEMCACHED_GET_START(); + if (ptr->hosts == NULL || ptr->number_of_hosts == 0) + { + *error= MEMCACHED_NO_SERVERS; + return NULL; + } + server_key= memcached_generate_hash(ptr, key, key_length); result_buffer= &ptr->result_buffer; @@ -218,6 +224,9 @@ memcached_return memcached_mget(memcached_st *ptr, if (number_of_keys == 0) return MEMCACHED_NOTFOUND; + if (ptr->number_of_hosts == 0) + return MEMCACHED_NO_SERVERS; + cursor_key_exec= (char *)malloc(sizeof(char) * ptr->number_of_hosts); memset(cursor_key_exec, 0, sizeof(char) * ptr->number_of_hosts); diff --git a/lib/memcached_hash.c b/lib/memcached_hash.c index 7e7814e6..33c1055b 100644 --- a/lib/memcached_hash.c +++ b/lib/memcached_hash.c @@ -17,6 +17,8 @@ unsigned int memcached_generate_hash(memcached_st *ptr, char *key, size_t key_le uint64_t hash= 1; /* Just here to remove compile warning */ unsigned int x; + WATCHPOINT_ASSERT(ptr->number_of_hosts); + switch (ptr->hash) { case MEMCACHED_HASH_DEFAULT: diff --git a/lib/memcached_quit.c b/lib/memcached_quit.c index 7670b06c..20a76e29 100644 --- a/lib/memcached_quit.c +++ b/lib/memcached_quit.c @@ -11,6 +11,11 @@ void memcached_quit_server(memcached_st *ptr, unsigned int server_key) { + if (ptr->hosts == NULL || + ptr->number_of_hosts == 0 || + server_key > ptr->number_of_hosts) + return; + if (ptr->hosts[server_key].fd != -1) { if (ptr->flags & MEM_NO_BLOCK && ptr->hosts[server_key].stack_responses) @@ -31,7 +36,7 @@ void memcached_quit(memcached_st *ptr) { unsigned int x; - if (ptr->hosts) + if (ptr->hosts && ptr->number_of_hosts) { for (x= 0; x < ptr->number_of_hosts; x++) memcached_quit_server(ptr, x); diff --git a/lib/memcached_storage.c b/lib/memcached_storage.c index f9ba64d6..70201489 100644 --- a/lib/memcached_storage.c +++ b/lib/memcached_storage.c @@ -41,6 +41,9 @@ static memcached_return memcached_send(memcached_st *ptr, if (!(ptr->flags & MEM_NO_BLOCK) && ptr->write_buffer_offset != 0) WATCHPOINT_ASSERT(0); #endif + + if (ptr->hosts == NULL || ptr->number_of_hosts == 0) + return MEMCACHED_NO_SERVERS; server_key= memcached_generate_hash(ptr, key, key_length); @@ -48,6 +51,7 @@ static memcached_return memcached_send(memcached_st *ptr, if (rc != MEMCACHED_SUCCESS) return rc; + write_length= snprintf(buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, "%s %.*s %x %llu %zu\r\n", storage_op_string(verb), (int)key_length, key, flags, diff --git a/tests/function.c b/tests/function.c index 16c75073..6bac2d53 100644 --- a/tests/function.c +++ b/tests/function.c @@ -870,6 +870,74 @@ uint8_t user_supplied_bug3(memcached_st *memc) return 0; } +/* Make sure we behave properly if server list has no values */ +uint8_t user_supplied_bug4(memcached_st *memc) +{ + memcached_return rc; + char *keys[]= {"fudge", "son", "food"}; + size_t key_length[]= {5, 3, 4}; + unsigned int x; + uint16_t flags; + + /* Here we free everything before running a bunch of mget tests */ + { + memcached_server_list_free(memc->hosts); + memc->hosts= NULL; + memc->number_of_hosts= 0; + } + + char return_key[MEMCACHED_MAX_KEY]; + size_t return_key_length; + char *return_value; + size_t return_value_length; + + /* We need to empty the server before continueing test */ + rc= memcached_flush(memc, 0); + WATCHPOINT_ERROR(rc); + assert(rc == MEMCACHED_NO_SERVERS); + + rc= memcached_mget(memc, keys, key_length, 3); + assert(rc == MEMCACHED_NO_SERVERS); + + while ((return_value= memcached_fetch(memc, return_key, &return_key_length, + &return_value_length, &flags, &rc)) != NULL) + { + assert(return_value); + } + assert(!return_value); + assert(return_value_length == 0); + assert(rc == MEMCACHED_NO_SERVERS); + + WATCHPOINT; + for (x= 0; x < 3; x++) + { + rc= memcached_set(memc, keys[x], key_length[x], + keys[x], key_length[x], + (time_t)50, (uint16_t)9); + assert(rc == MEMCACHED_NO_SERVERS); + } + + WATCHPOINT; + rc= memcached_mget(memc, keys, key_length, 3); + assert(rc == MEMCACHED_NO_SERVERS); + WATCHPOINT; + + x= 0; + while ((return_value= memcached_fetch(memc, return_key, &return_key_length, + &return_value_length, &flags, &rc))) + { + WATCHPOINT; + assert(return_value); + assert(rc == MEMCACHED_SUCCESS); + assert(return_key_length == return_value_length); + assert(!memcmp(return_value, return_key, return_value_length)); + free(return_value); + x++; + } + + return 0; +} + uint8_t result_static(memcached_st *memc) { memcached_result_st result; @@ -1258,6 +1326,7 @@ test_st user_tests[] ={ {"user_supplied_bug1", 0, user_supplied_bug1 }, {"user_supplied_bug2", 0, user_supplied_bug2 }, {"user_supplied_bug3", 0, user_supplied_bug3 }, + {"user_supplied_bug4", 0, user_supplied_bug4 }, {0, 0, 0} };