From a9bf741735f5749b49f58b47c29c0ff887754d9f Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Tue, 12 Sep 2023 13:43:14 -0700 Subject: [PATCH] [fuzzing] Make it easier for fuzzers to find experiments (#34296) The previous approach of generating strings was not converging well. Instead, load a bitfield from the protobuf and use the bits to select experiments. The fuzzers can explore this space swiftly. Downside is that as experiments rotate in/out the corpus gets a bit messed up, but I'm reasonably confident we'll recover quickly. --------- Co-authored-by: ctiller --- src/core/lib/config/config_vars.yaml | 1 + test/core/end2end/end2end_test_fuzzer.cc | 8 -------- test/core/util/fuzz_config_vars.proto | 2 +- test/core/util/fuzz_config_vars_helpers.cc | 20 +++++++++----------- test/core/util/fuzz_config_vars_helpers.h | 6 +++--- tools/codegen/core/gen_config_vars.py | 4 ++-- 6 files changed, 16 insertions(+), 25 deletions(-) diff --git a/src/core/lib/config/config_vars.yaml b/src/core/lib/config/config_vars.yaml index 1f300ab9640..8ccd41c2d41 100644 --- a/src/core/lib/config/config_vars.yaml +++ b/src/core/lib/config/config_vars.yaml @@ -35,6 +35,7 @@ A comma separated list of currently active experiments. Experiments may be prefixed with a '-' to disable them. default: + fuzz_type: uint64 fuzz: ValidateExperimentsStringForFuzzing - name: client_channel_backup_poll_interval_ms type: int diff --git a/test/core/end2end/end2end_test_fuzzer.cc b/test/core/end2end/end2end_test_fuzzer.cc index 5c14b898702..094f765e814 100644 --- a/test/core/end2end/end2end_test_fuzzer.cc +++ b/test/core/end2end/end2end_test_fuzzer.cc @@ -46,7 +46,6 @@ #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/fuzz_config_vars.pb.h" using ::grpc_event_engine::experimental::FuzzingEventEngine; using ::grpc_event_engine::experimental::GetDefaultEventEngine; @@ -100,8 +99,6 @@ DEFINE_PROTO_FUZZER(const core_end2end_test_fuzzer::Msg& msg) { return tests; }(); if (tests.empty()) return; - static const auto only_experiment = - grpc_core::GetEnv("GRPC_TEST_FUZZER_EXPERIMENT"); const int test_id = msg.test_id() % tests.size(); @@ -109,11 +106,6 @@ DEFINE_PROTO_FUZZER(const core_end2end_test_fuzzer::Msg& msg) { gpr_set_log_function(dont_log); } - if (only_experiment.has_value() && - msg.config_vars().experiments() != only_experiment.value()) { - return; - } - // TODO(ctiller): make this per fixture? grpc_core::ConfigVars::Overrides overrides = grpc_core::OverridesFromFuzzConfigVars(msg.config_vars()); diff --git a/test/core/util/fuzz_config_vars.proto b/test/core/util/fuzz_config_vars.proto index df71f6540f9..5c30dca2de8 100644 --- a/test/core/util/fuzz_config_vars.proto +++ b/test/core/util/fuzz_config_vars.proto @@ -25,6 +25,6 @@ message FuzzConfigVars { optional string dns_resolver = 76817901; optional string verbosity = 68420950; optional string stacktrace_minloglevel = 273035715; - optional string experiments = 510817011; + optional uint64 experiments = 510817011; optional string trace = 291231137; }; diff --git a/test/core/util/fuzz_config_vars_helpers.cc b/test/core/util/fuzz_config_vars_helpers.cc index e1b46a9d0c0..9029fdfd665 100644 --- a/test/core/util/fuzz_config_vars_helpers.cc +++ b/test/core/util/fuzz_config_vars_helpers.cc @@ -13,27 +13,25 @@ // limitations under the License. #include +#include -#include +#include #include +#include #include "absl/strings/str_join.h" -#include "absl/strings/str_split.h" -#include "absl/strings/string_view.h" #include "src/core/lib/experiments/config.h" #include "src/core/lib/experiments/experiments.h" namespace grpc_core { -std::string ValidateExperimentsStringForFuzzing(absl::string_view input) { - std::set experiments; - for (absl::string_view experiment : absl::StrSplit(input, ',')) { - for (size_t i = 0; i < kNumExperiments; i++) { - const auto& metadata = g_experiment_metadata[i]; - if (metadata.name == experiment && metadata.allow_in_fuzzing_config) { - experiments.insert(experiment); - } +std::string ValidateExperimentsStringForFuzzing(uint64_t input) { + std::vector experiments; + for (size_t i = 0; i < std::min(kNumExperiments, 64); i++) { + const auto& metadata = g_experiment_metadata[i]; + if ((input & (1ull << i)) && metadata.allow_in_fuzzing_config) { + experiments.push_back(metadata.name); } } return absl::StrJoin(experiments, ","); diff --git a/test/core/util/fuzz_config_vars_helpers.h b/test/core/util/fuzz_config_vars_helpers.h index 7024f083d20..9550b75bd7d 100644 --- a/test/core/util/fuzz_config_vars_helpers.h +++ b/test/core/util/fuzz_config_vars_helpers.h @@ -17,13 +17,13 @@ #include -#include +#include -#include "absl/strings/string_view.h" +#include namespace grpc_core { -std::string ValidateExperimentsStringForFuzzing(absl::string_view experiments); +std::string ValidateExperimentsStringForFuzzing(uint64_t experiments); } // namespace grpc_core diff --git a/tools/codegen/core/gen_config_vars.py b/tools/codegen/core/gen_config_vars.py index 4739c3351d1..0beae5d73e2 100755 --- a/tools/codegen/core/gen_config_vars.py +++ b/tools/codegen/core/gen_config_vars.py @@ -29,7 +29,7 @@ import sys import yaml with open("src/core/lib/config/config_vars.yaml") as f: - attrs = yaml.safe_load(f.read(), Loader=yaml.FullLoader) + attrs = yaml.safe_load(f.read()) error = False today = datetime.date.today() @@ -199,7 +199,7 @@ with open("test/core/util/fuzz_config_vars.proto", "w") as P: print( " optional %s %s = %d;" % ( - PROTO_TYPE[attr["type"]], + attr.get("fuzz_type", PROTO_TYPE[attr["type"]]), attr["name"], binascii.crc32(attr["name"].encode("ascii")) & 0x1FFFFFFF, ),