diff --git a/src/core/ext/xds/xds_endpoint.cc b/src/core/ext/xds/xds_endpoint.cc index d9e703a767c..aee1544c24d 100644 --- a/src/core/ext/xds/xds_endpoint.cc +++ b/src/core/ext/xds/xds_endpoint.cc @@ -21,6 +21,7 @@ #include #include +#include #include #include "absl/status/status.h" @@ -366,6 +367,19 @@ absl::StatusOr EdsResourceParse( const auto& priority = eds_resource.priorities[i]; if (priority.localities.empty()) { errors.AddError(absl::StrCat("priority ", i, " empty")); + } else { + // Check that the sum of the locality weights in this priority + // does not exceed the max value for a uint32. + uint64_t total_weight = 0; + for (const auto& p : priority.localities) { + total_weight += p.second.lb_weight; + if (total_weight > std::numeric_limits::max()) { + errors.AddError( + absl::StrCat("sum of locality weights for priority ", i, + " exceeds uint32 max")); + break; + } + } } } } diff --git a/test/core/xds/xds_endpoint_resource_type_test.cc b/test/core/xds/xds_endpoint_resource_type_test.cc index b3d8473ad9e..c60de87fb39 100644 --- a/test/core/xds/xds_endpoint_resource_type_test.cc +++ b/test/core/xds/xds_endpoint_resource_type_test.cc @@ -14,6 +14,9 @@ // limitations under the License. // +#include + +#include #include #include #include @@ -610,6 +613,45 @@ TEST_F(XdsEndpointTest, SparsePriorityList) { << decode_result.resource.status(); } +TEST_F(XdsEndpointTest, LocalityWeightsWithinPriorityExceedUint32Max) { + ClusterLoadAssignment cla; + cla.set_cluster_name("foo"); + // First locality has weight of 1. + auto* locality = cla.add_endpoints(); + locality->mutable_load_balancing_weight()->set_value(1); + auto* locality_name = locality->mutable_locality(); + locality_name->set_region("myregion"); + locality_name->set_zone("myzone"); + locality_name->set_sub_zone("mysubzone"); + auto* socket_address = locality->add_lb_endpoints() + ->mutable_endpoint() + ->mutable_address() + ->mutable_socket_address(); + socket_address->set_address("127.0.0.1"); + socket_address->set_port_value(443); + locality->set_priority(0); + // Second locality has weight of uint32 max. + locality = cla.add_endpoints(); + *locality = cla.endpoints(0); // Copy first locality. + locality->mutable_locality()->set_region("myregion2"); + locality->mutable_load_balancing_weight()->set_value( + std::numeric_limits::max()); + std::string serialized_resource; + ASSERT_TRUE(cla.SerializeToString(&serialized_resource)); + auto* resource_type = XdsEndpointResourceType::Get(); + auto decode_result = resource_type->Decode( + decode_context_, serialized_resource, /*is_v2=*/false); + ASSERT_TRUE(decode_result.name.has_value()); + EXPECT_EQ(*decode_result.name, "foo"); + EXPECT_EQ(decode_result.resource.status().code(), + absl::StatusCode::kInvalidArgument); + EXPECT_EQ(decode_result.resource.status().message(), + "errors parsing EDS resource: [" + "field:endpoints error:sum of locality weights for priority 0 " + "exceeds uint32 max]") + << decode_result.resource.status(); +} + TEST_F(XdsEndpointTest, DropConfig) { ClusterLoadAssignment cla; cla.set_cluster_name("foo");