[fuzzing] Extract and modernize ChannelArgs fuzzer configuration (#33161)

ChannelArgs fuzz configuration is expected to be used in other fuzzing
targets as well. This PR extracts the common code from the API fuzzer
and converts to use the C++ types.
pull/33187/head
AJ Heller 2 years ago committed by GitHub
parent ec31abdacf
commit 4fde5dabf6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      test/core/end2end/fuzzers/BUILD
  2. 85
      test/core/end2end/fuzzers/api_fuzzer.cc
  3. 16
      test/core/end2end/fuzzers/api_fuzzer.proto
  4. 19
      test/core/util/BUILD
  5. 54
      test/core/util/fuzzing_channel_args.cc
  6. 43
      test/core/util/fuzzing_channel_args.h
  7. 32
      test/core/util/fuzzing_channel_args.proto

@ -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",
],

@ -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 <google/protobuf/repeated_ptr_field.h>
@ -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<grpc_core::ResourceQuota> resource_quota_;
std::atomic<bool> channel_force_delete_{false};
std::vector<std::shared_ptr<Call>> calls_;
size_t active_call_ = 0;
@ -605,43 +609,6 @@ Call::~Call() {
grpc_metadata_array_destroy(&recv_trailing_metadata_);
}
template <typename ChannelArgContainer>
grpc_channel_args* ReadArgs(grpc_resource_quota* resource_quota,
const ChannelArgContainer& args) {
grpc_channel_args* res =
static_cast<grpc_channel_args*>(gpr_malloc(sizeof(grpc_channel_args)));
res->args =
static_cast<grpc_arg*>(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<const char*> builtins) {
@ -774,9 +741,10 @@ int force_experiments = []() {
}();
}
ApiFuzzer::ApiFuzzer() {
engine_ =
std::dynamic_pointer_cast<FuzzingEventEngine>(GetDefaultEventEngine());
ApiFuzzer::ApiFuzzer()
: engine_(std::dynamic_pointer_cast<FuzzingEventEngine>(
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;
}

@ -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 {

@ -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",
],
)

@ -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 <grpc/support/port_platform.h>
#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

@ -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 <grpc/support/port_platform.h>
#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<ResourceQuota> 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

@ -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;
}
Loading…
Cancel
Save