Skip to content

Commit

Permalink
x
Browse files Browse the repository at this point in the history
  • Loading branch information
ctiller committed Jan 21, 2024
1 parent 14d109b commit 1833829
Show file tree
Hide file tree
Showing 49 changed files with 508 additions and 61 deletions.
93 changes: 52 additions & 41 deletions src/core/ext/transport/chaotic_good/server/chaotic_good_server.cc
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ absl::StatusOr<int> ChaoticGoodServerListener::Bind(const char* addr) {
EventEngine::Listener::AcceptCallback accept_cb =
[self = Ref()](std::unique_ptr<EventEngine::Endpoint> ep,
MemoryAllocator) {
ExecCtx exec_ctx;
MutexLock lock(&self->mu_);
self->connection_list_.insert(self->connection_list_.end(),
MakeOrphanable<ActiveConnection>(self));
Expand Down Expand Up @@ -202,47 +203,57 @@ auto ChaoticGoodServerListener::ActiveConnection::HandshakingState::
// Parse frame header
auto frame_header = FrameHeader::Parse(reinterpret_cast<const uint8_t*>(
GRPC_SLICE_START_PTR(slice.c_slice())));
GPR_ASSERT(frame_header.ok());
return TrySeq(
self->connection_->endpoint_->Read(frame_header->GetFrameLength()),
[frame_header = *frame_header,
self](SliceBuffer buffer) -> absl::StatusOr<bool> {
// Read Setting frame.
SettingsFrame frame;
// Deserialize frame from read buffer.
BufferPair buffer_pair{std::move(buffer), SliceBuffer()};
auto status = frame.Deserialize(
&self->connection_->hpack_parser_, frame_header,
absl::BitGenRef(self->connection_->bitgen_),
GetContext<Arena>(), std::move(buffer_pair), FrameLimits{});
if (!status.ok()) return status;
if (frame.headers == nullptr) {
return absl::UnavailableError("no settings headers");
}
auto settings_metadata =
SettingsMetadata::FromMetadataBatch(*frame.headers);
if (!settings_metadata.ok()) {
return settings_metadata.status();
}
const bool is_control_endpoint =
settings_metadata->connection_type ==
SettingsMetadata::ConnectionType::kControl;
if (!is_control_endpoint) {
if (!settings_metadata->connection_id.has_value()) {
return absl::UnavailableError(
"no connection id in data endpoint settings frame");
}
if (!settings_metadata->alignment.has_value()) {
return absl::UnavailableError(
"no alignment in data endpoint settings frame");
}
// Get connection-id and data-alignment for data endpoint.
self->connection_->connection_id_ =
*settings_metadata->connection_id;
self->connection_->data_alignment_ =
*settings_metadata->alignment;
}
return is_control_endpoint;
return If(
frame_header.ok(),
[self, &frame_header]() {
return TrySeq(
self->connection_->endpoint_->Read(
frame_header->GetFrameLength()),
[frame_header = std::move(*frame_header),
self](SliceBuffer buffer) -> absl::StatusOr<bool> {
// Read Setting frame.
SettingsFrame frame;
// Deserialize frame from read buffer.
BufferPair buffer_pair{std::move(buffer), SliceBuffer()};
auto status = frame.Deserialize(
&self->connection_->hpack_parser_, frame_header,
absl::BitGenRef(self->connection_->bitgen_),
GetContext<Arena>(), std::move(buffer_pair),
FrameLimits{});
if (!status.ok()) return status;
if (frame.headers == nullptr) {
return absl::UnavailableError("no settings headers");
}
auto settings_metadata =
SettingsMetadata::FromMetadataBatch(*frame.headers);
if (!settings_metadata.ok()) {
return settings_metadata.status();
}
const bool is_control_endpoint =
settings_metadata->connection_type ==
SettingsMetadata::ConnectionType::kControl;
if (!is_control_endpoint) {
if (!settings_metadata->connection_id.has_value()) {
return absl::UnavailableError(
"no connection id in data endpoint settings frame");
}
if (!settings_metadata->alignment.has_value()) {
return absl::UnavailableError(
"no alignment in data endpoint settings frame");
}
// Get connection-id and data-alignment for data endpoint.
self->connection_->connection_id_ =
*settings_metadata->connection_id;
self->connection_->data_alignment_ =
*settings_metadata->alignment;
}
return is_control_endpoint;
});
},
[&frame_header]() {
return [r = frame_header.status()]() -> absl::StatusOr<bool> {
return r;
};
});
});
}
Expand Down
40 changes: 33 additions & 7 deletions test/core/end2end/fuzzers/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -121,24 +121,50 @@ grpc_proto_fuzzer(
],
)

grpc_proto_fuzzer(
grpc_cc_library(
name = "server_fuzzer",
srcs = ["server_fuzzer.cc"],
corpus = "server_fuzzer_corpus",
language = "C++",
proto = None,
tags = ["no_windows"],
uses_event_engine = False,
uses_polling = False,
hdrs = ["server_fuzzer.h"],
deps = [
"fuzzer_input_proto",
"fuzzing_common",
"network_input",
"//:gpr",
"//:grpc",
"//src/core:channel_args",
"//test/core/event_engine/fuzzing_event_engine",
"//test/core/util:fuzz_config_vars",
"//test/core/util:grpc_test_util",
"//test/core/util:grpc_test_util_base",
],
)

grpc_proto_fuzzer(
name = "server_fuzzer_chttp2",
srcs = ["server_fuzzer_chttp2.cc"],
corpus = "server_fuzzer_chttp2_corpus",
language = "C++",
proto = None,
tags = ["no_windows"],
uses_event_engine = False,
uses_polling = False,
deps = [
":server_fuzzer",
"//:grpc",
],
)

grpc_proto_fuzzer(
name = "server_fuzzer_chaotic_good",
srcs = ["server_fuzzer_chaotic_good.cc"],
corpus = "server_fuzzer_chaotic_good_corpus",
language = "C++",
proto = None,
tags = ["no_windows"],
uses_event_engine = False,
uses_polling = False,
deps = [
":server_fuzzer",
"//src/core:chaotic_good_server",
],
)
39 changes: 26 additions & 13 deletions test/core/end2end/fuzzers/server_fuzzer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,10 @@
#include <grpc/slice.h>
#include <grpc/support/log.h>

#include "src/core/lib/config/core_configuration.h"
#include "src/core/lib/experiments/config.h"
#include "src/core/lib/gprpp/env.h"
#include "src/core/lib/iomgr/exec_ctx.h"
#include "src/libfuzzer/libfuzzer_macro.h"
#include "test/core/end2end/fuzzers/api_fuzzer.pb.h"
#include "test/core/end2end/fuzzers/fuzzer_input.pb.h"
#include "test/core/end2end/fuzzers/fuzzing_common.h"
Expand All @@ -41,15 +41,24 @@ namespace testing {

class ServerFuzzer final : public BasicFuzzer {
public:
explicit ServerFuzzer(const fuzzer_input::Msg& msg)
explicit ServerFuzzer(
const fuzzer_input::Msg& msg,
absl::FunctionRef<void(grpc_server*, int, const ChannelArgs&)>
server_setup)
: BasicFuzzer(msg.event_engine_actions()) {
ExecCtx exec_ctx;
grpc_server_register_completion_queue(server_, cq(), nullptr);
// TODO(ctiller): add more registered methods (one for POST, one for PUT)
grpc_server_register_method(server_, "/reg", nullptr, {}, 0);
auto* creds = grpc_insecure_server_credentials_create();
grpc_server_add_http2_port(server_, "0.0.0.0:1234", creds);
grpc_server_credentials_release(creds);
server_setup(
server_, 1234,
CoreConfiguration::Get()
.channel_args_preconditioning()
.PreconditionChannelArgs(
CreateChannelArgsFromFuzzingConfiguration(
msg.channel_args(), FuzzingEnvironment{resource_quota()})
.ToC()
.get()));
grpc_server_start(server_);
for (const auto& input : msg.network_input()) {
UpdateMinimumRunTime(ScheduleConnection(
Expand Down Expand Up @@ -81,19 +90,23 @@ class ServerFuzzer final : public BasicFuzzer {
};

} // namespace testing
} // namespace grpc_core

DEFINE_PROTO_FUZZER(const fuzzer_input::Msg& msg) {
if (squelch && !grpc_core::GetEnv("GRPC_TRACE_FUZZER").has_value()) {
void RunServerFuzzer(
const fuzzer_input::Msg& msg,
absl::FunctionRef<void(grpc_server*, int, const ChannelArgs&)>
server_setup) {
if (squelch && !GetEnv("GRPC_TRACE_FUZZER").has_value()) {
gpr_set_log_function(dont_log);
}
static const int once = []() {
grpc_core::ForceEnableExperiment("event_engine_client", true);
grpc_core::ForceEnableExperiment("event_engine_listener", true);
ForceEnableExperiment("event_engine_client", true);
ForceEnableExperiment("event_engine_listener", true);
return 42;
}();
GPR_ASSERT(once == 42);
grpc_core::ApplyFuzzConfigVars(msg.config_vars());
grpc_core::TestOnlyReloadExperimentsFromConfigVariables();
grpc_core::testing::ServerFuzzer(msg).Run(msg.api_actions());
ApplyFuzzConfigVars(msg.config_vars());
TestOnlyReloadExperimentsFromConfigVariables();
testing::ServerFuzzer(msg, server_setup).Run(msg.api_actions());
}

} // namespace grpc_core
34 changes: 34 additions & 0 deletions test/core/end2end/fuzzers/server_fuzzer.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// Copyright 2024 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_END2END_FUZZERS_SERVER_FUZZER_H
#define GRPC_TEST_CORE_END2END_FUZZERS_SERVER_FUZZER_H

#include "absl/functional/function_ref.h"

#include <grpc/grpc.h>

#include "src/core/lib/channel/channel_args.h"
#include "test/core/end2end/fuzzers/fuzzer_input.pb.h"

namespace grpc_core {

void RunServerFuzzer(
const fuzzer_input::Msg& msg,
absl::FunctionRef<void(grpc_server*, int, const ChannelArgs&)>
server_setup);

} // namespace grpc_core

#endif
33 changes: 33 additions & 0 deletions test/core/end2end/fuzzers/server_fuzzer_chaotic_good.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// Copyright 2024 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/grpc_security.h>

#include "src/core/ext/transport/chaotic_good/server/chaotic_good_server.h"
#include "src/libfuzzer/libfuzzer_macro.h"
#include "test/core/end2end/fuzzers/server_fuzzer.h"

DEFINE_PROTO_FUZZER(const fuzzer_input::Msg& msg) {
grpc_core::RunServerFuzzer(
msg, [](grpc_server* server, int port_num,
const grpc_core::ChannelArgs& channel_args) {
grpc_core::ExecCtx exec_ctx;
auto* listener = new grpc_core::chaotic_good::ChaoticGoodServerListener(
grpc_core::Server::FromC(server), channel_args);
auto port =
listener->Bind(absl::StrCat("ipv4:0.0.0.0:", port_num).c_str());
GPR_ASSERT(port.ok());
GPR_ASSERT(port.value() == port_num);
});
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
network_input {
}
config_vars {
trace: ""
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
config_vars {
}
channel_args {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
channel_args {
args {
resource_quota {
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
api_actions {
}
event_engine_actions {
}
channel_args {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
api_actions {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
api_actions {
}
channel_args {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
config_vars {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
channel_args {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
api_actions {
}
api_actions {
}
channel_args {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
api_actions {
create_server {
}
}
channel_args {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
config_vars {
experiments: 0
}
channel_args {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
config_vars {
trace: ""
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
network_input {
single_read_bytes: "\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357"
}
channel_args {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
network_input {
input_segments {
segments {
header {
simple_header {
chaotic_good_alignment: "X"
}
}
}
}
}
config_vars {
stacktrace_minloglevel: ""
trace: ""
}
channel_args {
args {
i: 8
}
}
Loading

0 comments on commit 1833829

Please sign in to comment.