diff --git a/source/extensions/load_balancing_policies/common/thread_aware_lb_impl.cc b/source/extensions/load_balancing_policies/common/thread_aware_lb_impl.cc index dcfcc8d1f62de..3db19f9826b51 100644 --- a/source/extensions/load_balancing_policies/common/thread_aware_lb_impl.cc +++ b/source/extensions/load_balancing_policies/common/thread_aware_lb_impl.cc @@ -379,15 +379,19 @@ TypedHashLbConfigBase::TypedHashLbConfigBase(absl::Spanweight(); - if (host_sum > std::numeric_limits::max()) { - return absl::InvalidArgumentError( - fmt::format("The sum of weights of all upstream hosts in a locality exceeds {}", - std::numeric_limits::max())); + // Non-contiguous priorities can leave null entries in the priority vector. + // Only skip the host-weight check; locality weights are still validated. + if (hosts != nullptr) { + // Sum should be at most uint32_t max value, so we can validate it by accumulating into + // uint64_t and making sure there was no overflow. + uint64_t host_sum = 0; + for (const auto& host : *hosts) { + host_sum += host->weight(); + if (host_sum > std::numeric_limits::max()) { + return absl::InvalidArgumentError( + fmt::format("The sum of weights of all upstream hosts in a locality exceeds {}", + std::numeric_limits::max())); + } } } diff --git a/test/extensions/load_balancing_policies/ring_hash/ring_hash_lb_test.cc b/test/extensions/load_balancing_policies/ring_hash/ring_hash_lb_test.cc index e4597dd028271..978361f6dd892 100644 --- a/test/extensions/load_balancing_policies/ring_hash/ring_hash_lb_test.cc +++ b/test/extensions/load_balancing_policies/ring_hash/ring_hash_lb_test.cc @@ -1251,6 +1251,31 @@ TEST(RingHashMidBatchInitializeCrashTest, NoOobOnNewPriority) { EXPECT_NE(nullptr, worker_lb); } +// Regression test for https://github.com/envoyproxy/envoy/issues/44349. +// Null entries in PriorityState (from non-contiguous priority levels) must not segfault. +TEST_P(RingHashLoadBalancerTest, ValidateEndpointsSkipsNullPriorityEntries) { + PriorityState priorities; + + auto hosts_p0 = std::make_unique(); + hosts_p0->push_back(makeTestHost(info_, "tcp://127.0.0.1:80")); + priorities.emplace_back(std::move(hosts_p0), LocalityWeightsMap{}); + + // Gaps at priorities 1-4 (null host lists, as produced by non-contiguous EDS assignments). + for (int i = 0; i < 4; ++i) { + priorities.emplace_back(nullptr, LocalityWeightsMap{}); + } + + auto hosts_p5 = std::make_unique(); + hosts_p5->push_back(makeTestHost(info_, "tcp://127.0.0.1:81")); + priorities.emplace_back(std::move(hosts_p5), LocalityWeightsMap{}); + + absl::Status creation_status; + TypedRingHashLbConfig typed_config(config_, context_.regex_engine_, creation_status); + ASSERT_TRUE(creation_status.ok()); + + EXPECT_TRUE(typed_config.validateEndpoints(priorities).ok()); +} + } // namespace } // namespace Upstream } // namespace Envoy