From 411d5ae2fdcd66d8613d38c3725e4ef76f022fea Mon Sep 17 00:00:00 2001 From: Michael Wallner Date: Wed, 15 Jan 2020 17:42:53 +0100 Subject: [PATCH] libmemcached: fix a reallocation crash Also, re-enable memcached_server_add(many weighted) test which was presumably disabled because of this issue. When a continuum was allocated while not in weighted distribution mode, the actual space allocated at first would be to small to fit further updates when weighted changed to true at a later time. --- libmemcached/hosts.cc | 16 +++++++++------- tests/libmemcached-1.0/server_add.cc | 3 +-- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/libmemcached/hosts.cc b/libmemcached/hosts.cc index 75bfbee6..97f7c35b 100644 --- a/libmemcached/hosts.cc +++ b/libmemcached/hosts.cc @@ -174,18 +174,20 @@ static memcached_return_t update_continuum(Memcached *ptr) live_servers= memcached_server_count(ptr); } - uint32_t points_per_server= (uint32_t) (memcached_is_weighted_ketama(ptr) ? MEMCACHED_POINTS_PER_SERVER_KETAMA : MEMCACHED_POINTS_PER_SERVER); - if (live_servers == 0) { return MEMCACHED_SUCCESS; } - if (live_servers > ptr->ketama.continuum_count) + uint32_t points_per_server = (uint32_t) (memcached_is_weighted_ketama(ptr) ? MEMCACHED_POINTS_PER_SERVER_KETAMA : MEMCACHED_POINTS_PER_SERVER); + uint32_t continuum_limit = live_servers * points_per_server; + uint32_t continuum_extra = MEMCACHED_CONTINUUM_ADDITION * points_per_server; + + if (continuum_limit > ptr->ketama.continuum_count) { memcached_continuum_item_st *new_ptr; - new_ptr= libmemcached_xrealloc(ptr, ptr->ketama.continuum, (live_servers + MEMCACHED_CONTINUUM_ADDITION) * points_per_server, memcached_continuum_item_st); + new_ptr= libmemcached_xrealloc(ptr, ptr->ketama.continuum, continuum_limit + continuum_extra, memcached_continuum_item_st); if (new_ptr == 0) { @@ -193,7 +195,7 @@ static memcached_return_t update_continuum(Memcached *ptr) } ptr->ketama.continuum= new_ptr; - ptr->ketama.continuum_count= live_servers + MEMCACHED_CONTINUUM_ADDITION; + ptr->ketama.continuum_count= continuum_limit + continuum_extra; } assert_msg(ptr->ketama.continuum, "Programmer Error, empty ketama continuum"); @@ -221,7 +223,7 @@ static memcached_return_t update_continuum(Memcached *ptr) float pct= (float)list[host_index].weight / (float)total_weight; pointer_per_server= (uint32_t) ((::floor((float) (pct * MEMCACHED_POINTS_PER_SERVER_KETAMA / 4 * (float)live_servers + 0.0000000001))) * 4); pointer_per_hash= 4; - if (DEBUG) + if (0 && DEBUG) { printf("ketama_weighted:%s|%d|%llu|%u\n", list[host_index]._hostname, @@ -255,7 +257,7 @@ static memcached_return_t update_continuum(Memcached *ptr) memcached_literal_param("snprintf(sizeof(sort_host))")); } - if (DEBUG) + if (0 && DEBUG) { fprintf(stdout, "update_continuum: key is %s\n", sort_host); } diff --git a/tests/libmemcached-1.0/server_add.cc b/tests/libmemcached-1.0/server_add.cc index 495a7717..37470947 100644 --- a/tests/libmemcached-1.0/server_add.cc +++ b/tests/libmemcached-1.0/server_add.cc @@ -90,7 +90,6 @@ test_return_t memcached_server_many_TEST(memcached_st* memc) test_return_t memcached_server_many_weighted_TEST(memcached_st* memc) { - SKIP_IF(true); ASSERT_EQ(0, memcached_server_count(memc)); in_port_t base_port= 5555; @@ -98,7 +97,7 @@ test_return_t memcached_server_many_weighted_TEST(memcached_st* memc) { std::string hostname(random_hostname()); ASSERT_TRUE(hostname.size()); - test_compare(MEMCACHED_SUCCESS, memcached_server_add_with_weight(memc, hostname.c_str(), base_port +x, random() % 10)); + test_compare(MEMCACHED_SUCCESS, memcached_server_add_with_weight(memc, hostname.c_str(), base_port +x, x % 10)); } return TEST_SUCCESS; -- 2.30.2