Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -379,15 +379,19 @@ TypedHashLbConfigBase::TypedHashLbConfigBase(absl::Span<const HashPolicyProto* c
absl::Status TypedHashLbConfigBase::validateEndpoints(const PriorityState& priorities) const {

for (const auto& [hosts, locality_weights_map] : priorities) {
// 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<uint32_t>::max()) {
return absl::InvalidArgumentError(
fmt::format("The sum of weights of all upstream hosts in a locality exceeds {}",
std::numeric_limits<uint32_t>::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<uint32_t>::max()) {
return absl::InvalidArgumentError(
fmt::format("The sum of weights of all upstream hosts in a locality exceeds {}",
std::numeric_limits<uint32_t>::max()));
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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<HostVector>();
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<HostVector>();
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