├── .bazelrc ├── .clang-format ├── .github └── workflows │ ├── bazel_test.yml │ ├── bazel_test_centipede.yml │ └── cmake_test.yml ├── CMakeLists.txt ├── CONTRIBUTING.md ├── LICENSE ├── MODULE.bazel ├── README.md ├── bazel ├── BUILD ├── antlr_cpp_runtime.BUILD └── setup_configs.sh ├── build_defs ├── BUILD └── cc_fuzztest_grammar_library.bzl ├── centipede ├── .clang-format ├── .github │ └── PULL_REQUEST_TEMPLATE ├── .gitignore ├── AUTHORS ├── BUILD ├── CONTRIBUTING.md ├── README.md ├── USER_MIGRATION.md ├── analyze_corpora.cc ├── analyze_corpora.h ├── analyze_corpora_test.cc ├── batch_fuzz_example │ ├── BUILD │ ├── README.md │ ├── customized_centipede.cc │ ├── customized_centipede.h │ ├── customized_centipede_main.cc │ ├── customized_centipede_test.cc │ ├── customized_centipede_test.sh │ └── standalone_fuzz_target_main.cc ├── binary_info.cc ├── binary_info.h ├── binary_info_test.cc ├── blob_file_converter.cc ├── byte_array_mutator.cc ├── byte_array_mutator.h ├── byte_array_mutator_test.cc ├── call_graph.cc ├── call_graph.h ├── call_graph_test.cc ├── callstack.h ├── callstack_test.cc ├── centipede.cc ├── centipede.h ├── centipede_binary_test.sh ├── centipede_callbacks.cc ├── centipede_callbacks.h ├── centipede_default_callbacks.cc ├── centipede_default_callbacks.h ├── centipede_flags.inc ├── centipede_interface.cc ├── centipede_interface.h ├── centipede_main.cc ├── centipede_test.cc ├── clang-flags.txt ├── command.cc ├── command.h ├── command_test.cc ├── command_test_helper.cc ├── concurrent_bitset.h ├── concurrent_bitset_test.cc ├── concurrent_byteset.h ├── concurrent_byteset_test.cc ├── config_file.cc ├── config_file.h ├── config_file_test.cc ├── config_init.cc ├── config_init.h ├── config_util.cc ├── config_util.h ├── config_util_test.cc ├── control_flow.cc ├── control_flow.h ├── control_flow_test.cc ├── corpus.cc ├── corpus.h ├── corpus_io.cc ├── corpus_io.h ├── corpus_io_test.cc ├── corpus_test.cc ├── coverage.cc ├── coverage.h ├── coverage_test.cc ├── distill.cc ├── distill.h ├── distill_test.cc ├── doc │ ├── DESIGN.md │ └── sitemap.md ├── dso_example │ ├── BUILD │ ├── build_and_run.sh │ ├── dso_example_test.sh │ ├── fuzz_me.cc │ └── main.cc ├── environment.cc ├── environment.h ├── environment_flags.cc ├── environment_flags.h ├── environment_test.cc ├── execution_metadata.cc ├── execution_metadata.h ├── execution_metadata_test.cc ├── feature.cc ├── feature.h ├── feature_set.cc ├── feature_set.h ├── feature_set_test.cc ├── feature_test.cc ├── foreach_nonzero.h ├── foreach_nonzero_test.cc ├── fuzztest_mutator.cc ├── fuzztest_mutator.h ├── fuzztest_mutator_test.cc ├── hashed_ring_buffer.h ├── hashed_ring_buffer_test.cc ├── install_dependencies_debian.sh ├── instrument.bzl ├── int_utils.h ├── int_utils_test.cc ├── knobs.cc ├── knobs.h ├── knobs_test.cc ├── minimize_crash.cc ├── minimize_crash.h ├── minimize_crash_test.cc ├── mutation_input.h ├── mutation_input_test.cc ├── pc_info.cc ├── pc_info.h ├── pc_info_test.cc ├── periodic_action.cc ├── periodic_action.h ├── periodic_action_test.cc ├── puzzles │ ├── BUILD │ ├── autodictionary_stress.cc │ ├── byte_cmp_4.cc │ ├── callstack.cc │ ├── deep_recursion.cc │ ├── independent_compares.cc │ ├── memcmp_3.cc │ ├── memcmp_4.cc │ ├── memcmp_4_may_inline.cc │ ├── oom.cc │ ├── paths.cc │ ├── per_batch_timeout.cc │ ├── per_input_timeout.cc │ ├── pthread_exit_uint32_cmp_1.cc │ ├── puzzle.bzl │ ├── run_puzzle.sh │ ├── strcmp.cc │ ├── strncmp.cc │ ├── thread_uint32_cmp_1.cc │ └── uint32_cmp_1.cc ├── resource_pool.cc ├── resource_pool.h ├── resource_pool_test.cc ├── reverse_pc_table.h ├── reverse_pc_table_test.cc ├── rolling_hash.h ├── rolling_hash_test.cc ├── run_test_workflow.sh ├── run_test_workflow_using_docker.sh ├── runner.cc ├── runner.h ├── runner_cmp_trace.h ├── runner_cmp_trace_test.cc ├── runner_dl_info.cc ├── runner_dl_info.h ├── runner_flags.cc ├── runner_flags.h ├── runner_flags_test.cc ├── runner_fork_server.cc ├── runner_interceptors.cc ├── runner_interface.h ├── runner_main.cc ├── runner_request.cc ├── runner_request.h ├── runner_result.cc ├── runner_result.h ├── runner_result_test.cc ├── runner_sancov.cc ├── runner_sancov_object.cc ├── runner_sancov_object.h ├── runner_utils.cc ├── runner_utils.h ├── rusage_profiler.cc ├── rusage_profiler.h ├── rusage_profiler_test.cc ├── rusage_stats.cc ├── rusage_stats.h ├── rusage_stats_test.cc ├── seed_corpus_config.proto ├── seed_corpus_maker.cc ├── seed_corpus_maker_flags.cc ├── seed_corpus_maker_flags.h ├── seed_corpus_maker_lib.cc ├── seed_corpus_maker_lib.h ├── seed_corpus_maker_lib_test.cc ├── seed_corpus_maker_proto_lib.cc ├── seed_corpus_maker_proto_lib.h ├── seed_corpus_maker_proto_lib_test.cc ├── shared_memory_blob_sequence.cc ├── shared_memory_blob_sequence.h ├── shared_memory_blob_sequence_test.cc ├── stats.cc ├── stats.h ├── stats_test.cc ├── stop.cc ├── stop.h ├── symbol_table.cc ├── symbol_table.h ├── symbol_table_test.cc ├── test_coverage_util.cc ├── test_coverage_util.h ├── test_fuzzing_util.sh ├── test_util.sh ├── testing │ ├── BUILD │ ├── abort_fuzz_target.cc │ ├── build_defs.bzl │ ├── centipede_main_test.sh │ ├── clusterfuzz_format_target.cc │ ├── clusterfuzz_format_test.sh │ ├── data_only_dso_target_lib.cc │ ├── data_only_dso_target_lib.h │ ├── data_only_dso_target_main.cc │ ├── data_only_dso_test.sh │ ├── dump_binary_info_test.sh │ ├── empty_fuzz_target.cc │ ├── expensive_startup_fuzz_target.cc │ ├── external_target.cc │ ├── external_target_server.cc │ ├── external_target_test.sh │ ├── fuzz_target_with_config.cc │ ├── fuzz_target_with_custom_mutator.cc │ ├── hanging_fuzz_target.cc │ ├── inline_8bit_counters_test.sh │ ├── instrumentation_test.sh │ ├── minimize_crash_test.sh │ ├── minimize_me_fuzz_target.cc │ ├── multi_dso_target_lib.cc │ ├── multi_dso_target_lib.h │ ├── multi_dso_target_main.cc │ ├── multi_dso_test.sh │ ├── multi_sanitizer_fuzz_target.cc │ ├── no_startup_features_test.sh │ ├── runner_test.sh │ ├── seeded_fuzz_target.cc │ ├── standalone_fuzz_target_with_main.cc │ ├── test_fuzz_target.cc │ ├── test_input_filter.sh │ ├── threaded_fuzz_target.cc │ ├── trace_pc_test.sh │ ├── user_defined_features_target.cc │ └── user_defined_features_test.sh ├── thread_pool.h ├── util.cc ├── util.h ├── util_test.cc ├── weak_sancov_stubs.cc ├── workdir.cc ├── workdir.h └── workdir_test.cc ├── cmake ├── AddFuzzTest.cmake ├── BuildDependencies.cmake ├── CMakeLists.txt.jinja ├── CompatibilityModeLinkLibFuzzer.cmake ├── FuzzTestFlagSetup.cmake ├── FuzzTestHelpers.cmake └── generate_cmake_from_bazel.py ├── codelab ├── .bazelrc ├── BUILD ├── CMakeLists.txt ├── MODULE.bazel ├── escaping.cc ├── escaping.h └── escaping_test.cc ├── common ├── BUILD ├── CMakeLists.txt ├── bazel.cc ├── bazel.h ├── blob_file.cc ├── blob_file.h ├── blob_file_test.cc ├── defs.h ├── hash.cc ├── hash.h ├── hash_test.cc ├── logging.h ├── remote_file.cc ├── remote_file.h ├── remote_file_oss.cc ├── remote_file_test.cc ├── sha1.cc ├── sha1.h ├── status_macros.h ├── temp_dir.cc ├── temp_dir.h ├── test_util.cc └── test_util.h ├── doc ├── code-of-conduct.md ├── contributing.md ├── domains-reference.md ├── fixtures.md ├── flags-reference.md ├── fuzz-test-macro.md ├── overview.md ├── quickstart-bazel.md ├── quickstart-cmake.md ├── team │ └── implementation.md └── use-cases.md ├── domain_tests ├── BUILD ├── CMakeLists.txt ├── aggregate_combinators_test.cc ├── arbitrary_domains_protobuf_test.cc ├── arbitrary_domains_test.cc ├── bitgen_ref_domain_test.cc ├── container_combinators_test.cc ├── container_test.cc ├── domain_testing.h ├── in_grammar_domain_test.cc ├── in_regexp_domain_test.cc ├── map_filter_combinator_test.cc ├── misc_domains_test.cc ├── numeric_domains_test.cc ├── pointer_domains_test.cc ├── recursive_domains_test.cc ├── specific_value_domains_test.cc └── string_domains_test.cc ├── e2e_tests ├── BUILD ├── CMakeLists.txt ├── benchmark_test.cc ├── compatibility_mode_test.cc ├── corpus_database_test.cc ├── functional_test.cc ├── test_binary_util.cc ├── test_binary_util.h └── testdata │ ├── BUILD │ ├── CMakeLists.txt │ ├── corpus_database │ └── fuzz_tests_for_functional_testing.stripped │ │ ├── MySuite.CrashOnCrashingInput │ │ └── crashing │ │ │ ├── crashing1 │ │ │ ├── crashing2 │ │ │ └── non_crashing │ │ ├── MySuite.CrashOnFailingTestInput │ │ └── crashing │ │ │ ├── crashing1 │ │ │ ├── crashing2 │ │ │ └── non_crashing │ │ └── MySuite.DetectRegressionAndCoverageInputs │ │ ├── coverage │ │ ├── coverage1 │ │ └── coverage2 │ │ └── regression │ │ └── regression1 │ ├── dynamically_registered_fuzz_tests.cc │ ├── fuzz_tests_for_corpus_database_testing.cc │ ├── fuzz_tests_for_functional_testing.cc │ ├── fuzz_tests_for_microbenchmarking.cc │ ├── fuzz_tests_using_googletest.cc │ ├── fuzz_tests_with_invalid_seeds.cc │ ├── fuzz_tests_with_proto_inputs.cc │ ├── llvm_fuzzer_with_custom_mutator.cc │ └── unit_test_and_fuzz_tests.cc ├── fuzztest ├── BUILD ├── CMakeLists.txt ├── domain.h ├── domain_core.h ├── fuzzing_bit_gen.cc ├── fuzzing_bit_gen.h ├── fuzztest.h ├── fuzztest_core.h ├── fuzztest_gtest_main.cc ├── fuzztest_macros.cc ├── fuzztest_macros.h ├── fuzztest_macros_test.cc ├── googletest_fixture_adapter.h ├── grammars │ ├── BUILD │ ├── CMakeLists.txt │ └── JSON.g4 ├── init_fuzztest.cc ├── init_fuzztest.h ├── internal │ ├── BUILD │ ├── CMakeLists.txt │ ├── any.h │ ├── any_test.cc │ ├── centipede_adaptor.cc │ ├── centipede_adaptor.h │ ├── compatibility_mode.cc │ ├── compatibility_mode.h │ ├── configuration.cc │ ├── configuration.h │ ├── configuration_test.cc │ ├── corpus_database.cc │ ├── corpus_database.h │ ├── coverage.cc │ ├── coverage.h │ ├── domains │ │ ├── BUILD │ │ ├── CMakeLists.txt │ │ ├── absl_helpers.h │ │ ├── aggregate_of_impl.h │ │ ├── arbitrary_impl.h │ │ ├── bit_flag_combination_of_impl.h │ │ ├── bit_gen_ref.h │ │ ├── container_mutation_helpers.h │ │ ├── container_of_impl.h │ │ ├── domain.h │ │ ├── domain_base.h │ │ ├── domain_type_erasure.h │ │ ├── element_of_impl.h │ │ ├── filter_impl.h │ │ ├── flat_map_impl.h │ │ ├── in_grammar_impl.cc │ │ ├── in_grammar_impl.h │ │ ├── in_range_impl.h │ │ ├── in_regexp_impl.cc │ │ ├── in_regexp_impl.h │ │ ├── map_impl.h │ │ ├── mutation_metadata.h │ │ ├── one_of_impl.h │ │ ├── optional_of_impl.h │ │ ├── overlap_of_impl.h │ │ ├── protobuf_domain_impl.h │ │ ├── regexp_dfa.cc │ │ ├── regexp_dfa.h │ │ ├── rune.cc │ │ ├── rune.h │ │ ├── serialization_helpers.h │ │ ├── smart_pointer_of_impl.h │ │ ├── special_values.h │ │ ├── unique_elements_container_of_impl.h │ │ ├── utf.cc │ │ ├── utf.h │ │ ├── value_mutation_helpers.h │ │ └── variant_of_impl.h │ ├── escaping.cc │ ├── escaping.h │ ├── fixture_driver.cc │ ├── fixture_driver.h │ ├── fixture_driver_test.cc │ ├── flag_name.h │ ├── googletest_adaptor.cc │ ├── googletest_adaptor.h │ ├── io.cc │ ├── io.h │ ├── io_test.cc │ ├── logging.cc │ ├── logging.h │ ├── meta.h │ ├── printer.h │ ├── register_fuzzing_mocks.cc │ ├── register_fuzzing_mocks.h │ ├── registration.h │ ├── registry.cc │ ├── registry.h │ ├── runtime.cc │ ├── runtime.h │ ├── runtime_test.cc │ ├── seed_seq.cc │ ├── seed_seq.h │ ├── seed_seq_test.cc │ ├── serialization.cc │ ├── serialization.h │ ├── serialization_test.cc │ ├── status.cc │ ├── status.h │ ├── subprocess.cc │ ├── subprocess.h │ ├── subprocess_test.cc │ ├── table_of_recent_compares.h │ ├── table_of_recent_compares_test.cc │ ├── test_protobuf.proto │ ├── type_support.cc │ ├── type_support.h │ └── type_support_test.cc ├── llvm_fuzzer_main.cc └── llvm_fuzzer_wrapper.cc ├── grammar_codegen ├── BUILD ├── CMakeLists.txt ├── antlr_frontend.cc ├── antlr_frontend.h ├── backend.cc ├── backend.h ├── backend_test.cc ├── code_generation.cc ├── code_generation.h ├── code_generation_test.cc ├── generated_antlr_parser │ ├── ANTLRv4Lexer.cpp │ ├── ANTLRv4Lexer.h │ ├── ANTLRv4Parser.cpp │ ├── ANTLRv4Parser.h │ ├── ANTLRv4ParserBaseListener.cpp │ ├── ANTLRv4ParserBaseListener.h │ ├── ANTLRv4ParserListener.cpp │ ├── ANTLRv4ParserListener.h │ ├── BUILD │ ├── CMakeLists.txt │ └── README.md ├── grammar_info.h └── testdata │ ├── expected_json_grammar.h │ └── expected_json_grammar_with_spaces.h └── tools ├── BUILD ├── CMakeLists.txt ├── grammar_domain_code_generator.cc └── minimizer.sh /.bazelrc: -------------------------------------------------------------------------------- 1 | # Copyright 2022 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | common --enable_platform_specific_config 16 | 17 | # Force the use of Clang for all builds. 18 | build --action_env=CC=clang 19 | build --action_env=CXX=clang++ 20 | 21 | # Use the C++17 standard. 22 | build --cxxopt=-std=c++17 23 | # Warn about the extensions that are not supported in C++17. 24 | # TODO(b/391433873): Turn warnings into errors once existing warnings are fixed. 25 | build --cxxopt=-Wc++17-compat-pedantic 26 | # Required by the cc_fuzztest_grammar_library rule, which uses the 27 | # "exec configuration" (https://bazel.build/reference/be/general#cross-compilation-considerations). 28 | # The --cxxopt flag does not apply to the exec configuration, only the 29 | # --host_cxxopt flag (https://bazel.build/docs/user-manual#host-cxxopt). 30 | build --host_cxxopt=-std=c++17 31 | build --host_cxxopt=-Wc++17-compat-pedantic 32 | 33 | # Build GoogleTest with ABSL support. 34 | build --define absl=1 35 | 36 | build:macos --macos_minimum_os=10.15 37 | 38 | # To create this file, please run: 39 | # 40 | # bazel run //bazel:setup_configs > fuzztest.bazelrc 41 | # 42 | try-import %workspace%/fuzztest.bazelrc 43 | -------------------------------------------------------------------------------- /.clang-format: -------------------------------------------------------------------------------- 1 | # Copyright 2022 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | BasedOnStyle: Google 16 | Language: Cpp 17 | # Force int* foo spacing style: 18 | DerivePointerAlignment: false 19 | PointerAlignment: Left -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # How to Contribute 2 | 3 | We'd love to accept your patches and contributions to this project. There are 4 | just a few small guidelines you need to follow. 5 | 6 | ## Contributor License Agreement 7 | 8 | Contributions to this project must be accompanied by a Contributor License 9 | Agreement. You (or your employer) retain the copyright to your contribution; 10 | this simply gives us permission to use and redistribute your contributions as 11 | part of the project. Head over to to see 12 | your current agreements on file or to sign a new one. 13 | 14 | You generally only need to submit a CLA once, so if you've already submitted one 15 | (even if it was for a different project), you probably don't need to do it 16 | again. 17 | 18 | ## Code Reviews 19 | 20 | All submissions, including submissions by project members, require review. We 21 | use GitHub pull requests for this purpose. Consult 22 | [GitHub Help](https://help.github.com/articles/about-pull-requests/) for more 23 | information on using pull requests. 24 | 25 | ## Community Guidelines 26 | 27 | This project follows [Google's Open Source Community 28 | Guidelines](https://opensource.google/conduct/). 29 | -------------------------------------------------------------------------------- /bazel/BUILD: -------------------------------------------------------------------------------- 1 | # Copyright 2022 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | package(default_visibility = ["//visibility:private"]) 16 | 17 | licenses(["notice"]) 18 | 19 | sh_binary( 20 | name = "setup_configs", 21 | srcs = ["setup_configs.sh"], 22 | # To determine if the script runs from the fuzztest repo or from a client repo. 23 | args = [repository_name()], 24 | visibility = ["//visibility:public"], 25 | ) 26 | -------------------------------------------------------------------------------- /bazel/antlr_cpp_runtime.BUILD: -------------------------------------------------------------------------------- 1 | # Copyright 2023 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | licenses(["notice"]) 16 | 17 | cc_library( 18 | name = "antlr_cpp", 19 | srcs = glob(["runtime/src/**/*.cpp"]), 20 | hdrs = ["runtime/src/antlr4-runtime.h"], 21 | copts = ["-fexceptions"], 22 | defines = ["ANTLR4CPP_USING_ABSEIL"], 23 | features = ["-use_header_modules"], 24 | includes = ["runtime/src"], 25 | textual_hdrs = glob( 26 | ["runtime/src/**/*.h"], 27 | exclude = ["runtime/src/antlr4-runtime.h"], 28 | ), 29 | visibility = ["//visibility:public"], 30 | deps = [ 31 | "@abseil-cpp//absl/base", 32 | "@abseil-cpp//absl/base:core_headers", 33 | "@abseil-cpp//absl/container:flat_hash_map", 34 | "@abseil-cpp//absl/container:flat_hash_set", 35 | "@abseil-cpp//absl/synchronization", 36 | ], 37 | ) 38 | 39 | alias( 40 | name = "antlr4-cpp-runtime", 41 | actual = "@antlr_cpp//:antlr4-cpp-runtime", 42 | ) -------------------------------------------------------------------------------- /build_defs/BUILD: -------------------------------------------------------------------------------- 1 | # Copyright 2022 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | # Starlark rules. 16 | 17 | #load("//tools/build_defs/testing:bzl_library.bzl", "bzl_library") 18 | 19 | package(default_visibility = ["//visibility:public"]) 20 | 21 | licenses(["notice"]) 22 | -------------------------------------------------------------------------------- /centipede/.clang-format: -------------------------------------------------------------------------------- 1 | BasedOnStyle: Google 2 | Language: Cpp 3 | # Force int* foo spacing style: 4 | DerivePointerAlignment: false 5 | PointerAlignment: Left 6 | -------------------------------------------------------------------------------- /centipede/.github/PULL_REQUEST_TEMPLATE: -------------------------------------------------------------------------------- 1 | We are not yet accepting external contributions at this time. Stay tuned. 2 | -------------------------------------------------------------------------------- /centipede/.gitignore: -------------------------------------------------------------------------------- 1 | # Ignore the Google-only sources. 2 | /copybara 3 | /google 4 | /production 5 | /puzzles 6 | /testing 7 | -------------------------------------------------------------------------------- /centipede/AUTHORS: -------------------------------------------------------------------------------- 1 | # This is the list of Centipede's significant contributors. 2 | # 3 | # This does not necessarily list everyone who has contributed code, 4 | # especially since many employees of one corporation may be contributing. 5 | # To see the full list of contributors, see the revision history in 6 | # source control. 7 | Google LLC 8 | Kostya Serebryany 9 | -------------------------------------------------------------------------------- /centipede/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # How to contribute 2 | 3 | We are not yet accepting external contributions at this time. Stay tuned. 4 | -------------------------------------------------------------------------------- /centipede/USER_MIGRATION.md: -------------------------------------------------------------------------------- 1 | # Centipede User Migration 2 | 3 | Centipede has been merged into FuzzTest to consolidate fuzzing development. 4 | 5 | If your projects do not use Bazel other than building the Centipede binaries, 6 | the build instructions have been updated in [README.md](./README.md). 7 | 8 | If your projects integrate Centipede in Bazel workspaces, update your Centipede 9 | references with the following steps: 10 | 11 | 1. In the Bazel WORKSPACE files, remove the Centipede respository 12 | (https://github.com/google/centipede), and add the 13 | [FuzzTest](../doc/quickstart-bazel.md#set-up-a-bazel-workspace) repository 14 | and any missing dependencies instead. 15 | 16 | 2. In the Bazel BUILD/bzl files, replace any references of the Centipede 17 | repository `@centipede//` with the new package path 18 | `@com_google_fuzztest//centipede` in the FuzzTest repository. E.g. 19 | `@centipede//:centipede_runner` becomes 20 | `@com_google_fuzztest//centipede:centipede_runner`. 21 | -------------------------------------------------------------------------------- /centipede/batch_fuzz_example/README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google/fuzztest/61e6d3d42d981704941f026e139445ac460ed144/centipede/batch_fuzz_example/README.md -------------------------------------------------------------------------------- /centipede/batch_fuzz_example/customized_centipede.h: -------------------------------------------------------------------------------- 1 | // Copyright 2023 The Centipede Authors. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // https://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #ifndef THIRD_PARTY_CENTIPEDE_BATCH_FUZZ_EXAMPLE_CUSTOMIZED_CENTIPEDE_H_ 16 | #define THIRD_PARTY_CENTIPEDE_BATCH_FUZZ_EXAMPLE_CUSTOMIZED_CENTIPEDE_H_ 17 | 18 | #include 19 | 20 | #include 21 | 22 | #include "absl/strings/string_view.h" 23 | #include "./centipede/centipede_callbacks.h" 24 | #include "./centipede/environment.h" 25 | #include "./centipede/runner_result.h" 26 | #include "./common/defs.h" 27 | 28 | namespace fuzztest::internal { 29 | 30 | // This class implements the `Execute()` method of the `CentipedeCallbacks` 31 | // class. It saves a collection of inputs into files and passes them to a target 32 | // binary. The binary should exercise them in a batch and store the execution 33 | // result of each input into an output file. Those execution results will be 34 | // loaded from the output file and packed as the given `batch_result`. 35 | class CustomizedCallbacks : public CentipedeCallbacks { 36 | public: 37 | explicit CustomizedCallbacks(const Environment& env) 38 | : CustomizedCallbacks(env, /*feature_only_feedback=*/false) {} 39 | 40 | explicit CustomizedCallbacks(const Environment& env, 41 | bool feature_only_feedback); 42 | 43 | bool Execute(std::string_view binary, const std::vector& inputs, 44 | BatchResult& batch_result) override; 45 | 46 | private: 47 | const bool feature_only_feedback_; 48 | }; 49 | 50 | } // namespace fuzztest::internal 51 | 52 | #endif // THIRD_PARTY_CENTIPEDE_BATCH_FUZZ_EXAMPLE_CUSTOMIZED_CENTIPEDE_H_ 53 | -------------------------------------------------------------------------------- /centipede/batch_fuzz_example/customized_centipede_main.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2023 The Centipede Authors. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // https://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include "absl/base/nullability.h" 16 | #include "./centipede/batch_fuzz_example/customized_centipede.h" 17 | #include "./centipede/centipede_callbacks.h" 18 | #include "./centipede/centipede_interface.h" 19 | #include "./centipede/config_file.h" 20 | #include "./centipede/environment_flags.h" 21 | 22 | int main(int argc, char** absl_nonnull argv) { 23 | const auto runtime_state = fuzztest::internal::InitCentipede(argc, argv); 24 | // Reads flags; must happen after InitCentipede(). 25 | const auto env = fuzztest::internal::CreateEnvironmentFromFlags( 26 | runtime_state->leftover_argv()); 27 | fuzztest::internal::DefaultCallbacksFactory< 28 | fuzztest::internal::CustomizedCallbacks> 29 | callbacks_factory; 30 | return CentipedeMain(env, callbacks_factory); 31 | } 32 | -------------------------------------------------------------------------------- /centipede/centipede_binary_test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Copyright 2022 The Centipede Authors. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # https://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | # Verify that the `:centipede` build target indeed creates the expected binary. 18 | 19 | set -eu 20 | 21 | source "$(dirname "$0")/test_util.sh" 22 | 23 | centipede_test_srcdir="$(fuzztest::internal::get_centipede_test_srcdir)" 24 | centipede_binary="${centipede_test_srcdir}/centipede" 25 | if ! [[ -x "${centipede_binary}" ]]; then 26 | die "Build target ':centipede' failed to create expected executable \ 27 | ${centipede_binary}" 28 | fi 29 | -------------------------------------------------------------------------------- /centipede/centipede_default_callbacks.h: -------------------------------------------------------------------------------- 1 | // Copyright 2022 The Centipede Authors. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // https://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // Example fuzzer built on top of Centipede. It is capable of fuzzing any binary 16 | // target built with sancov (see build_defs.bzl). CentipedeCallbacks::Mutate 17 | // uses ByteArrayMutator. 18 | 19 | #ifndef THIRD_PARTY_CENTIPEDE_CENTIPEDE_DEFAULT_CALLBACKS_H_ 20 | #define THIRD_PARTY_CENTIPEDE_CENTIPEDE_DEFAULT_CALLBACKS_H_ 21 | 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | #include "absl/status/statusor.h" 29 | #include "./centipede/centipede_callbacks.h" 30 | #include "./centipede/environment.h" 31 | #include "./centipede/mutation_input.h" 32 | #include "./centipede/runner_result.h" 33 | #include "./common/defs.h" 34 | 35 | namespace fuzztest::internal { 36 | 37 | // Example of customized CentipedeCallbacks. 38 | class CentipedeDefaultCallbacks : public CentipedeCallbacks { 39 | public: 40 | explicit CentipedeDefaultCallbacks(const Environment &env); 41 | size_t GetSeeds(size_t num_seeds, std::vector &seeds) override; 42 | absl::StatusOr GetSerializedTargetConfig() override; 43 | bool Execute(std::string_view binary, const std::vector &inputs, 44 | BatchResult &batch_result) override; 45 | std::vector Mutate(const std::vector &inputs, 46 | size_t num_mutants) override; 47 | 48 | private: 49 | std::optional custom_mutator_is_usable_ = std::nullopt; 50 | }; 51 | 52 | } // namespace fuzztest::internal 53 | 54 | #endif // THIRD_PARTY_CENTIPEDE_CENTIPEDE_DEFAULT_CALLBACKS_H_ 55 | -------------------------------------------------------------------------------- /centipede/centipede_interface.h: -------------------------------------------------------------------------------- 1 | // Copyright 2022 The Centipede Authors. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // https://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #ifndef THIRD_PARTY_CENTIPEDE_CENTIPEDE_INTERFACE_H_ 16 | #define THIRD_PARTY_CENTIPEDE_CENTIPEDE_INTERFACE_H_ 17 | 18 | #include "./centipede/centipede_callbacks.h" 19 | #include "./centipede/environment.h" 20 | 21 | namespace fuzztest::internal { 22 | 23 | // Usage: 24 | // class MyCentipedeCallbacks: public CentipedeCallbacks { ... } 25 | // int main(int argc, char **argv) { 26 | // InitGoogle(argv[0], &argc, &argv, /*remove_flags=*/true); 27 | // fuzztest::internal::Environment env; // reads FLAGS. 28 | // fuzztest::internal::DefaultCallbacksFactory 29 | // callbacks_factory; return fuzztest::internal::CentipedeMain(env, 30 | // callbacks_factory); 31 | // } 32 | int CentipedeMain(const Environment &env, 33 | CentipedeCallbacksFactory &callbacks_factory); 34 | 35 | } // namespace fuzztest::internal 36 | 37 | #endif // THIRD_PARTY_CENTIPEDE_CENTIPEDE_INTERFACE_H_ 38 | -------------------------------------------------------------------------------- /centipede/centipede_main.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2022 The Centipede Authors. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // https://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include "absl/base/nullability.h" 16 | #include "./centipede/centipede_callbacks.h" 17 | #include "./centipede/centipede_default_callbacks.h" 18 | #include "./centipede/centipede_interface.h" 19 | #include "./centipede/config_file.h" 20 | #include "./centipede/environment_flags.h" 21 | 22 | int main(int argc, char** absl_nonnull argv) { 23 | const auto runtime_state = fuzztest::internal::InitCentipede(argc, argv); 24 | const auto env = fuzztest::internal::CreateEnvironmentFromFlags( 25 | runtime_state->leftover_argv()); 26 | fuzztest::internal::DefaultCallbacksFactory< 27 | fuzztest::internal::CentipedeDefaultCallbacks> 28 | callbacks; 29 | return CentipedeMain(env, callbacks); 30 | } 31 | -------------------------------------------------------------------------------- /centipede/clang-flags.txt: -------------------------------------------------------------------------------- 1 | -DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION 2 | -fno-builtin 3 | -fsanitize-coverage=trace-pc-guard,pc-table,trace-cmp 4 | -O2 5 | -gline-tables-only 6 | -------------------------------------------------------------------------------- /centipede/command_test_helper.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2022 The Centipede Authors. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // https://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include 16 | 17 | #include 18 | #include 19 | #include 20 | #include 21 | 22 | #include "absl/base/nullability.h" 23 | 24 | // A binary linked with the fork server that exits/crashes in different ways. 25 | int main(int argc, char** absl_nonnull argv) { 26 | assert(argc == 2); 27 | printf("Got input: %s", argv[1]); 28 | fflush(stdout); 29 | if (!strcmp(argv[1], "success")) return EXIT_SUCCESS; 30 | if (!strcmp(argv[1], "fail")) return EXIT_FAILURE; 31 | if (!strcmp(argv[1], "ret42")) return 42; 32 | if (!strcmp(argv[1], "abort")) abort(); 33 | // Sleep longer than kTimeout in CommandDeathTest_ForkServerHangingBinary. 34 | if (!strcmp(argv[1], "hang")) sleep(5); 35 | return 17; 36 | } 37 | -------------------------------------------------------------------------------- /centipede/corpus_io.h: -------------------------------------------------------------------------------- 1 | // Copyright 2022 The Centipede Authors. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // https://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #ifndef THIRD_PARTY_CENTIPEDE_SHARD_READER_H_ 16 | #define THIRD_PARTY_CENTIPEDE_SHARD_READER_H_ 17 | 18 | #include 19 | #include 20 | #include 21 | 22 | #include "absl/types/span.h" 23 | #include "./centipede/feature.h" 24 | #include "./common/defs.h" 25 | 26 | namespace fuzztest::internal { 27 | 28 | // `corpus_path` is a path to a BlobFile with corpus elements (inputs). If the 29 | // path is empty or non-existent, no processing is done. 30 | // 31 | // `features_path` is a path to a BlobFile with {features/hash} pairs created by 32 | // `PackFeaturesAndHash()`. If the path is empty or non-existent, an empty 33 | // `FeatureVec` is passed to every call of `callback`. 34 | // 35 | // For every {features/hash} pair we need to find an input with this hash. 36 | // This function reads `corpus_path` and `features_path` and calls `callback` 37 | // on every pair {input, features}. 38 | // 39 | // If features are not found for a given input, callback's 2nd argument is {}. 40 | // 41 | // If features are found for a given input but are empty, 42 | // then callback's 2nd argument is {feature_domains::kNoFeature}. 43 | void ReadShard(std::string_view corpus_path, std::string_view features_path, 44 | const std::function &callback); 45 | 46 | // Unpacks the corpus from `sharded_file_paths` and writes each input to an 47 | // individual file in `out_dir`. The file names are the inputs' hashes. 48 | void ExportCorpus(absl::Span sharded_file_paths, 49 | std::string_view out_dir); 50 | 51 | } // namespace fuzztest::internal 52 | 53 | #endif // THIRD_PARTY_CENTIPEDE_SHARD_READER_H_ 54 | -------------------------------------------------------------------------------- /centipede/distill.h: -------------------------------------------------------------------------------- 1 | // Copyright 2023 The Centipede Authors. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // https://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #ifndef THIRD_PARTY_CENTIPEDE_DISTILL_H_ 16 | #define THIRD_PARTY_CENTIPEDE_DISTILL_H_ 17 | 18 | #include 19 | #include 20 | #include 21 | 22 | #include "./centipede/environment.h" 23 | 24 | namespace fuzztest::internal { 25 | 26 | // Options for `Distill()`. 27 | struct DistillOptions { 28 | // From each feature-equivalent set of inputs, select up to this many winners. 29 | uint8_t feature_frequency_threshold = 1; 30 | }; 31 | 32 | // Reads `env.total_shards` input shards from `WorkDir{env}.CorpusFiles()` and 33 | // `WorkDir{env}.FeaturesFiles()`, distills them, and writes out the winning 34 | // inputs to `env.num_threads` output shards. 35 | // 36 | // All reads and writes are parallelized for higher throughput. A side effect of 37 | // that is that the results are generally non-deterministic (for a given 38 | // feature-equivalent set of inputs, any one can win and make it to the output). 39 | // 40 | // Returns EXIT_SUCCESS. 41 | int Distill(const Environment &env, const DistillOptions &opts = {}); 42 | 43 | // Same as `Distill()`, but runs distillation without I/O parallelization and 44 | // reads shards in the order specified by `shard_indices` for deterministic 45 | // results. 46 | void DistillForTests(const Environment &env, 47 | const std::vector &shard_indices); 48 | 49 | } // namespace fuzztest::internal 50 | 51 | #endif // THIRD_PARTY_CENTIPEDE_DISTILL_H_ 52 | -------------------------------------------------------------------------------- /centipede/doc/sitemap.md: -------------------------------------------------------------------------------- 1 | # third_party/googlefuzztest/centipede 2 | 3 | * [README](../README.md) 4 | * [Centipede Design](DESIGN.md) 5 | -------------------------------------------------------------------------------- /centipede/dso_example/BUILD: -------------------------------------------------------------------------------- 1 | # Copyright 2022 The Centipede Authors. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # https://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | # Build file for the dso_example 16 | 17 | # Shared library that we want to fuzz, built with (some) coverage instrumentation. 18 | # It has unresolved instrumentation symbol(s) which will be resolved dynamically. 19 | cc_binary( 20 | name = "fuzz_me.so", 21 | srcs = ["fuzz_me.cc"], 22 | copts = ["-fsanitize-coverage=trace-pc"], 23 | linkshared = True, 24 | linkstatic = False, 25 | ) 26 | 27 | # The main binary that calls into :fuzz_me, which is linked dynamically. 28 | # Not instrumented with coverage. 29 | cc_binary( 30 | name = "main", 31 | srcs = [ 32 | "main.cc", 33 | ":fuzz_me.so", 34 | ], 35 | linkopts = ["-ldl"], 36 | linkstatic = False, 37 | deps = [ 38 | "@com_google_fuzztest//centipede:centipede_runner_no_main", # build-cleaner:keep 39 | ], 40 | ) 41 | 42 | # The main binary which dlopen-s fuzz_me and then calls FuzzMe. 43 | cc_binary( 44 | name = "main_with_dlopen", 45 | srcs = ["main.cc"], 46 | linkopts = ["-ldl"], 47 | linkstatic = False, 48 | ) 49 | 50 | sh_test( 51 | name = "dso_example_test", 52 | srcs = ["dso_example_test.sh"], 53 | data = [ 54 | ":fuzz_me.so", 55 | ":main", 56 | ":main_with_dlopen", 57 | "@com_google_fuzztest//centipede", 58 | "@com_google_fuzztest//centipede:centipede_runner_no_main.so", 59 | ], 60 | deps = [ 61 | "@com_google_fuzztest//centipede:test_util_sh", 62 | ], 63 | ) 64 | -------------------------------------------------------------------------------- /centipede/dso_example/fuzz_me.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2022 The Centipede Authors. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // https://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // An example of a fuzz target that resides in a separate DSO. 16 | 17 | #include 18 | #include 19 | 20 | extern "C" void FuzzMe(const uint8_t *data, size_t size) { 21 | if (size == 3 && data[0] == 'F' && data[1] == 'U' && data[2] == 'Z') 22 | __builtin_trap(); 23 | } 24 | -------------------------------------------------------------------------------- /centipede/environment_flags.h: -------------------------------------------------------------------------------- 1 | // Copyright 2023 The Centipede Authors. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // https://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #ifndef THIRD_PARTY_CENTIPEDE_ENVIRONMENT_FLAGS_H_ 16 | #define THIRD_PARTY_CENTIPEDE_ENVIRONMENT_FLAGS_H_ 17 | 18 | #include 19 | #include 20 | 21 | #include "./centipede/environment.h" 22 | 23 | namespace fuzztest::internal { 24 | 25 | // Create an Environment object from command line flags defined in 26 | // environment_flags.cc. 27 | Environment CreateEnvironmentFromFlags( 28 | const std::vector &argv = {}); 29 | 30 | } // namespace fuzztest::internal 31 | 32 | #endif // THIRD_PARTY_CENTIPEDE_ENVIRONMENT_FLAGS_H_ 33 | -------------------------------------------------------------------------------- /centipede/execution_metadata.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2023 The Centipede Authors. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // https://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include "./centipede/execution_metadata.h" 16 | 17 | #include 18 | #include 19 | 20 | #include "./centipede/shared_memory_blob_sequence.h" 21 | #include "./common/defs.h" 22 | 23 | namespace fuzztest::internal { 24 | 25 | bool ExecutionMetadata::AppendCmpEntry(ByteSpan a, ByteSpan b) { 26 | if (a.size() != b.size()) return false; 27 | // Size must fit in a byte. 28 | if (a.size() >= 256) return false; 29 | cmp_data.push_back(a.size()); 30 | cmp_data.insert(cmp_data.end(), a.begin(), a.end()); 31 | cmp_data.insert(cmp_data.end(), b.begin(), b.end()); 32 | return true; 33 | } 34 | 35 | bool ExecutionMetadata::Write(Blob::SizeAndTagT tag, 36 | BlobSequence &outputs_blobseq) const { 37 | return outputs_blobseq.Write({tag, cmp_data.size(), cmp_data.data()}); 38 | } 39 | 40 | void ExecutionMetadata::Read(Blob blob) { 41 | cmp_data.assign(blob.data, blob.data + blob.size); 42 | } 43 | 44 | bool ExecutionMetadata::ForEachCmpEntry( 45 | std::function callback) const { 46 | size_t i = 0; 47 | while (i < cmp_data.size()) { 48 | auto size = cmp_data[i]; 49 | if (i + 2 * size + 1 > cmp_data.size()) return false; 50 | ByteSpan a(cmp_data.data() + i + 1, size); 51 | ByteSpan b(cmp_data.data() + i + size + 1, size); 52 | i += 1 + 2 * size; 53 | callback(a, b); 54 | } 55 | return true; 56 | } 57 | 58 | } // namespace fuzztest::internal 59 | -------------------------------------------------------------------------------- /centipede/feature.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2022 The Centipede Authors. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // https://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // TODO(kcc): remove this file if nothing else gets added here. 16 | -------------------------------------------------------------------------------- /centipede/feature_test.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2022 The Centipede Authors. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // https://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include "./centipede/feature.h" 16 | 17 | #include "gtest/gtest.h" 18 | 19 | namespace fuzztest::internal { 20 | namespace { 21 | 22 | TEST(Feature, FeatureArray) { 23 | FeatureArray<3> array; 24 | EXPECT_EQ(array.size(), 0); 25 | array.push_back(10); 26 | EXPECT_EQ(array.size(), 1); 27 | array.push_back(20); 28 | EXPECT_EQ(array.size(), 2); 29 | array.clear(); 30 | EXPECT_EQ(array.size(), 0); 31 | array.push_back(10); 32 | array.push_back(20); 33 | array.push_back(30); 34 | EXPECT_EQ(array.size(), 3); 35 | array.push_back(40); // no space left. 36 | EXPECT_EQ(array.size(), 3); 37 | EXPECT_EQ(array.data()[0], 10); 38 | EXPECT_EQ(array.data()[1], 20); 39 | EXPECT_EQ(array.data()[2], 30); 40 | } 41 | 42 | } // namespace 43 | } // namespace fuzztest::internal 44 | -------------------------------------------------------------------------------- /centipede/hashed_ring_buffer_test.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2022 The Centipede Authors. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // https://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include "./centipede/hashed_ring_buffer.h" 16 | 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | 23 | #include "gtest/gtest.h" 24 | #include "absl/container/flat_hash_set.h" 25 | 26 | namespace fuzztest::internal { 27 | namespace { 28 | 29 | TEST(Feature, HashedRingBuffer) { 30 | HashedRingBuffer<32> rb16; // used with ring_buffer_size == 16 31 | HashedRingBuffer<32> rb32; // used with ring_buffer_size == 32 32 | rb16.Reset(16); 33 | rb32.Reset(32); 34 | absl::flat_hash_set hashes16, hashes32; 35 | size_t kNumIter = 10000000; 36 | // push a large number of different numbers into rb, ensure that most of the 37 | // resulting hashes are different. 38 | for (size_t i = 0; i < kNumIter; i++) { 39 | hashes16.insert(rb16.push(i)); 40 | hashes32.insert(rb32.push(i)); 41 | } 42 | // No collisions. 43 | EXPECT_EQ(hashes16.size(), kNumIter); 44 | EXPECT_EQ(hashes32.size(), kNumIter); 45 | 46 | // Try all permutations of {0, 1, 2, ... 9}, ensure we have at least half 47 | // this many different hashes. 48 | std::vector numbers(10); 49 | std::iota(numbers.begin(), numbers.end(), 0); 50 | hashes32.clear(); 51 | size_t num_permutations = 0; 52 | while (std::next_permutation(numbers.begin(), numbers.end())) { 53 | ++num_permutations; 54 | rb32.Reset(32); 55 | for (const auto number : numbers) { 56 | rb32.push(number); 57 | } 58 | hashes32.insert(rb32.hash()); 59 | } 60 | EXPECT_GT(hashes32.size(), num_permutations / 2); 61 | } 62 | 63 | } // namespace 64 | } // namespace fuzztest::internal 65 | -------------------------------------------------------------------------------- /centipede/int_utils.h: -------------------------------------------------------------------------------- 1 | // Copyright 2023 The Centipede Authors. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // https://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #ifndef THIRD_PARTY_CENTIPEDE_INT_UTILS_H_ 16 | #define THIRD_PARTY_CENTIPEDE_INT_UTILS_H_ 17 | 18 | #include 19 | 20 | namespace fuzztest::internal { 21 | 22 | // Computes a hash of `bits`. The purpose is to use the result for XOR-ing with 23 | // some other values, such that all resulting bits look random. 24 | inline uint64_t Hash64Bits(uint64_t bits) { 25 | // This particular prime number seems to mix bits well. 26 | // TODO(kcc): find a more scientific way to mix bits, e.g. switch to Murmur. 27 | constexpr uint64_t kPrime = 13441014529ULL; 28 | return bits * kPrime; 29 | } 30 | 31 | } // namespace fuzztest::internal 32 | 33 | #endif // THIRD_PARTY_CENTIPEDE_INT_UTILS_H_ 34 | -------------------------------------------------------------------------------- /centipede/knobs.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2022 The Centipede Authors. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // https://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include "./centipede/knobs.h" 16 | 17 | #include 18 | #include 19 | 20 | namespace fuzztest::internal { 21 | size_t Knobs::next_id_ = 0; 22 | std::string_view Knobs::knob_names_[kNumKnobs]; 23 | 24 | KnobId Knobs::NewId(std::string_view knob_name) { 25 | if (next_id_ >= kNumKnobs) { 26 | // If we've run out of IDs, log using stderr (don't use extra deps). 27 | fprintf(stderr, "Knobs::NewId: no more IDs left, aborting\n"); 28 | __builtin_trap(); 29 | } 30 | knob_names_[next_id_] = knob_name; 31 | return next_id_++; 32 | } 33 | } // namespace fuzztest::internal 34 | -------------------------------------------------------------------------------- /centipede/minimize_crash.h: -------------------------------------------------------------------------------- 1 | // Copyright 2022 The Centipede Authors. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // https://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #ifndef THIRD_PARTY_CENTIPEDE_MINIMIZE_CRASH_H_ 16 | #define THIRD_PARTY_CENTIPEDE_MINIMIZE_CRASH_H_ 17 | 18 | #include "./centipede/centipede_callbacks.h" 19 | #include "./centipede/environment.h" 20 | #include "./common/defs.h" 21 | 22 | namespace fuzztest::internal { 23 | 24 | // Tries to minimize `crashy_input`. 25 | // Uses `callbacks_factory` to create `env.num_threads` workers. 26 | // Returns EXIT_SUCCESS if at least one smaller crasher was found, 27 | // EXIT_FAILURE otherwise. 28 | // Also returns EXIT_FAILURE if the original input didn't crash. 29 | // Stores the newly found crashy inputs in 30 | // `WorkDir{env}.CrashReproducerDirPath()`. 31 | int MinimizeCrash(ByteSpan crashy_input, const Environment &env, 32 | CentipedeCallbacksFactory &callbacks_factory); 33 | 34 | } // namespace fuzztest::internal 35 | 36 | #endif // THIRD_PARTY_CENTIPEDE_MINIMIZE_CRASH_H_ 37 | -------------------------------------------------------------------------------- /centipede/mutation_input.h: -------------------------------------------------------------------------------- 1 | // Copyright 2023 The Centipede Authors. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // https://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // Data types used for mutation inputs. 16 | // 17 | // This library is for both engine and runner. 18 | 19 | #ifndef THIRD_PARTY_CENTIPEDE_MUTATION_INPUT_H_ 20 | #define THIRD_PARTY_CENTIPEDE_MUTATION_INPUT_H_ 21 | 22 | #include 23 | 24 | #include "./centipede/execution_metadata.h" 25 | #include "./common/defs.h" 26 | 27 | namespace fuzztest::internal { 28 | 29 | // {data (required), metadata (optional)} reference pairs as mutation inputs. 30 | struct MutationInputRef { 31 | const ByteArray &data; 32 | const ExecutionMetadata *metadata = nullptr; 33 | }; 34 | 35 | inline std::vector CopyDataFromMutationInputRefs( 36 | const std::vector &inputs) { 37 | std::vector results; 38 | results.reserve(inputs.size()); 39 | for (const auto &input : inputs) results.push_back(input.data); 40 | return results; 41 | } 42 | 43 | inline std::vector GetMutationInputRefsFromDataInputs( 44 | const std::vector &inputs) { 45 | std::vector results; 46 | results.reserve(inputs.size()); 47 | for (const auto &input : inputs) results.push_back({/*data=*/input}); 48 | return results; 49 | } 50 | 51 | } // namespace fuzztest::internal 52 | 53 | #endif // THIRD_PARTY_CENTIPEDE_MUTATION_INPUT_H_ 54 | -------------------------------------------------------------------------------- /centipede/mutation_input_test.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2023 The Centipede Authors. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // https://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include "./centipede/mutation_input.h" 16 | 17 | #include 18 | 19 | #include "gmock/gmock.h" 20 | #include "gtest/gtest.h" 21 | #include "./common/defs.h" 22 | 23 | namespace fuzztest::internal { 24 | namespace { 25 | 26 | TEST(MutationInputTest, ConvertsDataToMutationInputRefsAndBack) { 27 | EXPECT_THAT( 28 | CopyDataFromMutationInputRefs(GetMutationInputRefsFromDataInputs({})), 29 | testing::IsEmpty()); 30 | std::vector data_inputs = {{0}, {1}}; 31 | EXPECT_EQ(CopyDataFromMutationInputRefs( 32 | GetMutationInputRefsFromDataInputs(data_inputs)), 33 | data_inputs); 34 | } 35 | 36 | } // namespace 37 | } // namespace fuzztest::internal 38 | -------------------------------------------------------------------------------- /centipede/pc_info.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2022 The Centipede Authors. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // https://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include "./centipede/pc_info.h" 16 | 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | 23 | #include "absl/log/check.h" 24 | #include "absl/types/span.h" 25 | #include "./common/defs.h" 26 | 27 | namespace fuzztest::internal { 28 | 29 | bool PCInfo::operator==(const PCInfo &rhs) const { 30 | return this->pc == rhs.pc && this->flags == rhs.flags; 31 | } 32 | 33 | PCTable ReadPcTable(std::istream &in) { 34 | std::string input_string(std::istreambuf_iterator(in), {}); 35 | 36 | ByteArray pc_infos_as_bytes(input_string.begin(), input_string.end()); 37 | CHECK_EQ(pc_infos_as_bytes.size() % sizeof(PCInfo), 0); 38 | size_t pc_table_size = pc_infos_as_bytes.size() / sizeof(PCInfo); 39 | const auto *pc_infos = reinterpret_cast(pc_infos_as_bytes.data()); 40 | PCTable pc_table{pc_infos, pc_infos + pc_table_size}; 41 | CHECK_EQ(pc_table.size(), pc_table_size); 42 | 43 | return pc_table; 44 | } 45 | 46 | void WritePcTable(const PCTable &pc_table, std::ostream &out) { 47 | auto pc_infos_as_bytes = 48 | absl::Span(reinterpret_cast(pc_table.data()), 49 | sizeof(PCInfo) * pc_table.size()); 50 | out.write(pc_infos_as_bytes.data(), pc_infos_as_bytes.size()); 51 | } 52 | 53 | } // namespace fuzztest::internal 54 | -------------------------------------------------------------------------------- /centipede/pc_info_test.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2023 The Centipede Authors. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // https://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include "./centipede/pc_info.h" 16 | 17 | #include 18 | 19 | #include "gtest/gtest.h" 20 | 21 | namespace fuzztest::internal { 22 | namespace { 23 | 24 | TEST(PCTableTest, SerializesAndDeserializesPCInfoSuccessfully) { 25 | PCTable input = {{/*pc=*/0, /*flags=*/1}, {/*pc=*/2, /*flags=*/3}}; 26 | 27 | std::stringstream stream; 28 | WritePcTable(input, stream); 29 | 30 | PCTable output = ReadPcTable(stream); 31 | 32 | EXPECT_EQ(input, output); 33 | } 34 | 35 | } // namespace 36 | } // namespace fuzztest::internal 37 | -------------------------------------------------------------------------------- /centipede/puzzles/BUILD: -------------------------------------------------------------------------------- 1 | # Copyright 2022 The Centipede Authors. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # https://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | # Centipede puzzles. 16 | # Simple fuzz targets used to test Centipede. 17 | # 18 | # TODO(kcc): [impl] move all puzzles from ../BUILD here. 19 | # TODO(kcc): [impl] allow custom sancov flags. 20 | 21 | # This is somewhat similar to libFuzzer puzzles: 22 | # https://github.com/llvm/llvm-project/tree/main/compiler-rt/test/fuzzer 23 | load(":puzzle.bzl", "puzzle") 24 | 25 | licenses(["notice"]) 26 | 27 | package(default_visibility = ["@com_google_fuzztest//centipede/puzzles:__subpackages__"]) 28 | 29 | # The puzzles use a simple configuration language, see run_puzzle.sh. 30 | [puzzle(name = n) for n in [ 31 | "byte_cmp_4", 32 | "callstack", 33 | "deep_recursion", 34 | "memcmp_4", 35 | "memcmp_4_may_inline", 36 | "memcmp_3", 37 | "strcmp", 38 | "strncmp", 39 | "uint32_cmp_1", 40 | "oom", 41 | "per_input_timeout", 42 | "per_batch_timeout", 43 | "independent_compares", 44 | "autodictionary_stress", 45 | "paths", 46 | "thread_uint32_cmp_1", 47 | "pthread_exit_uint32_cmp_1", 48 | ]] 49 | -------------------------------------------------------------------------------- /centipede/puzzles/byte_cmp_4.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2022 The Centipede Authors. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // https://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // Centipede puzzle: sequence of 4 1-byte comparisons. 16 | // RUN: Run && SolutionIs fuzZ 17 | #include 18 | #include 19 | #include 20 | 21 | extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { 22 | if (size == 4 && data[0] == 'f' && data[1] == 'u' && data[2] == 'z' && 23 | data[3] == 'Z') { 24 | abort(); 25 | } 26 | return 0; 27 | } 28 | -------------------------------------------------------------------------------- /centipede/puzzles/deep_recursion.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2023 The Centipede Authors. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // https://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // Centipede puzzle: use callstack features to reach deep recursion 16 | // clang-format off 17 | // RUN: Run --callstack_level=10 --use_cmp_features=0 --max_len=10 --num_runs=10000000 # NOLINT 18 | // RUN: SolutionIs ABCDEF 19 | // clang-format on 20 | #include 21 | 22 | #include 23 | #include 24 | #include 25 | 26 | // Deep recursion triggered by 'ABCDEF...' 27 | void Recursive(const uint8_t *data, size_t size, size_t idx) { 28 | if (idx > 5) std::abort(); 29 | if (idx >= size) return; 30 | if (data[idx] == 'A' + (idx % 26)) Recursive(data, size, idx + 1); 31 | } 32 | 33 | extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { 34 | Recursive(data, size, 0); 35 | return 0; 36 | } 37 | -------------------------------------------------------------------------------- /centipede/puzzles/independent_compares.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2022 The Centipede Authors. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // https://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // Centipede puzzle: 4 independent compares setting a mask. 16 | // RUN: Run && SolutionIs FUZZ 17 | #include 18 | #include 19 | #include 20 | 21 | extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { 22 | int mask = 0; 23 | if (size > 4) return 0; 24 | if (size > 0 && data[0] == 'F') mask |= 1; 25 | if (size > 1 && data[1] == 'U') mask |= 2; 26 | if (size > 2 && data[2] == 'Z') mask |= 4; 27 | if (size > 3 && data[3] == 'Z') mask |= 8; 28 | if (mask == 15) { 29 | abort(); 30 | } 31 | return 0; 32 | } 33 | -------------------------------------------------------------------------------- /centipede/puzzles/memcmp_3.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2022 The Centipede Authors. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // https://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // Centipede puzzle: one 3-byte memcmp. Check the output in the log. 16 | // Disable use_auto_dictionary so that we test other functionality. 17 | // RUN: Run --use_auto_dictionary=false && SolutionIs fUz 18 | // RUN: ExpectInLog "TEXT IN STDOUT" 19 | // RUN: ExpectInLog "TEXT IN STDERR" 20 | 21 | #include 22 | #include 23 | #include 24 | #include 25 | 26 | auto volatile memcmp_no_inline = &memcmp; 27 | 28 | extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { 29 | if (size == 3 && memcmp_no_inline(data, "fUz", 3) == 0) { 30 | printf("TEXT IN STDOUT\n"); 31 | // abort() does not flush stdout, so if we don't flush it, the output 32 | // may be lost after abort(). 33 | fflush(stdout); 34 | fprintf(stderr, "TEXT IN STDERR\n"); 35 | abort(); 36 | } 37 | return 0; 38 | } 39 | -------------------------------------------------------------------------------- /centipede/puzzles/memcmp_4.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2022 The Centipede Authors. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // https://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // Centipede puzzle: one 4-byte memcmp. 16 | // Disable use_auto_dictionary so that we test other functionality. 17 | // RUN: Run --use_auto_dictionary=false --max_len=10 && SolutionIs fuZz 18 | 19 | #include 20 | #include 21 | #include 22 | 23 | auto volatile memcmp_no_inline = &memcmp; 24 | 25 | extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { 26 | if (size == 4 && memcmp_no_inline(data, "fuZz", 4) == 0) { 27 | abort(); 28 | } 29 | return 0; 30 | } 31 | -------------------------------------------------------------------------------- /centipede/puzzles/memcmp_4_may_inline.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2022 The Centipede Authors. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // https://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // Centipede puzzle: one 4-byte memcmp, which may get inlined. 16 | // Disable use_auto_dictionary so that we test other functionality. 17 | // RUN: Run --use_auto_dictionary=false && SolutionIs FUZz 18 | 19 | #include 20 | #include 21 | #include 22 | 23 | extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { 24 | if (size == 4 && memcmp(data, "FUZz", 4) == 0) { 25 | abort(); 26 | } 27 | return 0; 28 | } 29 | -------------------------------------------------------------------------------- /centipede/puzzles/oom.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2022 The Centipede Authors. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // https://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // Centipede puzzle: easy-to-reach OOM. 16 | // RUN: Run --rss_limit_mb=1000 && SolutionIs OOM && ExpectOOM 17 | #include 18 | #include 19 | #include 20 | #include 21 | 22 | extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { 23 | if (size == 3 && data[0] == 'O' && data[1] == 'O' && data[2] == 'M') { 24 | size_t huge_mem_size = (1ULL << 30) + (1ULL << 20); // 1Gb + 1Mb 25 | char *ptr = new char[huge_mem_size]; // OOM here or one line below. 26 | memset(ptr, 42, huge_mem_size); 27 | fprintf(stderr, "%p\n", ptr); // so that ptr it's not optimized away. 28 | } 29 | return 0; 30 | } 31 | -------------------------------------------------------------------------------- /centipede/puzzles/paths.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2022 The Centipede Authors. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // https://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // Centipede puzzle: almost no control flow, needs paths to find the goal. 16 | // We disable use_dataflow_features because on this puzzle 17 | // it is also effective. 18 | 19 | // RUN: Run --use_dataflow_features=0 --path_level=10 20 | // RUN: ExpectInLog "Input bytes.*: .x1.x2.x3" 21 | 22 | // This puzzle aborts on input "\x1\x2\x3" 23 | // The code here has very little control flow, but an exponential number of 24 | // call paths. The input above triggers a call sequence F1->F2->F3. 25 | // The value `sink` generated by these functions represents the call sequence. 26 | // The goal of this test is to verify that "bounded-path" features work. 27 | 28 | #include 29 | #include 30 | 31 | static volatile uint64_t sink; 32 | 33 | using Func = void (*)(); 34 | 35 | template 36 | static void F() { 37 | sink = sink * 16 + kIdx; 38 | } 39 | 40 | void FN() {} 41 | 42 | // All functions in an array. 43 | static Func table[256] = { 44 | F<0>, F<1>, F<2>, F<3>, F<4>, F<5>, F<6>, F<7>, 45 | F<8>, F<9>, F<10>, F<11>, F<12>, F<13>, F<14>, F<15>, 46 | // The rest are set to FN below. 47 | }; 48 | 49 | // Set table[16:256] to FN. 50 | struct TableCtor { 51 | TableCtor() { 52 | for (size_t i = 16; i < 256; ++i) table[i] = FN; 53 | } 54 | }; 55 | 56 | [[maybe_unused]] static TableCtor table_ctor; 57 | 58 | extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { 59 | if (size != 3) return -1; 60 | sink = 0; 61 | table[data[0]](); 62 | table[data[1]](); 63 | table[data[2]](); 64 | sink /= 0x123 - sink; // Generates a crash (div by zero) w/o a control flow. 65 | return 0; 66 | } 67 | -------------------------------------------------------------------------------- /centipede/puzzles/per_batch_timeout.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2022 The Centipede Authors. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // https://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // Centipede puzzle: easy-to-reach per-batch timeout. 16 | // clang-format off 17 | // NOLINTNEXTLINE 18 | // RUN: Run --batch_size=10 --timeout_per_input=2 --timeout_per_batch=7 && ExpectPerBatchTimeout 19 | // clang-format on 20 | 21 | #include 22 | 23 | #include 24 | #include 25 | 26 | extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { 27 | // Within the --timeout_per_input, but we have no solution, so the runner 28 | // should keep running us until it exceeds --timeout_per_batch, then report a 29 | // failure back to the engine. 30 | sleep(1); 31 | return 0; 32 | } 33 | -------------------------------------------------------------------------------- /centipede/puzzles/per_input_timeout.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2022 The Centipede Authors. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // https://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // Centipede puzzle: easy-to-reach per-input timeout. 16 | // RUN: Run --timeout_per_input=2 && SolutionIs SLO && ExpectPerInputTimeout 17 | 18 | #include 19 | 20 | #include 21 | #include 22 | 23 | extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { 24 | if (size == 3 && data[0] == 'S' && data[1] == 'L' && data[2] == 'O') { 25 | sleep(1000); // Dies with timeout. 26 | } 27 | return 0; 28 | } 29 | -------------------------------------------------------------------------------- /centipede/puzzles/pthread_exit_uint32_cmp_1.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2023 The Centipede Authors. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // https://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // Centipede puzzle: one 4-byte cmp, in a separate thread using pthread 16 | // interface. We should be able to solve it w/o cmp features *or* w/o auto 17 | // dictionary. 18 | // 19 | // RUN: Run && SolutionIs Fuzz 20 | // RUN: Run --use_auto_dictionary=0 && SolutionIs Fuzz 21 | // RUN: Run --use_cmp_features=0 && SolutionIs Fuzz 22 | 23 | #include 24 | 25 | #include 26 | #include 27 | #include 28 | 29 | // non-const, to avoid compiler optimization. 30 | static char expected_data[] = "Fuzz"; 31 | 32 | extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { 33 | pthread_t pt; 34 | struct ThreadArg { 35 | const uint8_t *data; 36 | size_t size; 37 | } arg = {data, size}; 38 | auto pt_entry = +[](const ThreadArg *thread_arg) { 39 | uint32_t value, expected_value; 40 | if (thread_arg->size == sizeof(value)) { 41 | memcpy(&value, thread_arg->data, sizeof(value)); 42 | memcpy(&expected_value, expected_data, sizeof(expected_value)); 43 | if (value == expected_value) abort(); 44 | pthread_exit(nullptr); 45 | } 46 | }; 47 | if (pthread_create(&pt, nullptr, 48 | reinterpret_cast(pt_entry), &arg) != 0) 49 | return 1; 50 | if (pthread_join(pt, nullptr) != 0) return 1; 51 | return 0; 52 | } 53 | -------------------------------------------------------------------------------- /centipede/puzzles/puzzle.bzl: -------------------------------------------------------------------------------- 1 | # Copyright 2022 The Centipede Authors. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # https://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | """BUILD rule for Centipede puzzles""" 16 | 17 | load("@com_google_fuzztest//centipede/testing:build_defs.bzl", "centipede_fuzz_target") 18 | 19 | def puzzle(name): 20 | """Generates a cc_fuzz_target target instrumented with sancov and a sh script to run it. 21 | 22 | Args: 23 | name: A unique name for this target 24 | """ 25 | 26 | centipede_fuzz_target( 27 | name = name, 28 | deps = [ 29 | "@abseil-cpp//absl/base:nullability", 30 | ], 31 | ) 32 | 33 | # We test every puzzle with two different seeds so that the result is more 34 | # trustworthy. The seeds are fixed so that we have some degree of 35 | # repeatability. Each sh_test performs a single run with a single seed, so 36 | # that the log is minimal. 37 | for seed in ["1", "2"]: 38 | native.sh_test( 39 | name = "run_" + seed + "_" + name, 40 | srcs = ["run_puzzle.sh"], 41 | data = [ 42 | ":" + name, 43 | name + ".cc", 44 | "@com_google_fuzztest//centipede:centipede_uninstrumented", 45 | "@com_google_fuzztest//centipede:test_util_sh", 46 | ], 47 | ) 48 | -------------------------------------------------------------------------------- /centipede/puzzles/strcmp.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2023 The Centipede Authors. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // https://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // Centipede puzzle: one 4-byte strcmp. Check the output in the log. 16 | // Disable use_auto_dictionary so that we test other functionality. 17 | // RUN: Run --use_auto_dictionary=false && SolutionIs fUzZ 18 | // RUN: ExpectInLog "TEXT IN STDOUT" 19 | // RUN: ExpectInLog "TEXT IN STDERR" 20 | 21 | #include 22 | #include 23 | #include 24 | #include 25 | 26 | extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { 27 | constexpr size_t kBufSize = 32; 28 | char buf[kBufSize]; 29 | if (size >= kBufSize) size = kBufSize - 1; 30 | memcpy(buf, data, size); 31 | buf[size] = 0; 32 | if (strcmp(buf, "fUzZ") == 0) { 33 | printf("TEXT IN STDOUT\n"); 34 | // abort() does not flush stdout, so if we don't flush it, the output 35 | // may be lost after abort(). 36 | fflush(stdout); 37 | fprintf(stderr, "TEXT IN STDERR\n"); 38 | abort(); 39 | } 40 | return 0; 41 | } 42 | -------------------------------------------------------------------------------- /centipede/puzzles/strncmp.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2023 The Centipede Authors. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // https://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // Centipede puzzle: one 4-byte strncmp. Check the output in the log. 16 | // Disable use_auto_dictionary so that we test other functionality. 17 | // RUN: Run --use_auto_dictionary=false && SolutionIs fUzZ 18 | // RUN: ExpectInLog "TEXT IN STDOUT" 19 | // RUN: ExpectInLog "TEXT IN STDERR" 20 | 21 | #include 22 | #include 23 | #include 24 | #include 25 | 26 | extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { 27 | if (size >= 4 && 28 | strncmp(reinterpret_cast(data), "fUzZ", 4) == 0) { 29 | printf("TEXT IN STDOUT\n"); 30 | // abort() does not flush stdout, so if we don't flush it, the output 31 | // may be lost after abort(). 32 | fflush(stdout); 33 | fprintf(stderr, "TEXT IN STDERR\n"); 34 | abort(); 35 | } 36 | return 0; 37 | } 38 | -------------------------------------------------------------------------------- /centipede/puzzles/thread_uint32_cmp_1.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2023 The Centipede Authors. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // https://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // Centipede puzzle: one 4-byte cmp, in a separate thread. 16 | // We should be able to solve it w/o cmp features *or* w/o auto dictionary. 17 | // RUN: Run && SolutionIs Fuzz 18 | // RUN: Run --use_auto_dictionary=0 && SolutionIs Fuzz 19 | // RUN: Run --use_cmp_features=0 && SolutionIs Fuzz 20 | 21 | #include 22 | #include 23 | #include 24 | #include // NOLINT: Ok in a target. 25 | 26 | // non-const, to avoid compiler optimization. 27 | static char expected_data[] = "Fuzz"; 28 | 29 | extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { 30 | std::thread t([&]() { 31 | uint32_t value, expected_value; 32 | if (size == sizeof(value)) { 33 | memcpy(&value, data, sizeof(value)); 34 | memcpy(&expected_value, expected_data, sizeof(expected_value)); 35 | if (value == expected_value) abort(); 36 | } 37 | }); 38 | t.join(); 39 | return 0; 40 | } 41 | -------------------------------------------------------------------------------- /centipede/puzzles/uint32_cmp_1.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2022 The Centipede Authors. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // https://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // Centipede puzzle: one 4-byte cmp. 16 | // We should be able to solve it w/o cmp features *or* w/o auto dictionary. 17 | // RUN: Run && SolutionIs Fuzz 18 | // RUN: Run --use_cmp_features=0 && SolutionIs Fuzz 19 | // RUN: Run --use_auto_dictionary=0 && SolutionIs Fuzz 20 | 21 | #include 22 | #include 23 | #include 24 | 25 | // non-const, to avoid compiler optimization. 26 | static char expected_data[] = "Fuzz"; 27 | 28 | extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { 29 | uint32_t value, expected_value; 30 | if (size == sizeof(value)) { 31 | memcpy(&value, data, sizeof(value)); 32 | memcpy(&expected_value, expected_data, sizeof(expected_value)); 33 | if (value == expected_value) abort(); 34 | } 35 | return 0; 36 | } 37 | -------------------------------------------------------------------------------- /centipede/run_test_workflow_using_docker.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Copyright 2022 Centipede Authors 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # https://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | set -eu 18 | 19 | SCRIPT_DIR="$(cd -L "$(dirname "$0")" && echo "${PWD}")" 20 | readonly SCRIPT_DIR 21 | 22 | declare -r FUZZTEST_DIR="$(cd "${SCRIPT_DIR}/.." && echo "${PWD}")" 23 | declare -r OUTPUT_ARTIFACTS_DIR="${FUZZTEST_DIR}/test-outputs" 24 | # Must run under sudo, or else docker trips over insufficient permissions. 25 | declare -r DOCKER_CMD="sudo docker" 26 | declare -r DOCKER_IMAGE=debian 27 | 28 | echo "Will save test output artifacts to $OUTPUT_ARTIFACTS_DIR" 29 | 30 | ${DOCKER_CMD} run \ 31 | -v "${FUZZTEST_DIR}:/app" \ 32 | -v "${OUTPUT_ARTIFACTS_DIR}:/output" \ 33 | --env OUTPUT_ARTIFACTS_DIR=/output \ 34 | -w /app \ 35 | "${DOCKER_IMAGE}" \ 36 | /app/centipede/run_test_workflow.sh 37 | -------------------------------------------------------------------------------- /centipede/runner_main.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2022 The Centipede Authors. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // https://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include "absl/base/nullability.h" 16 | #include "./centipede/runner_interface.h" 17 | 18 | int main(int argc, char** absl_nonnull argv) { 19 | return LLVMFuzzerRunDriver(&argc, &argv, LLVMFuzzerTestOneInput); 20 | } 21 | -------------------------------------------------------------------------------- /centipede/runner_utils.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2022 The Centipede Authors. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // https://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include "./centipede/runner_utils.h" 16 | 17 | #include 18 | 19 | #include 20 | #include 21 | #include 22 | 23 | #include "absl/base/nullability.h" 24 | 25 | namespace fuzztest::internal { 26 | 27 | void PrintErrorAndExitIf(bool condition, const char* absl_nonnull error) { 28 | if (!condition) return; 29 | fprintf(stderr, "error: %s\n", error); 30 | exit(1); 31 | } 32 | 33 | uintptr_t GetCurrentThreadStackRegionLow() { 34 | #ifdef __APPLE__ 35 | pthread_t self = pthread_self(); 36 | const auto stack_addr = 37 | reinterpret_cast(pthread_get_stackaddr_np(self)); 38 | const auto stack_size = pthread_get_stacksize_np(self); 39 | return stack_addr - stack_size; 40 | #else // __APPLE__ 41 | pthread_attr_t attr = {}; 42 | if (pthread_getattr_np(pthread_self(), &attr) != 0) { 43 | fprintf(stderr, "Failed to get the pthread attr of the current thread.\n"); 44 | return 0; 45 | } 46 | void *stack_addr = nullptr; 47 | size_t stack_size = 0; 48 | if (pthread_attr_getstack(&attr, &stack_addr, &stack_size) != 0) { 49 | fprintf(stderr, "Failed to get the stack region of the current thread.\n"); 50 | pthread_attr_destroy(&attr); 51 | return 0; 52 | } 53 | pthread_attr_destroy(&attr); 54 | const auto stack_region_low = reinterpret_cast(stack_addr); 55 | RunnerCheck(stack_region_low != 0, 56 | "the current thread stack region starts from 0 - unexpected!"); 57 | return stack_region_low; 58 | #endif // __APPLE__ 59 | } 60 | 61 | } // namespace fuzztest::internal 62 | -------------------------------------------------------------------------------- /centipede/runner_utils.h: -------------------------------------------------------------------------------- 1 | // Copyright 2022 The Centipede Authors. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // https://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #ifndef THIRD_PARTY_CENTIPEDE_RUNNER_UTILS_H_ 16 | #define THIRD_PARTY_CENTIPEDE_RUNNER_UTILS_H_ 17 | 18 | #include 19 | 20 | #include "absl/base/nullability.h" 21 | 22 | namespace fuzztest::internal { 23 | 24 | // If `condition` prints `error` and calls exit(1). 25 | // TODO(kcc): change all uses of PrintErrorAndExitIf() to RunnerCheck() 26 | // as it is a more common pattern. 27 | void PrintErrorAndExitIf(bool condition, const char* absl_nonnull error); 28 | 29 | // A rough equivalent of "CHECK(condition) << error;". 30 | inline void RunnerCheck(bool condition, const char* absl_nonnull error) { 31 | PrintErrorAndExitIf(!condition, error); 32 | } 33 | 34 | // Returns the lower bound of the stack region for the current thread. 0 will be 35 | // returned on failures. 36 | uintptr_t GetCurrentThreadStackRegionLow(); 37 | 38 | } // namespace fuzztest::internal 39 | 40 | #endif // THIRD_PARTY_CENTIPEDE_RUNNER_UTILS_H_ 41 | -------------------------------------------------------------------------------- /centipede/seed_corpus_maker.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2023 The Centipede Authors. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // https://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include 16 | #include // NOLINT 17 | #include 18 | 19 | #include "absl/base/nullability.h" 20 | #include "absl/flags/flag.h" 21 | #include "absl/log/check.h" 22 | #include "absl/log/log.h" 23 | #include "./centipede/config_init.h" 24 | #include "./centipede/seed_corpus_maker_flags.h" 25 | #include "./centipede/seed_corpus_maker_proto_lib.h" 26 | #include "./centipede/util.h" 27 | #include "./common/remote_file.h" 28 | 29 | int main(int argc, char** absl_nonnull argv) { 30 | (void)fuzztest::internal::InitRuntime(argc, argv); 31 | 32 | const std::string config = absl::GetFlag(FLAGS_config); 33 | QCHECK(!config.empty()); 34 | const std::string override_out_dir = absl::GetFlag(FLAGS_override_out_dir); 35 | const std::string binary_path = absl::GetFlag(FLAGS_coverage_binary_path); 36 | const std::string binary_name = std::filesystem::path{binary_path}.filename(); 37 | QCHECK(!binary_name.empty()) 38 | << "--coverage_binary_path yields empty basename"; 39 | std::string binary_hash = absl::GetFlag(FLAGS_coverage_binary_hash); 40 | if (binary_hash.empty()) { 41 | QCHECK(fuzztest::internal::RemotePathExists(binary_path)) 42 | << "--coverage_binary_path doesn't exist"; 43 | binary_hash = fuzztest::internal::HashOfFileContents(binary_path); 44 | LOG(INFO) << "--coverage_binary_hash was not provided: computed " 45 | << binary_hash 46 | << " from actual file at --coverage_binary_path=" << binary_path; 47 | } 48 | 49 | QCHECK_OK(fuzztest::internal::GenerateSeedCorpusFromConfigProto( // 50 | config, binary_name, binary_hash, override_out_dir)); 51 | 52 | return EXIT_SUCCESS; 53 | } 54 | -------------------------------------------------------------------------------- /centipede/seed_corpus_maker_flags.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2023 The Centipede Authors. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // https://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include 16 | 17 | #include "absl/flags/flag.h" 18 | 19 | ABSL_FLAG( 20 | std::string, config, "", 21 | "A silifuzz.ccmp.SeedCorpusConfig proto that describes where and how to " 22 | "obtain seeding corpus elements. Can be either a verbatim textproto or a " 23 | "path to a textproto file.\n" 24 | "`sources.dir_glob`s and `destination.dir_path` can be relative paths: if " 25 | "so, they will be resolved to absolute ones using either the --config's " 26 | "parent dir, if --config is a filename, or the current dir otherwise.\n" 27 | "Furthermore, `destination.dir_path` can be overridden by passing a " 28 | "non-empty --out_dir."); 29 | ABSL_FLAG( 30 | std::string, coverage_binary_path, "", 31 | "The path of the binary from which coverage is to be collected. Can be " 32 | "just the basename of the binary, but in that case --coverage_binary_hash " 33 | "must also be provided."); 34 | ABSL_FLAG( 35 | std::string, coverage_binary_hash, "", 36 | "If not-empty, this hash is used instead of the actual hash of the " 37 | "contents of --coverage_binary_path. Use when the binary pointed at by " 38 | "--coverage_binary_path is not actually available on disk."); 39 | ABSL_FLAG( 40 | std::string, override_out_dir, "", 41 | "If non-empty, overrides the `destination.dir_path` field in the resolved " 42 | "--config protobuf."); 43 | -------------------------------------------------------------------------------- /centipede/seed_corpus_maker_flags.h: -------------------------------------------------------------------------------- 1 | // Copyright 2023 The Centipede Authors. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // https://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #ifndef THIRD_PARTY_CENTIPEDE_SEED_CORPUS_MAKER_FLAGS_H_ 16 | #define THIRD_PARTY_CENTIPEDE_SEED_CORPUS_MAKER_FLAGS_H_ 17 | 18 | #include 19 | 20 | #include "absl/flags/declare.h" 21 | 22 | ABSL_DECLARE_FLAG(std::string, config); 23 | ABSL_DECLARE_FLAG(std::string, coverage_binary_path); 24 | ABSL_DECLARE_FLAG(std::string, coverage_binary_hash); 25 | ABSL_DECLARE_FLAG(std::string, override_out_dir); 26 | 27 | #endif // THIRD_PARTY_CENTIPEDE_SEED_CORPUS_MAKER_FLAGS_H_ 28 | -------------------------------------------------------------------------------- /centipede/seed_corpus_maker_proto_lib.h: -------------------------------------------------------------------------------- 1 | // Copyright 2022 The Centipede Authors. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // https://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #ifndef THIRD_PARTY_CENTIPEDE_SEED_CORPUS_MAKER_PROTO_LIB_H_ 16 | #define THIRD_PARTY_CENTIPEDE_SEED_CORPUS_MAKER_PROTO_LIB_H_ 17 | 18 | #include 19 | 20 | #include "absl/status/status.h" 21 | #include "absl/status/statusor.h" 22 | #include "./centipede/seed_corpus_maker_lib.h" 23 | 24 | namespace fuzztest::internal { 25 | 26 | // Generates seed corpus similarly to `GenerateSeedCorpusFromConfig`, but using 27 | // `config_spec` based on its value: If a file with `config_spec` path exists, 28 | // tries to parse it as a `proto::SeedCorpusConfig` textproto. Otherwise, tries 29 | // to parse `config_spec` as a verbatim `proto::SeedCorpusConfig` textproto. 30 | // Resolves any relative paths and globs in the config fields to absolute ones, 31 | // using as the base dir either the file's parent dir (if `config_spec` is a 32 | // file) or the current dir (otherwise). If `override_out_dir` is non-empty, it 33 | // overrides `destination.dir_path` in the resolved config. 34 | absl::Status GenerateSeedCorpusFromConfigProto( // 35 | std::string_view config_spec, // 36 | std::string_view coverage_binary_name, // 37 | std::string_view coverage_binary_hash, // 38 | std::string_view override_out_dir); 39 | 40 | } // namespace fuzztest::internal 41 | 42 | #endif // THIRD_PARTY_CENTIPEDE_SEED_CORPUS_MAKER_PROTO_LIB_H_ 43 | -------------------------------------------------------------------------------- /centipede/stop.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2023 The Centipede Authors. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // https://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include "./centipede/stop.h" 16 | 17 | #include 18 | #include 19 | 20 | #include "absl/time/clock.h" 21 | #include "absl/time/time.h" 22 | 23 | namespace fuzztest::internal { 24 | namespace { 25 | 26 | struct EarlyStop { 27 | int exit_code = EXIT_SUCCESS; 28 | bool is_requested = false; 29 | }; 30 | std::atomic early_stop; 31 | 32 | absl::Time stop_time = absl::InfiniteFuture(); 33 | 34 | } // namespace 35 | 36 | bool EarlyStopRequested() { 37 | return early_stop.load(std::memory_order_acquire).is_requested; 38 | } 39 | 40 | void ClearEarlyStopRequestAndSetStopTime(absl::Time stop_time) { 41 | early_stop.store({}, std::memory_order_release); 42 | ::fuzztest::internal::stop_time = stop_time; 43 | } 44 | 45 | void RequestEarlyStop(int exit_code) { 46 | early_stop.store({exit_code, true}, std::memory_order_release); 47 | } 48 | 49 | bool ShouldStop() { return EarlyStopRequested() || stop_time < absl::Now(); } 50 | 51 | int ExitCode() { return early_stop.load(std::memory_order_acquire).exit_code; } 52 | 53 | } // namespace fuzztest::internal 54 | -------------------------------------------------------------------------------- /centipede/stop.h: -------------------------------------------------------------------------------- 1 | // Copyright 2023 The Centipede Authors. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // https://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #ifndef THIRD_PARTY_CENTIPEDE_STOP_H_ 16 | #define THIRD_PARTY_CENTIPEDE_STOP_H_ 17 | 18 | #include "absl/time/time.h" 19 | 20 | namespace fuzztest::internal { 21 | 22 | // Clears the request to stop early and sets the stop time. 23 | // 24 | // REQUIRES: Must be called before starting concurrent threads that may invoke 25 | // the functions defined in this header. In particular, calling this function 26 | // concurrently with `ShouldStop()` is not thread-safe. 27 | void ClearEarlyStopRequestAndSetStopTime(absl::Time stop_time); 28 | 29 | // Requests that Centipede soon stops whatever it is doing (fuzzing, minimizing 30 | // reproducer, etc.), with `exit_code` indicating success (zero) or failure 31 | // (non-zero). 32 | // 33 | // ENSURES: Thread-safe and safe to call from signal handlers. 34 | void RequestEarlyStop(int exit_code); 35 | 36 | // Returns whether `RequestEarlyStop()` was called or not since the most recent 37 | // call to `ClearEarlyStopRequestAndSetStopTime()` (if any). 38 | // 39 | // ENSURES: Thread-safe. 40 | bool EarlyStopRequested(); 41 | 42 | // Returns true iff it is time to stop, either because the stopping time has 43 | // been reached or `RequestEarlyStop()` was called since the most recent call to 44 | // `ClearEarlyStopRequestAndSetStopTime()` (if any). 45 | // 46 | // ENSURES: Thread-safe. 47 | bool ShouldStop(); 48 | 49 | // Returns the value most recently passed to `RequestEarlyStop()` or 0 if 50 | // `RequestEarlyStop()` was not called since the most recent call to 51 | // `ClearEarlyStopRequestAndSetStopTime()` (if any). 52 | // 53 | // ENSURES: Thread-safe. 54 | int ExitCode(); 55 | 56 | } // namespace fuzztest::internal 57 | 58 | #endif // THIRD_PARTY_CENTIPEDE_STOP_H_ 59 | -------------------------------------------------------------------------------- /centipede/symbol_table_test.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2023 The Centipede Authors. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // https://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include "./centipede/symbol_table.h" 16 | 17 | #include 18 | #include 19 | 20 | #include "gtest/gtest.h" 21 | 22 | namespace fuzztest::internal { 23 | namespace { 24 | 25 | TEST(SymbolTableTest, SerializesAndDeserializesCorrectly) { 26 | std::string input = 27 | R"(FunctionOne 28 | source/location/one.cc:1:0 29 | 30 | FunctionTwo 31 | source/location/two.cc:2:0 32 | 33 | )"; 34 | std::istringstream input_stream(input); 35 | SymbolTable symbol_table; 36 | 37 | symbol_table.ReadFromLLVMSymbolizer(input_stream); 38 | 39 | std::ostringstream output_stream; 40 | symbol_table.WriteToLLVMSymbolizer(output_stream); 41 | EXPECT_EQ(input, output_stream.str()); 42 | } 43 | 44 | TEST(SymbolTableTest, SerializesAndDeserializesCorrectlyWithUnknownFile) { 45 | std::string input = 46 | R"(? 47 | ? 48 | 49 | )"; 50 | std::istringstream input_stream(input); 51 | SymbolTable symbol_table; 52 | 53 | symbol_table.ReadFromLLVMSymbolizer(input_stream); 54 | 55 | std::ostringstream output_stream; 56 | symbol_table.WriteToLLVMSymbolizer(output_stream); 57 | EXPECT_EQ(input, output_stream.str()); 58 | } 59 | 60 | TEST(SymbolTableTest, SerializesEmptyOutput) { 61 | std::string input = 62 | R"( 63 | )"; 64 | std::istringstream input_stream(input); 65 | SymbolTable symbol_table; 66 | 67 | symbol_table.ReadFromLLVMSymbolizer(input_stream); 68 | } 69 | 70 | } // namespace 71 | } // namespace fuzztest::internal 72 | -------------------------------------------------------------------------------- /centipede/testing/abort_fuzz_target.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2022 The Centipede Authors. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // https://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // A fuzz target used for testing Centipede. 16 | // Induces an Abort. 17 | #include 18 | #include 19 | #include 20 | #include 21 | 22 | extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { 23 | // Print "I AM ABOUT TO ABORT" and abort, if the input is 'AbOrT'. 24 | // Used by exit_on_crash_test.sh. 25 | if (size == 5 && data[0] == 'A' && data[1] == 'b' && data[2] == 'O' && 26 | data[3] == 'r' && data[4] == 'T') { 27 | fprintf(stderr, "I AM ABOUT TO ABORT\n"); 28 | abort(); 29 | } 30 | return 0; 31 | } 32 | -------------------------------------------------------------------------------- /centipede/testing/clusterfuzz_format_target.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2023 The Centipede Authors. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // https://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // A simple fuzz target that contains bugs detectable by different sanitizers. 16 | // For now, asan and msan. 17 | 18 | #include 19 | 20 | #include 21 | #include 22 | #include 23 | #include 24 | 25 | [[maybe_unused]] static volatile void *sink; 26 | [[maybe_unused]] static volatile void *ptr_sink; 27 | 28 | extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { 29 | if (size != 3) return 0; // Make bugs easy to discover. 30 | 31 | // "uaf" => heap-use-after-free 32 | if (data[0] == 'u' && data[1] == 'a' && data[2] == 'f') { 33 | int *x = new int; 34 | fprintf(stderr, "uaf %p\n", x); 35 | sink = x; 36 | delete x; 37 | *x = 0; 38 | } 39 | 40 | // Allocate 4Gb of RAM if the input is 'oom'. 41 | // sanitizer_test provokes OOM by feeding 'oom' input here, 42 | // and checks its output format matches with the expectation of clusterfuzz. 43 | if (data[0] == 'o' && data[1] == 'o' && data[2] == 'm') { 44 | size_t oom_allocation_size = 1ULL << 32; 45 | void *ptr = malloc(oom_allocation_size); 46 | memset(ptr, 42, oom_allocation_size); 47 | ptr_sink = ptr; 48 | } 49 | 50 | // 'slo' => Sleep for 10 seconds to provoke timeout. 51 | if (data[0] == 's' && data[1] == 'l' && data[2] == 'o') { 52 | sleep(10); 53 | } 54 | 55 | return 0; 56 | } 57 | -------------------------------------------------------------------------------- /centipede/testing/data_only_dso_target_lib.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2024 The Centipede Authors. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // https://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // Here we try to produce a DSO with an empty sancov PC table. This is done by 16 | // building the library with unused code and enable -gc-sections in lld. Note 17 | // that GNU ld would not produce the intended result. 18 | 19 | #include "./centipede/testing/data_only_dso_target_lib.h" 20 | 21 | const char kCrashInputData[] = "GoCrash"; 22 | const char* kCrashInput = kCrashInputData; 23 | // Exclude the terminating \0. 24 | const int kCrashInputSize = sizeof(kCrashInputData) - 1; 25 | 26 | // With -gc-sections this function should be removed by the linker. 27 | __attribute__((visibility("hidden"))) int UnusedFunction(int x) { 28 | return x + 1; 29 | } 30 | -------------------------------------------------------------------------------- /centipede/testing/data_only_dso_target_lib.h: -------------------------------------------------------------------------------- 1 | // Copyright 2024 The Centipede Authors. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // https://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #ifndef THIRD_PARTY_CENTIPEDE_TESTING_DATA_ONLY_DSO_TARGET_LIB_H_ 16 | #define THIRD_PARTY_CENTIPEDE_TESTING_DATA_ONLY_DSO_TARGET_LIB_H_ 17 | 18 | extern const char* kCrashInput; 19 | extern const int kCrashInputSize; 20 | 21 | #endif // THIRD_PARTY_CENTIPEDE_TESTING_DATA_ONLY_DSO_TARGET_LIB_H_ 22 | -------------------------------------------------------------------------------- /centipede/testing/data_only_dso_target_main.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2024 The Centipede Authors. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // https://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | 21 | #include "./centipede/testing/data_only_dso_target_lib.h" 22 | 23 | // A fuzz target that uses data from a different DSO. 24 | extern "C" int __attribute__((optnone)) LLVMFuzzerTestOneInput( 25 | const uint8_t* data, size_t size) { 26 | if (size != kCrashInputSize) return -1; 27 | if (std::memcmp(kCrashInput, data, size) == 0) std::abort(); 28 | return 0; 29 | } 30 | -------------------------------------------------------------------------------- /centipede/testing/data_only_dso_test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Copyright 2024 The Centipede Authors. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # https://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | # Tests basic functionality for a target with data-only DSOs. 18 | set -eu 19 | 20 | source "$(dirname "$0")/../test_util.sh" 21 | 22 | CENTIPEDE_TEST_SRCDIR="$(fuzztest::internal::get_centipede_test_srcdir)" 23 | 24 | fuzztest::internal::maybe_set_var_to_executable_path \ 25 | CENTIPEDE_BINARY "${CENTIPEDE_TEST_SRCDIR}/centipede" 26 | 27 | fuzztest::internal::maybe_set_var_to_executable_path \ 28 | TARGET_BINARY "${CENTIPEDE_TEST_SRCDIR}/testing/data_only_dso_target" 29 | 30 | fuzztest::internal::maybe_set_var_to_executable_path \ 31 | LLVM_SYMBOLIZER "$(fuzztest::internal::get_llvm_symbolizer_path)" 32 | 33 | # Run fuzzing until the first crash. 34 | declare -r WD="${TEST_TMPDIR}/WD" 35 | declare -r LOG="${TEST_TMPDIR}/log" 36 | fuzztest::internal::ensure_empty_dir "${WD}" 37 | 38 | "${CENTIPEDE_BINARY}" --binary="${TARGET_BINARY}" --workdir="${WD}" \ 39 | --exit_on_crash=1 --seed=1 --log_features_shards=1 \ 40 | --symbolizer_path="${LLVM_SYMBOLIZER}" \ 41 | 2>&1 | tee "${LOG}" 42 | 43 | echo "Fuzzing DONE" 44 | 45 | fuzztest::internal::assert_regex_in_file "Batch execution failed:" "${LOG}" 46 | fuzztest::internal::assert_regex_in_file "Input bytes.*: GoCrash" "${LOG}" 47 | fuzztest::internal::assert_regex_in_file "Symbolizing 1 instrumented DSOs" "${LOG}" 48 | 49 | echo "PASS" 50 | -------------------------------------------------------------------------------- /centipede/testing/dump_binary_info_test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Copyright 2022 The Centipede Authors. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # https://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | set -eu 17 | 18 | source "$(dirname "$0")/../test_util.sh" 19 | 20 | binary="$(fuzztest::internal::get_centipede_test_srcdir)/testing/multi_dso_target" 21 | 22 | pc_table="${TEST_TMPDIR}/pc_table" 23 | cf_table="${TEST_TMPDIR}/cf_table" 24 | dso_table="${TEST_TMPDIR}/dso_table" 25 | 26 | # Dump the binary info tables on disk 27 | CENTIPEDE_RUNNER_FLAGS=":dump_binary_info:arg1=${pc_table}:arg2=${cf_table}:arg3=${dso_table}:" \ 28 | "${binary}" 29 | 30 | # Check the pc table size. 31 | size=$(stat -c %s "${pc_table}") 32 | echo "pc table file size: ${size}" 33 | (( size >= 1 )) || die "pc table is too small: ${size}" 34 | 35 | # Check the cf table size 36 | size=$(stat -c %s "${cf_table}") 37 | echo "cf table size: ${size}" 38 | (( size >= 1 )) || die "cf table is too small: ${size}" 39 | 40 | # Check the DSO table size (in lines) 41 | cat "${dso_table}" 42 | size=$(cat "${dso_table}" | wc -l) 43 | echo "dso table size: ${size}" 44 | (( size == 2 )) || die "dso table should have exactly 2 entries" 45 | fuzztest::internal::assert_regex_in_file "lib.so [1-9]" "${dso_table}" 46 | # Check the path to main binary in the dso table. 47 | # It may differe from $binary but it should point to the same file. 48 | binary_path=$(grep -v '.so ' "${dso_table}" | grep -o "^[^ ]\+") 49 | cmp "${binary_path}" "${binary}" \ 50 | || die "the path to main binary in dso table is wrong" 51 | 52 | # Check the DSO path in the dso table. 53 | so_path=$(grep '.so ' "${dso_table}" | grep -o "^[^ ]\+") 54 | [[ -f "${so_path}" ]] || die "dso path from dso table is wrong" 55 | 56 | echo "PASS" 57 | -------------------------------------------------------------------------------- /centipede/testing/empty_fuzz_target.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2022 The Centipede Authors. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // https://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include 16 | #include 17 | 18 | // A fuzz target used for testing Centipede. 19 | // Does nothing, returns 0. 20 | extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { 21 | return 0; 22 | } 23 | -------------------------------------------------------------------------------- /centipede/testing/expensive_startup_fuzz_target.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2023 The Centipede Authors. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // https://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | static int sink; 21 | 22 | // Instrumented function that runs at startup. We want it's coverage ignored. 23 | __attribute__((constructor, noinline, optnone)) void Startup() { 24 | fprintf(stderr, "Startup\n"); 25 | // Function entry: generate a coverage feature. 26 | sink++; // generate data flow feature 27 | if (sink == (sink == 42)) // generate some cmp features 28 | Startup(); 29 | char str[] = {'F', 'u', 'z', 'z'}; 30 | if (memcmp(str, "Null", 4) == 0) // generate some cmp traces 31 | Startup(); 32 | } 33 | 34 | // A fuzz target used for testing Centipede. 35 | // Does nothing, returns 0. There is a startup code that runs before the target. 36 | extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { 37 | return 0; 38 | } 39 | -------------------------------------------------------------------------------- /centipede/testing/fuzz_target_with_config.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2024 The Centipede Authors. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // https://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include 16 | #include 17 | 18 | #include "absl/base/nullability.h" 19 | #include "absl/flags/flag.h" 20 | #include "absl/flags/parse.h" 21 | #include "./centipede/runner_interface.h" 22 | #include "./common/defs.h" 23 | 24 | ABSL_FLAG(bool, simulate_failure, false, 25 | "If true, the binary will return EXIT_FAILURE to simulate a " 26 | "failure."); 27 | 28 | using fuzztest::internal::ByteSpan; 29 | 30 | class FakeSerializedConfigRunnerCallbacks 31 | : public fuzztest::internal::RunnerCallbacks { 32 | public: 33 | // Trivial implementations for the execution and mutation logic, even though 34 | // they should not be used in the tests that use this test binary. 35 | bool Execute(ByteSpan input) override { return true; } 36 | bool HasCustomMutator() const override { return false; } 37 | 38 | std::string GetSerializedTargetConfig() override { 39 | return "fake serialized config"; 40 | } 41 | }; 42 | 43 | int main(int argc, char** absl_nonnull argv) { 44 | absl::ParseCommandLine(argc, argv); 45 | if (absl::GetFlag(FLAGS_simulate_failure)) { 46 | return EXIT_FAILURE; 47 | } 48 | FakeSerializedConfigRunnerCallbacks runner_callbacks; 49 | return fuzztest::internal::RunnerMain(argc, argv, runner_callbacks); 50 | } 51 | -------------------------------------------------------------------------------- /centipede/testing/fuzz_target_with_custom_mutator.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2025 The Centipede Authors. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // https://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include 16 | #include 17 | #include 18 | 19 | #include "absl/base/nullability.h" 20 | #include "absl/flags/flag.h" 21 | #include "absl/flags/parse.h" 22 | #include "./centipede/mutation_input.h" 23 | #include "./centipede/runner_interface.h" 24 | #include "./common/defs.h" 25 | 26 | ABSL_FLAG(bool, simulate_failure, false, 27 | "If true, the binary will return EXIT_FAILURE to simulate a " 28 | "failure."); 29 | 30 | using fuzztest::internal::ByteSpan; 31 | 32 | class CustomMutatorRunnerCallbacks 33 | : public fuzztest::internal::RunnerCallbacks { 34 | public: 35 | bool Execute(ByteSpan input) override { return true; } 36 | 37 | bool HasCustomMutator() const override { return true; } 38 | 39 | bool Mutate(const std::vector& inputs, 40 | size_t num_mutants, 41 | std::function new_mutant_callback) override { 42 | size_t i = 0; 43 | for (fuzztest::internal::MutationInputRef input : inputs) { 44 | if (i++ >= num_mutants) break; 45 | // Just return the original input as a mutant. 46 | new_mutant_callback(input.data); 47 | } 48 | return true; 49 | } 50 | }; 51 | 52 | int main(int argc, char** absl_nonnull argv) { 53 | absl::ParseCommandLine(argc, argv); 54 | if (absl::GetFlag(FLAGS_simulate_failure)) { 55 | return EXIT_FAILURE; 56 | } 57 | CustomMutatorRunnerCallbacks runner_callbacks; 58 | return fuzztest::internal::RunnerMain(argc, argv, runner_callbacks); 59 | } 60 | -------------------------------------------------------------------------------- /centipede/testing/hanging_fuzz_target.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2025 The Centipede Authors. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // https://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include 16 | #include 17 | #include 18 | 19 | // A fuzz target that hangs even during abort. 20 | extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { 21 | signal(SIGABRT, SIG_IGN); // Ignore abort signals and let the process hang. 22 | while (true) { 23 | } 24 | return 0; 25 | } 26 | -------------------------------------------------------------------------------- /centipede/testing/inline_8bit_counters_test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Copyright 2022 The Centipede Authors. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # https://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | # Test a target binary instrumented with trace_pc 18 | 19 | set -eu 20 | 21 | source "$(dirname "$0")/../test_util.sh" 22 | 23 | CENTIPEDE_TEST_SRCDIR="$(fuzztest::internal::get_centipede_test_srcdir)" 24 | 25 | fuzztest::internal::maybe_set_var_to_executable_path \ 26 | CENTIPEDE_BINARY "${CENTIPEDE_TEST_SRCDIR}/centipede" 27 | 28 | fuzztest::internal::maybe_set_var_to_executable_path \ 29 | TARGET_BINARY "${CENTIPEDE_TEST_SRCDIR}/testing/abort_fuzz_target_inline_8bit_counters" 30 | 31 | # Run fuzzing until the first crash. 32 | WD="${TEST_TMPDIR}/WD" 33 | LOG="${TEST_TMPDIR}/log" 34 | fuzztest::internal::ensure_empty_dir "${WD}" 35 | "${CENTIPEDE_BINARY}" --binary="${TARGET_BINARY}" --workdir="${WD}" \ 36 | --exit_on_crash=1 --seed=1 \ 37 | 2>&1 |tee "${LOG}" 38 | 39 | # Check that we observe the edge coverage, not just random features. 40 | fuzztest::internal::assert_regex_in_file "cov: [3456] " "${LOG}" 41 | # Check that we found the crashy input. 42 | fuzztest::internal::assert_regex_in_file "Input bytes.*: AbOrT" "${LOG}" 43 | 44 | echo "PASS" 45 | -------------------------------------------------------------------------------- /centipede/testing/instrumentation_test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Copyright 2022 The Centipede Authors. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # https://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | # This sh_test checks the size of the pc table generated by a tiny fuzz target. 18 | # If the pc table is not small, it means some redundant instrumentation 19 | # is applied to the runner library. 20 | 21 | set -eu 22 | 23 | source "$(dirname "$0")/../test_util.sh" 24 | 25 | # Max allowed PC table size is 16 bytes, i.e. one entry. 26 | ALLOWED_SIZE=16 27 | 28 | echo "pc table allowed size: ${ALLOWED_SIZE}" 29 | 30 | target="$(fuzztest::internal::get_centipede_test_srcdir)/testing/empty_fuzz_target" 31 | pc_table="${TEST_TMPDIR}/pc_table" 32 | unused1="${TEST_TMPDIR}/unused1" 33 | unused2="${TEST_TMPDIR}/unused2" 34 | 35 | # Dump the pc table on disk. 36 | CENTIPEDE_RUNNER_FLAGS=":dump_binary_info:arg1=${pc_table}:arg2=${unused1}:arg3=${unused2}:" \ 37 | "${target}" 38 | 39 | # Check the pc table size. 40 | if [[ "$OSTYPE" == 'darwin'* ]]; then 41 | size=$(stat -f %z "${pc_table}") 42 | else 43 | size=$(stat -c %s "${pc_table}") 44 | fi 45 | echo "pc table size: ${size}" 46 | (( size < 1 )) && die "pc table is too small: ${size}" 47 | (( size > ALLOWED_SIZE )) && die "pc table is too large: ${size}" 48 | 49 | echo "PASS" 50 | -------------------------------------------------------------------------------- /centipede/testing/minimize_me_fuzz_target.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2022 The Centipede Authors. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // https://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include 16 | #include 17 | #include 18 | 19 | // A fuzz target used for testing Centipede's ability to minimize crashes. 20 | // Crashes on inputs like ?f???u???z?. 21 | extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { 22 | if (size < 3) return 0; 23 | if (data[1] == 'f' && data[size / 2] == 'u' && data[size - 2] == 'z') abort(); 24 | return 0; 25 | } 26 | -------------------------------------------------------------------------------- /centipede/testing/multi_dso_target_lib.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2023 The Centipede Authors. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // https://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include "./centipede/testing/multi_dso_target_lib.h" 16 | 17 | #include 18 | #include 19 | 20 | void DSO(const uint8_t *data, size_t size) { 21 | if (size >= 4 && data[2] == 'z' && data[3] == 'z') __builtin_trap(); 22 | } 23 | -------------------------------------------------------------------------------- /centipede/testing/multi_dso_target_lib.h: -------------------------------------------------------------------------------- 1 | // Copyright 2023 The Centipede Authors. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // https://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #ifndef THIRD_PARTY_CENTIPEDE_TESTING_MULTI_DSO_TARGET_LIB_H_ 16 | #define THIRD_PARTY_CENTIPEDE_TESTING_MULTI_DSO_TARGET_LIB_H_ 17 | 18 | #include 19 | #include 20 | 21 | void DSO(const uint8_t *data, size_t size); 22 | 23 | #endif // THIRD_PARTY_CENTIPEDE_TESTING_MULTI_DSO_TARGET_LIB_H_ 24 | -------------------------------------------------------------------------------- /centipede/testing/multi_dso_target_main.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2023 The Centipede Authors. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // https://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include 16 | #include 17 | 18 | #include "./centipede/testing/multi_dso_target_lib.h" 19 | 20 | // A fuzz target that calls into a different DSO. 21 | extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { 22 | if (size >= 2 && data[0] == 'f' && data[1] == 'u') DSO(data, size); 23 | return 0; 24 | } 25 | -------------------------------------------------------------------------------- /centipede/testing/multi_dso_test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Copyright 2023 The Centipede Authors. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # https://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | # Tests basic functionality for a target with multiple instrumented DSOs. 18 | set -eu 19 | 20 | source "$(dirname "$0")/../test_util.sh" 21 | 22 | 23 | CENTIPEDE_TEST_SRCDIR="$(fuzztest::internal::get_centipede_test_srcdir)" 24 | 25 | fuzztest::internal::maybe_set_var_to_executable_path \ 26 | CENTIPEDE_BINARY "${CENTIPEDE_TEST_SRCDIR}/centipede" 27 | 28 | fuzztest::internal::maybe_set_var_to_executable_path \ 29 | TARGET_BINARY "${CENTIPEDE_TEST_SRCDIR}/testing/multi_dso_target" 30 | 31 | fuzztest::internal::maybe_set_var_to_executable_path \ 32 | LLVM_SYMBOLIZER "$(fuzztest::internal::get_llvm_symbolizer_path)" 33 | 34 | 35 | # Run fuzzing until the first crash. 36 | WD="${TEST_TMPDIR}/WD" 37 | LOG="${TEST_TMPDIR}/log" 38 | fuzztest::internal::ensure_empty_dir "${WD}" 39 | 40 | "${CENTIPEDE_BINARY}" --binary="${TARGET_BINARY}" --workdir="${WD}" \ 41 | --exit_on_crash=1 --seed=1 --log_features_shards=1 \ 42 | --symbolizer_path="${LLVM_SYMBOLIZER}" \ 43 | 2>&1 |tee "${LOG}" 44 | 45 | echo "Fuzzing DONE" 46 | 47 | fuzztest::internal::assert_regex_in_file "Batch execution failed:" "${LOG}" 48 | fuzztest::internal::assert_regex_in_file "Input bytes.*: fuzz" "${LOG}" 49 | fuzztest::internal::assert_regex_in_file "Symbolizing 2 instrumented DSOs" "${LOG}" 50 | fuzztest::internal::assert_regex_in_file "FUNC: LLVMFuzzerTestOneInput" "${LOG}" 51 | fuzztest::internal::assert_regex_in_file "FUNC: DSO" "${LOG}" 52 | 53 | echo "PASS" 54 | -------------------------------------------------------------------------------- /centipede/testing/no_startup_features_test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Copyright 2022 The Centipede Authors. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # https://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | # Tests __attribute__((section("__centipede_extra_features"))) 18 | 19 | set -eu 20 | 21 | source "$(dirname "$0")/../test_util.sh" 22 | 23 | CENTIPEDE_TEST_SRCDIR="$(fuzztest::internal::get_centipede_test_srcdir)" 24 | 25 | fuzztest::internal::maybe_set_var_to_executable_path \ 26 | CENTIPEDE_BINARY "${CENTIPEDE_TEST_SRCDIR}/centipede" 27 | 28 | fuzztest::internal::maybe_set_var_to_executable_path \ 29 | TARGET_BINARY "${CENTIPEDE_TEST_SRCDIR}/testing/expensive_startup_fuzz_target" 30 | 31 | WD="${TEST_TMPDIR}/WD" 32 | LOG="${TEST_TMPDIR}/log" 33 | 34 | # Fuzz the target for a bit with callstacks and paths. 35 | # Ensure that we don't see coverage from the Startup() function. 36 | fuzztest::internal::ensure_empty_dir "${WD}" 37 | "${CENTIPEDE_BINARY}" --binary="${TARGET_BINARY}" --workdir="${WD}" \ 38 | --num_runs=10000 --callstack_level=10 --path_level=10 2>&1 |tee "${LOG}" 39 | 40 | fuzztest::internal::assert_regex_in_file "end-fuzz:.*cov: 1 " "${LOG}" 41 | fuzztest::internal::assert_regex_in_file "end-fuzz:.*stk: 2 " "${LOG}" 42 | fuzztest::internal::assert_regex_in_file "end-fuzz:.*path: 1 " "${LOG}" 43 | fuzztest::internal::assert_regex_not_in_file "end-fuzz:.*cmp" "${LOG}" 44 | fuzztest::internal::assert_regex_not_in_file "end-fuzz:.*df" "${LOG}" 45 | 46 | echo "PASS" 47 | -------------------------------------------------------------------------------- /centipede/testing/seeded_fuzz_target.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2023 The Centipede Authors. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // https://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include 16 | #include 17 | #include 18 | 19 | #include "absl/base/nullability.h" 20 | #include "./centipede/runner_interface.h" 21 | #include "./common/defs.h" 22 | 23 | using fuzztest::internal::ByteSpan; 24 | 25 | class SeededRunnerCallbacks : public fuzztest::internal::RunnerCallbacks { 26 | public: 27 | bool Execute(ByteSpan input) override { 28 | // Should not be called in the test, but return true anyway. 29 | return true; 30 | } 31 | 32 | void GetSeeds(std::function seed_callback) override { 33 | constexpr size_t kNumAvailSeeds = 10; 34 | for (size_t i = 0; i < kNumAvailSeeds; ++i) 35 | seed_callback({static_cast(i)}); 36 | } 37 | 38 | bool HasCustomMutator() const override { return false; } 39 | }; 40 | 41 | int main(int argc, char** absl_nonnull argv) { 42 | SeededRunnerCallbacks runner_callbacks; 43 | return fuzztest::internal::RunnerMain(argc, argv, runner_callbacks); 44 | } 45 | -------------------------------------------------------------------------------- /centipede/testing/standalone_fuzz_target_with_main.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2022 The Centipede Authors. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // https://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // A simple standalone binary that takes one file path as an argument. 16 | // It reads that file and traps if the file starts with 'fuz'. 17 | // Returns EXIT_FAILURE on any error. 18 | // 19 | // For testing how Centipede can fuzz standalone binaries with their main(). 20 | #include 21 | #include 22 | #include 23 | 24 | #include "absl/base/nullability.h" 25 | 26 | // Separate no-inline function so that the compiler doesn't know 27 | // the size of `data`. Crashes when the input starts with 'fuz'. 28 | __attribute__((noinline)) static void FuzzMe(const uint8_t* absl_nonnull data, 29 | size_t size) { 30 | if (size >= 3 && data[0] == 'f' && data[1] == 'u' && data[2] == 'z') 31 | __builtin_trap(); 32 | } 33 | 34 | int main(int argc, char* argv[]) { 35 | if (argc != 2) return EXIT_FAILURE; 36 | constexpr size_t kMaxSize = 1000; 37 | uint8_t bytes[kMaxSize] = {}; 38 | FILE* f = fopen(argv[1], "r"); 39 | if (!f) return EXIT_FAILURE; 40 | auto n_bytes = fread(bytes, 1, kMaxSize, f); 41 | if (n_bytes == 0) return EXIT_FAILURE; 42 | if (fclose(f) != 0) return EXIT_FAILURE; 43 | FuzzMe(bytes, n_bytes); 44 | } 45 | -------------------------------------------------------------------------------- /centipede/testing/test_input_filter.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Copyright 2022 The Centipede Authors. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # https://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | # Test input_filter to be used with --input_filter. 18 | # Returns non-0 if the input contains a letter 'b'. 19 | grep -v b "$1" > /dev/null 20 | -------------------------------------------------------------------------------- /centipede/testing/trace_pc_test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Copyright 2022 The Centipede Authors. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # https://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | # Test a target binary instrumented with trace_pc 18 | 19 | set -eu 20 | 21 | source "$(dirname "$0")/../test_util.sh" 22 | 23 | CENTIPEDE_TEST_SRCDIR="$(fuzztest::internal::get_centipede_test_srcdir)" 24 | 25 | fuzztest::internal::maybe_set_var_to_executable_path \ 26 | CENTIPEDE_BINARY "${CENTIPEDE_TEST_SRCDIR}/centipede" 27 | 28 | fuzztest::internal::maybe_set_var_to_executable_path \ 29 | TARGET_BINARY "${CENTIPEDE_TEST_SRCDIR}/testing/abort_fuzz_target_trace_pc" 30 | 31 | fuzztest::internal::maybe_set_var_to_executable_path \ 32 | OBJDUMP "$(fuzztest::internal::get_objdump_path)" 33 | 34 | 35 | # Run fuzzing until the first crash. 36 | WD="${TEST_TMPDIR}/WD" 37 | LOG="${TEST_TMPDIR}/log" 38 | fuzztest::internal::ensure_empty_dir "${WD}" 39 | "${CENTIPEDE_BINARY}" --binary="${TARGET_BINARY}" --workdir="${WD}" \ 40 | --objdump_path="${OBJDUMP}" \ 41 | --exit_on_crash=1 --seed=1 \ 42 | 2>&1 |tee "${LOG}" 43 | 44 | # Check that we observe the edge coverage, not just random features. 45 | fuzztest::internal::assert_regex_in_file "cov: [3456] " "${LOG}" 46 | # Check that we fell back to GetPcTableFromBinaryWithTracePC. 47 | fuzztest::internal::assert_regex_in_file \ 48 | "falling back to legacy PC table extraction using trace-pc and objdump" "${LOG}" 49 | # Check that we found the crashy input. 50 | fuzztest::internal::assert_regex_in_file "Input bytes.*: AbOrT" "${LOG}" 51 | 52 | echo "PASS" 53 | -------------------------------------------------------------------------------- /centipede/testing/user_defined_features_test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Copyright 2022 The Centipede Authors. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # https://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | # Tests __attribute__((section("__centipede_extra_features"))) 18 | 19 | set -eu 20 | 21 | source "$(dirname "$0")/../test_util.sh" 22 | 23 | CENTIPEDE_TEST_SRCDIR="$(fuzztest::internal::get_centipede_test_srcdir)" 24 | 25 | fuzztest::internal::maybe_set_var_to_executable_path \ 26 | CENTIPEDE_BINARY "${CENTIPEDE_TEST_SRCDIR}/centipede" 27 | 28 | fuzztest::internal::maybe_set_var_to_executable_path \ 29 | TARGET_BINARY "${CENTIPEDE_TEST_SRCDIR}/testing/user_defined_features_target" 30 | 31 | WD="${TEST_TMPDIR}/WD" 32 | LOG="${TEST_TMPDIR}/log" 33 | 34 | "${TARGET_BINARY}" 2>&1 | tee "${LOG}" 35 | 36 | fuzztest::internal::assert_regex_in_file \ 37 | "section..__centipede_extra_features.. detected with 10000 elements" "${LOG}" 38 | 39 | fuzztest::internal::ensure_empty_dir "${WD}" 40 | "${CENTIPEDE_BINARY}" --binary="${TARGET_BINARY}" --workdir="${WD}" \ 41 | --num_runs=10000 2>&1 |tee "${LOG}" 42 | 43 | fuzztest::internal::assert_regex_in_file "usr0: [0-9]\{3,\} " "${LOG}" 44 | fuzztest::internal::assert_regex_in_file "usr1: [0-9]\{3,\} " "${LOG}" 45 | fuzztest::internal::assert_regex_not_in_file "usr2: " "${LOG}" 46 | fuzztest::internal::assert_regex_not_in_file "usr3: " "${LOG}" 47 | 48 | echo "PASS" 49 | -------------------------------------------------------------------------------- /cmake/AddFuzzTest.cmake: -------------------------------------------------------------------------------- 1 | # Copyright 2023 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | function(link_fuzztest name) 16 | target_link_libraries( 17 | ${name} 18 | PRIVATE 19 | fuzztest::fuzztest 20 | fuzztest::fuzztest_gtest_main 21 | ) 22 | endfunction() 23 | 24 | function(link_fuzztest_core name) 25 | target_link_libraries( 26 | ${name} 27 | PRIVATE 28 | fuzztest::fuzztest_core 29 | fuzztest::fuzztest_gtest_main 30 | ) 31 | endfunction() 32 | -------------------------------------------------------------------------------- /cmake/CMakeLists.txt.jinja: -------------------------------------------------------------------------------- 1 | # Copyright 2023 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | {%- for target in targets %} 16 | 17 | fuzztest_{{ target.type }}( 18 | NAME 19 | {{ target.name }} 20 | {%- if target.hdrs is defined %} 21 | HDRS 22 | {%- for hdr in target.hdrs %} 23 | "{{ hdr }}" 24 | {%- endfor %} 25 | {%- endif %} 26 | {%- if target.srcs is defined %} 27 | SRCS 28 | {%- for src in target.srcs %} 29 | "{{ src }}" 30 | {%- endfor %} 31 | {%- endif %} 32 | {%- if target.deps is defined %} 33 | DEPS 34 | {%- for dep in target.deps %} 35 | {{ dep }} 36 | {%- endfor %} 37 | {%- endif %} 38 | ) 39 | {%- endfor %} -------------------------------------------------------------------------------- /cmake/CompatibilityModeLinkLibFuzzer.cmake: -------------------------------------------------------------------------------- 1 | # Copyright 2025 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | function(_link_libfuzzer_in_compatibility_mode name) 16 | if (FUZZTEST_COMPATIBILITY_MODE STREQUAL "libfuzzer") 17 | EXECUTE_PROCESS ( 18 | COMMAND bash -c "find \${PATH//:/ } -maxdepth 1 -executable -name 'llvm-config*'" 19 | OUTPUT_VARIABLE LLVM_CONFIG OUTPUT_STRIP_TRAILING_WHITESPACE 20 | ) 21 | EXECUTE_PROCESS( 22 | COMMAND bash -c "find $(${LLVM_CONFIG} --libdir) \ 23 | -name libclang_rt.fuzzer_no_main-x86_64.a" 24 | OUTPUT_VARIABLE FUZZER_NO_MAIN OUTPUT_STRIP_TRAILING_WHITESPACE 25 | ) 26 | if(NOT FUZZER_NO_MAIN) 27 | # LLVM_ENABLE_PER_TARGET_RUNTIME_DIR was set to ON when building LLVM. 28 | EXECUTE_PROCESS( 29 | COMMAND bash -c "find / -regex \ 30 | \"$(${LLVM_CONFIG} --libdir).*$(${LLVM_CONFIG} --host-target).*libclang_rt.fuzzer_no_main.a\"" 31 | OUTPUT_VARIABLE FUZZER_NO_MAIN OUTPUT_STRIP_TRAILING_WHITESPACE 32 | ) 33 | endif() 34 | target_link_libraries(${name} PRIVATE ${FUZZER_NO_MAIN}) 35 | endif () 36 | endfunction() -------------------------------------------------------------------------------- /cmake/FuzzTestFlagSetup.cmake: -------------------------------------------------------------------------------- 1 | # Copyright 2023 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | macro(fuzztest_setup_fuzzing_flags) 16 | if (FUZZTEST_FUZZING_MODE OR (FUZZTEST_COMPATIBILITY_MODE STREQUAL "libfuzzer")) 17 | SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION -UNDEBUG -fsanitize=address") 18 | SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g -DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION -UNDEBUG -fsanitize=address") 19 | SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=address") 20 | endif () 21 | if (FUZZTEST_COMPATIBILITY_MODE STREQUAL "libfuzzer") 22 | SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=fuzzer-no-link -DFUZZTEST_COMPATIBILITY_MODE") 23 | SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=fuzzer-no-link -DFUZZTEST_COMPATIBILITY_MODE") 24 | endif () 25 | if (FUZZTEST_FUZZING_MODE OR (FUZZTEST_COMPATIBILITY_MODE STREQUAL "libfuzzer")) 26 | SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize-coverage=inline-8bit-counters -fsanitize-coverage=trace-cmp -fsanitize=address -DADDRESS_SANITIZER") 27 | SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize-coverage=inline-8bit-counters -fsanitize-coverage=trace-cmp -fsanitize=address -DADDRESS_SANITIZER") 28 | endif () 29 | endmacro () 30 | -------------------------------------------------------------------------------- /codelab/.bazelrc: -------------------------------------------------------------------------------- 1 | # Copyright 2022 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | # Force the use of Clang for all builds. 16 | build --action_env=CC=clang 17 | build --action_env=CXX=clang++ 18 | 19 | # Use the C++17 standard. 20 | build --cxxopt=-std=c++17 21 | 22 | # Show everything when running tests. 23 | test --test_output=streamed 24 | 25 | # To create this file, please run: 26 | # 27 | # bazel run @com_google_fuzztest//bazel:setup_configs > fuzztest.bazelrc 28 | # 29 | try-import %workspace%/fuzztest.bazelrc 30 | -------------------------------------------------------------------------------- /codelab/BUILD: -------------------------------------------------------------------------------- 1 | # Copyright 2022 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | # The Escaping Library example for the FuzzTest Codelab. 16 | 17 | package(default_visibility = ["//visibility:private"]) 18 | 19 | licenses(["notice"]) 20 | 21 | cc_library( 22 | name = "escaping", 23 | srcs = ["escaping.cc"], 24 | hdrs = ["escaping.h"], 25 | ) 26 | 27 | cc_test( 28 | name = "escaping_test", 29 | srcs = ["escaping_test.cc"], 30 | deps = [ 31 | ":escaping", 32 | "@com_google_fuzztest//fuzztest", 33 | "@com_google_fuzztest//fuzztest:fuzztest_gtest_main", 34 | ], 35 | ) 36 | -------------------------------------------------------------------------------- /codelab/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.19) 2 | project(escaping_test) 3 | set(CMAKE_CXX_STANDARD 17) 4 | 5 | include(FetchContent) 6 | 7 | set(FUZZTEST_REPO "google/fuzztest" CACHE STRING "FuzzTest repository." ) 8 | set(FUZZTEST_REPO_BRANCH "main" CACHE STRING "FuzzTest repository branch.") 9 | message("Building fuzztest from ${FUZZTEST_REPO} at branch ${FUZZTEST_REPO_BRANCH}") 10 | 11 | FetchContent_Declare( 12 | fuzztest 13 | GIT_REPOSITORY https://github.com/${FUZZTEST_REPO}.git 14 | GIT_TAG ${FUZZTEST_REPO_BRANCH} 15 | ) 16 | 17 | FetchContent_MakeAvailable(fuzztest) 18 | 19 | enable_testing() 20 | include(GoogleTest) 21 | 22 | fuzztest_setup_fuzzing_flags() 23 | 24 | add_library(escaping 25 | OBJECT 26 | escaping.cc 27 | escaping.h 28 | ) 29 | 30 | add_executable( 31 | escaping_test 32 | escaping_test.cc 33 | ) 34 | 35 | target_link_libraries( 36 | escaping_test 37 | PRIVATE 38 | escaping 39 | ) 40 | 41 | link_fuzztest(escaping_test) 42 | gtest_discover_tests(escaping_test) 43 | 44 | -------------------------------------------------------------------------------- /codelab/MODULE.bazel: -------------------------------------------------------------------------------- 1 | # Copyright 2025 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | module( 16 | name = "fuzztest_codelab", 17 | version = "head", 18 | ) 19 | 20 | bazel_dep( 21 | name = "fuzztest", 22 | version = "20250214.0", 23 | repo_name = "com_google_fuzztest", 24 | ) 25 | 26 | bazel_dep( 27 | name = "googletest", 28 | version = "1.16.0" 29 | ) 30 | -------------------------------------------------------------------------------- /codelab/escaping.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2022 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include "./escaping.h" 16 | 17 | namespace codelab { 18 | 19 | std::string Escape(std::string_view str) { 20 | std::string result; 21 | for (size_t i = 0; i < str.size(); ++i) { 22 | switch (str[i]) { 23 | case '\n': 24 | result.push_back('\\'); 25 | result.push_back('n'); 26 | break; 27 | case '\r': 28 | result.push_back('\\'); 29 | result.push_back('r'); 30 | break; 31 | case '\t': 32 | result.push_back('\\'); 33 | result.push_back('t'); 34 | break; 35 | case '\\': 36 | result.push_back('\\'); 37 | result.push_back('\\'); 38 | break; 39 | default: 40 | result.push_back(str[i]); 41 | break; 42 | } 43 | } 44 | return result; 45 | } 46 | 47 | std::string Unescape(std::string_view str) { 48 | std::string result; 49 | for (size_t i = 0; i < str.size(); ++i) { 50 | if (str[i] == '\\') { 51 | ++i; 52 | switch (str[i]) { 53 | case 'n': 54 | result.push_back('\n'); 55 | break; 56 | case 't': 57 | result.push_back('\t'); 58 | break; 59 | case '\\': 60 | result.push_back('\\'); 61 | break; 62 | default: 63 | break; 64 | } 65 | } else { 66 | result.push_back(str[i]); 67 | } 68 | } 69 | return result; 70 | } 71 | 72 | } // namespace codelab 73 | -------------------------------------------------------------------------------- /codelab/escaping.h: -------------------------------------------------------------------------------- 1 | // Copyright 2022 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #ifndef FUZZTEST_CODELAB_ESCAPING_H_ 16 | #define FUZZTEST_CODELAB_ESCAPING_H_ 17 | 18 | #include 19 | #include 20 | 21 | namespace codelab { 22 | 23 | // Escapes `str`, by replacing special characters, such as '\n' and '\t', 24 | // with their corresponding C escape sequences, i.e., "\\n" and "\\t". 25 | std::string Escape(std::string_view str); 26 | 27 | // Unescapes `str`, by replacing any occurrence of C escape sequences with their 28 | // equivalent character. Invalid sequences are ignored. 29 | std::string Unescape(std::string_view str); 30 | 31 | } // namespace codelab 32 | 33 | #endif // FUZZTEST_CODELAB_ESCAPING_H_ 34 | -------------------------------------------------------------------------------- /codelab/escaping_test.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2022 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include "./escaping.h" 16 | 17 | #include "gtest/gtest.h" 18 | #include "fuzztest/fuzztest.h" 19 | 20 | namespace codelab { 21 | namespace { 22 | 23 | TEST(EscapingTest, EscapingEmptyStringReturnsEmptyString) { 24 | EXPECT_EQ(Escape(""), ""); 25 | } 26 | 27 | TEST(EscapingTest, UnescapingEmptyStringReturnsEmptyString) { 28 | EXPECT_EQ(Unescape(""), ""); 29 | } 30 | 31 | TEST(EscapingTest, EscapingPlainStringIsReturnedAsIs) { 32 | EXPECT_EQ(Escape("plain text"), "plain text"); 33 | } 34 | 35 | TEST(EscapingTest, UnescapingPlainStringIsReturnedAsIs) { 36 | EXPECT_EQ(Unescape("plain text"), "plain text"); 37 | } 38 | 39 | TEST(EscapingTest, EscapingReplacesSpecialCharacters) { 40 | EXPECT_EQ(Escape("two\nlines"), "two\\nlines"); 41 | EXPECT_EQ(Escape("back\\slash"), "back\\\\slash"); 42 | } 43 | 44 | TEST(EscapingTest, UnescapingReplacesEscapeSequences) { 45 | EXPECT_EQ(Unescape("two\\nlines"), "two\nlines"); 46 | EXPECT_EQ(Unescape("back\\\\slash"), "back\\slash"); 47 | } 48 | 49 | // Comment out the following fuzz tests: 50 | 51 | // void UnescapingEscapedStringGivesOriginal(std::string_view s) { 52 | // EXPECT_EQ(s, Unescape(Escape(s))); 53 | // } 54 | // FUZZ_TEST(EscapingTest, UnescapingEscapedStringGivesOriginal); 55 | 56 | // void EscapingAStringNeverTriggersUndefinedBehavior(std::string_view s) { 57 | // Escape(s); 58 | // } 59 | // FUZZ_TEST(EscapingTest, EscapingAStringNeverTriggersUndefinedBehavior); 60 | 61 | // void UnescapingAStringNeverTriggersUndefinedBehavior(std::string_view s) { 62 | // Unescape(s); 63 | // } 64 | // FUZZ_TEST(EscapingTest, UnescapingAStringNeverTriggersUndefinedBehavior); 65 | 66 | } // namespace 67 | } // namespace codelab 68 | -------------------------------------------------------------------------------- /common/bazel.h: -------------------------------------------------------------------------------- 1 | // Copyright 2024 The Centipede Authors. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // https://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #ifndef FUZZTEST_COMMON_BAZEL_H_ 16 | #define FUZZTEST_COMMON_BAZEL_H_ 17 | 18 | #include "absl/status/status.h" 19 | #include "absl/time/time.h" 20 | 21 | namespace fuzztest::internal { 22 | 23 | struct TestShard { 24 | int index = 0; 25 | int total_shards = 1; 26 | }; 27 | 28 | // Get Bazel sharding information based on 29 | // https://bazel.build/reference/test-encyclopedia#initial-conditions 30 | TestShard GetBazelTestShard(); 31 | 32 | // Returns Ok if there is enough time left to run a single test for 33 | // `test_time_limit` given `target_start_time` and timeout and sharding 34 | // information from Bazel, or returns an error status otherwise. It uses 35 | // `executed_tests_in_shard` and `fuzz_test_count` to include suggestions into 36 | // the error status message. 37 | absl::Status VerifyBazelHasEnoughTimeToRunTest(absl::Time target_start_time, 38 | absl::Duration test_time_limit, 39 | int executed_tests_in_shard, 40 | int fuzz_test_count); 41 | 42 | } // namespace fuzztest::internal 43 | 44 | #endif // FUZZTEST_COMMON_BAZEL_H_ 45 | -------------------------------------------------------------------------------- /common/defs.h: -------------------------------------------------------------------------------- 1 | // Copyright 2022 The Centipede Authors. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // https://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #ifndef FUZZTEST_COMMON_DEFS_H_ 16 | #define FUZZTEST_COMMON_DEFS_H_ 17 | 18 | // Only simple definitions here. No code, no dependencies. 19 | // span.h is an exception as it's header-only and very simple. 20 | 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | 27 | #include "absl/types/span.h" 28 | 29 | namespace fuzztest::internal { 30 | 31 | // Just a good random number generator. 32 | using Rng = std::mt19937_64; 33 | 34 | using ByteArray = std::vector; 35 | using ByteSpan = absl::Span; 36 | 37 | // Wraps a container's data into a `ByteSpan`. The lifetime of `blob` should be 38 | // >= that of the returned object. 39 | template 40 | ByteSpan AsByteSpan(const Container &blob) { 41 | return ByteSpan(reinterpret_cast(blob.data()), 42 | blob.size() * sizeof(typename Container::value_type)); 43 | } 44 | 45 | // Reinterprets a `ByteSpan` as a string_view pointing at the same data. The 46 | // lifetime of `str` should be >= that of the returned object. 47 | inline std::string_view AsStringView(ByteSpan str) { 48 | return std::string_view(reinterpret_cast(str.data()), 49 | str.size()); 50 | } 51 | 52 | inline std::string AsString(ByteSpan str) { 53 | return std::string(AsStringView(str)); 54 | } 55 | 56 | // Macro used to allow tests to access protected or private members of a class. 57 | #define FRIEND_TEST(test_case_name, test_name) \ 58 | friend class test_case_name##_##test_name##_Test 59 | 60 | } // namespace fuzztest::internal 61 | 62 | #endif // FUZZTEST_COMMON_DEFS_H_ 63 | -------------------------------------------------------------------------------- /common/hash.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2022 The Centipede Authors. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // https://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include "./common/hash.h" 16 | 17 | #include 18 | #include 19 | #include 20 | #include 21 | 22 | #include "./common/defs.h" 23 | #include "./common/sha1.h" 24 | 25 | namespace fuzztest::internal { 26 | 27 | std::string Hash(ByteSpan span) { 28 | // Compute SHA1. 29 | uint8_t sha1[kShaDigestLength]; 30 | SHA1(span.data(), span.size(), sha1); 31 | // Convert SHA1 to text. 32 | static_assert(kHashLen == 2 * kShaDigestLength); 33 | char sha1_hex_text[kHashLen]; 34 | static const char hex[16] = {'0', '1', '2', '3', '4', '5', '6', '7', 35 | '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; 36 | for (size_t i = 0; i < kShaDigestLength; i++) { 37 | sha1_hex_text[i * 2 + 0] = hex[sha1[i] / 16]; 38 | sha1_hex_text[i * 2 + 1] = hex[sha1[i] % 16]; 39 | } 40 | return {sha1_hex_text, sha1_hex_text + kHashLen}; 41 | } 42 | 43 | std::string Hash(std::string_view str) { 44 | static_assert(sizeof(decltype(str)::value_type) == sizeof(uint8_t)); 45 | return Hash(AsByteSpan(str)); 46 | } 47 | 48 | } // namespace fuzztest::internal 49 | -------------------------------------------------------------------------------- /common/hash.h: -------------------------------------------------------------------------------- 1 | // Copyright 2022 The Centipede Authors. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // https://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #ifndef FUZZTEST_COMMON_UTIL_H_ 16 | #define FUZZTEST_COMMON_UTIL_H_ 17 | 18 | #include 19 | #include 20 | #include 21 | 22 | #include "./common/defs.h" 23 | 24 | namespace fuzztest::internal { 25 | 26 | // Returns a printable hash of a byte array. Currently sha1 is used. 27 | std::string Hash(ByteSpan span); 28 | // Same as above, but for std::string_view. 29 | std::string Hash(std::string_view str); 30 | // Hashes are always this many bytes. 31 | inline constexpr size_t kHashLen = 40; 32 | 33 | } // namespace fuzztest::internal 34 | 35 | #endif // FUZZTEST_COMMON_UTIL_H_ 36 | -------------------------------------------------------------------------------- /common/hash_test.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2022 The Centipede Authors. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // https://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include "./common/hash.h" 16 | 17 | #include "gtest/gtest.h" 18 | 19 | namespace fuzztest::internal { 20 | namespace { 21 | 22 | TEST(UtilTest, Hash) { 23 | // The current implementation of Hash() is sha1. 24 | // Here we test a couple of inputs against their known sha1 values 25 | // obtained from the sha1sum command line utility. 26 | EXPECT_EQ(Hash({'a', 'b', 'c'}), "a9993e364706816aba3e25717850c26c9cd0d89d"); 27 | EXPECT_EQ(Hash({'x', 'y'}), "5f8459982f9f619f4b0d9af2542a2086e56a4bef"); 28 | } 29 | 30 | } // namespace 31 | } // namespace fuzztest::internal 32 | -------------------------------------------------------------------------------- /common/logging.h: -------------------------------------------------------------------------------- 1 | // Copyright 2022 The Centipede Authors. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // https://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #ifndef FUZZTEST_COMMON_LOGGING_H_ 16 | #define FUZZTEST_COMMON_LOGGING_H_ 17 | 18 | // TODO(b/315519925): Temporary leftover from switching to now-available 19 | // OSS Abseil VLOG and friends. Explicitly include these wherever necessary and 20 | // remove from here. 21 | #include "absl/log/check.h" // IWYU pragma: keep 22 | #include "absl/log/log.h" // IWYU pragma: keep 23 | 24 | // Easy variable value logging: LOG(INFO) << VV(foo) << VV(bar); 25 | #define VV(x) #x ": " << (x) << " " 26 | 27 | #endif // FUZZTEST_COMMON_LOGGING_H_ 28 | -------------------------------------------------------------------------------- /common/sha1.h: -------------------------------------------------------------------------------- 1 | // Copyright 2024 The Centipede Authors. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // https://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #ifndef FUZZTEST_COMMON_SHA1_H_ 16 | #define FUZZTEST_COMMON_SHA1_H_ 17 | 18 | #include 19 | #include 20 | 21 | #include "absl/base/nullability.h" 22 | 23 | namespace fuzztest::internal { 24 | 25 | inline constexpr size_t kShaDigestLength = 20; 26 | 27 | // Computes the SHA1 hash of the data given by `data` and `len`, and writes the 28 | // result to `out`. `out` must have at least `kShaDigestLength` bytes of space. 29 | void SHA1(const uint8_t* absl_nonnull data, size_t len, 30 | uint8_t* absl_nonnull out); 31 | 32 | } // namespace fuzztest::internal 33 | 34 | #endif // FUZZTEST_COMMON_SHA1_H_ 35 | -------------------------------------------------------------------------------- /common/temp_dir.cc: -------------------------------------------------------------------------------- 1 | #include "./common/temp_dir.h" 2 | 3 | #include 4 | #include // NOLINT 5 | #include // NOLINT 6 | 7 | #include "absl/log/check.h" 8 | #include "absl/strings/str_cat.h" 9 | #include "absl/strings/string_view.h" 10 | 11 | namespace fuzztest::internal { 12 | 13 | namespace fs = std::filesystem; 14 | 15 | TempDir::TempDir(absl::string_view custom_prefix) { 16 | fs::path temp_root; 17 | temp_root = absl::NullSafeStringView(getenv("TEST_TMPDIR")); 18 | if (temp_root.empty()) { 19 | std::error_code error; 20 | temp_root = std::filesystem::temp_directory_path(error); 21 | CHECK(!error) << "Failed to get the root temp directory path: " 22 | << error.message(); 23 | } 24 | absl::string_view prefix = custom_prefix.empty() ? "temp_dir" : custom_prefix; 25 | const fs::path path_template = temp_root / absl::StrCat(prefix, "_XXXXXX"); 26 | #if !defined(_MSC_VER) 27 | path_ = mkdtemp(path_template.string().data()); 28 | #else 29 | CHECK(false) << "Windows is not supported yet."; 30 | #endif 31 | CHECK(std::filesystem::is_directory(path_)); 32 | } 33 | 34 | TempDir::~TempDir() { 35 | std::error_code error; 36 | std::filesystem::remove_all(path_, error); 37 | CHECK(!error) << "Unable to clean up temporary dir " << path_ << ": " 38 | << error.message(); 39 | } 40 | 41 | } // namespace fuzztest::internal 42 | -------------------------------------------------------------------------------- /common/temp_dir.h: -------------------------------------------------------------------------------- 1 | #ifndef FUZZTEST_COMMON_TEMP_DIR_H_ 2 | #define FUZZTEST_COMMON_TEMP_DIR_H_ 3 | 4 | #include // NOLINT 5 | 6 | #include "absl/strings/string_view.h" 7 | 8 | namespace fuzztest::internal { 9 | 10 | // A helper class for creating a temporary directory. Removes the directory 11 | // when it goes out of scope. 12 | class TempDir { 13 | public: 14 | explicit TempDir(absl::string_view custom_prefix = ""); 15 | ~TempDir(); 16 | 17 | TempDir(const TempDir& other) = delete; 18 | TempDir& operator=(const TempDir& other) = delete; 19 | 20 | const std::filesystem::path& path() const { return path_; } 21 | 22 | private: 23 | std::filesystem::path path_; 24 | }; 25 | 26 | } // namespace fuzztest::internal 27 | 28 | #endif // FUZZTEST_COMMON_TEMP_DIR_H_ 29 | -------------------------------------------------------------------------------- /doc/contributing.md: -------------------------------------------------------------------------------- 1 | # How to Contribute 2 | 3 | We'd love to accept your patches and contributions to this project. There are 4 | just a few small guidelines you need to follow. 5 | 6 | ## Contributor License Agreement 7 | 8 | Contributions to this project must be accompanied by a Contributor License 9 | Agreement. You (or your employer) retain the copyright to your contribution; 10 | this simply gives us permission to use and redistribute your contributions as 11 | part of the project. Head over to to see 12 | your current agreements on file or to sign a new one. 13 | 14 | You generally only need to submit a CLA once, so if you've already submitted one 15 | (even if it was for a different project), you probably don't need to do it 16 | again. 17 | 18 | ## Code Reviews 19 | 20 | All submissions, including submissions by project members, require review. We 21 | use GitHub pull requests for this purpose. Consult 22 | [GitHub Help](https://help.github.com/articles/about-pull-requests/) for more 23 | information on using pull requests. 24 | 25 | ## Community Guidelines 26 | 27 | This project follows [Google's Open Source Community 28 | Guidelines](https://opensource.google/conduct/). 29 | -------------------------------------------------------------------------------- /doc/flags-reference.md: -------------------------------------------------------------------------------- 1 | # FuzzTest Flags Reference 2 | 3 | You can run the FuzzTest binary in different modes/configurations by providing 4 | the following flags. 5 | 6 | | Purpose | Flag | Value | 7 | | :------------------ | :-----------------------------------: | -------------: | 8 | | Run a fuzz test in | `--fuzz=MySuite.MyTest` | Fuzz test name | 9 | : fuzzing mode : : : 10 | : indefinitely : : : 11 | | Run all fuzz tests | `--fuzz_for=T` | Duration | 12 | : in fuzzing mode for : : : 13 | : `T` duration : : : 14 | | Limit memory usage | `--rss_limit_mb=123` | Mb | 15 | | Limit time | `--time_limit_per_input=90s` | Duration | 16 | | Limit stack-trace | `--stack_limit_kb=123` | Kb | 17 | -------------------------------------------------------------------------------- /domain_tests/bitgen_ref_domain_test.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2025 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include 16 | 17 | #include "gtest/gtest.h" 18 | #include "absl/random/bit_gen_ref.h" 19 | #include "absl/random/random.h" 20 | #include "./fuzztest/domain_core.h" 21 | #include "./domain_tests/domain_testing.h" 22 | 23 | namespace fuzztest { 24 | namespace { 25 | 26 | TEST(BitGenRefDomainTest, DistinctVariatesGeneratedByCallOperator) { 27 | absl::BitGen bitgen_for_seeding; 28 | 29 | Domain domain = Arbitrary(); 30 | Value v0(domain, bitgen_for_seeding); 31 | Value v1(domain, bitgen_for_seeding); 32 | 33 | // Discard the first value, which may be from the data stream. 34 | // If the implementation of BitGenRefDomain changes this may break. 35 | v0.user_value(); 36 | v1.user_value(); 37 | 38 | std::vector a, b; 39 | for (int i = 0; i < 10; ++i) { 40 | a.push_back(v0.user_value()); 41 | b.push_back(v1.user_value()); 42 | } 43 | EXPECT_NE(a, b); 44 | } 45 | 46 | TEST(BitGenRefDomainTest, AbseilUniformReturnsLowerBoundWhenExhausted) { 47 | absl::BitGen bitgen_for_seeding; 48 | 49 | Domain domain = Arbitrary(); 50 | Value v0(domain, bitgen_for_seeding); 51 | 52 | // Discard the first value, which may be from the data stream. 53 | // If the implementation of BitGenRefDomain changes this may break. 54 | v0.user_value(); 55 | 56 | for (int i = 0; i < 10; ++i) { 57 | EXPECT_EQ(absl::Uniform(v0.user_value, 0, 100), 0); 58 | } 59 | } 60 | 61 | } // namespace 62 | } // namespace fuzztest 63 | -------------------------------------------------------------------------------- /e2e_tests/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | fuzztest_cc_library( 3 | NAME 4 | test_binary_util 5 | HDRS 6 | test_binary_util.h 7 | SRCS 8 | test_binary_util.cc 9 | DEPS 10 | absl::check 11 | absl::flat_hash_map 12 | absl::strings 13 | absl::string_view 14 | absl::time 15 | fuzztest_flag_name 16 | fuzztest_subprocess 17 | TESTONLY 18 | ) 19 | 20 | add_executable( 21 | functional_test 22 | functional_test.cc 23 | ) 24 | target_link_libraries( 25 | functional_test 26 | PUBLIC 27 | fuzztest_escaping 28 | fuzztest_io 29 | fuzztest_logging 30 | fuzztest_printer 31 | fuzztest_serialization 32 | fuzztest_subprocess 33 | fuzztest_test_binary_util 34 | fuzztest_type_support 35 | fuzztest_temp_dir 36 | re2 37 | absl::flat_hash_map 38 | absl::strings 39 | absl::str_format 40 | absl::time 41 | GTest::gmock_main 42 | ) 43 | add_test( 44 | NAME 45 | functional_test 46 | COMMAND 47 | functional_test --test_srcdir="${CMAKE_BINARY_DIR}" 48 | ) 49 | set_property( 50 | TEST 51 | functional_test 52 | PROPERTY ENVIRONMENT 53 | "TEST_SRCDIR=${CMAKE_BINARY_DIR}" 54 | ) 55 | 56 | add_executable( 57 | benchmark_test 58 | benchmark_test.cc 59 | ) 60 | target_link_libraries( 61 | benchmark_test 62 | PUBLIC 63 | fuzztest_logging 64 | fuzztest_subprocess 65 | re2 66 | absl::flat_hash_map 67 | absl::flags 68 | absl::flags_parse 69 | absl::strings 70 | absl::str_format 71 | absl::time 72 | GTest::gmock_main 73 | ) 74 | -------------------------------------------------------------------------------- /e2e_tests/testdata/corpus_database/fuzz_tests_for_functional_testing.stripped/MySuite.CrashOnCrashingInput/crashing/crashing1: -------------------------------------------------------------------------------- 1 | FUZZTESTv1 2 | sub { 3 | s: "crashing input number 1" 4 | } 5 | -------------------------------------------------------------------------------- /e2e_tests/testdata/corpus_database/fuzz_tests_for_functional_testing.stripped/MySuite.CrashOnCrashingInput/crashing/crashing2: -------------------------------------------------------------------------------- 1 | FUZZTESTv1 2 | sub { 3 | s: "crashing input number 2" 4 | } 5 | -------------------------------------------------------------------------------- /e2e_tests/testdata/corpus_database/fuzz_tests_for_functional_testing.stripped/MySuite.CrashOnCrashingInput/crashing/non_crashing: -------------------------------------------------------------------------------- 1 | FUZZTESTv1 2 | sub { 3 | s: "non-crashing input in crashing dir!" 4 | } 5 | -------------------------------------------------------------------------------- /e2e_tests/testdata/corpus_database/fuzz_tests_for_functional_testing.stripped/MySuite.CrashOnFailingTestInput/crashing/crashing1: -------------------------------------------------------------------------------- 1 | FUZZTESTv1 2 | sub { 3 | s: "crashing input number 1" 4 | } 5 | -------------------------------------------------------------------------------- /e2e_tests/testdata/corpus_database/fuzz_tests_for_functional_testing.stripped/MySuite.CrashOnFailingTestInput/crashing/crashing2: -------------------------------------------------------------------------------- 1 | FUZZTESTv1 2 | sub { 3 | s: "crashing input number 2" 4 | } 5 | -------------------------------------------------------------------------------- /e2e_tests/testdata/corpus_database/fuzz_tests_for_functional_testing.stripped/MySuite.CrashOnFailingTestInput/crashing/non_crashing: -------------------------------------------------------------------------------- 1 | FUZZTESTv1 2 | sub { 3 | s: "non-crashing input in crashing dir!" 4 | } 5 | -------------------------------------------------------------------------------- /e2e_tests/testdata/corpus_database/fuzz_tests_for_functional_testing.stripped/MySuite.DetectRegressionAndCoverageInputs/coverage/coverage1: -------------------------------------------------------------------------------- 1 | FUZZTESTv1 2 | sub { 3 | s: "coverage input number 1" 4 | } 5 | -------------------------------------------------------------------------------- /e2e_tests/testdata/corpus_database/fuzz_tests_for_functional_testing.stripped/MySuite.DetectRegressionAndCoverageInputs/coverage/coverage2: -------------------------------------------------------------------------------- 1 | FUZZTESTv1 2 | sub { 3 | s: "coverage input number 2" 4 | } 5 | -------------------------------------------------------------------------------- /e2e_tests/testdata/corpus_database/fuzz_tests_for_functional_testing.stripped/MySuite.DetectRegressionAndCoverageInputs/regression/regression1: -------------------------------------------------------------------------------- 1 | FUZZTESTv1 2 | sub { 3 | s: "regression input number 1" 4 | } 5 | -------------------------------------------------------------------------------- /e2e_tests/testdata/dynamically_registered_fuzz_tests.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2023 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include "./fuzztest/fuzztest.h" 16 | 17 | namespace { 18 | 19 | void DoesNothing(int) {} 20 | 21 | [[maybe_unused]] static bool registration = [] { 22 | fuzztest::RegisterFuzzTest(fuzztest::GetRegistration( 23 | "TestSuiteOne", "DoesNothing/1", __FILE__, __LINE__, DoesNothing)); 24 | fuzztest::RegisterFuzzTest(fuzztest::GetRegistration( 25 | "TestSuiteTwo", "DoesNothing/2", __FILE__, __LINE__, DoesNothing)); 26 | return true; 27 | }(); 28 | 29 | } // namespace 30 | -------------------------------------------------------------------------------- /e2e_tests/testdata/fuzz_tests_with_invalid_seeds.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2022 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // Fuzz test examples to be used by `functional_test` only. 16 | 17 | #include "./fuzztest/fuzztest.h" 18 | 19 | namespace { 20 | 21 | // TODO(b/203465367): Investigate if we can delay execution of seed parsing 22 | // until main(). 23 | void InvalidSeedDueToUserValueNotConvertibleToCorpusValue(int) {} 24 | FUZZ_TEST(MySuite, InvalidSeedDueToUserValueNotConvertibleToCorpusValue) 25 | // Map does not support seeds. 26 | .WithDomains(fuzztest::Map([](int) { return 0; }, 27 | fuzztest::Arbitrary())) 28 | .WithSeeds({{17}}); 29 | 30 | void InvalidSeedDueToCorpusValueOutOfDomain(int) {} 31 | FUZZ_TEST(MySuite, InvalidSeedDueToCorpusValueOutOfDomain) 32 | .WithDomains(fuzztest::InRange(0, 10)) 33 | .WithSeeds({{2}, {17}, {6}}); 34 | 35 | struct MyTest { 36 | void ShouldNotCrash(int) {} 37 | std::vector> GetSeeds() { return {{2}, {17}, {6}}; } 38 | }; 39 | FUZZ_TEST_F(MyTest, ShouldNotCrash) 40 | .WithDomains(fuzztest::InRange(0, 10)) 41 | .WithSeeds(&MyTest::GetSeeds); 42 | 43 | } // namespace 44 | -------------------------------------------------------------------------------- /e2e_tests/testdata/llvm_fuzzer_with_custom_mutator.cc: -------------------------------------------------------------------------------- 1 | // A LLVM fuzzer puzzle that are supposed be solvable with the custom mutator 2 | // calling LLVMFuzzerMutate (with auto-dictionary support). 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | extern "C" size_t LLVMFuzzerMutate(uint8_t *data, size_t size, size_t max_size); 11 | 12 | static void Transform(char *data, size_t size) { 13 | for (char *c = data; c < data + size; ++c) { 14 | if (*c < std::numeric_limits::max()) ++*c; 15 | } 16 | } 17 | 18 | static void InvTransform(char *data, size_t size) { 19 | for (char *c = data; c < data + size; ++c) { 20 | if (*c > std::numeric_limits::min()) --*c; 21 | } 22 | } 23 | 24 | extern "C" size_t LLVMFuzzerCustomMutator(uint8_t *data, size_t size, 25 | size_t max_size, unsigned int seed) { 26 | size = LLVMFuzzerMutate(data, size, max_size); 27 | InvTransform(reinterpret_cast(data), size); 28 | return size; 29 | } 30 | 31 | extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { 32 | std::string s = {reinterpret_cast(data), size}; 33 | Transform(s.data(), size); 34 | if (s == "bingo") { 35 | std::abort(); 36 | } 37 | return 0; 38 | } 39 | -------------------------------------------------------------------------------- /e2e_tests/testdata/unit_test_and_fuzz_tests.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2024 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include "gtest/gtest.h" 16 | #include "./fuzztest/fuzztest.h" 17 | 18 | namespace { 19 | 20 | TEST(UnitTest, AlwaysPasses) {} 21 | 22 | void AlwaysPasses(int) {} 23 | FUZZ_TEST(FuzzTest, AlwaysPasses); 24 | 25 | void AlsoAlwaysPasses(int) {} 26 | FUZZ_TEST(FuzzTest, AlsoAlwaysPasses); 27 | 28 | } // namespace 29 | -------------------------------------------------------------------------------- /fuzztest/fuzztest.h: -------------------------------------------------------------------------------- 1 | // Copyright 2022 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #ifndef FUZZTEST_FUZZTEST_FUZZTEST_H_ 16 | #define FUZZTEST_FUZZTEST_FUZZTEST_H_ 17 | 18 | // IWYU pragma: begin_exports 19 | #include "./fuzztest/domain.h" 20 | #include "./fuzztest/fuzztest_macros.h" 21 | // IWYU pragma: end_exports 22 | 23 | #endif // FUZZTEST_FUZZTEST_FUZZTEST_H_ 24 | -------------------------------------------------------------------------------- /fuzztest/fuzztest_core.h: -------------------------------------------------------------------------------- 1 | // Copyright 2023 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #ifndef FUZZTEST_FUZZTEST_FUZZTEST_CORE_H_ 16 | #define FUZZTEST_FUZZTEST_FUZZTEST_CORE_H_ 17 | 18 | // IWYU pragma: begin_exports 19 | #include "./fuzztest/domain_core.h" 20 | #include "./fuzztest/fuzztest_macros.h" 21 | // IWYU pragma: end_exports 22 | 23 | #endif // FUZZTEST_FUZZTEST_FUZZTEST_CORE_H_ 24 | -------------------------------------------------------------------------------- /fuzztest/fuzztest_gtest_main.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2022 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include "gtest/gtest.h" 16 | #include "./fuzztest/init_fuzztest.h" 17 | 18 | int main(int argc, char** argv) { 19 | testing::InitGoogleTest(&argc, argv); 20 | // We call fuzztest::ParseAbslFlags rather than absl::ParseCommandLine 21 | // since the latter would complain about any unknown flags that need 22 | // to be passed to legacy fuzzing engines (e.g. libfuzzer). 23 | fuzztest::ParseAbslFlags(argc, argv); 24 | fuzztest::InitFuzzTest(&argc, &argv); 25 | return RUN_ALL_TESTS(); 26 | } 27 | -------------------------------------------------------------------------------- /fuzztest/grammars/BUILD: -------------------------------------------------------------------------------- 1 | # Copyright 2022 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | # Commonly used grammars. 16 | 17 | load( 18 | "//build_defs:cc_fuzztest_grammar_library.bzl", 19 | "cc_fuzztest_grammar_library", 20 | ) 21 | 22 | package(default_visibility = ["//visibility:public"]) 23 | 24 | licenses(["notice"]) 25 | 26 | exports_files(["JSON.g4"]) 27 | 28 | cc_fuzztest_grammar_library( 29 | name = "json_grammar", 30 | srcs = ["JSON.g4"], 31 | top_level_rule = "json", 32 | ) 33 | -------------------------------------------------------------------------------- /fuzztest/grammars/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | function(fuzztest_grammar_library lib_name top_level_rule) 2 | if (ARGN) 3 | set(${lib_name}_grammar_files "") 4 | set(${lib_name}_output_file ${lib_name}.h) 5 | foreach(grammar_file ${ARGN}) 6 | get_filename_component(abs_path ${grammar_file} ABSOLUTE) 7 | list(APPEND ${lib_name}_grammar_files ${abs_path}) 8 | endforeach() 9 | string(JOIN "," all_grammar_files ${${lib_name}_grammar_files}) 10 | 11 | add_custom_command( 12 | OUTPUT ${${lib_name}_output_file} 13 | COMMAND 14 | $ 15 | --top_level_rule ${top_level_rule} 16 | --input_grammar_files ${all_grammar_files} 17 | --output_header_file_path 18 | ${CMAKE_CURRENT_BINARY_DIR}/${${lib_name}_output_file} 19 | DEPENDS ${${lib_name}_grammar_files} 20 | ) 21 | 22 | add_library( 23 | ${lib_name} 24 | INTERFACE 25 | ${${lib_name}_output_file} 26 | ) 27 | 28 | target_include_directories( 29 | ${lib_name} 30 | INTERFACE 31 | ${CMAKE_CURRENT_BINARY_DIR}/.. 32 | ) 33 | 34 | add_dependencies( 35 | ${lib_name} 36 | grammar_domain_code_generator 37 | ) 38 | else() 39 | message(FATAL_ERROR "No grammar files specified!") 40 | endif() 41 | endfunction() 42 | 43 | fuzztest_grammar_library("json_grammar" "json" ./JSON.g4) 44 | -------------------------------------------------------------------------------- /fuzztest/grammars/JSON.g4: -------------------------------------------------------------------------------- 1 | // Copyright 2022 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // Based on JSON spec at http://json.org. 16 | // 17 | // With some simplifications: 18 | // - Restricted character set (e.g., no unicode chars). 19 | // - No escape sequences (e.g., \n, \t, \uff01, etc.) 20 | 21 | grammar JSON_GRAMMAR; 22 | 23 | json : element ; 24 | 25 | value : object | array | STRING | NUMBER | 'true' | 'false' | 'null' ; 26 | 27 | object : '{' '}' | '{' members '}' ; 28 | 29 | members : member | member ',' members ; 30 | 31 | member : STRING ':' element ; 32 | 33 | array : '[' ']' | '[' elements ']' ; 34 | 35 | elements : element (',' element)* ; 36 | 37 | element : value ; 38 | 39 | STRING : '"' CHARACTER* '"' ; 40 | 41 | CHARACTER : [a-zA-Z0-9_]; 42 | 43 | NUMBER : INTEGER FRACTION? EXPONENT? ; 44 | 45 | INTEGER : DIGIT | ONETONINE DIGITS | '-' DIGIT | '-' ONETONINE DIGITS ; 46 | 47 | DIGITS : DIGIT+ ; 48 | 49 | DIGIT : '0' | ONETONINE ; 50 | 51 | ONETONINE : [1-9] ; 52 | 53 | FRACTION : '.' DIGITS ; 54 | 55 | EXPONENT : [Ee] SIGN? ONETONINE DIGIT?; 56 | 57 | SIGN : '+' | '-' ; 58 | 59 | WSPACE : [ \t\n\r]+ -> skip; 60 | -------------------------------------------------------------------------------- /fuzztest/internal/centipede_adaptor.h: -------------------------------------------------------------------------------- 1 | // Copyright 2023 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #ifndef FUZZTEST_FUZZTEST_INTERNAL_CENTIPEDE_ADAPTOR_H_ 16 | #define FUZZTEST_FUZZTEST_INTERNAL_CENTIPEDE_ADAPTOR_H_ 17 | 18 | #include 19 | 20 | #include "./fuzztest/internal/configuration.h" 21 | #include "./fuzztest/internal/fixture_driver.h" 22 | #include "./fuzztest/internal/runtime.h" 23 | 24 | namespace fuzztest::internal { 25 | 26 | class CentipedeFixtureDriver; 27 | 28 | // Adaptor for running FuzzTest fuzzers with the Centipede engine. 29 | class CentipedeFuzzerAdaptor : public FuzzTestFuzzer { 30 | public: 31 | CentipedeFuzzerAdaptor(const FuzzTest& test, 32 | std::unique_ptr fixture_driver); 33 | bool RunInUnitTestMode(const Configuration& configuration) override; 34 | bool RunInFuzzingMode(int* argc, char*** argv, 35 | const Configuration& configuration) override; 36 | 37 | private: 38 | bool Run(int* argc, char*** argv, RunMode mode, 39 | const Configuration& configuration); 40 | bool ReplayCrashInSingleProcess(const Configuration& configuration); 41 | 42 | Runtime& runtime_ = Runtime::instance(); 43 | const FuzzTest& test_; 44 | CentipedeFixtureDriver* centipede_fixture_driver_; 45 | FuzzTestFuzzerImpl fuzzer_impl_; 46 | }; 47 | 48 | // Lists crash IDs for `test_name` with `configuration` using Centipede. 49 | std::vector ListCrashIdsUsingCentipede( 50 | const Configuration& configuration, absl::string_view test_name); 51 | 52 | // Returns whether the current process is a Centipede runner process. 53 | bool IsCentipedeRunner(); 54 | 55 | } // namespace fuzztest::internal 56 | 57 | #endif // FUZZTEST_FUZZTEST_INTERNAL_CENTIPEDE_ADAPTOR_H_ 58 | -------------------------------------------------------------------------------- /fuzztest/internal/domains/mutation_metadata.h: -------------------------------------------------------------------------------- 1 | // Copyright 2024 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #ifndef FUZZTEST_FUZZTEST_INTERNAL_DOMAINS_MUTATION_METADATA_H_ 16 | #define FUZZTEST_FUZZTEST_INTERNAL_DOMAINS_MUTATION_METADATA_H_ 17 | 18 | #include "./fuzztest/internal/table_of_recent_compares.h" 19 | 20 | namespace fuzztest::domain_implementor { 21 | 22 | // Opaque pointer to comparison tables used by builtin domains, imported here 23 | // for domain implementors who do not need the internal header. 24 | using ConstCmpTablesPtr = const internal::TablesOfRecentCompares*; 25 | 26 | // A struct holding metadata for domain mutation. 27 | struct MutationMetadata { 28 | ConstCmpTablesPtr cmp_tables = nullptr; 29 | }; 30 | 31 | } // namespace fuzztest::domain_implementor 32 | 33 | #endif // FUZZTEST_FUZZTEST_INTERNAL_DOMAINS_MUTATION_METADATA_H_ 34 | -------------------------------------------------------------------------------- /fuzztest/internal/domains/rune.h: -------------------------------------------------------------------------------- 1 | /* 2 | * The authors of this software are Rob Pike and Ken Thompson. 3 | * Copyright (c) 2002 by Lucent Technologies. 4 | * Permission to use, copy, modify, and distribute this software for any 5 | * purpose without fee is hereby granted, provided that this entire notice 6 | * is included in all copies of any software which is or includes a copy 7 | * or modification of this software and in all copies of the supporting 8 | * documentation for such software. 9 | * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED 10 | * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE 11 | * ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY OF 12 | * THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. 13 | * 14 | * rune.* have been converted to compile as C++ code in fuzztest::internal 15 | * namespace. 16 | */ 17 | 18 | #ifndef FUZZTEST_FUZZTEST_INTERNAL_DOMAINS_RUNE_H_ 19 | #define FUZZTEST_FUZZTEST_INTERNAL_DOMAINS_RUNE_H_ 20 | 21 | namespace fuzztest::internal { 22 | 23 | typedef signed int Rune; /* Code-point values in Unicode 4.0 are 21 bits wide.*/ 24 | 25 | enum { 26 | UTFmax = 4, /* maximum bytes per rune */ 27 | Runesync = 0x80, /* cannot represent part of a UTF sequence (<) */ 28 | Runeself = 0x80, /* rune and UTF sequences are the same (<) */ 29 | Runeerror = 0xFFFD, /* decoding error in UTF */ 30 | Runemax = 0x10FFFF, /* maximum rune value */ 31 | }; 32 | 33 | int runetochar(char* s, const Rune* r); 34 | int chartorune(Rune* r, const char* s); 35 | 36 | } // namespace fuzztest::internal 37 | 38 | #endif // FUZZTEST_FUZZTEST_INTERNAL_DOMAINS_RUNE_H_ 39 | -------------------------------------------------------------------------------- /fuzztest/internal/domains/special_values.h: -------------------------------------------------------------------------------- 1 | // Copyright 2024 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #ifndef FUZZTEST_FUZZTEST_INTERNAL_DOMAINS_SPECIAL_VALUES_H_ 16 | #define FUZZTEST_FUZZTEST_INTERNAL_DOMAINS_SPECIAL_VALUES_H_ 17 | 18 | #include 19 | #include 20 | #include 21 | #include 22 | 23 | namespace fuzztest::internal { 24 | 25 | template 26 | class SpecialValues { 27 | public: 28 | static constexpr std::array Get() { return {}; } 29 | }; 30 | 31 | template 32 | class SpecialValues::is_integer>> { 33 | public: 34 | static constexpr auto Get() { 35 | // NB: std::to_array() is not available until C++20. 36 | return std::array{ 37 | T{0}, T{1}, 38 | // For some types, ~T{} is promoted to int. Convert back to T. 39 | static_cast(~T{}), 40 | std::numeric_limits::is_signed 41 | ? std::numeric_limits::max() 42 | : static_cast(std::numeric_limits::max() >> 1)}; 43 | } 44 | }; 45 | 46 | template 47 | class SpecialValues>> { 48 | public: 49 | static auto Get() { 50 | return std::array{ 51 | T{0.0}, T{-0.0}, T{1.0}, T{-1.0}, std::numeric_limits::max(), 52 | std::numeric_limits::infinity(), -std::numeric_limits::infinity(), 53 | // std::nan is double. Cast to T explicitly. 54 | static_cast(std::nan(""))}; 55 | } 56 | }; 57 | 58 | } // namespace fuzztest::internal 59 | 60 | #endif // FUZZTEST_FUZZTEST_INTERNAL_DOMAINS_SPECIAL_VALUES_H_ 61 | -------------------------------------------------------------------------------- /fuzztest/internal/domains/utf.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2025 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include "./fuzztest/internal/domains/utf.h" 16 | 17 | #include 18 | #include 19 | #include 20 | #include 21 | 22 | #include "absl/strings/string_view.h" 23 | #include "./fuzztest/internal/domains/rune.h" 24 | 25 | namespace fuzztest::internal { 26 | 27 | std::string EncodeAsUTF8(const std::vector& code_points) { 28 | std::string out; 29 | out.reserve(code_points.size()); 30 | for (int c : code_points) { 31 | if ((static_cast(c) < 0xD800) || (c >= 0xE000 && c <= 0x10FFFF)) { 32 | char buf[4]; 33 | out.append(std::string(buf, runetochar(buf, &c))); 34 | } else { 35 | static constexpr char ReplacementChars[] = {'\xEF', '\xBF', '\xBD'}; 36 | out.append(ReplacementChars, sizeof(ReplacementChars)); 37 | } 38 | } 39 | return out; 40 | } 41 | 42 | std::optional> DecodeFromUTF8(const std::string& utf8) { 43 | std::vector out; 44 | absl::string_view in(utf8); 45 | out.reserve(in.size()); 46 | while (!in.empty()) { 47 | Rune r; 48 | int len = chartorune(&r, in.data()); 49 | out.push_back(r); 50 | if (r == Runeerror && len != 3) return std::nullopt; 51 | in.remove_prefix(len); 52 | } 53 | return out; 54 | } 55 | 56 | } // namespace fuzztest::internal 57 | -------------------------------------------------------------------------------- /fuzztest/internal/domains/utf.h: -------------------------------------------------------------------------------- 1 | // Copyright 2025 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #ifndef FUZZTEST_INTERNAL_DOMAINS_UTF_H_ 16 | #define FUZZTEST_INTERNAL_DOMAINS_UTF_H_ 17 | 18 | #include 19 | #include 20 | #include 21 | 22 | namespace fuzztest::internal { 23 | 24 | // Encode a sequence of code points as UTF-8 string. 25 | std::string EncodeAsUTF8(const std::vector& code_points); 26 | 27 | // Decode a UTF-8 string into a sequence of code points. Returns nullopt if the 28 | // string is not valid UTF-8. 29 | std::optional> DecodeFromUTF8(const std::string& utf8); 30 | 31 | } // namespace fuzztest::internal 32 | 33 | #endif // FUZZTEST_INTERNAL_DOMAINS_UTF_H_ 34 | -------------------------------------------------------------------------------- /fuzztest/internal/escaping.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2025 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include "./fuzztest/internal/escaping.h" 16 | 17 | #include 18 | 19 | #include "absl/strings/str_cat.h" 20 | #include "absl/strings/str_replace.h" 21 | #include "absl/strings/string_view.h" 22 | 23 | namespace fuzztest::internal { 24 | 25 | std::string ShellEscape(absl::string_view s) { 26 | return absl::StrCat("'", absl::StrReplaceAll(s, {{"'", "'\\''"}}), "'"); 27 | } 28 | 29 | } // namespace fuzztest::internal 30 | -------------------------------------------------------------------------------- /fuzztest/internal/escaping.h: -------------------------------------------------------------------------------- 1 | // Copyright 2025 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #ifndef FUZZTEST_FUZZTEST_INTERNAL_ESCAPING_H_ 16 | #define FUZZTEST_FUZZTEST_INTERNAL_ESCAPING_H_ 17 | 18 | #include 19 | 20 | #include "absl/strings/string_view.h" 21 | 22 | namespace fuzztest::internal { 23 | 24 | // Returns a Bourne shell string literal to be expanded into `s` 25 | std::string ShellEscape(absl::string_view s); 26 | 27 | } // namespace fuzztest::internal 28 | 29 | #endif // FUZZTEST_FUZZTEST_INTERNAL_ESCAPING_H_ 30 | -------------------------------------------------------------------------------- /fuzztest/internal/fixture_driver.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2022 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include "./fuzztest/internal/fixture_driver.h" 16 | 17 | #include 18 | 19 | #include "absl/functional/any_invocable.h" 20 | 21 | namespace fuzztest::internal { 22 | 23 | UntypedFixtureDriver::~UntypedFixtureDriver() = default; 24 | void UntypedFixtureDriver::RunFuzzTest(absl::AnyInvocable run_test) { 25 | std::move(run_test)(); 26 | } 27 | void UntypedFixtureDriver::RunFuzzTestIteration( 28 | absl::AnyInvocable run_iteration) { 29 | std::move(run_iteration)(); 30 | } 31 | 32 | } // namespace fuzztest::internal 33 | -------------------------------------------------------------------------------- /fuzztest/internal/flag_name.h: -------------------------------------------------------------------------------- 1 | // Copyright 2023 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #ifndef FUZZTEST_FUZZTEST_INTERNAL_FLAG_NAME_H_ 16 | #define FUZZTEST_FUZZTEST_INTERNAL_FLAG_NAME_H_ 17 | 18 | #define FUZZTEST_FLAG_PREFIX "" 19 | #define FUZZTEST_FLAG_NAME(name) name 20 | #define FUZZTEST_FLAG(name) FLAGS_##name 21 | 22 | #endif 23 | -------------------------------------------------------------------------------- /fuzztest/internal/register_fuzzing_mocks.h: -------------------------------------------------------------------------------- 1 | // Copyright 2025 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #ifndef FUZZTEST_FUZZTEST_INTERNAL_REGISTER_FUZZING_MOCKS_H_ 16 | #define FUZZTEST_FUZZTEST_INTERNAL_REGISTER_FUZZING_MOCKS_H_ 17 | 18 | #include 19 | 20 | #include "absl/base/fast_type_id.h" 21 | #include "absl/functional/function_ref.h" 22 | #include "absl/types/span.h" 23 | 24 | namespace fuzztest::internal { 25 | 26 | // TypeErasedFuzzFunctionT(datastream, args_tuple, result) is a type erased 27 | // function pointer for use with absl::MockingBitGen and fuzztest mocking. 28 | using TypeErasedFuzzFunctionT = void (*)(absl::Span&, void*, 29 | void*); 30 | 31 | // Registers the fuzzing functions for Abseil distributions. 32 | void RegisterAbslRandomFuzzingMocks( 33 | absl::FunctionRef 34 | register_fn); 35 | 36 | } // namespace fuzztest::internal 37 | 38 | #endif // FUZZTEST_FUZZTEST_INTERNAL_REGISTER_FUZZING_MOCKS_H_ 39 | -------------------------------------------------------------------------------- /fuzztest/internal/status.cc: -------------------------------------------------------------------------------- 1 | #include "./fuzztest/internal/status.h" 2 | 3 | #include "absl/status/status.h" 4 | #include "absl/strings/cord.h" 5 | #include "absl/strings/str_cat.h" 6 | #include "absl/strings/string_view.h" 7 | 8 | absl::Status SetMessage(const absl::Status& status, absl::string_view message) { 9 | absl::Status result(status.code(), message); 10 | status.ForEachPayload( 11 | [&](absl::string_view type_url, const absl::Cord& payload) { 12 | result.SetPayload(type_url, payload); 13 | }); 14 | return result; 15 | } 16 | 17 | absl::Status Prefix(const absl::Status& status, absl::string_view prefix) { 18 | if (status.ok() || prefix.empty()) return status; 19 | return SetMessage(status, absl::StrCat(prefix, " >> ", status.message())); 20 | } 21 | 22 | absl::Status Postfix(const absl::Status& status, absl::string_view postfix) { 23 | if (status.ok() || postfix.empty()) return status; 24 | return SetMessage(status, absl::StrCat(status.message(), " >> ", postfix)); 25 | } 26 | -------------------------------------------------------------------------------- /fuzztest/internal/status.h: -------------------------------------------------------------------------------- 1 | #ifndef FUZZTEST_FUZZTEST_INTERNAL_STATUS_H_ 2 | #define FUZZTEST_FUZZTEST_INTERNAL_STATUS_H_ 3 | 4 | #include "absl/status/status.h" 5 | #include "absl/strings/string_view.h" 6 | 7 | // Prefix status error message with `prefix`, if `status` is not OK. 8 | absl::Status Prefix(const absl::Status& status, absl::string_view prefix); 9 | 10 | // Postfix status error message with `postfix`, if `status` is not OK. 11 | absl::Status Postfix(const absl::Status& status, absl::string_view postfix); 12 | 13 | #endif // FUZZTEST_FUZZTEST_INTERNAL_STATUS_H_ 14 | -------------------------------------------------------------------------------- /fuzztest/llvm_fuzzer_main.cc: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "gtest/gtest.h" 4 | #include "absl/flags/flag.h" 5 | #include "absl/flags/parse.h" 6 | #include "./fuzztest/init_fuzztest.h" 7 | 8 | extern "C" int __attribute__((weak)) LLVMFuzzerInitialize(int* argc, 9 | char*** argv); 10 | 11 | ABSL_FLAG(std::string, llvm_fuzzer_wrapper_dict_file, "", 12 | "Path to dictionary file used by the wrapped legacy LLVMFuzzer " 13 | "target (https://llvm.org/docs/LibFuzzer.html#fuzz-target)."); 14 | ABSL_FLAG(std::string, llvm_fuzzer_wrapper_corpus_dir, "", 15 | "Path to seed corpus directory used by the wrapped legacy LLVMFuzzer " 16 | "target (https://llvm.org/docs/LibFuzzer.html#fuzz-target)."); 17 | 18 | int main(int argc, char** argv) { 19 | absl::ParseCommandLine(argc, argv); 20 | testing::InitGoogleTest(&argc, argv); 21 | if (LLVMFuzzerInitialize) { 22 | LLVMFuzzerInitialize(&argc, &argv); 23 | } 24 | fuzztest::InitFuzzTest(&argc, &argv); 25 | return RUN_ALL_TESTS(); 26 | } 27 | -------------------------------------------------------------------------------- /grammar_codegen/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | add_library( 3 | grammar_info 4 | INTERFACE 5 | grammar_info.h 6 | ) 7 | 8 | add_library( 9 | antlr_frontend 10 | STATIC 11 | antlr_frontend.cc 12 | antlr_frontend.h 13 | ) 14 | 15 | target_link_libraries( 16 | antlr_frontend 17 | PUBLIC 18 | grammar_info 19 | absl::str_format 20 | absl::strings 21 | fuzztest_logging 22 | generated_antlr_parser 23 | ) 24 | 25 | add_library( 26 | backend 27 | OBJECT 28 | backend.cc 29 | backend.h 30 | ) 31 | 32 | target_link_libraries( 33 | backend 34 | PUBLIC 35 | absl::btree 36 | absl::flat_hash_set 37 | absl::strings 38 | absl::str_format 39 | fuzztest_logging 40 | ) 41 | 42 | add_library( 43 | code_generation 44 | STATIC 45 | code_generation.cc 46 | code_generation.h 47 | ) 48 | 49 | target_link_libraries( 50 | code_generation 51 | PUBLIC 52 | antlr_frontend 53 | backend 54 | ) 55 | 56 | target_include_directories( 57 | code_generation 58 | PUBLIC 59 | ${PARENT_DIR} 60 | ) 61 | 62 | # TODO(changochen): Enable the test if we can figure out how to specify the path. 63 | #if (FUZZTEST_BUILD_TESTING) 64 | # add_executable( 65 | # code_generation_test 66 | # code_generation_test.cc 67 | # ) 68 | # target_link_libraries( 69 | # code_generation_test 70 | # PUBLIC 71 | # code_generation 72 | # absl::strings 73 | # GTest::gmock_main 74 | # ) 75 | # add_test( 76 | # NAME 77 | # code_generation_test 78 | # COMMAND 79 | # code_generation_test 80 | # ) 81 | #endif () 82 | -------------------------------------------------------------------------------- /grammar_codegen/backend_test.cc: -------------------------------------------------------------------------------- 1 | #include "./grammar_codegen/backend.h" 2 | 3 | #include 4 | 5 | #include "gtest/gtest.h" 6 | #include "./grammar_codegen/antlr_frontend.h" 7 | #include "./grammar_codegen/grammar_info.h" 8 | 9 | namespace fuzztest::internal::grammar { 10 | 11 | namespace { 12 | 13 | TEST(BackendTest, PreprocessInsertRuleForEOFAsNonTerminal) { 14 | const std::string grammar_str = R"( 15 | grammar TEST_GRAMMAR; 16 | root: "A" EOF; 17 | )"; 18 | GrammarInfoBuilder builder; 19 | Grammar grammar = builder.BuildGrammarInfo({grammar_str}, "test"); 20 | CodeGenerator backend(grammar); 21 | backend.Preprocess(grammar); 22 | EXPECT_EQ(grammar.rules.back().symbol_name, "EOF"); 23 | } 24 | 25 | TEST(BackendTest, PreprocessInsertRuleForEOFAsSubProduction) { 26 | const std::string kGrammar = R"foo( 27 | grammar TEST_GRAMMAR; 28 | root: "A" ("b" EOF)*; 29 | )foo"; 30 | GrammarInfoBuilder builder; 31 | Grammar grammar = builder.BuildGrammarInfo({kGrammar}, "test"); 32 | CodeGenerator backend(grammar); 33 | backend.Preprocess(grammar); 34 | EXPECT_EQ(grammar.rules.back().symbol_name, "EOF"); 35 | } 36 | 37 | } // namespace 38 | 39 | } // namespace fuzztest::internal::grammar 40 | -------------------------------------------------------------------------------- /grammar_codegen/code_generation.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2022 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include "./grammar_codegen/code_generation.h" 16 | 17 | #include 18 | #include 19 | #include 20 | 21 | #include "./grammar_codegen/backend.h" 22 | 23 | namespace fuzztest::internal::grammar { 24 | 25 | std::string GenerateGrammarHeader( 26 | const std::vector& input_grammar_specs, 27 | std::optional grammar_name, bool insert_space_between_blocks) { 28 | GrammarInfoBuilder builder; 29 | CodeGenerator backend(builder.BuildGrammarInfo( 30 | input_grammar_specs, grammar_name, insert_space_between_blocks)); 31 | return backend.Generate(); 32 | } 33 | } // namespace fuzztest::internal::grammar 34 | -------------------------------------------------------------------------------- /grammar_codegen/code_generation.h: -------------------------------------------------------------------------------- 1 | // Copyright 2022 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #ifndef FUZZTEST_GRAMMAR_CODEGEN_CODE_GENERATION_H_ 16 | #define FUZZTEST_GRAMMAR_CODEGEN_CODE_GENERATION_H_ 17 | 18 | #include 19 | #include 20 | #include 21 | 22 | #include "./grammar_codegen/antlr_frontend.h" 23 | #include "./grammar_codegen/backend.h" 24 | 25 | namespace fuzztest::internal::grammar { 26 | 27 | // Generate the code given the input grammar files. This simply combine the 28 | // process of building grammar information from grammar files and generating 29 | // code from grammar information. 30 | std::string GenerateGrammarHeader( 31 | const std::vector& input_grammar_specs, 32 | std::optional grammar_name = std::nullopt, 33 | bool insert_space_between_blocks = false); 34 | 35 | } // namespace fuzztest::internal::grammar 36 | 37 | #endif // FUZZTEST_GRAMMAR_CODEGEN_CODE_GENERATION_H_ 38 | -------------------------------------------------------------------------------- /grammar_codegen/generated_antlr_parser/ANTLRv4ParserBaseListener.cpp: -------------------------------------------------------------------------------- 1 | // [The "BSD 3-clause license"] 2 | // Copyright (c) 2005-2007 Terence Parr 3 | // Copyright (c) 2012-2015 Terence Parr 4 | // Copyright (c) 2012-2015 Sam Harwell 5 | // Copyright (c) 2014-2015 Gerald Rosenberg 6 | // Copyright (c) 2023 Google LLC 7 | // All rights reserved. 8 | 9 | // Redistribution and use in source and binary forms, with or without 10 | // modification, are permitted provided that the following conditions 11 | // are met: 12 | 13 | // 1. Redistributions of source code must retain the above copyright 14 | // notice, this list of conditions and the following disclaimer. 15 | // 2. Redistributions in binary form must reproduce the above copyright 16 | // notice, this list of conditions and the following disclaimer in the 17 | // documentation and/or other materials provided with the distribution. 18 | // 3. Neither the name of the copyright holder nor the names of its 19 | // contributors may be used to endorse or promote products derived from this 20 | // software without specific prior written permission. 21 | // 22 | // THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 23 | // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 24 | // OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 25 | // IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 26 | // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 27 | // NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 31 | // THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 | 33 | // Generated from ANTLRv4Parser.g4 by ANTLR 4.11.2 34 | 35 | #include "ANTLRv4ParserBaseListener.h" 36 | 37 | using namespace antlr4_grammar; 38 | -------------------------------------------------------------------------------- /grammar_codegen/generated_antlr_parser/ANTLRv4ParserListener.cpp: -------------------------------------------------------------------------------- 1 | // [The "BSD 3-clause license"] 2 | // Copyright (c) 2005-2007 Terence Parr 3 | // Copyright (c) 2012-2015 Terence Parr 4 | // Copyright (c) 2012-2015 Sam Harwell 5 | // Copyright (c) 2014-2015 Gerald Rosenberg 6 | // Copyright (c) 2023 Google LLC 7 | // All rights reserved. 8 | 9 | // Redistribution and use in source and binary forms, with or without 10 | // modification, are permitted provided that the following conditions 11 | // are met: 12 | 13 | // 1. Redistributions of source code must retain the above copyright 14 | // notice, this list of conditions and the following disclaimer. 15 | // 2. Redistributions in binary form must reproduce the above copyright 16 | // notice, this list of conditions and the following disclaimer in the 17 | // documentation and/or other materials provided with the distribution. 18 | // 3. Neither the name of the copyright holder nor the names of its 19 | // contributors may be used to endorse or promote products derived from this 20 | // software without specific prior written permission. 21 | // 22 | // THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 23 | // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 24 | // OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 25 | // IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 26 | // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 27 | // NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 31 | // THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 | 33 | // Generated from ANTLRv4Parser.g4 by ANTLR 4.11.2 34 | 35 | #include "ANTLRv4ParserListener.h" 36 | 37 | using namespace antlr4_grammar; 38 | -------------------------------------------------------------------------------- /grammar_codegen/generated_antlr_parser/BUILD: -------------------------------------------------------------------------------- 1 | # Copyright 2022 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | # Generated parser for antlr4 grammar. 16 | 17 | package(default_visibility = ["@com_google_fuzztest//grammar_codegen:__pkg__"]) 18 | 19 | licenses(["notice"]) 20 | 21 | cc_library( 22 | name = "generated_antlr_parser", 23 | srcs = [ 24 | "ANTLRv4Lexer.cpp", 25 | "ANTLRv4Parser.cpp", 26 | "ANTLRv4ParserBaseListener.cpp", 27 | "ANTLRv4ParserListener.cpp", 28 | ], 29 | hdrs = [ 30 | "ANTLRv4Lexer.h", 31 | "ANTLRv4Parser.h", 32 | "ANTLRv4ParserBaseListener.h", 33 | "ANTLRv4ParserListener.h", 34 | ], 35 | copts = [ 36 | "-fexceptions", 37 | # FIXME: antlr generates broken C++ code that attempts to construct 38 | # a std::string from nullptr. It's not clear whether the relevant 39 | # constructs are reachable. 40 | "-Wno-nonnull", 41 | ], 42 | features = ["-use_header_modules"], # Incompatible with -fexceptions. 43 | deps = ["@antlr_cpp//:antlr4-cpp-runtime"], 44 | ) 45 | -------------------------------------------------------------------------------- /grammar_codegen/generated_antlr_parser/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_library( 2 | generated_antlr_parser 3 | STATIC 4 | ANTLRv4Lexer.cpp 5 | ANTLRv4Parser.cpp 6 | ANTLRv4ParserBaseListener.cpp 7 | ANTLRv4ParserListener.cpp 8 | ) 9 | 10 | target_link_libraries( 11 | generated_antlr_parser 12 | PUBLIC 13 | antlr4_static 14 | ) 15 | 16 | target_include_directories( 17 | generated_antlr_parser 18 | PUBLIC 19 | ${antlr_cpp_SOURCE_DIR}/runtime/src 20 | ${CMAKE_CURRENT_SOURCE_DIR} 21 | ) -------------------------------------------------------------------------------- /grammar_codegen/generated_antlr_parser/README.md: -------------------------------------------------------------------------------- 1 | The files under this directory are generated! Do not edit! 2 | 3 | To generate these files, use the grammar files at 4 | https://github.com/antlr/grammars-v4/tree/4f16c947878c303da520e21ac75272eb8443fc2f/antlr/antlr4. 5 | 6 | We make the following modification: 7 | 8 | 1. Merged LexerAdaptor.h/cpp and LexBasic.g4 with ANTLRv4Lexer.g4. 9 | 2. Fix grammar to work with C++ following 10 | https://github.com/antlr/grammars-v4/issues/2239. 11 | -------------------------------------------------------------------------------- /tools/BUILD: -------------------------------------------------------------------------------- 1 | # Copyright 2022 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | # Tools. 16 | 17 | package(default_visibility = ["//visibility:public"]) 18 | 19 | licenses(["notice"]) 20 | 21 | sh_binary( 22 | name = "minimizer", 23 | srcs = ["minimizer.sh"], 24 | ) 25 | 26 | cc_binary( 27 | name = "grammar_domain_code_generator", 28 | srcs = ["grammar_domain_code_generator.cc"], 29 | deps = [ 30 | "@abseil-cpp//absl/flags:flag", 31 | "@abseil-cpp//absl/flags:parse", 32 | "@com_google_fuzztest//fuzztest/internal:logging", 33 | "@com_google_fuzztest//grammar_codegen:code_generation", 34 | ], 35 | ) 36 | -------------------------------------------------------------------------------- /tools/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_executable( 2 | grammar_domain_code_generator 3 | grammar_domain_code_generator.cc 4 | ) 5 | 6 | target_link_libraries( 7 | grammar_domain_code_generator 8 | absl::flags 9 | absl::flags_parse 10 | fuzztest_logging 11 | code_generation 12 | ) --------------------------------------------------------------------------------