diff --git a/test/core/end2end/fuzzers/BUILD b/test/core/end2end/fuzzers/BUILD index 71a33217144..542a8ab992a 100644 --- a/test/core/end2end/fuzzers/BUILD +++ b/test/core/end2end/fuzzers/BUILD @@ -26,6 +26,7 @@ grpc_proto_library( deps = [ "//test/core/event_engine/fuzzing_event_engine:fuzzing_event_engine_proto", "//test/core/util:fuzz_config_vars_proto", + "//test/core/util:fuzzing_channel_args_proto", ], ) @@ -65,6 +66,7 @@ grpc_proto_fuzzer( "//test/core/end2end:ssl_test_data", "//test/core/event_engine/fuzzing_event_engine", "//test/core/util:fuzz_config_vars", + "//test/core/util:fuzzing_channel_args", "//test/core/util:grpc_test_util", "//test/core/util:grpc_test_util_base", ], diff --git a/test/core/end2end/fuzzers/api_fuzzer.cc b/test/core/end2end/fuzzers/api_fuzzer.cc index d341dcdf216..9cc71a3a9c0 100644 --- a/test/core/end2end/fuzzers/api_fuzzer.cc +++ b/test/core/end2end/fuzzers/api_fuzzer.cc @@ -52,6 +52,7 @@ #include "src/core/lib/experiments/config.h" #include "src/core/lib/gprpp/debug_location.h" #include "src/core/lib/gprpp/env.h" +#include "src/core/lib/gprpp/ref_counted_ptr.h" #include "src/core/lib/gprpp/time.h" #include "src/core/lib/iomgr/closure.h" #include "src/core/lib/iomgr/exec_ctx.h" @@ -61,6 +62,8 @@ #include "src/core/lib/iomgr/resolved_address.h" #include "src/core/lib/iomgr/timer_manager.h" #include "src/core/lib/resolver/server_address.h" +#include "src/core/lib/resource_quota/memory_quota.h" +#include "src/core/lib/resource_quota/resource_quota.h" #include "src/core/lib/slice/slice_internal.h" #include "src/core/lib/surface/channel.h" #include "src/libfuzzer/libfuzzer_macro.h" @@ -70,6 +73,7 @@ #include "test/core/event_engine/fuzzing_event_engine/fuzzing_event_engine.h" #include "test/core/event_engine/fuzzing_event_engine/fuzzing_event_engine.pb.h" #include "test/core/util/fuzz_config_vars.h" +#include "test/core/util/fuzzing_channel_args.h" // IWYU pragma: no_include @@ -272,7 +276,7 @@ class ApiFuzzer : public BasicFuzzer { grpc_completion_queue* cq_ = nullptr; grpc_server* server_ = nullptr; grpc_channel* channel_ = nullptr; - grpc_resource_quota* resource_quota_; + grpc_core::RefCountedPtr resource_quota_; std::atomic channel_force_delete_{false}; std::vector> calls_; size_t active_call_ = 0; @@ -605,43 +609,6 @@ Call::~Call() { grpc_metadata_array_destroy(&recv_trailing_metadata_); } -template -grpc_channel_args* ReadArgs(grpc_resource_quota* resource_quota, - const ChannelArgContainer& args) { - grpc_channel_args* res = - static_cast(gpr_malloc(sizeof(grpc_channel_args))); - res->args = - static_cast(gpr_malloc(sizeof(grpc_arg) * args.size())); - int j = 0; - for (int i = 0; i < args.size(); i++) { - switch (args[i].value_case()) { - case api_fuzzer::ChannelArg::kStr: - res->args[j].type = GRPC_ARG_STRING; - res->args[j].value.string = gpr_strdup(args[i].str().c_str()); - break; - case api_fuzzer::ChannelArg::kI: - res->args[j].type = GRPC_ARG_INTEGER; - res->args[j].value.integer = args[i].i(); - break; - case api_fuzzer::ChannelArg::kResourceQuota: - if (args[i].key() != GRPC_ARG_RESOURCE_QUOTA) continue; - grpc_resource_quota_ref(resource_quota); - res->args[j].type = GRPC_ARG_POINTER; - res->args[j].value.pointer.p = resource_quota; - res->args[j].value.pointer.vtable = grpc_resource_quota_arg_vtable(); - break; - case api_fuzzer::ChannelArg::VALUE_NOT_SET: - res->args[j].type = GRPC_ARG_INTEGER; - res->args[j].value.integer = 0; - break; - } - res->args[j].key = gpr_strdup(args[i].key().c_str()); - ++j; - } - res->num_args = j; - return res; -} - static const char* ReadCredArtifact( const api_fuzzer::CredArtifact& artifact, std::initializer_list builtins) { @@ -774,9 +741,10 @@ int force_experiments = []() { }(); } -ApiFuzzer::ApiFuzzer() { - engine_ = - std::dynamic_pointer_cast(GetDefaultEventEngine()); +ApiFuzzer::ApiFuzzer() + : engine_(std::dynamic_pointer_cast( + GetDefaultEventEngine())), + resource_quota_(grpc_core::MakeResourceQuota("api_fuzzer")) { grpc_init(); grpc_timer_manager_set_threading(false); { @@ -791,7 +759,6 @@ ApiFuzzer::ApiFuzzer() { GPR_ASSERT(channel_ == nullptr); GPR_ASSERT(server_ == nullptr); - resource_quota_ = grpc_resource_quota_create("api_fuzzer"); cq_ = grpc_completion_queue_create_for_next(nullptr); } @@ -853,7 +820,6 @@ ApiFuzzer::~ApiFuzzer() { GPR_ASSERT(PollCq() == Result::kComplete); grpc_completion_queue_destroy(cq_); - grpc_resource_quota_unref(resource_quota_); grpc_shutdown_blocking(); engine_->UnsetGlobalHooks(); } @@ -885,20 +851,22 @@ ApiFuzzer::Result ApiFuzzer::PollCq() { ApiFuzzer::Result ApiFuzzer::CreateChannel( const api_fuzzer::CreateChannel& create_channel) { if (channel_ == nullptr) return Result::kComplete; - grpc_channel_args* args = - ReadArgs(resource_quota_, create_channel.channel_args()); + // ExecCtx is needed for ChannelArgs destruction. + grpc_core::ExecCtx exec_ctx; + grpc_core::testing::FuzzingEnvironment fuzzing_env; + fuzzing_env.resource_quota = resource_quota_; + grpc_core::ChannelArgs args = + grpc_core::testing::CreateChannelArgsFromFuzzingConfiguration( + create_channel.channel_args(), fuzzing_env); grpc_channel_credentials* creds = create_channel.has_channel_creds() ? ReadChannelCreds(create_channel.channel_creds()) : grpc_insecure_credentials_create(); - channel_ = grpc_channel_create(create_channel.target().c_str(), creds, args); + channel_ = grpc_channel_create(create_channel.target().c_str(), creds, + args.ToC().get()); grpc_channel_credentials_release(creds); GPR_ASSERT(channel_ != nullptr); channel_force_delete_ = false; - { - grpc_core::ExecCtx exec_ctx; - grpc_channel_args_destroy(args); - } return Result::kComplete; } @@ -915,14 +883,15 @@ ApiFuzzer::Result ApiFuzzer::CloseChannel() { ApiFuzzer::Result ApiFuzzer::CreateServer( const api_fuzzer::CreateServer& create_server) { if (server_ == nullptr) { - grpc_channel_args* args = - ReadArgs(resource_quota_, create_server.channel_args()); - server_ = grpc_server_create(args, nullptr); + // ExecCtx is needed for ChannelArgs destruction. + grpc_core::ExecCtx exec_ctx; + grpc_core::testing::FuzzingEnvironment fuzzing_env; + fuzzing_env.resource_quota = resource_quota_; + grpc_core::ChannelArgs args = + grpc_core::testing::CreateChannelArgsFromFuzzingConfiguration( + create_server.channel_args(), fuzzing_env); + server_ = grpc_server_create(args.ToC().get(), nullptr); GPR_ASSERT(server_ != nullptr); - { - grpc_core::ExecCtx exec_ctx; - grpc_channel_args_destroy(args); - } grpc_server_register_completion_queue(server_, cq_, nullptr); grpc_server_start(server_); server_shutdown_ = false; @@ -1131,7 +1100,7 @@ ApiFuzzer::Result ApiFuzzer::ValidateChannelTarget() { ApiFuzzer::Result ApiFuzzer::ResizeResourceQuota( uint32_t resize_resource_quota) { - grpc_resource_quota_resize(resource_quota_, resize_resource_quota); + resource_quota_->memory_quota()->SetSize(resize_resource_quota); return Result::kComplete; } diff --git a/test/core/end2end/fuzzers/api_fuzzer.proto b/test/core/end2end/fuzzers/api_fuzzer.proto index d00f63523cf..64d62671efa 100644 --- a/test/core/end2end/fuzzers/api_fuzzer.proto +++ b/test/core/end2end/fuzzers/api_fuzzer.proto @@ -18,6 +18,7 @@ package api_fuzzer; import "test/core/event_engine/fuzzing_event_engine/fuzzing_event_engine.proto"; import "test/core/util/fuzz_config_vars.proto"; +import "test/core/util/fuzzing_channel_args.proto"; message Empty {} @@ -33,17 +34,6 @@ message StringSlice { string value = 1; } -message ResourceQuota {} - -message ChannelArg { - string key = 1; - oneof value { - string str = 2; - int64 i = 3; - ResourceQuota resource_quota = 4; - } -} - message CredArtifact { oneof type { string custom = 1; @@ -95,12 +85,12 @@ message Metadatum { message CreateChannel { string target = 1; - repeated ChannelArg channel_args = 2; + grpc.testing.FuzzingChannelArgs channel_args = 2; ChannelCreds channel_creds = 3; } message CreateServer { - repeated ChannelArg channel_args = 1; + grpc.testing.FuzzingChannelArgs channel_args = 1; } message CreateCall { diff --git a/test/core/util/BUILD b/test/core/util/BUILD index 4e42201be97..48d7b11bbb8 100644 --- a/test/core/util/BUILD +++ b/test/core/util/BUILD @@ -421,3 +421,22 @@ grpc_cc_library( "//src/core:experiments", ], ) + +grpc_proto_library( + name = "fuzzing_channel_args_proto", + srcs = ["fuzzing_channel_args.proto"], + has_services = False, +) + +grpc_cc_library( + name = "fuzzing_channel_args", + srcs = ["fuzzing_channel_args.cc"], + hdrs = ["fuzzing_channel_args.h"], + deps = [ + "fuzzing_channel_args_proto", + "//:gpr_platform", + "//:ref_counted_ptr", + "//src/core:channel_args", + "//src/core:resource_quota", + ], +) diff --git a/test/core/util/fuzzing_channel_args.cc b/test/core/util/fuzzing_channel_args.cc new file mode 100644 index 00000000000..8e25f4d4003 --- /dev/null +++ b/test/core/util/fuzzing_channel_args.cc @@ -0,0 +1,54 @@ +// Copyright 2023 The gRPC Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#include + +#include "test/core/util/fuzzing_channel_args.h" + +#include "src/core/lib/channel/channel_args.h" +#include "src/core/lib/resource_quota/resource_quota.h" +#include "test/core/util/fuzzing_channel_args.pb.h" + +namespace grpc_core { +namespace testing { + +namespace { +using grpc::testing::FuzzingChannelArg; +} // namespace + +ChannelArgs CreateChannelArgsFromFuzzingConfiguration( + const grpc::testing::FuzzingChannelArgs& fuzzing_channel_args, + const FuzzingEnvironment& fuzzing_environment) { + ChannelArgs channel_args; + for (const auto& fuzz_arg : fuzzing_channel_args.args()) { + switch (fuzz_arg.value_case()) { + case FuzzingChannelArg::kStr: + channel_args = channel_args.Set(fuzz_arg.key(), fuzz_arg.str()); + break; + case FuzzingChannelArg::kI: + channel_args = channel_args.Set(fuzz_arg.key(), fuzz_arg.i()); + break; + case FuzzingChannelArg::kResourceQuota: + channel_args = + channel_args.SetObject(fuzzing_environment.resource_quota); + break; + default: + // ignore + break; + } + } + return channel_args; +} + +} // namespace testing +} // namespace grpc_core diff --git a/test/core/util/fuzzing_channel_args.h b/test/core/util/fuzzing_channel_args.h new file mode 100644 index 00000000000..4ace14a513d --- /dev/null +++ b/test/core/util/fuzzing_channel_args.h @@ -0,0 +1,43 @@ +// Copyright 2023 gRPC authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef GRPC_TEST_CORE_UTIL_FUZZING_CHANNEL_ARGS_H +#define GRPC_TEST_CORE_UTIL_FUZZING_CHANNEL_ARGS_H + +#include + +#include "src/core/lib/channel/channel_args.h" +#include "src/core/lib/gprpp/ref_counted_ptr.h" +#include "src/core/lib/resource_quota/resource_quota.h" +#include "test/core/util/fuzzing_channel_args.pb.h" + +namespace grpc_core { +namespace testing { + +struct FuzzingEnvironment { + // This resource quota is only added to ChannelArgs if the fuzzing + // configuration requests it. + RefCountedPtr resource_quota = + MakeResourceQuota("fuzzing_quota"); +}; + +// Create ChannelArgs from a fuzzer configuration. +ChannelArgs CreateChannelArgsFromFuzzingConfiguration( + const grpc::testing::FuzzingChannelArgs& fuzzing_channel_args, + const FuzzingEnvironment& fuzzing_environment); + +} // namespace testing +} // namespace grpc_core + +#endif // GRPC_TEST_CORE_UTIL_FUZZING_CHANNEL_ARGS_H diff --git a/test/core/util/fuzzing_channel_args.proto b/test/core/util/fuzzing_channel_args.proto new file mode 100644 index 00000000000..952f4d8d35b --- /dev/null +++ b/test/core/util/fuzzing_channel_args.proto @@ -0,0 +1,32 @@ +// Copyright 2023 gRPC authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +syntax = "proto3"; + +package grpc.testing; + +message ResourceQuota {} + +message FuzzingChannelArg { + string key = 1; + oneof value { + string str = 2; + int64 i = 3; + ResourceQuota resource_quota = 4; + } +} + +message FuzzingChannelArgs { + repeated FuzzingChannelArg args = 1; +}