├── .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