From 78956324e490072374858f70b1d3145705bccbd6 Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Mon, 27 Jan 2025 20:22:29 -0800 Subject: [PATCH] x --- test/core/xds/BUILD | 36 ++- .../xds_client_corpora/assert_entry_is_null | 26 -- .../core/xds/xds_client_corpora/basic_cluster | 41 --- .../xds/xds_client_corpora/basic_endpoint | 57 ---- .../xds/xds_client_corpora/basic_listener | 50 ---- .../xds/xds_client_corpora/basic_route_config | 45 ---- .../bootstrap_xds_servers_empty | 10 - .../fake_transport_trigger_connection_failure | 24 -- .../xds_client_corpora/resource_wrapper_empty | 26 -- .../rls_missing_typed_extension_config | 26 -- ...nd_message_to_client_before_stream_created | 9 - test/core/xds/xds_client_fuzzer.cc | 255 +++++++++++++++++- 12 files changed, 273 insertions(+), 332 deletions(-) delete mode 100644 test/core/xds/xds_client_corpora/assert_entry_is_null delete mode 100644 test/core/xds/xds_client_corpora/basic_cluster delete mode 100644 test/core/xds/xds_client_corpora/basic_endpoint delete mode 100644 test/core/xds/xds_client_corpora/basic_listener delete mode 100644 test/core/xds/xds_client_corpora/basic_route_config delete mode 100644 test/core/xds/xds_client_corpora/bootstrap_xds_servers_empty delete mode 100644 test/core/xds/xds_client_corpora/fake_transport_trigger_connection_failure delete mode 100644 test/core/xds/xds_client_corpora/resource_wrapper_empty delete mode 100644 test/core/xds/xds_client_corpora/rls_missing_typed_extension_config delete mode 100644 test/core/xds/xds_client_corpora/send_message_to_client_before_stream_created diff --git a/test/core/xds/BUILD b/test/core/xds/BUILD index b5775b27771df..dc1ba80cc4869 100644 --- a/test/core/xds/BUILD +++ b/test/core/xds/BUILD @@ -16,9 +16,9 @@ load( "//bazel:grpc_build_system.bzl", "grpc_cc_library", "grpc_cc_test", - "grpc_package", + "grpc_package","grpc_cc_proto_library", "grpc_internal_proto_library" ) -load("//test/core/test_util:grpc_fuzzer.bzl", "grpc_proto_fuzzer") +load("//test/core/test_util:grpc_fuzzer.bzl", "grpc_fuzz_test") grpc_package(name = "test/core/xds") @@ -176,19 +176,29 @@ grpc_cc_test( ], ) -grpc_proto_fuzzer( - name = "xds_client_fuzzer", - srcs = ["xds_client_fuzzer.cc"], - corpus = "xds_client_corpora", - external_deps = ["absl/log:log"], - proto = "xds_client_fuzzer.proto", - proto_deps = [ +grpc_internal_proto_library( + name = "xds_client_fuzzer_proto", + srcs = [ + "xds_client_fuzzer.proto" + ], + deps = [ "//test/core/event_engine/fuzzing_event_engine:fuzzing_event_engine_proto", "@envoy_api//envoy/service/discovery/v3:pkg", - ], + ] +) + +grpc_cc_proto_library( + name = "xds_client_fuzzer_cc_proto", + deps = [ + "xds_client_fuzzer_proto", + ] +) + +grpc_fuzz_test( + name = "xds_client_fuzzer", + srcs = ["xds_client_fuzzer.cc"], + external_deps = ["absl/log:log", "fuzztest", "fuzztest_main", "gtest"], tags = ["no_windows"], - uses_event_engine = True, - uses_polling = False, deps = [ ":xds_client_test_peer", ":xds_transport_fake", @@ -196,6 +206,7 @@ grpc_proto_fuzzer( "//test/core/test_util:grpc_test_util", "//test/core/event_engine/fuzzing_event_engine", "//test/core/event_engine:event_engine_test_utils", + "xds_client_fuzzer_cc_proto", # These proto deps are needed to ensure that we can read these # resource types out of the google.protobuf.Any fields in the # textproto files in the corpora. @@ -205,6 +216,7 @@ grpc_proto_fuzzer( "@envoy_api//envoy/config/route/v3:pkg_cc_proto", "@envoy_api//envoy/extensions/filters/http/router/v3:pkg_cc_proto", "@envoy_api//envoy/extensions/filters/network/http_connection_manager/v3:pkg_cc_proto", + "@envoy_api//envoy/service/discovery/v3:pkg_cc_proto", ], ) diff --git a/test/core/xds/xds_client_corpora/assert_entry_is_null b/test/core/xds/xds_client_corpora/assert_entry_is_null deleted file mode 100644 index 188377b6a23a9..0000000000000 --- a/test/core/xds/xds_client_corpora/assert_entry_is_null +++ /dev/null @@ -1,26 +0,0 @@ -bootstrap: "{\"xds_servers\": [{\"server_uri\":\"xds.example.com:443\", \"channel_creds\":[{\"type\": \"fake\"}]}]}" -actions { - start_watch { - resource_type { - route_config { - } - } - } -} -actions { - stop_watch { - resource_type { - route_config { - } - } - } -} -actions { - start_watch { - resource_type { - route_config { - } - } - resource_name: "{\"xds_servers\": [\203\2600\027erver_uri\":\"xds\013.example.com:443\", \"channel_creds\":[{\"type\": \"fake\"}]}]}" - } -} diff --git a/test/core/xds/xds_client_corpora/basic_cluster b/test/core/xds/xds_client_corpora/basic_cluster deleted file mode 100644 index 9fd3f10dc4e70..0000000000000 --- a/test/core/xds/xds_client_corpora/basic_cluster +++ /dev/null @@ -1,41 +0,0 @@ -bootstrap: "{\"xds_servers\": [{\"server_uri\":\"xds.example.com:443\", \"channel_creds\":[{\"type\": \"fake\"}]}]}" -actions { - start_watch { - resource_type { - cluster {} - } - resource_name: "cluster1" - } -} -actions { - read_message_from_client { - stream_id { - ads {} - } - ok: true - } -} -actions { - send_message_to_client { - stream_id { - ads {} - } - response { - version_info: "1" - nonce: "A" - type_url: "type.googleapis.com/envoy.config.cluster.v3.Cluster" - resources { - [type.googleapis.com/envoy.config.cluster.v3.Cluster] { - name: "cluster1" - type: EDS - eds_cluster_config { - eds_config { - ads {} - } - service_name: "endpoint1" - } - } - } - } - } -} diff --git a/test/core/xds/xds_client_corpora/basic_endpoint b/test/core/xds/xds_client_corpora/basic_endpoint deleted file mode 100644 index 818fb2b44b13b..0000000000000 --- a/test/core/xds/xds_client_corpora/basic_endpoint +++ /dev/null @@ -1,57 +0,0 @@ -bootstrap: "{\"xds_servers\": [{\"server_uri\":\"xds.example.com:443\", \"channel_creds\":[{\"type\": \"fake\"}]}]}" -actions { - start_watch { - resource_type { - endpoint {} - } - resource_name: "endpoint1" - } -} -actions { - read_message_from_client { - stream_id { - ads {} - } - ok: true - } -} -actions { - send_message_to_client { - stream_id { - ads {} - } - response { - version_info: "1" - nonce: "A" - type_url: "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment" - resources { - [type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment] { - cluster_name: "endpoint1" - endpoints { - locality { - region: "region1" - zone: "zone1" - sub_zone: "sub_zone1" - } - load_balancing_weight { - value: 1 - } - lb_endpoints { - load_balancing_weight { - value: 1 - } - endpoint { - address { - socket_address { - address: "127.0.0.1" - port_value: 443 - } - } - } - } - } - } - } - } - } -} diff --git a/test/core/xds/xds_client_corpora/basic_listener b/test/core/xds/xds_client_corpora/basic_listener deleted file mode 100644 index e55f73e7278e6..0000000000000 --- a/test/core/xds/xds_client_corpora/basic_listener +++ /dev/null @@ -1,50 +0,0 @@ -bootstrap: "{\"xds_servers\": [{\"server_uri\":\"xds.example.com:443\", \"channel_creds\":[{\"type\": \"fake\"}]}]}" -actions { - start_watch { - resource_type { - listener {} - } - resource_name: "server.example.com" - } -} -actions { - read_message_from_client { - stream_id { - ads {} - } - ok: true - } -} -actions { - send_message_to_client { - stream_id { - ads {} - } - response { - version_info: "1" - nonce: "A" - type_url: "type.googleapis.com/envoy.config.listener.v3.Listener" - resources { - [type.googleapis.com/envoy.config.listener.v3.Listener] { - name: "server.example.com" - api_listener { - api_listener { - [type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager] { - http_filters { - name: "router" - typed_config { - [type.googleapis.com/envoy.extensions.filters.http.router.v3.Router] {} - } - } - rds { - route_config_name: "route_config" - config_source { self {} } - } - } - } - } - } - } - } - } -} diff --git a/test/core/xds/xds_client_corpora/basic_route_config b/test/core/xds/xds_client_corpora/basic_route_config deleted file mode 100644 index 8585134e15b60..0000000000000 --- a/test/core/xds/xds_client_corpora/basic_route_config +++ /dev/null @@ -1,45 +0,0 @@ -bootstrap: "{\"xds_servers\": [{\"server_uri\":\"xds.example.com:443\", \"channel_creds\":[{\"type\": \"fake\"}]}]}" -actions { - start_watch { - resource_type { - route_config {} - } - resource_name: "route_config1" - } -} -actions { - read_message_from_client { - stream_id { - ads {} - } - ok: true - } -} -actions { - send_message_to_client { - stream_id { - ads {} - } - response { - version_info: "1" - nonce: "A" - type_url: "type.googleapis.com/envoy.config.route.v3.RouteConfiguration" - resources { - [type.googleapis.com/envoy.config.route.v3.RouteConfiguration] { - name: "route_config1" - virtual_hosts { - domains: "*" - routes { - match { - prefix: "" - } - route { - cluster: "cluster1" - } - } - } - } - } - } - } -} diff --git a/test/core/xds/xds_client_corpora/bootstrap_xds_servers_empty b/test/core/xds/xds_client_corpora/bootstrap_xds_servers_empty deleted file mode 100644 index 04308e93c1ff2..0000000000000 --- a/test/core/xds/xds_client_corpora/bootstrap_xds_servers_empty +++ /dev/null @@ -1,10 +0,0 @@ -bootstrap: "{\"xds_servers\": []}" -actions { - start_watch { - resource_type { - listener { - } - } - resource_name: "\003" - } -} diff --git a/test/core/xds/xds_client_corpora/fake_transport_trigger_connection_failure b/test/core/xds/xds_client_corpora/fake_transport_trigger_connection_failure deleted file mode 100644 index 655b710d4af61..0000000000000 --- a/test/core/xds/xds_client_corpora/fake_transport_trigger_connection_failure +++ /dev/null @@ -1,24 +0,0 @@ -bootstrap: "{\"xds_servers\": [{\"server_uri\":\"xds.example.com:659\", \"channel_creds\":[{\"type\": \"fake\"}]}]}" -actions { - start_watch { - resource_type { - endpoint { - } - } - resource_name_url: "//ClientHello" - value: "J\001-8\377\248󠀬03209960555158341825735263247\213\1110977990980586646490508\377\377\377\377\377\0227\227\227\227\227\227\226\227\227\227\2vers\\\": [{\\\"server_uri\\\":\\\"xds.example.com:443\\\"\\\"channel_cr␜␜␜␜␜␜␜␜␜␜␜␜␜␜␜␜␜␜␜␜␜␜␜␜␜␜␜␜␜␜␜␜␜␜␜␜␜␜␜␜␜␜␜␜␜␜␜␜␜␜␜␜␜␜␜␜␜␜␜␜␜␜␜␜␜␜␜␜␜␜␜␜␜␜␜␜␜␜␜␜␜␜␜␜␜␜␜␜␜␜␜␜␜␜␜␜␜␜␜␜␜␜␜␜␜␜␜␜␜␜␜␜␜␜␜␜␜␜n start_watch {\n resource_type {\n route_config {\n }\n }\n resource_name: \"/\"\n }\n}\nactions {\n stop_watch {\n resource_name: \"QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ\"\n }\n}\nactions {\n stop_watch {\n resource_type {\n cluster {\n }\n }\n }\n}\n" - } -} -actions { - stop_watch { - resource_type { - endpoint { - } - } - resou2ce_name: "QQQQQQQQQQQQQQQQQQQQQQQ\177\177\177\177\177\177\177\177\177\177\177\177\177\177\177\177\177\177\177\177\177\177\177\177\177\177\177\177\177\0178\177\177\177\177\177\177\177\177\177\002\177\177\177W\177\177\177\177\177\177\177\177\177\177\177\177\177\177\177\177\177\177\177\177\177\177\177\177\0018446744073709551615\177\177QQQQQQQQQQ" - } -} -actions { - trigger_connection_failure { - } -} diff --git a/test/core/xds/xds_client_corpora/resource_wrapper_empty b/test/core/xds/xds_client_corpora/resource_wrapper_empty deleted file mode 100644 index 534b6a4286b71..0000000000000 --- a/test/core/xds/xds_client_corpora/resource_wrapper_empty +++ /dev/null @@ -1,26 +0,0 @@ -bootstrap: "{\"xds_servers\": [{\"server_uri\":\"xds.example.com:443\", \"channel_creds\":[{\"type\": \"fake\"}]}]}" -actions { - start_watch { - resource_type { - cluster { - } - } - } -} -actions { - send_message_to_client { - stream_id { - ads { - } - } - response { - version_info: "envoy.config.cluster.v3.Cluster" - resources { - type_url: "envoy.service.discovery.v3.Resource" - } - canary: true - type_url: "envoy.config.cluster.v3.Cluster" - nonce: "envoy.config.cluster.v3.Cluster" - } - } -} diff --git a/test/core/xds/xds_client_corpora/rls_missing_typed_extension_config b/test/core/xds/xds_client_corpora/rls_missing_typed_extension_config deleted file mode 100644 index cd2a6dfbc9fb7..0000000000000 --- a/test/core/xds/xds_client_corpora/rls_missing_typed_extension_config +++ /dev/null @@ -1,26 +0,0 @@ -bootstrap: "{\"xds_servers\": [{\"server_uri\":\"xds.example.com:-257\", \"channel_creds\":[{\"type\": \"fake\"}]}]}" -actions { - start_watch { - resource_type { - route_config { - } - } - } -} -actions { - send_message_to_client { - stream_id { - ads { - } - } - response { - version_info: "grpc.lookup.v1.RouteLookup" - resources { - type_url: "envoy.config.route.v3.RouteConfiguration" - value: "\010\001b\000" - } - type_url: "envoy.config.route.v3.RouteConfiguration" - nonce: "/@\001\000\\\000\000x141183468234106731687303715884105729" - } - } -} diff --git a/test/core/xds/xds_client_corpora/send_message_to_client_before_stream_created b/test/core/xds/xds_client_corpora/send_message_to_client_before_stream_created deleted file mode 100644 index 1184f2408fc41..0000000000000 --- a/test/core/xds/xds_client_corpora/send_message_to_client_before_stream_created +++ /dev/null @@ -1,9 +0,0 @@ -bootstrap: "{\"xds_servers\": [{\"server_uri\":\"xds.example.com:443\", \"channel_creds\":[{\"type\": \"fake\"}]}]}" -actions { - send_message_to_client { - stream_id { - ads { - } - } - } -} diff --git a/test/core/xds/xds_client_fuzzer.cc b/test/core/xds/xds_client_fuzzer.cc index bfa7cdadfa17c..221ae2a267deb 100644 --- a/test/core/xds/xds_client_fuzzer.cc +++ b/test/core/xds/xds_client_fuzzer.cc @@ -14,6 +14,7 @@ // limitations under the License. // +#include #include #include @@ -30,6 +31,8 @@ #include "absl/strings/string_view.h" #include "absl/time/time.h" #include "envoy/service/discovery/v3/discovery.pb.h" +#include "fuzztest/fuzztest.h" +#include "gtest/gtest.h" #include "src/core/lib/iomgr/timer_manager.h" #include "src/core/util/orphanable.h" #include "src/core/util/ref_counted_ptr.h" @@ -45,7 +48,6 @@ #include "src/core/xds/grpc/xds_route_config_parser.h" #include "src/core/xds/xds_client/xds_bootstrap.h" #include "src/core/xds/xds_client/xds_client.h" -#include "src/libfuzzer/libfuzzer_macro.h" #include "test/core/event_engine/event_engine_test_utils.h" #include "test/core/event_engine/fuzzing_event_engine/fuzzing_event_engine.h" #include "test/core/xds/xds_client_fuzzer.pb.h" @@ -345,14 +347,255 @@ class Fuzzer { std::map> endpoint_watchers_; }; -} // namespace grpc_core +static const char* assert_entry_is_null = R"pb( + bootstrap: "{\"xds_servers\": [{\"server_uri\":\"xds.example.com:443\", \"channel_creds\":[{\"type\": \"fake\"}]}]}" + actions { start_watch { resource_type { route_config {} } } } + actions { stop_watch { resource_type { route_config {} } } } + actions { + start_watch { + resource_type { route_config {} } + resource_name: "{\"xds_servers\": [\203\2600\027erver_uri\":\"xds\013.example.com:443\", \"channel_creds\":[{\"type\": \"fake\"}]}]}" + } + } +)pb"; -bool squelch = true; +static const char* basic_cluster = R"pb( + bootstrap: "{\"xds_servers\": [{\"server_uri\":\"xds.example.com:443\", \"channel_creds\":[{\"type\": \"fake\"}]}]}" + actions { + start_watch { + resource_type { cluster {} } + resource_name: "cluster1" + } + } + actions { + read_message_from_client { + stream_id { ads {} } + ok: true + } + } + actions { + send_message_to_client { + stream_id { ads {} } + response { + version_info: "1" + nonce: "A" + type_url: "type.googleapis.com/envoy.config.cluster.v3.Cluster" + resources { + [type.googleapis.com/envoy.config.cluster.v3.Cluster] { + name: "cluster1" + type: EDS + eds_cluster_config { + eds_config { ads {} } + service_name: "endpoint1" + } + } + } + } + } + } +)pb"; -DEFINE_PROTO_FUZZER(const xds_client_fuzzer::Msg& message) { - grpc_core::Fuzzer fuzzer(message.bootstrap(), - message.fuzzing_event_engine_actions()); +static const char* basic_endpoint = R"pb( + bootstrap: "{\"xds_servers\": [{\"server_uri\":\"xds.example.com:443\", \"channel_creds\":[{\"type\": \"fake\"}]}]}" + actions { + start_watch { + resource_type { endpoint {} } + resource_name: "endpoint1" + } + } + actions { + read_message_from_client { + stream_id { ads {} } + ok: true + } + } + actions { + send_message_to_client { + stream_id { ads {} } + response { + version_info: "1" + nonce: "A" + type_url: "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment" + resources { + [type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment] { + cluster_name: "endpoint1" + endpoints { + locality { region: "region1" zone: "zone1" sub_zone: "sub_zone1" } + load_balancing_weight { value: 1 } + lb_endpoints { + load_balancing_weight { value: 1 } + endpoint { + address { + socket_address { address: "127.0.0.1" port_value: 443 } + } + } + } + } + } + } + } + } + } +)pb"; + +static const char* basic_listener = R"pb( + bootstrap: "{\"xds_servers\": [{\"server_uri\":\"xds.example.com:443\", \"channel_creds\":[{\"type\": \"fake\"}]}]}" + actions { + start_watch { + resource_type { listener {} } + resource_name: "server.example.com" + } + } + actions { + read_message_from_client { + stream_id { ads {} } + ok: true + } + } + actions { + send_message_to_client { + stream_id { ads {} } + response { + version_info: "1" + nonce: "A" + type_url: "type.googleapis.com/envoy.config.listener.v3.Listener" + resources { + [type.googleapis.com/envoy.config.listener.v3.Listener] { + name: "server.example.com" + api_listener { + api_listener { + [type.googleapis.com/envoy.extensions.filters.network + .http_connection_manager.v3.HttpConnectionManager] { + http_filters { + name: "router" + typed_config { + [type.googleapis.com/ + envoy.extensions.filters.http.router.v3.Router] {} + } + } + rds { + route_config_name: "route_config" + config_source { self {} } + } + } + } + } + } + } + } + } + } +)pb"; + +static const char* basic_route_config = R"pb( + bootstrap: "{\"xds_servers\": [{\"server_uri\":\"xds.example.com:443\", \"channel_creds\":[{\"type\": \"fake\"}]}]}" + actions { + start_watch { + resource_type { route_config {} } + resource_name: "route_config1" + } + } + actions { + read_message_from_client { + stream_id { ads {} } + ok: true + } + } + actions { + send_message_to_client { + stream_id { ads {} } + response { + version_info: "1" + nonce: "A" + type_url: "type.googleapis.com/envoy.config.route.v3.RouteConfiguration" + resources { + [type.googleapis.com/envoy.config.route.v3.RouteConfiguration] { + name: "route_config1" + virtual_hosts { + domains: "*" + routes { + match { prefix: "" } + route { cluster: "cluster1" } + } + } + } + } + } + } + } +)pb"; + +static const char* basic_xds_servers_empty = R"pb( + bootstrap: "{\"xds_servers\": []}" + actions { + start_watch { + resource_type { listener {} } + resource_name: "\003" + } + } +)pb"; + +static const char* resource_wrapper_empty = R"pb( + bootstrap: "{\"xds_servers\": [{\"server_uri\":\"xds.example.com:443\", \"channel_creds\":[{\"type\": \"fake\"}]}]}" + actions { start_watch { resource_type { cluster {} } } } + actions { + send_message_to_client { + stream_id { ads {} } + response { + version_info: "envoy.config.cluster.v3.Cluster" + resources { type_url: "envoy.service.discovery.v3.Resource" } + canary: true + type_url: "envoy.config.cluster.v3.Cluster" + nonce: "envoy.config.cluster.v3.Cluster" + } + } + } +)pb"; + +static const char* rls_missing_typed_extension_config = R"pb( + bootstrap: "{\"xds_servers\": [{\"server_uri\":\"xds.example.com:-257\", \"channel_creds\":[{\"type\": \"fake\"}]}]}" + actions { start_watch { resource_type { route_config {} } } } + actions { + send_message_to_client { + stream_id { ads {} } + response { + version_info: "grpc.lookup.v1.RouteLookup" + resources { + type_url: "envoy.config.route.v3.RouteConfiguration" + value: "\010\001b\000" + } + type_url: "envoy.config.route.v3.RouteConfiguration" + nonce: "/@\001\000\\\000\000x141183468234106731687303715884105729" + } + } + } +)pb"; + +static const char* send_message_to_client_before_stream_created = R"pb( + bootstrap: "{\"xds_servers\": [{\"server_uri\":\"xds.example.com:443\", \"channel_creds\":[{\"type\": \"fake\"}]}]}" + actions { send_message_to_client { stream_id { ads {} } } } +)pb"; + +auto ParseTestProto(const std::string& proto) { + xds_client_fuzzer::Msg msg; + CHECK(google::protobuf::TextFormat::ParseFromString(proto, &msg)); + return msg; +} + +void Fuzz(const xds_client_fuzzer::Msg& message) { + Fuzzer fuzzer(message.bootstrap(), message.fuzzing_event_engine_actions()); for (int i = 0; i < message.actions_size(); i++) { fuzzer.Act(message.actions(i)); } } +FUZZ_TEST(XdsClientFuzzer, Fuzz) + .WithDomains(::fuzztest::Arbitrary().WithSeeds( + {ParseTestProto(assert_entry_is_null), ParseTestProto(basic_cluster), + ParseTestProto(basic_endpoint), ParseTestProto(basic_listener), + ParseTestProto(basic_route_config), + ParseTestProto(basic_xds_servers_empty), + ParseTestProto(resource_wrapper_empty), + ParseTestProto(rls_missing_typed_extension_config), + ParseTestProto(send_message_to_client_before_stream_created)})); + +} // namespace grpc_core